Archive

Posts Tagged ‘WCF’

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 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 :

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 : , ,

WCF Data Services : Exposer toutes les entités à l’exception de quelques unes

Lorsqu’on travaille avec WCF Data Services et lors de la définition de notre service de données, nous devons configurer notre service de données à travers la méthode statique InitializeService. La configuration concerne l’accès aux ressources et opérations de service, la version d’OData prise en charge etc…

Si nous avons plusieurs ressources dont les accès doivent être configurés à l’exception de quelques unes, ça peut vite devenir lassant de devoir saisir la configuration de chaque ressource et peut aussi entraîner l’oubli de configuration et des erreurs.

Par exemple nous avons 30 ressources dont l’accès pour chaque ressource doit être défini à EntitySetRights.All et qu’il y en a deux ou un petit nombre dont l’accès n’est pas autorisé donc EntitySetRights.None. Pour ne pas avoir à effectuer la configuration pour chaque ressource, la méthode la plus simple dans le cas de notre exemple est de :

  1. mettre l’accès de toutes nos ressources à EntitySetRights.All
  2. configurer chaque ressource dont l’accès ne devrait pas être autorisé donc mettre EntitySetRights.None

Exemple :

public static void InitializeService(DataServiceConfiguration config)
        {
            // étape 1 
            config.SetEntitySetAccessRule("*", EntitySetRights.All);
            // étape 2
            config.SetEntitySetAccessRule("CollectionNonAutoriséeUn", EntitySetRights.None);
            config.SetEntitySetAccessRule("CollectionNonAutoriséeDeux", EntitySetRights.None);
            
            config.DataServiceBehavior.MaxProtocolVersion = DataServiceProtocolVersion.V2;
        }

Nota Béné : Qu’on commence par l’étape 2 et qu’on termine par l’étape 1 on aura le même résultat. 😉
Donc le code ci-dessous donnera le même résultat que le code précédent 😀 :

public static void InitializeService(DataServiceConfiguration config)
        {
            // étape 2
            config.SetEntitySetAccessRule("CollectionNonAutoriséeUn", EntitySetRights.None);
            config.SetEntitySetAccessRule("CollectionNonAutoriséeDeux", EntitySetRights.None);
            
            // étape 1 
            config.SetEntitySetAccessRule("*", EntitySetRights.All);
            config.DataServiceBehavior.MaxProtocolVersion = DataServiceProtocolVersion.V2;
        }
Catégories :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 :