Archive

Archive for mars 2011

Configurer votre contexte EF avec WCF Data Services

Quand on définit notre service de données WCF Data Services, nous devons dériver de la classe générique DataService<T> où T doit représenter le type de notre contexte Entity Framework. Une fois cet héritage effectué nous nous attaquons à la configuration notre service de données, à la mise en place des opérations de services et des intercepteurs.

À aucun moment on se soucis de l’instanciation du contexte de données EF encore moins de sa configuration parce que l’instanciation est faite automatiquement par WCF Data Services. Comment faire pour configurer certaines propriétés de notre contexte telles que la proprieté LazyLoadingEnbled et la propriété ProxyCreationEnabled ? On peut se dire que puisqu’on a accès à la propriété CurrentDataSource de notre source de données autant configurer ces propriétés dans la méthode d’initialisation du service InitializeService sauf que cette dernière est statique et la propriété CurrentDataSource est un membre d’instance ;).

Pour pouvoir configurer certains paramètres de notre contexte EF, il faut redéfinir la méthode CreateDataSource (elle est appelée lors de la création de notre contexte EF) de notre source de données comme suit :

protected override AdventureWorksLTEntities CreateDataSource()
{
	AdventureWorksLTEntities context = base.CreateDataSource();

	// Ici nous configurons les différentes propriétés de notre contexte

	return context;
}
Catégories :WCF Data Services Étiquettes :

Effectuer une demande PUT avec la bibliothèque cliente WCF Data Services

Avec le protocole Open Data, nous pouvons mettre à jour une entité en effectuant soit une demande PUT (dans ce cas l’entité de notre source de données est remplacée et les propriétés qui ne seraient pas fournies lors de l’envoi de la charge données auront des valeurs par défaut) ou soit une demande MERGE (dans ce cas seules les propriétés renseignées dans la charge de données sont mises à jour).
Par défaut la bibliothèque cliente WCF Data Services utilise la demande MERGE pour effectuer la mise à jour d’une entité (ce qui est normal ;)). Mais il se peut qu’on ait besoin de faire une demande PUT, alors dans ce cas la bibliothèque cliente nous permet d’effectuer cela en utilisant une surcharge de la méthode SaveChanges de notre contexte de données. Cette surcharge reçoit en paramètre un enum de type SaveChangesOptions et sa valeur doit être positionnée à ReplaceOnUpdate

// Ici notre contexte de données est représentée par la variable context
context.SaveChanges(SaveChangesOptions.ReplaceOnUpdate);
Catégories :WCF Data Services É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 : , ,
%d blogueurs aiment cette page :