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 5: Astoria, Add Service Reference and WinForms.
Astoria, ajouter une référence de service et WinForms▲
Encore plus de mises à jour sur ma présentation du Mix09 intitulée « building business applications with Silverlight 3 ». Cette fois ce sera du contenu nouveau - ce qui n'aurait pas pu être fait avant cette version.
Cette démo prendra la logique d'application que nous avons créée dans ma présentation Mix09 et placera dessus un point d'entrée de service web basé sur REST avec ADO.NET Data Services.
Ceci pourrait être utile si une application commence en tant que simple application Internet riche (RIA) mais que plus tard vous découvrez que vous voudriez ajouter une couche de services plus explicite afin de permettre à un large éventail de clients d'accéder à votre application. Heureusement tout votre investissement dans la logique de l'application serveur continue à porter ses fruits.
Juste pour démontrer ce point, nous consommerons par la suite le service à partir d'une application WinForms. Cela étend encore plus votre portée et votre marge d'utilisation des RIA Services !
La démo requiert les éléments suivants (tout est 100 % gratuit) :
- Visual Studio 2008 Express SP1 (qui comprend SQL Server 2008 Express) ;
- Silverlight 3 ;
- .NET RIA Services.
Vous pouvez, de plus, télécharger les fichiers de la démo complète et jeter un œil à l'application en cours d'exécution.
Démarrez avec l'application là où nous avions laissé les choses dans la quatrième partie. Dans le projet de serveur, ajoutons un point d'entrée REST au DomainService. Cela permettra à n'importe quel client arbitraire d'accéder au DomainService et nous donne une chance de contrôler sélectivement ce qui sera exposé.
Ensuite nous personnalisons la classe qui a été créée pour nous.
public
class
SuperEmployeeService :
DataService<
SuperEmployeeDomainService>,
IServiceProvider
{
// This method is called only once to initialize service-wide policies.
public
static
void
InitializeService
(
IDataServiceConfiguration config)
{
config.
SetEntitySetAccessRule
(
"*"
,
EntitySetRights.
All);
config.
SetServiceOperationAccessRule
(
"*"
,
ServiceOperationRights.
All);
}
Remarquez qu'ici j'utilise le mode « démo » avec « * » et « All »… C'est ici que vous pouvez contrôler quels aspects du Domain sont destinés à être accessibles via n'importe quel client et qui font vraiment partie de l'application Silverlight. C'est une bonne pratique de les lister explicitement.
Maintenant je vais tout simplement faire un clic droit et visualiser dans le navigateur… Nous obtenons le point d'entrée RESTd'ADO.NET Data Services(Astoria). Mais plutôt que d'attaquer directement ma base de données, j'ai maintenant un moyen formel pour ajouter la logique d'application.
Nous pouvons même parcourir les données via les formats standards d'URL Astoria.
Encore une fois, remarquez ici que tous les appels sont exécutés à travers votre DomainService afin que la logique d'application contrôle l'accès, la forme et le contenu de toutes les données.
http://localhost:52878/SuperEmployeeService.svc/$metadata.
http://localhost:52878/SuperEmployeeService.svc/SuperEmployee(12).
Ok, ça c'est cool… mais faisons quelque chose de plus utile. Que diriez-vous de créer un client WinForms à partir de ce service ? Remarquez que cela fonctionnerait avec WPF, Ajax ou même n'importe quel client Java !
Ajoutez une nouvelle application WinForms, ensuite ajoutez une référence de service.
Oh, et Shawn Wildermuth, ce « Ajouter une référence de service » est pour toi ! Nous en avons parlé durant le Mix et le voici maintenant dans les détails ! Amuse-toi !
Maintenant nous ajoutons un petit formulaire…
Et un peu de code-behind assez simple… Nous mettons en place le proxy à Astoria.
SuperEmployeeDomainService context;
public
Form1
(
)
{
InitializeComponent
(
);
context =
new
SuperEmployeeDomainService
(
new
Uri
(
"http://localhost:52878/SuperEmployeeService.svc/"
));
context.
MergeOption =
MergeOption.
AppendOnly;
}
Maintenant nous pouvons tout simplement charger les données.
private
void
loadButton_Click
(
object
sender,
EventArgs e){
var
savedCursor =
Cursor.
Current;
Cursor.
Current =
Cursors.
WaitCursor;
var
q =
from
emp in
context.
SuperEmployee
where
emp.
Issues >
10
orderby
emp.
Name
select
emp;
dataGridView1.
DataSource =
q.
ToList
(
);
dataGridView1.
CellEndEdit +=
dataGridView1_CellEndEdit;
Cursor.
Current =
savedCursor;
}
Appuyez sur F5 ensuite sur Load et vous obtenez vos données ! Encore une fois, à travers ce même ensemble de logique d'application.
Ajoutons maintenant un peu de code afin de mettre à jour le serveur quand les données sur le client changent.
void
dataGridView1_CellEndEdit
(
object
sender,
DataGridViewCellEventArgs e)
{
var
row =
dataGridView1.
Rows[
e.
RowIndex].
Cells;
int
empId =
Convert.
ToInt32
(
row[
"EmployeeId"
].
Value);
var
q =
from
emp in
context.
SuperEmployee
where
emp.
EmployeeID ==
empId
select
emp;
var
employee =
q.
FirstOrDefault
(
);
employee.
Gender =
row[
"Gender"
].
Value as
string
;
employee.
Issues =
Convert.
ToInt32
(
row[
"Issues"
].
Value);
employee.
LastEdit =
DateTime.
Now;
employee.
Name =
row[
"Name"
].
Value as
string
;
employee.
Origin =
row[
"Origin"
].
Value as
string
;
employee.
Publishers =
row[
"Publishers"
].
Value as
string
;
employee.
Sites =
row[
"Sites"
].
Value as
string
;
var
savedCursor =
Cursor.
Current;
Cursor.
Current =
Cursors.
WaitCursor;
context.
UpdateObject
(
employee);
context.
SaveChanges
(
);
Cursor.
Current =
savedCursor;
}
Ici nous gérons simplement l'évènement quand la cellule a fini d'être éditée… Ensuite nous cherchons l'objet employé qui correspond à cette ligne et nous mettons à jour ces valeurs.
Là encore, ce même schéma pourrait fonctionner pour tout client qui fonctionne avec Astoria aujourd'hui…
NDT Il y a une façon de faire plus simple
void
dataGridView1_CellEndEdit
(
object
sender,
DataGridViewCellEventArgs e)
{
var
employee =
(
Employee)dataGridView1.
Rows[
e.
RowIndex].
DataboundItem;
var
savedCursor =
Cursor.
Current;
Cursor.
Current =
Cursors.
WaitCursor;
context.
UpdateObject
(
employee);
context.
SaveChanges
(
);
Cursor.
Current =
savedCursor;
}
Conclusion▲
Ceci conclut donc la cinquième partie de cette série. Dans la sixième partie, nous aborderons les objets de transfert de données (en anglais, Data Transfer Objects - DTOs).
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.