RIAServices.jQuery for pure HTML Rich Internet Apps
Cristian Merighi ()

Using RIA/JS for pure HTML+Javascript MVVM business applications.
This article is obsolete. Some functionalities might not work anymore. Comments are disabled.
RIAServices.jQuery (aka RIA/JS) is a Microsoft signed project that promises, in a near future, to be an affordable solution on the client MVVM frameworks' scene.
I gave it credit - please dear MS don't make me repent - and decided to spend some of my "ultra-precious" time upon.
Reference site is as usual codeplex, where the project is so far defined as "In progress"
and in fact upgrades seem to come out with an encouraging steady path (last in August 2011).
How the libraries that compose RIA/JS have to be used then?
Spitting out the whole truth, a project designed to "inspire" the developers already exists: it's the BigShelf project, but...
- Trying to make it run it's a serious pain in the back (I didn't succeed);
- Third party installations are necessary, but they are not relevant to RIA/JS itself (that's unfair and bad).
Ok, with that said, let's try to build up a step-by-step tutorial about the configuration of a WebApplication
(RIAServices can be hosted only in this kind of web project in Visual Studio 2010) meant to use RIA/JS.
Through the super-useful package installer NuGet (for the few of those who don't know nor use it yet
→ nuget.org/) let us include the necessary client and server libraries:
You can search for the online package querying «RIAServices.jQuery»,
Once you've installed the package,
new items will appear in your Solution Explorer panel:
 |
Package includes (as highlighted in the first image) jQuery 1.5.2 (last version at the moment I'm writing is 1.6.2 and works perfectly as well).
Strictly related to the jQuery world also come jQuery.Templates ($.tmpl) and jQuery.Validation ($.validation),
the latter is exploited when metadata get parsed (see Ln 162 @ RemoteDataSource.js).
A useful plugin not included via NuGet install is the jQuery.DataLink (api.jquery.com/link),
get it. Hope to see soon a merge with the jquery.observable API.
Please notice the reference added to the Microsoft.ServiceModel.DomainServices.Hosting.dll assembly, along with
the modifications to the Web.config file (see code-snippet below).
|
What gets modified in the Web.config: A Json EndPoint gets enabled for the RIAService:
Web.config:
- <system.serviceModel>
- <domainServices>
- <endpoints>
- <add name="soap" type="Microsoft.ServiceModel.DomainServices.Hosting.SoapXmlEndpointFactory, Microsoft.ServiceModel.DomainServices.Hosting, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
- <add name="JSON" type="Microsoft.ServiceModel.DomainServices.Hosting.JsonEndpointFactory, Microsoft.ServiceModel.DomainServices.Hosting, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" transmitMetadata="true" />
- </endpoints>
- </domainServices>
- <serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" />
- </system.serviceModel>
Suppose we're now done with the configuration of our model using - let's say - Entity Framework and that there is a very simple class in our model
called Family that consists of jus two members: ID (Guid) and Name (String). Enrich it with the forenamed metadata:
Family partial class:
- [MetadataType(typeof(FamilyMetadata))]
- public partial class Family
- {
- public Family()
- {
- this._ID = Guid.NewGuid();
- }
- }
-
- [DisplayColumn("Name")]
- sealed class FamilyMetadata
- {
- [Key]
- public Guid ID { get; set; }
-
- [Required, StringLength(63)]
- public string Name { get; set; }
- }
Please notice how the Name property is marked to be required and of a maximum length of 63 chars.
Done with it. Let's add the RIAService...
Public url of a RIAService has the following form: http://mysite/Namespace-SubNamespace-ClassName.svc (the dots in any namespace toward the classname are changed into a hyphen).
The code generator adds methods for data writing and retrieving that we now omit.
Straight to the point: javascript code!
Now it's all set, here is the html markup for our sample:
Html:
- <script src="Scripts/jquery-1.6.2.min.js" type="text/javascript"></script>
- <script src="Scripts/jquery.tmpl.min.js" type="text/javascript"></script>
- <script src="Scripts/jquery.datalink.js" type="text/javascript"></script>
- <script src="Scripts/jquery.validate.min.js" type="text/javascript"></script>
- <script src="Scripts/jquery.observable.js" type="text/javascript"></script>
- <script src="Scripts/jquery.datasource.js" type="text/javascript"></script>
- <script src="Scripts/DomainServiceProxy.js" type="text/javascript"></script>
- <script src="Scripts/EntitySet.js" type="text/javascript"></script>
- <script src="Scripts/DataContext.js" type="text/javascript"></script>
- <script src="Scripts/DataSource.js" type="text/javascript"></script>
- <script src="Scripts/LocalDataSource.js" type="text/javascript"></script>
- <script src="Scripts/RemoteDataSource.js" type="text/javascript"></script>
- <script src="Scripts/AssociatedEntitiesDataSource.js" type="text/javascript"></script>
-
- <script type="text/javascript">
- $(function () {
- var svcUri = 'http://gauss/pacem_housesystem/Services/Pacem-HouseSystem-Services-HouseSystemRIAService.svc';
- var render = function (families) {
- var family = families[0];
- $("form input[name='Name']").val(family.Name);
- // track changes at UI level
- $("form").link(family)
- // get validation policies and revert 'em into the layout
- .validate({ rules: ds.getEntityValidationRules().rules });
- //
- $(family).bind("changeField", function (args, field, value) {
- if (field === "Name") {
- $("#familyName").html(value);
- }
- // IMPORTANT: track changes at datasource level!
- $.observable(family).setProperty(field, value);
- });
- //
- $.each(family, function (fieldName, value) {
- $(family).setField(fieldName, value);
- });
- // handlers on both submit and cancel buttons
- $('#submit').click(function (evt) {
- evt.stopPropagation();
- evt.preventDefault();
- if ($('form').valid()) {
- ds.commitChanges();
- }
- else
- alert('not valid!');
- });
- $('#cancel').click(function (evt) {
- evt.stopPropagation();
- evt.preventDefault();
- ds.dataContext().revertChanges(family, 'Name');
- // update layout via datalink (tedious)
- $(family).setField('Name', family.Name);
- });
- // just a test method
- ds.option("entityStateChange", function () {
- //alert('entity state changed');
- $('#changeTracker b').html("yes");
- });
- };
- var ds = $.dataSource({ serviceUrl: svcUri,
- queryName: "GetFamilySet",// ← default retrieving method generated by the RIAService designer
- bufferChanges: true,// buffer all occurred changes, then commit
- refresh: render
- }).refresh();
- });
-
- </script>
-
- <input type="text" name="Name" />
-
- <div id="familyName">...</div>
-
- <div id="changeTracker">has changes: <b></b></div>
-
- <input id="submit" type="submit" value="submit" />
- <input id="cancel" type="reset" value="cancel" />
Screenshot:
Fiddler inspector:
Hope it helped.
Take care. Bye.