Cover

RIA Services, Silverlight and MVVM

Url: http://wilderminds.blob.core.windows.net/downloads/MVVMExample_RIA…

I’ve finally had a chance to take a look at the July CTP of RIA Services. My opinion is mixed, but its still pretty early. I ran through the simple walkthrough and it was easy to set up but it still felt as if there is too much Visual Studio magic (a complaint I’ve had for a long time now).

A Brief Overview

For the uninitiated let me explain a couple of things (though, please don’t assume this blog entry is an introduction to RIA Services):

RIA Services is trying to share logic with the Silverlight client. That’s the big story (IMHO). Some of this logic is a surface to query, validation attributes and outright code in other cases. Its trying to solve a difficult problem, but they’ve made a fundamental mistake in my book: RIA Services requires that all pieces are in a single solution file. But why? The magic is code generation.

RIA Services starts with a Domain class which normally uses a model (Entity Framework or others) to expose the data.  As you change the domain class and the entities, RIA Services builds a code generated file in the Silverlight project (or other client files) for you:

The RIA Magic

As the GameDomain file and the GameModel’s entities are changed, the generated code is regenerated to keep up with the changes.

Why This is Troubling

This makes sense in one case because as the domain and entities are changed, the code magically stays updated.  Which is a better experience than updating a Service Reference.  But it requires something called a RIA Link.  This link is between a client-side component (typically a Silverlight application) and a server-side component (typically an ASP.NET Web Site/Project).

The cost of this approach is that the projects must exist in the same solution file. This works for demo’s and small projects, but in the big world of enterprise or Internet development this breaks down. Throw in composition strategies (like Prism solves) and it complicates it quite a lot.  I certainly hope that when it reaches 1.0 they’ll have a solution for this. The current solution for this is to wrap the domain service with an ADO.NET Data Service, but that means there are two layers to go through instead of one and if that’s the approach, just use ADO.NET Data Service instead, right?

Another Concern

While reading the well-written and lengthy overview on RIA Services (that comes with the RIA Services CTP) I noticed that RIA Services comes with a data source object (called DomainDataSource) that can be used directly within XAML to communicate with the domain class:

RIA Services Data Source

If you’ve been reading this blog for any length of time, you’ll know that I think that data source objects are almost always evil in that they suggest that its ok to include data access in the user interface.  And the depth of interaction with the data source is really troubling here.

So What About RIA Services in MVVM?

My first thought was how this impact the best-practices of not co-minging UI and data.  I thought it might not work at all, but as often happens in these cases, the example isn’t the exemplar that I can suggest.  The framework (aside from my concern about the solution file) actually allows this pretty easily.

So I went back and grabbed my MVVM example from my MSDN article (seen here: http://msdn.microsoft.com/en-us/magazine/dd458800.aspx) and refactored it to use RIA Services. The breakdown of that architecture was pretty simple:

MVVM Architecture

Notice I am using a RIA Domain Service on the server to expose the data model (instead of ADO.NET Data Services). This is broken up in the solution as a set of client-side projects and server-side projects:

RIA Services Project Breakdown

Notice that while in the typcial scenario (and walkthrough’s) the RIA Link is betwen the Silverlight application and the web project, RIA Services allows you to have that link between separated parts of the solution. In this case, we have a MVVM.Data library that contains the entity model and the domain service class.  This allows us to re-use this in separate web projects (which is something that is harder to do in ADO.NET Data Services). We also have a MVVM.Client.Data Silverlight library that contains the model for the Silverlight application (and separates the access to the services so the client does not need to change).

The refactoring was fairly painless in that the entity types that were created with the generated code were identical to the data contract classes created by the ADO.NET Data Services - Service Reference class. I had to change the namespaces but the rest was identical.

In the model class I had to change how I was performing the queries, but the major change there was using the extension method syntax for the query instead of the LINQ syntax. The separation of the Model meant that the refactoring was simple (as the whole pattern is supposed to do).

public void GetGamesByGenre(string genre)
{
  // Get all the games ordered by release date
  var qry = Context.GetGamesQuery()
    .Where(g => g.Genre.ToLower() == genre.ToLower())     
    .OrderByDescending(g => g.ReleaseDate)
    .Take(MAX_RESULTS);

  ExecuteGameQuery(qry);
}

I do wish that the RIA Services style wasn’t so RPC (Remote Procedure Call) but that may be because I see the value in client-side LINQ queries instead of “GetGamesQuery()” and such. I think the syntax could be a lot simpler.

Overall, I think that RIA Services can help solve some problems but the bottom line is still too much Visual Studio magic for my taste and the validation is still only covering the very simple cases. Rich validation is always going to be hard (read Rocky Lhotka’s book if you don’t believe me).

If you want to play with it, you can grab the code here:

http://wilderminds.blob.core.windows.net/downloads/MVVMExample_RIA.zip

What do you think?