Samedi 21 juin 2008
Sur un serveur Windows 2003 Server, vous avez deux possibilités principales pour héberger vos services WCF : IIS ou un service Windows. L'avantage de IIS est que cet hébergement va gérer par lui même le recyclage, le monitoring et surtout est très avantageux par sa simplicité de déploiement.
Par contre vous n'allez pas pouvoir avec IIS héberger des services WCFavec points de communication non http (ce qui est possible avec Windows 2008 Server avec le système WAS Windows Activation Services).

Sous 2003 Server pour héberger des services avec des points de communication non http, vous allez donc privilégier l'hébergement par service windows.
Pour vous aider à mettre en place ce type de solution, je vous propose une solution démo (compatible Visual Studio 2008 uniquement) :
Démonstration d'un Service Windows hébergeant des services WCF.

Dans cette solution de démonstration vous trouverez donc un service Windows hébergeant deux services WCF "Service A" et "Services B" (leur contrat étant dans le projet "Demo.Interfaces" et leur implémentation dans "Demo.Services). Le projet "Demo.WindowsService" est le projet hébergeant le service windows et la classe installer permettant d'installer le service Windows à partir d'un Msi. Le projet "Demo.Setup" est le projet msi installant le service Windows et enfin le projet "Demo.Client" est une simple application cliente communiquant avec les deux services hébergés par le service Windows.

Les deux services ont chacun un point de communication de type tcp aussi bien pour l'échange des données que des méta données.

par DotNet Dev publié dans : WCF communauté : Microsoft .NET
ajouter un commentaire commentaires (0)    créer un trackback recommander
Dimanche 15 juin 2008
Voici quelques conseils pour bien choisir vos liaisons (ou binding in english) WCF :

  1.  - Si vous cherchez la perfomance et que vous avez aucune contrainte d'interopérabilité, privilégiez les liaisons orientés connexion ("netNamedPipeBinding" pour un service hébergé sur la machine où se trouve le consomateur de ce service ou encore "netTcpBinding" pour un service pouvant être appelé d'une autre machine).
  2.  - En règle général, pour des services internes à l'entreprise privilégiez les liaisons orientés connexion si vous n'avez pas de beoin d'interopérabilité avec d'autres systèmes.
  3.  - En mode http, privilégiez la liaison "wsHttpBinding" (compatible SOAP 1.2) et qui supporte les dernières extensions WS*.
  4.  - En mode http, utilisez la laison "basicHttpBinding" pour être compatible avec des clients webservice asmx et SOAP 1.1. Dans le cas contraire, privilégiez toujours en http la liaison "wsHttpBinding".
  5.  - Dans le besoin d'avoir des messages de retour en http, utilisez la liaison "wsDualHttpBinding". Attention cette liaison ne supporte pas toutes les fonctionnalités de la liaison "wsHttpBinding" notamment en terme de sécurité.

Pour finir et en règle générale, n'oubliez pas qu'un service WCF peut avoir plusieurs points de communications. On peut donc très bien imaginer pour un même service de créer un point de communication avec une liason "basicHttpBinding" pour les clients SOAP 1.1 et un autre point avec une liaison "wsHttpBinding" pour les clients SOAP 1.2.

par DotNet Dev publié dans : WCF communauté : Microsoft .NET
ajouter un commentaire commentaires (0)    créer un trackback recommander
Dimanche 15 juin 2008

L'équipe Microsoft de WCF ainsi que des acteurs externes ont réalisé un livre blanc (actuellement en beta) sur les bonnes pratiques pour la mise en place d'une architecture SOA sécurisée avec WCF. Un guide vraiment très complet que je vous recommande : WCF Security Guide.

Vous trouverez dans ce livre blanc plusieurs scénarios de systèmes sécurisés en spécifiant les meilleurs pratiques de sécurisation de vos services que ce soit au niveau de la tuyauterie WCF via sa configuration ou de l'implémentation de ces services, gestion des identités utilisateurs, politique de sécurité d'accès aux bases de données via les services WCF...

par DotNet Dev publié dans : WCF communauté : Microsoft .NET
ajouter un commentaire commentaires (0)    créer un trackback recommander
Mardi 10 juin 2008

Avant d'aller plus loin, pour ceux qui ne connaisent pas Unity Application Block, je vous renvoit vers mon post de Présentation d'Unity Application Block.

J'ai été confronté aujourd'hui à une problématique qui était de gérer un service générique. Nous utiliserons dans ce post pour exemple l'interface du service  IServiceGenerique
<T, U> avec son implémentation MonServiceGenerique
<T, U>.
Nous utilisions alors toujours la version 1.0 d'Unity Application Block (grosse erreur !) et en faisant le code suivant pour récupérer nos services (en mode singleton via le "ContainerControlledLifetimeManager") :

container.Resolve<IServiceGenerique<ClassA, ClassB
>>();
container.Resolve<IServiceGenerique<ClassA, ClassA>>();

Unity nous récupérait alors bien le premier service IServiceGenerique<ClassA, ClassB> mais lors du deuxième Resolve, unity nous renvoyait toujours le IServiceGenerique<ClassA, ClassB> au lieu du IServiceGenerique<ClassA, ClassA> !

En faisant ensuite une recherche sur internet, c'était effectivement un bug d'unity v 1.0 qui a été corrigé avec unity 1.1. Si vous utilisez Unity, je vous conseille donc vivement de mettre à jour vos dépendances en récupérant
Unity V 1.1.

Avec Unity 1.1, le code suivant  (toujours en mode singleton) :

container.Resolve<IServiceGenerique<ClassA, ClassB>>();
container.Resolve<IServiceGenerique<ClassA, ClassA
>>();
container.Resolve<IServiceGenerique<ClassA, ClassA
>>();
container.Resolve<IServiceGenerique<ClassB, ClassA
>>();

nous retournera 3 instances de type IServiceGenerique<ClassA, ClassB>, IServiceGenerique<ClassA, ClassA> et IServiceGenerique<ClassB, ClassA>.

Pour information pour configurer l'enregistrement de votre type générique, voici la config unity :

<type type="UAB.Demo.Interfaces.IServiceGenerique`2, UAB.Demo.Interfaces" mapTo="UAB.Demo.Services.MonServiceGenerique`2, UAB.Demo.Services">
<
lifetime type="singleton" />
</
type>

Pour une classe générique avec un seul type et non deux, remplacez le '2 par '1 etc...

 

par DotNet Dev publié dans : MS Application Blocks communauté : Microsoft .NET
ajouter un commentaire commentaires (0)    créer un trackback recommander
Lundi 9 juin 2008
Une des fonctionnalités assez intéressante  dans Visual Studio 2008 pour les développeurs WCF est l'ajout d'un mini  serveur pour héberger les services WCF en debug. Sur un projet "Service WCF", il est en effet possible de lancer directement le projet, action qui lancera un serveur "WCF Service Host" hébergeant vos services configurés dans la librairie (à l'image du lancement d'un mini serveur web ex Casini pour les projets Web ASP.NET) :



Si vous avez créé un simple projet librairie et non un projet "WCF Service" et vous souhaitez lancer "WCF Service Host" directement à partir de Visual Studio, rien n'est perdu. Il suffit d'ajouter la ligne suivante dans votre fichier de projet MsBuild (dans la section "Project/PropertyGroup") :

< ProjectTypeGuids>{3D9AD99F-2412-4246-B90B-4EAA41C64699};
{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids
>

Pour lancer en même temps l'outil "WCF Test Client" qui vous permet de tester votre service à partir d'une application windows, il suffit d'ajouter la ligne suivante (toujours dans votre fichier de projet MsBuild) :

<StartArguments>/client:"WcfTestClient.exe"</StartArguments> 

par DotNet Dev publié dans : WCF communauté : Microsoft .NET
ajouter un commentaire commentaires (0)    créer un trackback recommander
Lundi 9 juin 2008

Il est souvent utile d'éditer directement son ficher de projet MsBuild notamment pour gérer ses tâches et imports MsBuild.

Lorsque votre fichier MsBuild est chargé, il est impossible de l'éditer directement dans Visual Studio. Il vous faut donc auparavant le décharger à partir du menu contextuel sur le projet en sélectionnant "Unload Project" :


Une fois votre fichier projet MsBuild déchargé, il ne vous reste plus qu'à l'éditer à partir du menu "Edit CsProj" :


par DotNet Dev publié dans : Visual Studio communauté : Microsoft .NET
ajouter un commentaire commentaires (0)    créer un trackback recommander
Dimanche 8 juin 2008
L'un des intérêts d'exposer plusieurs contrats (ou interfaces) sur un service WCF est de notamment permettre de fournir des opérations différentes suivant les acteurs accédants au service. Prenons le diagramme de classe suivant :


Nous avons donc un service "TradeService" qui expose l'opération "GetOrder" permettant de récupérer un ordre aussi bien pour un manager q'un analyste, l'opération "CreateOrder" destinée aux analystes pour créer un ordre et l'opération "ValidateOrder" destinée aux managers pour valider un ordre.

Le faire d'exposer le service sous la forme de deux contrats nous permettra ainsi d'exposer le contrat "IAnalysteTradeService" en protocole tcp sur le port 8000 (acteurs internes à l'entreprise) et d'exposer le contrat "IManagerTradeService" en protocole http sur le port 80 (acteurs externes à l'entreprise). Voici la configuration WCF correspondant à ce cas de figure :

<system.serviceModel>
  <services
>
    <
service behaviorConfiguration="serviceBehavior" name="TradeSystem.Services.TradeService"
>

      <
endpoint address="ManagerTradeService" binding="basicHttpBinding" bindingConfiguration="" name="managerEndPoint" contract="TradeSystem.Interfaces.IManagerTradeService"
/>
      <
endpoint address="AnalystTradeSystem" binding="netTcpBinding" bindingConfiguration="" name="analystEndPoint" contract="TradeSystem.Interfaces.IAnalystTradeService" />

      <host>
        <
baseAddresses
>
          <
add baseAddress="http://localhost:80"
/>
          <
add baseAddress="net.tcp://localhost:9000"
/>
        </
baseAddresses
>
      </
host
>
    </
service
>
  </
services
>
</
system.serviceModel
>

L'un des problèmes de cette solution réside dans le fait où le client interroge les méta données du service, il récupéra aussi les opérations des deux acteurs (même si suivant le endpoint utilisé, il ne pourra utiliser que certaines de ces opérations). Pour éviter cela, le moyen est donc d'exposer non pas un service mais deux services.

par DotNet Dev publié dans : WCF communauté : Microsoft .NET
ajouter un commentaire commentaires (1)    créer un trackback recommander
Samedi 7 juin 2008
Nous avons vu dans un précédent post la mise en place d'une classe générique pour parser vos chaînes de caractères en énumération pour éviter la ligne de code suivante qui était assez fastidieuse :

MyEnum myEnum1 = (MyEnum) Enum.Parse(typeof(MyEnum), "Enum1", true
);

Voyons à présent une nouvelle fonctionnalité proposée par le langage C# 3.0 qui est la méthode d'extension. Une méthode d'extension va vous permettre d'étendre les méthodes de base qui sont présentes sur vos types pour ajouter vos propres méthodes.

Nous allons dans notre exemple ajouter une nouvelle méthode "EnumParse<T>" sur le type string pour permettre de convertir directement votre string en une énumération de type T. Pour créer une méthode d'extension, il vous faut créer une méthode statique en utilisant le mot clef "this" suivi du type sur lequel vous voulez ajouter votre méthode d'extension dans le premier paramètre.

Voici donc la méthode d'extension pour convertir votre chaîne en énumération  :

public static class StringExtension
{
    public static T EnumParse<T>(this string
value)
            where T :
struct
    {
        return (T) EnumParse<T>(value, false
);
    }
  

    public static T EnumParse<T>(this string value, bool ignoreCase)
             where T :
struct
    {
        return (T)Enum.Parse(typeof
(T), value, ignoreCase);
    }
}

Et pour l'utiliser, il vous suffira simplement de faire appel à la méthode "EnumParse<T>" à partir de vos types "string" :

string value = "Enum1";
MyEnum myEnum = value.EnumParse<MyEnum
>();

Le compilateur C# pour transformer votre méthode en méthode d'extension se contentera de positionner l'attribut "System.Runtime.CompilerServices.Extension" au-dessus de chaque méthode où le mot clef "this" se trouve.

Restez tout de même vigilant dans l'utilisation de vos méthodes d'extensions. Une des plus grosses problématiques dans les méthodes d'extensions réside dans le fait de réaliser une méthode "EnumParse<T>" et plus tard de se retrouver avec le framework 4.0 avec la même méthode. Du coup ca sera la méthode du framework qui sera appelé et non votre méthode d'extension. Pour éviter cela, n'hésitez pas à préfixer vos méthodes d'extensions.

Nous verrons dans des prochains post l'utilisation des méthodes d'extensions au sein de Linq ainsi que la possibilité de surcharger vos méthodes d'extensions.

par DotNet Dev publié dans : C# communauté : Microsoft .NET
ajouter un commentaire commentaires (0)    créer un trackback recommander
Jeudi 5 juin 2008
Un gros manque que ce soit en  2.0 ou 3.5 concernant la manipulation des énumérations est l'absence d'une méthode générique pour traiter une chaîne de caractère pour la transformer en énumération.

Que ce soit en .NET 1.0, 2.0 ou 3.5, le moyen par défaut pour arriver à ce résultat est le suivant :

MyEnum myEnum1 = (MyEnum) Enum.Parse(typeof(MyEnum), "Enum1", true);

Créons à présent une classe "EnumHelper" permettant de gérer une méthode générique permettant d'arriver au même résultat mais en simplifiant la syntaxe :

public static class EnumHelper
{
    public static T Parse<T>(string
value)
          where T :
struct
    {
        return Parse<T>(value, false
);
    }
 

    public static T Parse<T>(string value, bool ignoreCase)
          where T :
struct
    {
        return (T)Enum.Parse(typeof
(T), value, ignoreCase);
    }
}

Avec notre classe "EnumHelper", nous obtenons donc :

MyEnum myEnum2 = EnumHelper.Parse<MyEnum>("Enum1");

Nous verrons dans un prochain post comment utiliser la fonctionnalité des méthodes d'extension en C# 3.0 pour ajouter une méthode sur le type string permettant de le transformer en une énumération.

par DotNet Dev publié dans : C# communauté : Microsoft .NET
ajouter un commentaire commentaires (0)    créer un trackback recommander
Mercredi 4 juin 2008

Le fait de ne pas pouvoir affecter la valeur null sur des types valeurs en .NET 1.0 pouvait poser problème. Il est en effet impossible d'affecter la valeur null à un type int par exemple comme suit :

int
number = null;

La solution était tout simplement alors d'affecter par exemple une valeur arbitraire pour désigner la valeur null (int
.MinValue par exemple) ou encore de créer une structure wrapper sur le type pour indiquer via un booléen si le type était null.

C'est ce dernier choix qui a été fait avec l'arrivée de C# 2.0 avec le type Nullable
<T> qui permet donc d'affecter la valeur null sur un type valeur et seulement valeur. En effet, une contrainte sur le type T de la classe Nullable<T> a été placé pour ne pouvoir passer que des types valeurs (un type par référence n'ayant aucune raison d'être géré).

Pour affecter la valeur null sur le type int, nous allons donc avoir :

Nullable
<int> number = null;

A savoir que toujours depuis C# 2.0, l'opérateur "?" placé devant le type valeur va vous permettre de faire appel directement au type Nullable
<T>. Le code peut donc être remplacé par le suivant :

int
? number = null;

Deux moyens seront mis alors à votre disposition pour pouvoir tester la nullité de votre type valeur. Le premier en faisant appel à la propriété "HasValue" et le deuxième en testant tout simplement l'égalité sur null comme suit :

if (!number.HasValue)
  return
;
if (number == null
)
  return
;

Il faut ensuite faire attention à la manipulation de ces types nullables. Il vous sera impossible par exemple d'avoir la ligne de code suivante :

int
number2 = number.Value + 2;

...pour la simple raison que le compilateur ne peut convertir un type int? en int. Deux moyen là encore seront mis à votre disposition. Le premier est de déclarer le type number2 en type nullable :

int
? number2 = number + 2;

Le deuxième est d'utiliser la propriété "Value" du type nullable :

int
number2 = number.Value + 2;

Concernant le boxing, il vous sera possible de boxer un type seulement si celui-ci est nullable. Nous pourrions donc avoir :

object
o = 33;
int? number = (int?)o;

par DotNet Dev publié dans : C# communauté : Microsoft .NET
ajouter un commentaire commentaires (0)    créer un trackback recommander

Partenaires

Contact - C.G.U. - Signaler un abus