Resumé

RIAServices.jQuery e la Gestione Dati via Javascript

Cristian Merighi () 0,00

RIA/JS per applicazioni business che sfruttano il pattern MVVM utilizzando solo markup e codice javascript.
Questo articolo è da considerarsi obsoleto. Alcune funzionalità potrebbero non essere più disponibili e non è possibile aggiungere commenti.

RIAServices.jQuery (aka RIA/JS) è un progetto firmato Microsoft che - nel marasma attuale dei framework MVVM client - promette di essere una soluzione affidabile nel prossimo futuro e quindi degna di tempo speso per impararne l'utilizzo (ecco me la sono gufata...).
Il sito di riferimento è al solito codeplex, dove il progetto è definito "In progress" e dove effettivamente continuano ad essere pubblicate rincuoranti updates (ultimo quello di agosto 2011).

Come utilizzare le librerie che tutte assieme compongono RIA/JS?
A dire il vero esiste già un progetto (BigShelf project) che prevede d'illustrarne le modalità d'impiego, ma:

  1. Sono dolori di panza a cercare di farlo girare. Io non ci sono riuscito;
  2. È necessario installare librerie di terze-parti che nulla hanno a che fare con RIA/JS in sé (pessima clausola questa).

Vediamo allora di istruire passo-passo sulla configurazione di una WebApplication (se il site è lo stesso che contiene i RIAServices è necessario utilizzare questo tipo di progetto web, e non il WebSite, in Visual Studio 2010) per l'utilizzo di RIA/JS.

Attraverso il potentissimo distributore di packages NuGet (per i pochi che ancora non l'avessero installato → nuget.org/) vediamo di andare ad incorporare le librerie (client e server) necessarie:

NuGet screenshot

Il pacchetto è cercabile online con la query di ricerca «RIAServices.jQuery».
Successivamente all'installazione del pacchetto, vedrete nuovi elementi inseriti nel progetto:

Solution Explorer

Il pacchetto include (come evidenziato nella prima immagine) la libreria jQuery 1.5.2 (al momento in cui scrivo quest'articolo la versione ultima è la 1.6.2 e funziona anch'essa perfettamente). Oltre ad essa, e sempre strettamente correlate al mondo jQuery che definirei "usuale" in termini di UI, i plugin jQuery.Templates ($.tmpl) e jQuery.Validation ($.validation) quest'ultimo strettamente correlato ai metadati gestiti dal framework (cfr. Ln 162 @ RemoteDataSource.js).
Una libreria non inclusa automaticamente ma di cui caldeggio l'utilizzo è quella jQuery.DataLink (api.jquery.com/link), ne vedremo l'utilizzo all'interno del codice d'esempio che seguirà. Una mia speranza è altresì vederla fusa assieme a jquery.observable in una unica.

Si noti l'inclusione - evidenziata sopra - della libreria server Microsoft.ServiceModel.DomainServices.Hosting.dll.
Assieme ad essa è stato modificato il contenuto del file di configurazione Web.Config (vedi codice sotto).

Ecco di seguito un blocco di codice incluso nel Web.config con l'installazione del pacchetto. Abilita un EndPoint Json per il RIAService per il quale è prevista la trasmissione dei metadati relativi alle entities:

Web.config:
  1. <system.serviceModel>
  2.     <domainServices>
  3.       <endpoints>
  4.         <add name="soap" type="Microsoft.ServiceModel.DomainServices.Hosting.SoapXmlEndpointFactory, Microsoft.ServiceModel.DomainServices.Hosting, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
  5.         <add name="JSON" type="Microsoft.ServiceModel.DomainServices.Hosting.JsonEndpointFactory, Microsoft.ServiceModel.DomainServices.Hosting, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" transmitMetadata="true" />
  6.       </endpoints>
  7.     </domainServices>
  8.     <serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" />
  9.   </system.serviceModel>

Ora poniamo di aver già configurato il nostro model utilizzando - ad esempio - Entity Framework (salto questo aspetto che considero noto a chi legge) e di avere al suo interno una semplicissima classe Family costituita da due membri: un ID (Guid) e un Name (String). La arricchisco dei metadati cui abbiamo accennato sopra:

Family partial class:
  1. [MetadataType(typeof(FamilyMetadata))]
  2. public partial class Family
  3. {
  4.     public Family()
  5.     {
  6.         this._ID = Guid.NewGuid();
  7.     }
  8. }
  9.  
  10. [DisplayColumn("Name")]
  11. sealed class FamilyMetadata
  12. {
  13.     [Key]
  14.     public Guid ID { get; set; }
  15.  
  16.     [Required, StringLength(63)]
  17.     public string Name { get; set; }
  18. }

Focalizzando l'attenzione sulla property Name vediamo come essa venga flaggata Required e con massima lunghezza ammissibile a 63 caratteri.

Ora passiamo alla creazione del nostro RIAService: aggiungi nuovo elemento...

VS 2010

VS 2010

L'url del nostro servizio avrà la seguente forma pubblica: http://mysite/Namespace-SubNamespace-ClassName.svc (i punti presenti tra i vari namespaces vanno sostituiti con trattini).
All'interno del codice generato vedrete metodi creati per il recupero e la scrittura dei dati che ommettiamo di riportare qui.

Saltiamo ora diretti al nocciolo del problema: l'utilizzo delle librerie javascript!
Ora che tutto è debitamente configurato non ci resta che scrivere la pagina per il consumo dei dati. Eccone l'intero contenuto:

Html:
  1. <script src="Scripts/jquery-1.6.2.min.js" type="text/javascript"></script>
  2. <script src="Scripts/jquery.tmpl.min.js" type="text/javascript"></script>
  3. <script src="Scripts/jquery.datalink.js" type="text/javascript"></script>
  4. <script src="Scripts/jquery.validate.min.js" type="text/javascript"></script>
  5. <script src="Scripts/jquery.observable.js" type="text/javascript"></script>
  6. <script src="Scripts/jquery.datasource.js" type="text/javascript"></script>
  7. <script src="Scripts/DomainServiceProxy.js" type="text/javascript"></script>
  8. <script src="Scripts/EntitySet.js" type="text/javascript"></script>
  9. <script src="Scripts/DataContext.js" type="text/javascript"></script>
  10. <script src="Scripts/DataSource.js" type="text/javascript"></script>
  11. <script src="Scripts/LocalDataSource.js" type="text/javascript"></script>
  12. <script src="Scripts/RemoteDataSource.js" type="text/javascript"></script>
  13. <script src="Scripts/AssociatedEntitiesDataSource.js" type="text/javascript"></script>
  14.  
  15. <script type="text/javascript">
  16.     $(function () {
  17.         var svcUri = 'http://gauss/pacem_housesystem/Services/Pacem-HouseSystem-Services-HouseSystemRIAService.svc';
  18.         var render = function (families) {
  19.             var family = families[0];
  20.             $("form input[name='Name']").val(family.Name);
  21.             // track changes at UI level
  22.             $("form").link(family)
  23.             // get validation policies and revert 'em into the layout
  24.             .validate({ rules: ds.getEntityValidationRules().rules });
  25.             //
  26.             $(family).bind("changeField", function (args, field, value) {
  27.                 if (field === "Name") {
  28.                     $("#familyName").html(value);
  29.                 }
  30.                 // IMPORTANT: track changes at datasource level!
  31.                 $.observable(family).setProperty(field, value);
  32.             });
  33.             //
  34.             $.each(family, function (fieldName, value) {
  35.                 $(family).setField(fieldName, value);
  36.             });
  37.             // handlers on both submit and cancel buttons
  38.             $('#submit').click(function (evt) {
  39.                 evt.stopPropagation();
  40.                 evt.preventDefault();
  41.                 if ($('form').valid()) {
  42.                     ds.commitChanges();
  43.                 }
  44.                 else
  45.                     alert('not valid!');
  46.             });
  47.             $('#cancel').click(function (evt) {
  48.                 evt.stopPropagation();
  49.                 evt.preventDefault();
  50.                 ds.dataContext().revertChanges(family, 'Name');
  51.                 // update layout via datalink (tedious)
  52.                 $(family).setField('Name', family.Name);
  53.             });
  54.             // just a test method
  55.             ds.option("entityStateChange", function () {
  56.                 //alert('entity state changed');
  57.                 $('#changeTracker  b').html("yes");
  58.             });
  59.         };
  60.         var ds = $.dataSource({ serviceUrl: svcUri,
  61.             queryName: "GetFamilySet",// ← default retrieving method generated by the RIAService designer
  62.             bufferChanges: true,// buffer all occurred changes, then commit
  63.             refresh: render
  64.         }).refresh();
  65.     });
  66.  
  67. </script>
  68.         
  69. <input type="text" name="Name" />
  70.  
  71. <div id="familyName">...</div>
  72.  
  73. <div id="changeTracker">has changes: <b></b></div>
  74.  
  75. <input id="submit" type="submit" value="submit" />
  76. <input id="cancel" type="reset" value="cancel" />

Porzione di screenshot:

UI screenshot
UI screenshot

Fiddler:

Fiddler

Spero possa essere stato d'aiuto.

Take care. Bye.

Feedbacks

  • Re: RIAServices.jQuery for pure HTML Rich Internet Apps

    Darryl Stratford martedì 24 gennaio 2012 0,00

    I'm impressed with RIA/JS. A big problem for me, however, is that it does not support multi-part keys. Great if all your tables have single keys. I see a lot of "TODO" comments in the code and I hope these will be addressed soon.

feedback
 

Syndicate

Autore

Cristian Merighi facebook twitter google+ youtube

Ultimi articoli

Top rated

Archivio

Dove sono?

Autore

Cristian Merighi facebook twitter google+ youtube

Le mie letture

Feeds