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.