Exemple d'application métier avec Silverlight 3 et .NET RIA Services - Partie 16 : Exposer un service

| Brad Abrams | Thomas Levesque (Traduction) |

Cet article fait partie d'une série de traductions d'articles de Brad Abrams sur le développement d'applications métier avec Silverlight et .NET RIA Services.

Retrouvez l'ensemble des articles de la série sur cette page : Exemple d'application métier avec Silverlight 3 et .NET RIA Services.

Commentez cet article : Commentez ♪

- Titre : Exemple d'application métier avec Silverlight 3 et .NET RIA Services - Partie 16 : Exposer un service

- Auteurs : Brad Abrams, Thomas Levesque (Traduction)

- Parution : 15 janvier 2011

- Licence : Copyright ® 2011 Brad Abrams. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.

Sommaire

- Traduction

- Article

- Conclusion

- Remerciements

Traduction

Cet article est la traduction la plus fidèle possible de l'article original de Brad Abrams, Business Apps Example for Silverlight 3 RTM and .NET RIA Services July Update: Part 16: Exposing a WCF Service.

Article

Je m'éclate sur cette série où je mets à jour ma simple démo d'application métier du Mix 09. Dans cette partie, je voulais traiter un scénario qui est, je l'espère, assez fréquent. Le développeur écrit son application Silverlight en utilisant le modèle « RIA Services » et l'application rencontre un grand succès. Un si grand succès qu'il y a une forte demande pour exposer la logique de l'application via un service pour faciliter l'écriture de plein d'autres clients. C'est le genre de scénario qu'on voit apparaitre avec des applications comme Twitter et Sharepoint.

Cette démo nécessite les éléments suivants (tout est 100 % gratuit) :

- Visual Studio 2008 SP1 (qui inclut SQL Server Express 2008) ;

- Silverlight 3 RTM ;

- .NET RIA Services July '09 Preview (facultatif pour cette partie de la démo).

Téléchargez aussi les fichiers de la démo complète, et jetez un œil à l'application en cours d'exécution.

Pour commencer, reprenons l'application des parties précédentes de la série et ajoutons-y un point d'accès WCF. Pour cet exemple, supposons qu'on veuille simplement fournir la possibilité d'obtenir et de définir les « sites » pour nos superhéros. Cela permettra à un paquet de gens de vous aider à trouver les superhéros.

Dans les posts précédents, nous avions défini un DomainService :

[EnableClientAccess]
public class SuperEmployeeDomainService :
LinqToEntitiesDomainService<NORTHWNDEntities>
{
public virtual IQueryable<SuperEmployee> GetSuperEmployees()
{
return this.Context.SuperEmployeeSet
.Where(emp=>emp.Issues>100)
.OrderBy(emp=>emp.EmployeeID);
}

public virtual SuperEmployee GetSuperEmployee(int employeeID)
{
return this.Context.SuperEmployeeSet
.Where(emp => emp.EmployeeID == employeeID)
.FirstOrDefault();
}

public virtual void InsertSuperEmployee(SuperEmployee superEmployee)
{
this.Context.AddToSuperEmployeeSet(superEmployee);
}

public override void Submit(ChangeSet changeSet)
{
base.Submit(changeSet);
}

public virtual void UpdateSuperEmployee(SuperEmployee currentSuperEmployee)
{
var org = this.ChangeSet.GetOriginal(currentSuperEmployee);
this.Context.AttachAsModified(currentSuperEmployee, org);
}

et un client Silverlight.

Et nous avons créé une application Silverlight pour fonctionner avec :

Dans cette partie, commençons par ajouter un simple service WCF à notre projet web :

Nous pouvons ensuite définir notre contrat de service. Remarquez qu'il peut prendre la forme que l'on veut. Il n'a pas besoin d'être conforme en aucune manière à notre DomainService.

[ServiceContract]
public interface ISuperHeroSitesService
{
[OperationContract]
void SetSite(string superHeroName, string site);

[OperationContract]
string GetSite(string superHeroName);

[OperationContract]
IEnumerable<string> GetSuperHeroNames();
}

Ensuite, implémentons le service.

La façon la plus simple de faire ceci est d'utiliser l'infobulle :

[AspNetCompatibilityRequirements(RequirementsMode=AspNetCompatibilityRequirementsMode.Required)]
[ServiceBehavior(IncludeExceptionDetailInFaults=true)]
public class SuperHeroSitesService : ISuperHeroSitesService
{

SuperEmployeeDomainService domainService =   DomainServiceProxy.Create<SuperEmployeeDomainService>();

On commence ensuite à implémenter le service. Remarquez que je mets le service en mode de compatibilité ASP.NET, ce qui nous permet d'accéder aux informations de session d'ASP.NET pour gérer des choses comme l'authentification, etc. Ensuite, j'inclus les informations d'exception pour faciliter le débogage.

Enfin, je crée une instance de notre DomainService que j'utiliserai pour implémenter le service. Comme dans l'exemple ASP.NET MVC, on n'appelle pas explicitement le constructeur de SuperEmployeesDomainService, parce qu'on veut tirer parti du pipeline de validation. Nous appelons donc une méthode de fabrication (Factory Method) pour créer notre instance de SuperEmployeeService. Remarquez qu'avec la CTP actuelle, vous aurez besoin d'ajouter une référence à l'assembly DomainServiceExtensions.dll de cet exemple pour avoir cette fonctionnalité.

On commence ensuite à implémenter nos méthodes. GetSuperHeroNames() est assez simple. On récupère simplement tous les SuperHeros auxquels la classe DomainService nous permet d'accéder, et on renvoie simplement leurs noms.

public IEnumerable<string> GetSuperHeroNames()
{
var q = domainService.GetSuperEmployees();
return q.Select(emp => emp.Name);
}

C'est très similaire pour GetSite. Ici, on cherche l'employé en question et on renvoie son site.

public string GetSite(string superHeroName)
{
var q = domainService.GetSuperEmployees();
var employee = q.Where(emp => emp.Name.ToUpper() == superHeroName.ToUpper()).FirstOrDefault();
return employee.Sites;
}

Pour SetSite, j'ai défini une méthode dans mon DomainService pour gérer cette opération. Mais j'ai trouvé qu'il était plus générique d'avoir une méthode commune de DomainService qui prend l'ID plutôt que le nom.

[ServiceOperation]

public virtual void SetSite(int empId, string site)

{
var employee = GetSuperEmployee(empId);
employee.Sites = site;
this.Context.SaveChanges();
}

Ensuite la méthode dans le service WCF était assez facile à implémenter :

public void SetSite(string superHeroName, string site)
{
var q = domainService.GetSuperEmployees();
var employee = q.Where(emp => emp.Name.ToUpper() == superHeroName.ToUpper())
.FirstOrDefault();
if (employee == null) throw new Exception(String.Format("Employee named '{0}' not found.",superHeroName));
domainService.SetSite(employee.EmployeeID, site);
}

Nous avons maintenant un service fonctionnel.

Créons maintenant une application en ligne de commande qui teste notre petit service. À ce stade, vous pourriez créer n'importe quel client arbitraire, que ce soit en ASP.NET, Windows Forms, ou même Java ou PHP.

Créons une application console :

Nous devons maintenant ajouter une référence au service que l'on vient de créer :

On écrit ensuite le code de notre client.

Console.WriteLine("List of all SuperHero names");
foreach (var name in context.GetSuperHeroNames())
{
Console.WriteLine(name);
}

Récupération du site pour un employé donné :

Console.WriteLine("'{0}' site is currently: '{1}' ", args[0], context.GetSite(args[0]));

Définition du site pour un employé donné :

var site = string.Join(" ", args.Skip(1).ToArray());
Console.WriteLine("siting superhero '{0}' site to '{1}' ", args[0], site);
context.SetSite(args[0], site);

Dans cet exemple, je vous ai montré comme « augmenter » votre application Silverlight basée sur .NET RIA Services pour offrir un service WCF personnalisé avec juste le contrat que vous voulez. Ce service peut être utilisé à partir de n'importe quel client.

Profitez-en !

Conclusion

Ceci conclut la seizième partie de cette série. La partie suivante expliquera comment faire évoluer une application.

Remerciements

Je tiens ici à remercier Brad Abrams de nous avoir autorisés à traduire son article.
Je remercie également ClaudeLELOUP pour sa relecture et ses propositions.