Silverlight, RIA Services, and Your Business Objects

Posted Thu, Nov 5 2009 13:12 by Deborah Kurata

With RIA Services, it is easy to use your own business objects in your Silverlight application… once you have the basic plumbing in place. However, there are quite a few steps required to set up that plumbing. This post details the process of hooking up your business objects, RIA Services, and Silverlight.

So … you follow best practices and build business objects for all of the entities involved in your application. Or maybe you generate those business objects with something like Entity Framework (EF), Linq to SQL or other similar tool. In any case, you now want to use those business objects from a Silverlight application.

Seems like it should be easy, right? Just define a reference from your Silverlight application to your business object component and proceed just like with your WinForms or ASP.NET application. But no.

Silverlight does not allow you to set a reference to a non-Silverlight component. There are a number of ways you can deal with this:

  1. Use a Silverlight class library project type and build your business objects in there. Not a good solution if you are using those same business objects with other user interfaces.
  2. Build a WCF service that provides your business objects to your Silverlight application. You can find out more about this option here.
  3. Use Rich Internet Application (RIA) Services. This is a new Microsoft technology that is currently out in preview.

This post demonstrates option #3: Using RIA Services. The example presented in this post uses business objects you build yourself. These "home made" business objects are often referred to as POCO, or plain old CLR objects. Use the techniques presented in this post any time you start a new Silverlight application and want to access your POCOs from that application.

[To use RIA with Entity Framework, there is video walkthrough here.]

The basic idea behind RIA Services is to use an ASP.NET application between your business object component and your Silverlight application to provide the communication between the two as shown below.

image

Starting right to left, you build your business objects in a Class Library component. This example uses a Customer class to define a customer and a Customers class to provide the list of customers.

The ASP.NET application has a standard project reference to the POCO class library. The ASP.NET application includes a Domain Service class, called CustomerService in this example, that calls the desired methods in the POCO class library.

The Silverlight application has an RIA Services link to the ASP.NET Web application. When the Silverlight application is compiled, it generates a client-side copy of the entity referenced by the ASP.NET application. In this case, it generates a Customer class. It also generates a entity context (CustomerContext in this case) that can be used for Silverlight data binding.

The remainder of this post walks through this process one step at a time.

Prerequisites

Before you can begin, there are some prerequisite steps:

  1. If you don't have it, download and install Silverlight 3 using the information provided here.
  2. Download and install RIA Services using the information provided here. (You may have already done this if you followed all of the instructions in step #1)
  3. Create a new Visual Studio Solution.
  4. Create a new Class Library project in that solution and build your business objects. This example uses the Customer and Customers classes defined below.

In C#:

public class Customer
{
    public int CustomerId { get; set; }
    public string LastName { get; set; }
    public string FirstName { get; set; }
    public string EmailAddress { get; set; }
}


public class Customers
{
   public static List<Customer> Retrieve()
   {
      List<Customer> custList = new List<Customer>
                    {new Customer()
                          { CustomerId = 1,
                            FirstName="Bilbo",
                            LastName = "Baggins",
                            EmailAddress = "bb@hob.me"},
                    new Customer()
                          { CustomerId = 2,
                            FirstName="Frodo",
                            LastName = "Baggins",
                            EmailAddress = "fb@hob.me"},
                    new Customer()
                          { CustomerId = 3,
                            FirstName="Samwise",
                            LastName = "Gamgee",
                            EmailAddress = "sg@hob.me"},
                    new Customer()
                          { CustomerId = 4,
                            FirstName="Rosie",
                            LastName = "Cotton",
                            EmailAddress = "
rc@hob.me"}};
      return custList;
   }
}

In VB:

Public Class Customer

    Private _CustomerId As Integer
    Public Property CustomerId() As Integer
        Get
            Return _CustomerId
        End Get
        Set(ByVal value As Integer)
            _CustomerId = value
        End Set
    End Property

    Private _FirstName As String
    Public Property FirstName() As String
        Get
            Return _FirstName
        End Get
        Set(ByVal value As String)
            _FirstName = value
        End Set
    End Property

    Private _LastName As String   
    Public Property LastName() As String
        Get
            Return _LastName
        End Get
        Set(ByVal value As String)
            _LastName = value
        End Set
    End Property

    Private _EmailAddress As String
    Public Property EmailAddress () As String
        Get
            Return _EmailAddress
        End Get
        Set(ByVal value As String)
            _EmailAddress = value
        End Set
    End Property
End Class

Public Class Customers

    Public Shared Function Retrieve() As List(Of Customer)
        Dim custList As New List(Of Customer)
        custList.Add(New Customer With {.CustomerId = 1, _
                                        .LastName = "Baggins", _
                                        .FirstName = "Bilbo", _
                                        .EmailAddress = "bb@hob.me"})
        custList.Add(New Customer With {.CustomerId = 2, _
                                        .LastName = "Baggins", _
                                        .FirstName = "Frodo", _
                                        .EmailAddress = "fb@hob.me"})
        custList.Add(New Customer With {.CustomerId = 3, _
                                        .LastName = "Gamgee", _
                                        .FirstName = "Samwise", _
                                        .EmailAddress = "sg@hob.me"})
        custList.Add(New Customer With {.CustomerId = 4, _
                                        .LastName = "Cotton", _
                                        .FirstName = "Rosie", _
                                        .EmailAddress = "rc@hob.me"})
        Return custList
    End Function

End Class

The C# code here uses auto-implemented properties to shorten the property syntax. The VB code uses the full property syntax.

In a real application, the Retrieve method would collect the data from the database. This example uses hard-coded values to make it easier for you to try this code without having to set up data access.

Decorating your Business Objects

Once you have the prerequisites complete, you need to add some attributes to your business objects so they are recognized by RIA Services when it generates the Silverlight entity.

1. Open the solution containing your business objects.

2. Open the Class Library project properties window for the project containing your business objects.

3. Add a reference to System.ComponentModel.DataAnnotations.

image

I had two of these. Be sure to pick the one from the Microsoft SDKs\RIA Services directory.

This namespace contains the attributes you need to annotate your business objects for RIA Services.

4. Add the Key attribute on the property that represents the unique key of the business object.

In C#:

[System.ComponentModel.DataAnnotations.Key()]
public int CustomerId { get; set; }

In VB:

Private _CustomerId As Integer
<System.ComponentModel.DataAnnotations.Key()> _
Public Property CustomerId() As Integer
    Get
        Return _CustomerId
    End Get
    Set(ByVal value As Integer)
        _CustomerId = value
    End Set
End Property

In this example, CustomerId is the unique key, so it is marked with the Key attribute.

5. Optionally, add RIA attributes for validation as desired. (More on this in a future post.)

Adding the Silverlight Project

Now that the business objects are ready, you can add the Silverlight project to your solution. This will automatically generate the associated ASP.NET project as well.

1. Add a new Silverlight Application to your solution.

image

You can create your Silverlight project in VB or in C#.

2. Be sure to enable RIA Services.

image

3. Click OK.

Visual Studio creates both the Silverlight project and the associated ASP.NET project. At runtime, the ASP.NET project launches the Silverlight project. The ASP.NET project also provides access to your business objects through RIA services.

NOTE: If you already have a Silverlight project that you wish to use with RIA Services, you can enable .NET RIA Services in the Silverlight project properties window:

image

Adding the Domain Service Classes

The ASP.NET application provides the communication between your business objects and the Silverlight application. This is accomplished with RIA Services by creating a set of Domain Service classes in the ASP.NET application.

1. Add a Domain Service class to the ASP.NET application.

image

2. Be sure to enable client access.

image

Notice that the bottom of this dialog is empty. If you used Entity Framework to generate your entities, they would appear in this dialog. But since this example uses POCOs, there won't be any entities displayed.

3. Click OK.

Visual Studio creates the basic structure of your Domain Service class as shown below.

In C#:

namespace SLCSharp.Web
{
    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.ComponentModel.DataAnnotations;
    using System.Linq;
    using System.Web.Ria;
    using System.Web.Ria.Data;
    using System.Web.DomainServices;

    // TODO: Create methods containing your application logic.
    [EnableClientAccess()]
    public class CustomerService : DomainService
    {
    }
}

In VB:

Option Strict Off
Option Explicit On

Imports System
Imports System.Collections.Generic
Imports System.ComponentModel
Imports System.ComponentModel.DataAnnotations
Imports System.Linq
Imports System.Web.DomainServices
Imports System.Web.Ria
Imports System.Web.Ria.Data

'TODO: Create methods containing your application logic.
<EnableClientAccess()>  _
Public Class CustomerService
    Inherits DomainService
End Class

NOTE: IMMEDIATELY change the Option Strict Off to Option Strict ON OR remove the lines entirely if you have them both on by default in your Compile options.

You can also remove any import statements for namespaces you already import through the References tab of the Properties window.

Accessing Your Business Objects From the Domain Service Class

The code to access your business objects goes into the Domain Service class created above. You can think of the Domain Service class as a wrapper around your business object members that provides a way for Silverlight to access the object properties and methods.

Any time you need to access any properties or call any methods on your business objects, you need to write a wrapper for that access in the Domain Service class.

Normally, you create one Domain Service class for each entity. So if your business objects included Customer/Customers, Purchase/Purchases, Invoice/Invoices, for example, you would create a CustomerService, PurchaseService, and InvoiceService class.

1. In your ASP.NET project containing your Domain Service class, set a reference to your business object component.

image

My sample project has two sets of business objects, one in VB and one in C#. You can access business objects in either language.

2. In the Domain Service class, import the namespace for the business object component.

In C#:

using BoCSharp;

In VB:

Imports BoVB

Or if you are using VB, import this namespace using the References tab of the Properties window:

image

3. Add the code that wraps the functionality of your business object.

For the purposes of this post, the code retrieves the set of customers.

In C#:

public IEnumerable<Customer> GetCustomers()
{
    return Customers.Retrieve();
}

In VB:

Public Function GetCustomers() As IEnumerable(Of Customer)
    Return Customers.Retrieve()
End Function

Note that this must be a method and not a property. If you attempt to use a property here, the compiler won't generate the required code.

The GetCustomers method simply calls the static/shared Retrieve method of the Customers class (defined at the beginning of this post).

Accessing the Domain Service Class from Silverlight

Finally! You are ready to use your business object from Silverlight by way of the Domain Service class.

1. Open the Silverlight Application project.

2. This example uses a grid to display the customer data, so set a reference to System.windows.Controls.Data.

3. To use the RIA Service controls, set a reference to System.Windows.Ria.Controls.

3. Open the MainPage.xaml file that was created for you in the Silverlight Application project.

4. Set up the XML namespaces.

<UserControl x:Class="SLCSharp.MainPage"
 xmlns="
http://schemas.microsoft.com/winfx/2006/xaml/presentation"
 xmlns:x=http://schemas.microsoft.com/winfx/2006/xaml
xmlns:d=
http://schemas.microsoft.com/expression/blend/2008
xmlns:mc=http://schemas.openxmlformats.org/markup-compatibility/2006
 xmlns:data="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Data"
 xmlns:riaControls="clr-namespace:System.Windows.Controls;assembly=System.Windows.Ria.Controls"
 xmlns:domain="clr-namespace:SLCSharp.Web"
mc:Ignorable="d" d:DesignWidth="640" d:DesignHeight="480">

NOTE: If you copy and paste these namespaces into your application, be sure that you change the values shown in red. The x:Class is the name of the associated code behind class file. the xmlns:domain is the name of the associated ASP.Net application namespace.

These namespaces are as follows:

  • xmlns - Default for Silverlight and WPF.
  • xmlns:x – XAML-defined language elements for Silverlight and WPF, required for even basic features such as mapping a XAML file to its code behind file using x:Class.
  • xmlns:data – XAML data controls, such as the DataGrid.
  • xmlns:riaControls – RIA Service controls, such as the DomainDataSource
  • xmlns:domain – Defines the associated ASP.NET namespace, required when using RIA services.

5. Add code to display a bound grid.

<Grid x:Name="LayoutRoot">
    <riaControls:DomainDataSource x:Name="CustomerSource"
                        QueryName="GetCustomers" AutoLoad="True">
        <riaControls:DomainDataSource.DomainContext>
            <domain:CustomerContext/>
        </riaControls:DomainDataSource.DomainContext>
    </riaControls:DomainDataSource>

    <data:DataGrid x:Name="CustomerList"
          ItemsSource="{Binding Data, ElementName=CustomerSource}">
    </data:DataGrid>
</Grid>

This code sets up an RIA Services DomainDataSource defining the source of the data for this UserControl. It defines a name (CustomerSource) and a QueryName (GetCustomers). The query name must match the name of the method to call in the Domain Service class.

It also sets a DomainContext, which associates the DomainDataSource with the Domain Service. This must match the name of the DomainContext in the generated code. Intellisense should help you define the correct name.

The DataGrid element uses the ItemsSource attribute to define the binding source. In this case, it is CustomerSource. This name must match the name given to the DomainDataSource.

6. Run it.

If everything works, it should appear as follows:

image

Now you can use your mad skills with styles and other Silverlight features to make this look nice.

Wow! That seemed like a lot of work.

The good news is that once you set this up, adding more features is easy:

  • Add appropriate wrappers to the ASP.Net project using the Domain Service classes.
  • Use the wrappers as needed from your Silverlight application.

Enjoy!

Comments

# Social comments and analytics for this post

Friday, November 06, 2009 10:17 AM by uberVU - social comments

This post was mentioned on Twitter by brada: Great post on RIA Services with VB.. http://bit.ly/1eplar

# re: Silverlight, RIA Services, and Your Business Objects

Friday, November 06, 2009 8:02 PM by Robert Martin

I am CEO of a software development company in Australia and I have to say that this is without doubt the single most informative, thorough and extensive .NET blog on the entire Internet. It is so good  I feel almost guilty about getting this for free. Deborah, you are amazing.

# re: Silverlight, RIA Services, and Your Business Objects

Saturday, November 07, 2009 3:46 PM by Deborah Kurata

Hi Robert -

Thank you for the kind words.

They really encourage me to keep going!

# Silverlight and RIA: Ignoring a Property in Your Business Object

Tuesday, November 10, 2009 1:22 PM by Deborah's Developer MindScape

There may be times when you want RIA Services to ignore a property in your business object. This may

# Silverlight and RIA: Sharing Your Business Object Files

Tuesday, November 10, 2009 2:23 PM by Deborah's Developer MindScape

So I have read in dozens of places that you can easily share a source code file between your business

# Silverlight and RIA: Enum Properties

Tuesday, November 10, 2009 2:59 PM by Deborah's Developer MindScape

I mentioned in this prior post that RIA Services did not know how to handle properties that have an Enum

# re: Silverlight, RIA Services, and Your Business Objects

Wednesday, November 11, 2009 7:58 AM by Andre Stegplatten

I have to say that this is without doubt the single most informative, thorough and extensive .NET blog on the entire Internet. It is so good  I feel almost guilty about getting this for free.

# re: Silverlight, RIA Services, and Your Business Objects

Friday, November 13, 2009 10:40 AM by Sat

I was tired of seeing all the examples with Entity Framework , this example is clean , clear and provide an excellent way to understand the basic concepts,

 I am trying to use your example with the ViewModel , will update my progress later. Thanks

# re: Silverlight, RIA Services, and Your Business Objects

Friday, November 13, 2009 7:13 PM by Deborah Kurata

Hi Sat -

Thanks! Glad this was helpful.

Keep us posted on how you are doing!

# Silverlight, RIA Services, and Your Business Objects - Deborah's Developer MindScape

Tuesday, November 17, 2009 10:53 PM by progg.ru

Thank you for submitting this cool story - Trackback from progg.ru

# re: Silverlight, RIA Services, and Your Business Objects

Saturday, November 21, 2009 6:56 PM by Geoff Fox

Deborah,

This is up to your usual standard - a potentially complex topic made simple and crystal clear. I have followed your guidance since VB5 days with your book "Doing Objects" and met you the last time at the San Diego .net users group. Thanks again I will be building upon this for my work.

Happy Thanks Giving to you and your family!

# re: Silverlight, RIA Services, and Your Business Objects

Saturday, November 21, 2009 7:03 PM by Deborah Kurata

Hi Geoff -

Thank you for the kind words and Happy Thanksgiving to you and your family as well!

# Silverlight and RIA Services: Managing Your Codes

Wednesday, November 25, 2009 1:15 PM by Deborah's Developer MindScape

Every application has some type of codes: customer types, reason codes, states, and so on. Sometimes

# Silverlight and RIA Services: Managing Your Codes

Wednesday, November 25, 2009 2:47 PM by Deborah's Developer MindScape

Every application has some type of codes: customer types, reason codes, states, and so on. Sometimes

# Silverlight and RIA Services: Binding to a DataForm

Wednesday, November 25, 2009 4:24 PM by Deborah's Developer MindScape

When building line of business (LOB) applications, a common feature is create, review, update, and delete

# re: Silverlight, RIA Services, and Your Business Objects

Wednesday, January 06, 2010 9:06 AM by vinod

Add new is not working

# re: Silverlight, RIA Services, and Your Business Objects

Wednesday, January 06, 2010 7:06 PM by Marcos Hass

This post is really amazing !

Some guys like me are concerned about ** how much control ** is available when you start to use a framework ... and this post fills the gap. When you start a risky project you must be sure that you will be able to workaround some issues and with this information I feel more confortable.

All other examples I've found in the web are "Entity Framework Centric" and this one simply explains how to put all pieces together (most of the time you already have DAL + BLL)

Thank you very much and please don't give up your blog !

--marcos

# re: Silverlight, RIA Services, and Your Business Objects

Thursday, January 07, 2010 12:56 PM by HB

Thanks. This was very helpful.

As you mentioned, the next step is to change the Retrieve() method. What is the recommended way to collect data from an MSSQL database? Should I just use a stored procedure or Entity Framework?

Could you point me to some good examples?

Thanks.

# re: Silverlight, RIA Services, and Your Business Objects

Wednesday, March 31, 2010 11:07 AM by tom

this is a great article!  it's nice to see something about how to integrate this with existing work, when most of what we're seeing from MS is only focussed on new, simple projects.  

To that end, we found this article in trying to resolve a problem integrating into an existing project.  We found that if you're actually adding to an existing site, some of the configs don't get applied.  That was not noted in your article because you created a new ASP.NET site, even though you're targetting an 'existing' POCO layer.  

if you create the POCO, then create the ASP.NET, THEN add the SL, you will find there are some WPF configs missing for the 'DomainServiceModule' and the 'serviceHostingEnvironment.'  these missing configs cause the dreaded, "Load operation failed for query xx. The remote server returned an error: NotFound."

# Followup question

Friday, April 09, 2010 10:36 AM by SHannon

Hate to post a question.. but can't figure it out.. I've tried to follow the code above and i can build the solution with no errors, but when i run it, i get an error 4004.  Message:System.Windows.Ria.DomainException: An error occurred while loading data through the GetCustomers query on Domain context of type

and that is where the message ends...

hope someone can help.. this POCO would be nice to get familiar with.

thanks

# re: Silverlight, RIA Services, and Your Business Objects

Thursday, May 06, 2010 7:40 PM by Srinivas

Hi,

We have an existing project for Silverlight3 & WCF web services. We have created two separate solutions, one for Silverlight UI (with Web project)  and another solution for WCF web services using WCF Service Library template projects (one for each application area).

Can you please guide me (high level) what changes that need to be made for WCF web projects to enable RIA services and UI side to consume? Currently, we use Add Service reference to .svc file and make async calls to web services. We are using VS2008.

Great article and gave me some confidence in moving forward with our existing projects using RIA services. thanks

I really appreciate your help.

- Srinivas

# re: Silverlight, RIA Services, and Your Business Objects

Thursday, May 06, 2010 8:05 PM by Deborah Kurata

Hi Srinivas -

I have not done Silverlight 3 with WCF. I have only been using RIA with my own business objects. So I don't have any answers for you on that topic.

# re: Silverlight, RIA Services, and Your Business Objects

Tuesday, May 25, 2010 4:51 AM by Mark Mac

Great stuff, finally an example of RIA Services that is not using the Entity Framework, I new this was possible but couldn't for the life of me find an example of RIA Services using POCO.

# re: Silverlight, RIA Services, and Your Business Objects

Thursday, June 17, 2010 9:08 AM by ste

Finally! A tutorial on RIA Services without the damn Entity Framework.

Great article, helped me a lot. Thanks!

Long live POCO!! :)

# re: Silverlight, RIA Services, and Your Business Objects

Thursday, July 08, 2010 12:48 PM by TalMcMahon

I really enjoyed the post, I am curious what do you do about functions and Methods from your PCOC objects.  seems like we just get property bags.

# re: Silverlight, RIA Services, and Your Business Objects

Thursday, July 08, 2010 5:04 PM by Deborah Kurata

There are several ways to call methods, depending on what they do. I am planning a set of blog posts demonstrating these techniques in the near term future.

# re: Silverlight, RIA Services, and Your Business Objects

Friday, September 03, 2010 3:52 PM by Mike Griffin

The problem is the objects aren't editable, if you try to use the details grid it wont work, this is very frustrating because it only works for architectures that implement a DomainContext and therefully fully implement linq and so on, so in reality, at least thus far, RIA is really for the EF

# re: Silverlight, RIA Services, and Your Business Objects

Friday, September 03, 2010 7:48 PM by Deborah Kurata

Hi Mike -

It was great talking with you. We are using RIA for our project and NOT EF. So far we are still in the prototyping/design phase, but we have been able to get editing to work using the techniques I presented here:

msmvps.com/.../sl-ria-poco-update.aspx

Hope this helps you!

# re: Silverlight, RIA Services, and Your Business Objects

Wednesday, October 13, 2010 11:47 AM by Frank

This is probably a silly question .. lets say I have a solution with 5 pages .. each page uses the same load entity (observable collection) from a SQL database as all of the other pages. I want to CRUD the observable collection on each page. Is there any way I can go to the server once, get the load entity, then on each of the other pages access the load entity without keep going back to the Server? I assume the load entity is always bound to the server, so if i update it, i can make sure the server file is updated.

Thanks!

# re: Silverlight, RIA Services, and Your Business Objects

Friday, October 15, 2010 9:58 AM by Frank

got the following suggestion from Kevin Dockx, a co-author of a fabulous book .. Microsoft Silverlight 4 Data and Services Cookbook:

"It appears you’re using a DomainContext instance on each page, right?  One of the ways to solve your problem would be to create some kind of local state context container, eg: a class which holds a static instance of your DomainContext.  You can access this instance from each of your pages, and reuse the product entities once they’ve been loaded – if the Products have already been loaded: don’t execute the load query again.

Another interesting thing to look into might be “LoadBehavior”: with this (add as parameter to your load op), you can control what RIA Services should do when it returns from the server with entities which are already in your context: keep ‘em, overwrite ‘em, … "

# re: Silverlight, RIA Services, and Your Business Objects

Thursday, February 03, 2011 11:39 AM by Susette McCann

Thanks so much for a great article. I've always worked with business objects and this gives me the starting point to be able to do so in a Silverlight app.

# re: Silverlight, RIA Services, and Your Business Objects

Thursday, February 24, 2011 4:10 AM by blaise

I must admit this post seems to be the best I've read in last month about ria services (as mentionned, not E.F. centric). Let's make a trial of this architecture ;)

# re: Silverlight, RIA Services, and Your Business Objects

Monday, March 28, 2011 2:13 PM by Faye

I am new to RIA Services and and I am stuck on 3. Add a reference to System.ComponentModel.DataAnnotations.

I cant find the dataAnotaions dll that you are refering to. I reinstalled the Silverlight4_tools and it didnt put it in there?  I have it all set up except for that and I cant add the referance to the xaml file.

xmlns:riaControls="clr-namespace:System.Windows.Controls;assembly=System.Windows.Ria.Controls"

Thanks!

Faye

# re: Silverlight, RIA Services, and Your Business Objects

Tuesday, March 29, 2011 11:25 PM by Deborah Kurata

Hi Faye -

Have you loaded on Visual Studio SP 1? It just came out earlier this month (March). It contains RIA Services.

Hope this helps.

# re: Silverlight, RIA Services, and Your Business Objects

Tuesday, April 26, 2011 3:55 PM by Manny

Thank you so much.  Just what I was looking for.  In most of the apps, the architecture is predefined and I can't really use a straight forward EF Domain Service.  Your blog got me a step closer to my solution.

Leave a Comment

(required) 
(required) 
(optional)
(required) 
If you can't read this number refresh your screen
Enter the numbers above: