To be honest I was somewhat underwhelmed by the content of Techdays’09. A number of speakers talked –again– about RAD, databinding, Entity Framework, etc… Nothing really new here, getting data from a datasource all the way up to any kind of rich client is a pain. All the plumbing, like CRUD operations and validation, is usually completely left up to the developer.
So I was not very hopeful that there would be anything exciting or new in this space at MIX09, which started in Las Vegas just days after Techdays. In fact there was: Microsoft Rich Internet Application Services or RIA Services for short.
To explain what RIA Services is, perhaps it’s best to start with what it is not: RIA Services is not another data access technology. It is also not a mapping or communication framework. Which would make it… something new! In fact it can use most existing data access technologies or webservices even POCO’s as backend datasource and uses standard communication technologies between tiers. RIA Services is in fact a combination of number of different things. The basic parts are:
-
a new serverside concept called DomainService which is basically a wrapper for any LINQ-enabled datasource, exposing the underlying entities to the client
-
four basic operations defined for each entity on the DomainService to support CRUD operations
-
support for user-defined operations on the backend datasource
-
a set of new metadata attributes that can be added to operations and entities and individual fields to annotate for access control and validation
-
clientside it features a new rich bindingsource, called the DomainContext, which automatically implements all validation defined serverside, but validates clientside (more about this feature later), and takes care of all the state and invocations of server operations
So in short RIA Services is not just another serverside framework, it actually attempts for the first time, at least for Microsoft frameworks (Euricom server frameworks have done this for years using Business Entities), to span the divide between the client and server.
But how does it work? Well, the two most powerful parts of RIA Services are the DomainService and DomainContext. You could just look upon them as a single concept which spans both the client and server tiers, but the DomainContext will cache the data and changes on the client allowing the DomainService to remain stateless.
The DomainContext is actually generated automatically out of the serverside DomainService, thus carrying the validation metadata, specified by attributed on entity fields on the server tier, over onto the client tier. This metadata could be simple like ‘cannot be null’ or ‘must be between n and m’, but can also be a call to a user-defined validation function. These user-defined functions are, like the metadata, also only defined once on the server tier.
So, I hear you thinking, there will be server calls to validate using user-defined functions – that will be slow and so I will have to write my own code on the client to avoid these. Well, in fact, the serverside custom validation functions are also copied over to the client tier during the generation of the DomainContext and will be executed on the client tier. This means that any field validations that you write yourself will be also be run both clientside during data entry and serverside during saving to the backend datasource.
Security is provided at operation level using another set of attributes (EnableClientAccess, RequiresAuthentication and RequiresRoles) which you can set on operations. These work rather like code access security, defining which role or roles you need to call each operation.
But that’s not all: one of the neatest things, I think, about the DomainService/DomainContext design is the fact that entities are exposed on the client tier as IQueryable. That means that I don’t need to specify custom operations on the server to get entities using arbitrary criteria to the client. I can just issue a LINQ query on the client which will get serialized over the wire to the server, to the server’s datasource, and will only be executed there to return me the results.
If you hear your head of security cringe at the thought of client side code being executed unchecked on the backend database, you can put him at ease. The LINQ query is perfectly safe from SQL-injection attacks and you can in fact intercept the query before it goes to the datasource to inspect the expression tree or to add your own restrictions on the query. This feature has another very important benefit: it allows the DomainDatasource to do paging of requests all by itself on behalf of controls like treeviews and grids, thus reducing the amount of data sent to the client on initial loads.
There is much more to tell about RIA Services, but I’ll leave you to explore these feature in depth by yourself. Some of other the highlights:
-
You can for example intercept the create, update and delete entity operations serverside to do your own validation and if need be stop an entire set of changes from being committed. The error will travel to the client and all state will remain so another attempt to submit can be done, or you can change the data that returns to the client if, for example an update has occurred meanwhile on the database
-
You can specify your own additional Get methods for specific loading of data using LINQ on your DAL and returning an IQueryable. If a client now uses the corresponding new Load method the LINQ expression trees from client and server will be combined and executed as a single query on your backend database
-
You can access DomainServices using a host of other technologies besides ASP.Net and Silverlight. You can even use plain old JavaScript or Ajax to call them. You will lose out on a lot of benefits, but the serverside validation and access control are still nice and you will not need to worry about maintaining several different services for different clients.
-
Live databinding in Silverlight 3 which means that any change to an entity in one control is automatically and immediately reflected in all other controls bound to the same entity
-
Cross-DomainServices/DomainContext relationships allowing you to setup relationships between entities serviced by different DomainServices either by specifying the relationship on the server tier or alternatively on the client tier, but still have the convenience of one single DomainContext to manage state and operations
-
The Silverlight 3 DomainDatasource gives you control over data shaping , filtering, sorting and grouping
-
The ASP.Net DomainDataSource control which enables access and binding to RIA DomainServices for any control on ASP.Net WebForms. One limitation is that, of course, the validations cannot be converted into Javascript, so they get executed on the webserver. Maybe for standard validations you could fix this yourself by automatically emitting validation controls along with the databound controls based on the metadata of the bindingsource. As for user-defined validations written in C#, you will have to manually write you own Javascript equivalent.
In short I am sure we will be hearing a lot more about Microsoft .Net RIA Services in the near future, in fact the entire preview package runs on VisualStudio 2008 SP 1 and is not reliant on any new features of C# 4.0. I have not seen any definite release date yet, but it seems likely it will be shipping together with Silverlight 3.
Additional resources:
Microsoft .NET RIA Services March '09 Preview:
.Net RIA Services Samples:
MIX09 Conference Video’s:
By Nick Verschueren, .Net Solutions Architect