US / UK-EMEA / Contact Ask DevelopMentor a Question800.699.1932

Simple MVVM Toolkit: Ready for RIA Services

Part of Microsoft’s Silverlight strategy is to position it as a platform for building rich line of business applications.  One reason for this is the deployment story: in or out of the browser on Windows, Mac or Linux.  Another is the availability of WCF RIA Services, which eases n-tier application development for Silverlight by providing advanced features such as query composability, change-tracking and transactional batch updates, end-to-end data validation, better handling of async operations, application security with support for both authentication and authorization.  (For more information see my blog post and presentation of RIA Services.)

NOTE: You can obtain the code for this blog post from the SimpleMvvm-RiaServices sample project that’s part of the download for my Simple Mvvm Toolkit.

So how well does RIA Services play with MVVM?  Very nicely, I am happy to say.  In fact, you can easily use my Simple MVVM Toolkit to build a Silverlight app that uses RIA Services.  All you have to do is create a ServiceAgent that uses the generated DomainContext class to load and persist entities from the RIA Services web app.

Developing a Silverlight app that uses RIA Services is fairly straightforward.  You can start either with a plain vanilla Silverlight app by selecting the “Silverlight Application” Visual Studio project template, or you can choose the “Silverlight Business Application” template, which is based on the “Silverlight Navigation Application” template and has a few more bells and whistles (mainly user membership and authentication).  I suggest you start with a basic project template and then move on to the business application template when you want to explore features related to application security.

sl-app-dialog

After clicking OK you’ll be presented with another dialog in which you specify a web project to host your Silverlight app and if you wish to enable WCF RIA Services.  You should probably go ahead and check the box to enable RIA Services, but you can add a RIA Services link later on if you wish.

enable-ria

Now you have to decide where you want to get your data from.  Most of the time that would be from a database using the Entity Framework.  But to keep it simple we’ll just create some in-memory objects and expose them over RIA Services.  The important point to keep in mind here is that RIA Services is not in any way wedded to Entity Framework – you can use another ORM (such as NHibernate) or none at all.

Let’s say we create a Customer class with three properties: CustomerId, CustomerName and City.  Then for convenience we’ll add a factory method to return a List of them.  To play nice with RIA, you will need to add a [Key] attribute to one of the properties in Customer, such as CustomerId.

public class Customer

{

    [Key]

    public int CustomerId { get; set; }

    public string CustomerName { get; set; }

    public string City { get; set; }



    public static List<Customer> GetCustomers()

    {

        return new List<Customer>

        {

            new Customer { CustomerId = 1,

                CustomerName = "Bill Gates", City = "Redmond" },

            new Customer { CustomerId = 2,

                CustomerName = "Steve Jobs", City = "Cupertino" },

            new Customer { CustomerId = 3,

                CustomerName = "Mark Zuckerberg", City = "Palo Alto" }

        };

    }

}

Next create a CustomerDomainService class using the Domain Service Class item template.

domain-service

Then add a GetCustomers method and return an IQueryable<Customer> by calling Customer.GetCustomers and invoking AsQueryable on the result.  IQueryable signifies that you are returning a query that can be further refined with things like filters or sorting.


[EnableClientAccess()]

public class CustomerDomainService : DomainService

{

    // Will surface as a method on the client DomainContext

    public IQueryable<Customer> GetCustomers()

    {

        return Customer.GetCustomers().AsQueryable<Customer>();

    }

}

When you build the project, RIA Services will project a CustomerDomainContext class on the client (it’s hiding inside the Generated_Code folder that’s visible only when you show all files).  There you have a GetCustomersQuery method that calls the GetCustomers service method and returns, you guessed it, an IQueryable<Customer>.

Now that you’ve done the RIA Services bit, it’s time to put in MVVM pieces in place.  For that you follow the instructions I’ve laid out in the Getting Started guide for the toolkit.  (TheSimpleMvvm-RiaServices sample also has a readme file with step-by-step instructions.)  The key difference is that the ServiceAgent implementation will load entities from the query returned by CustomersDomainContext.GetCustomersQuery.

First create an ICustomerServiceAgent interface with a GetCustomers method.  Note that the method signature should reflect the asynchronous nature of services in Silverlight, with a callback parameter that returns either a sequence of customers or an exception.

public interface ICustomerServiceAgent

{

    void GetCustomers(Action<IEnumerable<Customer>,

        Exception> completed);

}

The implementation looks like this.

public void GetCustomers(Action<IEnumerable<Customer>,

    Exception> completed)

{

    // Load GetCustomersQuery

    EntityQuery<Customer> query = _domainContext.GetCustomersQuery();

    _domainContext.Load(query, loadOp =>

        {

            // Declare error and customers

            Exception error = null;

            IEnumerable<Customer> customers = null;



            // Set error or customers

            if (loadOp.HasError)

            {

                error = loadOp.Error;

            }

            else

            {

                customers = loadOp.Entities;

            }



            // Invoke completion callback

            completed(customers, error);

        }, null);

}

The code looks a little bit funny at first, because you have to call Load on an EntityQuery<Customer>, passing a callback method in which you harvest the result, which is an IEnumerable<Customer>.  The ViewModel simply invokes the ServiceAgent’s GetCustomers method, perhaps creating an ObservableCollection<Customer> for binding to a grid.

public void GetCustomers()

{

    serviceAgent.GetCustomers(GetCustomersCompleted);

}



private void GetCustomersCompleted(IEnumerable<Customer> result,

    Exception error)

{

    // Notify view of an error

    if (error != null)

    {

        NotifyError("There was an error retrieving customers", error);

    }

    // Set Customers property

    else

    {

        this.Customers = new ObservableCollection<Customer>(result);

    }

}

If you have a DataGrid with an ItemsSource bound to the ViewModel Customers property, you should see the results displayed like so.

customers-grid

Now you have an Silverlight MVVM application that uses WCF RIA Services! The nice thing is that you can use the Simple MVVM Toolkit as is with RIA Services.  The ServiceAgent already abstracts away the task of retrieving entities, and the ViewModel doesn’t really care how it happens.  From the perspective of the ViewModel, RIA Services is simply an implementation detail.  Nice.


Connect
Signup for our Free Newsletter!
Latest news
Twitter Feed MORE
Got an email from a developer in Holland about my Onion Architecture blog post http://t.co/Z5DTvJob Nice to have a worldwide audience! #dm
1 day ago (details)
There is something to this statement: Why Quit? Because They Have Bigger Monitors http://t.co/9FrGETG5 #dm (via @mkennedy)
1 day ago (details)
Testimonials
  • Very good! Brock Allen is very knowledgable and used his experience to great effect. Callaghan R.