Archive

Archive for the ‘WCF’ Category

WCF 4.5 – Récupérer tout le contenu WSDL en un seul et unique fichier

La version 4.5 de WCF a introduit une nouvelle manière de récupérer le contenu des métadonnées. Auparavant si vous avez activé l’exposition des métadonnées vous y accéder en utilisant une url du genre http://addresipdemonservice?wsdl. Le hic avec cette méthode est que cela posait des soucis d’interopérabilités si on était amené à travailler avec des clients pas développés avec la technologie .Net. En effet ces clients n’arrivent pas à lire contenu du wsdl. Pourquoi ? Il suffit d’observer le contenu du wsdl, vous verrez que tout n’y est pas par exemple les métadonnées sur les types utilisés par votre service. Les métadonnées concernant les types sont en effet importées via la balise xsd:import et l’attribut schemaLocation spécifie où chercher ces données. Bref ce procédé n’est pas compréhensible par les clients faits en Java, Php etc…

Pour récupérer toutes les métadonnées dans un seul et unique fichier vous pouvez au lieu de mettre ?wsdl utiliser ?singleWsdl à la place donc http://addresipdemonservice?singlewsdl pour assurer l’interopérabilité.

J’espère que ce post vous a servi 🙂

Catégories :WCF Étiquettes :

Comment étendre le binding d’un endpoint par défaut ?

D’habitude lorsque je fais un petit test en WCF, j’ai l’habitude, pour aller plus vite, de laisser mon ServiceHost créer automatiquement les endpoints dont j’aurai besoin suivant l’adresse de base que j’aurai fournie dans le fichier de configuration. C’est cool et les endpoints créés de façon automatique sont appelés en fait des default endpoints (les points de terminaison par défaut).

Sauf que j’ai voulu, lors d’un de mes tests, changer l’encodage utilisé pour les messages alors je me suis dit qu’il fallait obligatoirement passer par un endpoint créé manuellement dans le fichier de configuration et par la suite utiliser l’attribut bindingConfiguration pour lui attribuer le nom de la nouvelle configuration créée. Mais il y a deux méthodes plus simples :

  • Passer par une configuration de binding par défaut. Pour info une configuration de binding par défaut est une configuration qui n’a pas de nom. L’attribut name n’est pas renseigné donc tout endpoint dont l’attribut bindingConfiguration n’est pas défini, utilisera cette configuration associée si son binding lui correspondant. Cela est valable pour les endpoints par défaut.
  • Un peu plus complexe mais le problème avec la première méthode est que si on a déjà une configuration par défaut déjà disponible utilisée par d’autres endpoints et qu’on n’aimerait pas modifier alors cette deuxième méthode nous permet de pallier à ce problème. Pour cela il faut passer par le mappage des endpoints par défaut c’est à dire utiliser l’élément protocolMappings, dans le mappage ajouté pour le protocole http et le binding basicHttpBinding dans notre cas, j’utilse l’attribut bindingConfiguration fourni.

Voilà j’espère que ce billet vous a été utile 😉

Catégories :WCF Étiquettes :

Comment déboguer un service windows sous Visual Studio ?

Lorsque vous créez un projet de type Service Windows sous Visual Studio, vous avez remarqué que la boîte de dialogue ci-dessous s’affiche quand on essaie d’exécuter le service :

En résumé il est tout simplement impossible d’exécuter un service windows sous Visual Studio, on doit obligatoirement passer par la commande NET START pour démarrer le service après avoir préalablement installé celui-ci grâce à la commande INSTALLUTIL. Sauf que cette méthode nous empêche de faire facilement un deboguage du service Windows. En effet il faut installer le service, le démarrer, puis dans Visual Studio attacher un processus (qui sera bien sûr le processus du service windows) pour pouvoir déboguer notre code. Sans oublier qu’il va falloir aussi arrêter le service windows pour pouvoir compiler suite à quelques modifications qu’on aura effectuées dans le code du service. Bref c’est un peu lourd :D.

Il y a plus simple. on utilisera les symboles de compilation pour détecter dans quel mode nous sommes : RELEASE ou DEBUG. Si nous sommes en :

  • DEBUG : nous allons traiter notre service windows comme une simple application windows forms en affichant une boîte de dialogue indiquant que le service est démarré
  • RELEASE : le fonctionnement sera le même que quand nous avons essayé d’exécuter notre service windows sous Visual Studio. En d’autres termes, ce mode doit être utilisé en production une fois le débogage terminé

Pour notre cas d’utilisation ce sera très simple. Il s’agira ici de rendre possible l’exécution du service Windows et de déboguer un service WCF qu’il héberge. Voici les étapes à suivre :

  1. Modification du code du service windows : nous allons ajouter deux méthodes StartWCFService et StopWCFService qui ont pour tâches respectives de démarrer et d’arrêter l’écoute des requêtes entrantes WCF. La première méthode sera appelée dans la rédéfinition de la méthode OnStart et la seconde dans celle de la méthode OnStop. Ci-dessous le code :
    private ServiceHost host;
    
    public MyWindowsService() {
        InitializeComponent();
    }
    
    protected override void OnStart(string[] args) {
        this.StartWCFService();
    }
    
    protected override void OnStop() {
        this.StopWCFService();
    }
    
    public void StartWCFService() {
        this.host = new ServiceHost(typeof(IWCFService));
        this.host.Open();
    }
    
    public void StopWCFService() {
        if (this.host != null && this.host.State == CommunicationState.Opened)
            this.host.Close();
    }
    
  2. Modification du fichier Program.cs : c’est dans la méthode Main que nous allons faire la détection du mode de compilation dans lequel nous sommes. Si nous sommes en mode RELEASE, alors le service windows s’exéctute comme d’habitude et forcément on aura la fameuse boîte de dialogue si on essaie de l’exécuter sous Visual Studio avec ce mode. Si par contre, nous sommes en mode DEBUG, alors c’est très simple on fait appel directement à la méthode StartWCFService de l’instance de notre service windows (donc la méthode OnStart ne sera pas appelée) puis on affiche une boîte de dialogue pour en informer l’utilisateur. si ce dernier ferme la boîte de dialogue alors la méthode StopWCFService est appelée pour arrêter le service WCF (donc la méthode OnStop du service Windows ne sera pas appelée).
    Ci-dessous le code de la méthode Main :

    static void Main() {
    
        MyWindowsService service = new MyWindowsService();
    
    #if DEBUG
        service.StartWCFService();
        MessageBox.Show("Le service a démarré...");
        service.StopWCFService();
    #else
    
        ServiceBase[] ServicesToRun;
        ServicesToRun = new ServiceBase[]
    	{
    		service
    	};
        ServiceBase.Run(ServicesToRun);
    #endif
    }
    

J’espère que ce billet vous a été utile 😉

Catégories :.Net, WCF Étiquettes : , , ,

Astuce : [WCF] Exposer son service WCF sous IIS sans passer par la directive ServiceHost

Lorsqu’on veut héberger son service WCF sous IIS nous utilisons la plupart du temps le template de fichier sous Visual Studio portant l’extension *.svc. Dans ce template nous devons effectuer un certain nombre de paramétrages pour que IIS puisse héberger le service et l’activer lors de la réception de la première requête client en utilisant la directive ServiceHost comme dans l’exemple ci-dessous :

<%@ ServiceHost Language= »C# » Debug= »true »  Service= »WebApplicationTest.MyService » CodeBehind= »MyService.svc.cs » %>

Une nouveauté venue avec la sortie de WCF 4.0 permet de ne pas utiliser le fichier template *.svc et par conséquent de ne pas utiliser la directive ServiceHost, mais de tout paramétrer via le fichier de configuration web.config comme suit :

<system.serviceModel>
  <serviceHostingEnvironment>
    <serviceActivations>
      <add service="WebApplicationTest.MyService" relativeAddress="MyService.svc" />
    </serviceActivations>
  </serviceHostingEnvironment>
</system.serviceModel>

Dans l’exemple ci-dessus, nous venons d’héberger notre service MyService sans passer par la directive ServiceHost du traditionnel fichier *.svc. Les seules choses dont il faut faire attention lors de la configuration sont :

  1. la présence de l’espace de noms de notre service dans l’attribut service.
  2. la présence obligatoire de l’extension .svc dans la valeur de l’attribut relativeAddress

Notez que vous pouvez aussi configurer le factory à utiliser via l’attribut factory.

Catégories :Astuces, WCF Étiquettes :

Services web et services WCF : Quelle est la différence ?

27 août 2011 1 commentaire

Avant de répondre à la question, il faut savoir qu’est-ce qu’est un service web. D’après la définition de Wikipedia :

Un service web est un programme informatique permettant la communication et l’échange de données entre applications et systèmes hétérogènes dans des environnements distribués. Il s’agit donc d’un ensemble de fonctionnalités exposées sur internet ou sur un intranet, par et pour des applications ou machines, sans intervention humaine, et de manière synchrone.

En gros un service web est une application exposant ses services en se basant sur le protocole HTTP ou HTTPS. Comme exemple on peut citer les services utilisant l’architecture REST (REpresentational State Transfert), les services OData et les services web traditionnels déployés en utilisant les fichiers de type ASMX avec ASP.Net.

WCF va au delà du simple fait d’exposer des services à travers le protocole HTTP/HTTPS. Parce qu’avec cette technologie nous ne sommes pas limités à l’utilisation de HTTP/HTTPS comme protocole mais il nous est possible d’utiliser TCP, IPC ou MSMQ. Ce qu’il faut comprendre c’est qu’à partir du moment où on n’utilise plus le protocole HTTP/HTTPS alors on ne parle plus de service web mais de service WCF tout simplement.

En travaillant avec WCF, nous définissons un ou plusieurs endpoints. Chaque endpoint utilise un binding et le binding est étroitement lié au protocole que nous utilisons ainsi j’ai fourni une liste des bindings WCF les plus utilisés en les classant selon la dénomination qu’ils entraînent :

  • Service web : BasicHttpBinding, WSHttpBinding
  • Service WCF : NetTcpBinding, NetNamedPipeBinding et NetMsmqBinding

Limiter l’accès d’un service web WCF à un ou plusieurs types d’appareils

Dans certaines situations, nous pourrions avoir besoin de limiter l’accés d’un service web à un type d’appareil donné (Ex : l’accés ne sera autorisé que pour les utilisateurs d’Iphone).
Dans ce billet je vais montrer comment mettre cela en place avec un service web WCF hébergé par une application web.

Prenons comme un cas pratique simple : l’accès à notre service ne sera possible que les périphériques mobiles utisant le système IPhone ou Windows Phone.

Comment via notre service WCF allons-nous récupérer les infos sur le système utilisé par le client ?
Réponse : cela est possible grâce à la proprieté UserAgent de la requête entrante.
Pour accéder à cette propriété rien de plus simple : HttpContext.Current.Request.UserAgent. Cette propriété renvoie une chaine de caractère contenant l’information sur le système utilisé par l’utilisateur ;).
Ainsi nous pouvons alors créer la fonction GetUserOS qui renvoie un enum UserOS qui correspond à l’OS utilisé 😀

public enum UserOS
{
	Windows,
	Mac,
	IPhone,
	WindowsPhone,
	Linux,
	FreeBSD,
	SunOS,
	TRIX,
	BeOS,
	OS2,
	AIX, 
	Other
}

public UserOS GetUserOs()
{
	string userAgent = HttpContext.Current.Request.UserAgent.ToLower();
	if (userAgent.Contains("windows phone")) return UserOS.WindowsPhone;
	else if (userAgent.Contains("win")) return UserOS.Windows;
	else if (userAgent.Contains("mac")) return UserOS.Mac;
	else if (userAgent.Contains("iphone")) return UserOS.IPhone;
	else if (userAgent.Contains("linux")) return UserOS.Linux;
	else if (userAgent.Contains("freebsd")) return UserOS.FreeBSD;
	else if (userAgent.Contains("sunos")) return UserOS.SunOS;
	else if (userAgent.Contains("trix")) return UserOS.TRIX;
	else if (userAgent.Contains("beos")) return UserOS.BeOS;
	else if (userAgent.Contains("os/2")) return UserOS.OS2;
	else if (userAgent.Contains("aix")) return UserOS.AIX;
	return UserOS.Other;
}
	

Nota Béné : Comme vous pouvez le voir on utilise le contexte HTTP, donc pour que HttpContext.Current ne renvoie pas null il faut que notre service soit hébergé dans un serveur web tel que IIS ou WAS.

Cette méthode peut être utilisée à divers endroit de notre application web où il est possible d’intercepter les requêtes, on peut par exemple s’abonner à l’évènement BeginRequest et décider de ce qu’on veut faire :

// Dans le gestionnaire de l'évènement BeginRequest de l'application
protected void Application_BeginRequest(object sender, EventArgs e)
{
	UserOS userOS = this.GetUserOs();
	List<UserOS> authorizedOS = new List<UserOS> { UserOS.IPhone, UserOS.WindowsPhone };
	if (authorizedOS.Exists(os => os == userOS))
	{
		HttpContext.Current.Response.Write("Le service n'est limité qu'aux utilisateurs d'IPhone");
		HttpContext.Current.Response.End();
	}
}

Dans le code ci-dessus j’ai géré l’évènement BeginRequest de l’application web (dans le cas d’un service WCF Data Services, la redéfinition de la méthode protégée OnStartProcessingRequest est plus élégante et joue le même rôle que la gestion de l’évènement BeginRequest).
Cette méthode permet de centraliser la gestion de l’accès mais rien ne vous empêche de créer une méthode qui se chargera de vérfier l’accés et d’appeler celle-ci avant le début de chaque opération de votre service WCF (cette méthode doit être privilégiée si certaines opérations doivent être accessible par tous les OS et d’autres non ;)).

Nota Béné : Pour récupérer l’OS utilisé nous utilisons la chaîne de caractère USER AGENT envoyée à notre serveur mais il se trouve que certains navigateurs tels que FireFox permettent à l’utilisateur de changer cette chaîne :(. Donc tout cela pour dire que cette manière de limiter l’accès d’un service à un ensemble de périphérique n’est pas fiable à 100%.

Catégories :WCF, WCF Data Services Étiquettes : , ,

Gérer les évènements de la classe ServiceHost sous IIS et WAS

Pour héberger un service web WCF sous IIS ou sous WAS, nous sommes obligés de passer par un fichier portant l’extension .svc et d’utiliser la directive @ServiceHost. Par exemple pour héberger le service WCFLibrary.Service, la directive ressemblera à ceci :
Ceci est la syntaxe de base et ne nous permet pas de savoir à quel moment notre service est ouvert ou fermé (le service peut être fermé par IIS parce que le recyclage est en train de s’effectuer).

Pour pouvoir gérer ces deux évènements (Openned et Closed) nous devons créer une classe que je nomme MyServiceHostFactory et cette classe doit dériver de ServiceHostFactory.

Après la définition la classe nous allons changer la directive de notre fichier *.svc, en y ajoutant l’attribut Factory et nous lui assignes le type MyServiceHostFactory :

L’activation du service s’effectue une fois dès la première requête reçue par le service WCF et après chaque recyclage de IIS. Donc du coup il se peut que l’évènement Opened par exemple soit déclenché plusieurs fois durant toute la durée d’exécution de ton serveur IIS.

J’espère que ce billet vous a aidé.

Catégories :WCF Étiquettes : , , ,
%d blogueurs aiment cette page :