Deborah's Developer MindScape






         Tips and Techniques for Web and .NET developers.

July 19, 2010

The World’s Simplest Silverlight/RIA/POCO Example

Filed under: ASP.NET RIA Services,C#,Silverlight,VB.NET @ 10:33 am

This post demonstrates how to use Silverlight and WCF RIA Services to access YOUR server-side business objects to build a line of business application.

This particular example is as absolutely simple as possible to help you get up and running with these technologies. To meet this goal, this first post covers only how to retrieve data. Later posts will cover update operations.

So first, the prerequisites:

1) Download and install Silverlight 4 and WCF RIA Services 1.0.

Visual Studio 2010 comes with Silverlight 3. You need to download and install the Silverlight 4 Tools for Visual Studio 2010 from here. It comes with WCF RIA Services, so no additional download is required for RIA.

2) Download the Silverlight Toolkit.

This download provides many additional controls and themes. You can download it from here.

3) Build the Business Layer component.

When building a Silverlight/RIA application, you have probably already built your business layer and have business objects that you want to use in your Silverlight application. But if not, you need to do that first.

This example uses an overly simplified business layer component with the Customer class shown below.

Build a standard Class Library project and add the following code:

In C#:

using System.Collections.Generic;

namespace ACM.BLCSharp
{
    /// <summary>
    /// Manages a customer
    /// </summary>
    public class Customer
    {
        public int CustomerId { get; set; }
        public string LastName { get; set; }
        public string FirstName { get; set; }
        public string EmailAddress { get; set; }

        /// <summary>
        /// Retrieves a list of customers.
        /// </summary>
        /// <returns></returns>
        /// <remarks>
        /// In a "real" application, this code would
        /// call a data access component that retrieves
        /// the data from a database.
        /// </remarks>
        public 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:

”’ <summary>
”’ Manages a customer
”’ </summary>
”’ <remarks></remarks>
”’ <editHistory></editHistory>
Public Class Customer
    Public Property CustomerId As Integer
    Public Property FirstName() As String
    Public Property LastName() As String
    Public Property EmailAddress() As String

    ”’ <summary>
    ”’ Retrieves a list of customers.
    ”’ </summary>
    ”’ <returns></returns>
    ”’ <remarks>
    ”’ In a "real" application, this code would
    ”’ call a data access component that retrieves
    ”’ the data from a database.
    ”’ </remarks>
    Public Function Retrieve() As List(Of Customer)
        Dim custList As New List(Of Customer) From
                    {New Customer() With
                          {.CustomerId = 1,
                            .FirstName = "Bilbo",
                            .LastName = "Baggins",
                            .EmailAddress = "bb@hob.me"},
                    New Customer() With
                          {.CustomerId = 2,
                            .FirstName = "Frodo",
                            .LastName = "Baggins",
                            .EmailAddress = "fb@hob.me"},
                    New Customer() With
                          {.CustomerId = 3,
                            .FirstName = "Samwise",
                            .LastName = "Gamgee",
                            .EmailAddress = "sg@hob.me"},
                    New Customer() With
                          {.CustomerId = 4,
                            .FirstName = "Rosie",
                            .LastName = "Cotton",
                            .EmailAddress = "rc@hob.me"}}
        Return custList
    End Function
End Class

NOTE: This code does not use a data access layer at this time. To keep this example as simple as possible, the Retrieve method "mocks" a retrieve that would call your data access component and retrieve the data from the database. This code will be replaced in a later post to actually access a database.

NOTE: Normally I build a Customer class (singular) with the properties and methods that mange a singe customer and a Customers class (plural) that works with a list of those customers. The functionality for both were added to one class to keep this example as simple as possible.

Once the prerequisites are in place, we can get started.

STEP 1: Attribute your business objects to work with Silverlight

There are several different attributes you can define in your business objects so they work better with Silverlight, but in keeping with our goal of creating the simplest Silverlight/RIA/POCO example, you are only required to have one.

For WCF RIA services to work properly, you must have the Key attribute defined on the property that represents the unique key for your business object. This is most often the property of the class that stores the primary key value from your underlying table. In this example, it is the CustomerId property.

The Key attribute is defined in System.ComponentModel.DataAnnotations. So you must add a reference to that namespace and import it to use it.

In C#:

using System.ComponentModel.DataAnnotations;

[Key()]
public int CustomerId { get; set; }

In VB:

Imports System.ComponentModel.DataAnnotations

<Key()>
Public Property CustomerId As Integer

STEP 2: Add the Silverlight Project

1) Right-click on the solution and select Add | New Project.

2) Select Silverlight | Silverlight Application.

Be sure to select the template under Visual Basic for VB applications or the template under Visual C# for C# applications.

3) Check Enable WCF RIA Services.

Be sure to check the WCF RIA Services checkbox as shown below.

image

When you add a Silverlight project, Visual Studio creates both a Silverlight project and a Web (ASP.NET) project. The ASP.NET project is crucial because:

  • It provides the startup code to start up your Silverlight project.
  • It provides the WCF service "behind the scenes" to communicate between your Silverlight application and your business objects.

NOTE: If you already have a Silverlight project, you can still enable WCF RIA Services by accessing the Silverlight project properties and defining the WCF RIA Services link as shown below.

image

STEP 3: Set a reference in the ASP.NET project to your business layer component.

Select the ASP.NET project. Then add a reference to your business layer component.

image

The solution for this post has both the C# and VB components. If you are working through this example in your language of choice, you should only have one business layer component project on this list.

By setting this reference, the ASP.NET project code can call your business layer.

STEP 4: Add a Domain Service Class

Add a domain service class to the ASP.NET application. This is the class that calls your business layer methods.

The class must be in the ASP.NET application and not the Silverlight application because you cannot define a direct reference between your Silverlight application and a standard class library project. This makes sense because the Silverlight application runs in the client browser and the ASP.NET application runs on the server where it can access your business layer component.

To add a domain service class, right-click on the ASP.NET application and select Add | New Item. Then pick the Domain Service Class template.

image

This is where this example varies greatly from an Entity Framework example. If you are using Entity Framework, you will get the list of entities here and can set some entity attributes. If you are using your own business objects, you don’t have anything shown in the Entities grid. That’s fine. Just click OK.

Since you are building your own Domain Service Class, Visual Studio will inherit your Domain Service class from DomainService. If you were building the class using Entity Framework, the class would instead inherit from LinqToEntitiesDomainService.

In most cases, you will build one Domain Service Class for each business class that you want to access from your Silverlight project.

STEP 5: Add a Query method to the Domain Service class

The query method in the Domain Service class will in turn call the Retrieve method in the business layer component.

In C#:

namespace ACM.SilverlightCSharp.Web
{
    using System.Collections.Generic;
    using System.ServiceModel.DomainServices.Hosting;
    using System.ServiceModel.DomainServices.Server;
    using ACM.BLCSharp;

    [EnableClientAccess()]
    public class CustomerDomainService : DomainService
    {

        public IEnumerable<Customer> GetCustomers()
        {
            Customer cust = new Customer();
            return cust.Retrieve();
        }

    }
}

In VB:

Imports System.ServiceModel.DomainServices.Hosting
Imports System.ServiceModel.DomainServices.Server
Imports ACM.BLVB

<EnableClientAccess()> _
Public Class CustomerDomainService
    Inherits DomainService

    Public Function GetCustomers() As IEnumerable(Of Customer)
        Dim cust As New Customer
        Return cust.Retrieve
    End Function

End Class

A few notes about this GetCustomers method:

  • It must be a method and not a property.
  • Must return one of the following:
    • A single entity
    • An IEnumerable<T> where T is the entity
    • An IQueryable<T> where T is the entity
  • Can have any parameters.
  • Can have any name.
  • Can (but does not have to) have a Query attribute to define the method as a query.

WCF RIA Services recognizes the method as a query method because of its return value. Therefore, the return value must specify the entity either by returning it or returning an IEnumerable or IQueryable of the entity.

If you build at this point and view all files in your Silverlight project, you will see a Generated_Code folder containing a *.g.cs file. This contains the code generated by Visual Studio and defines the following classes:

  • Entity class (Customer in this example): This class is generated from the business layer and includes all of the entity’s properties.
  • Domain Context class (CustomerDomainContext in this example): This class makes the WCF service calls to the Domain Service class in the ASP.NET project.

In addition, the generated code creates a service contract for the ASP.NET Domain Service class.

[For more information on the generated code, see this post.]

Step 6: Build the UI

Again, keeping with the goal of staying as simple as possible, the UI in this example is a data grid.

1) Open the designer for MainPage.xaml by double-clicking on the file.

2) Open the Data Sources window (Data | Show Data Sources).

Visual Studio automatically added the defined domain context class to your data sources:

image

Simply drag and drop the Customer data source onto the designer and Visual Studio creates the user interface for you:

image

STEP 7: Run

If you run the application, you should get this:

image

This works because when you drag and drop the data source onto the page, Visual Studio defines a DomainDataSource control and a DataGrid control on the page. It sets the DomainDataSource QueryName property to "GetCustomersQuery" and sets the DataGrid ItemsSource property to the DomainDataSource. This causes the code to call your GetCustomers method and use the results to populate the grid.

NOTE: The generated code appends the "Query" suffix to your method name in the domain context class (CustomerDomainContext). That is the method that is called from the UI, which in turn calls the GetCustomers method that you created in the domain service class (CustomerDomainService), which in turn calls the Retrieve method in your business layer via a WCF service.

So your Silverlight application is calling your business layer using the ASP.NET application as a WCF service. Here it is in picture form:

 image

To add a feature to update your data, see this post.

For a more complete example, download the extended source from here.

If you want to learn more about using Silverlight and RIA Services, come and see my talk at VSLive in Redmond Washington August 4, 2010. See this post for more information.

Use these techniques as a starting point when accessing your server-side business layer from a Silverlight application.

Enjoy!

19 Comments

  1.   shiva — January 1, 2011 @ 1:14 pm    Reply

    Awesome. It made 2 things clear to me. 1) Making an existing silverlight app to be RIA supportive. 2) Data sources – I didnt know this existed.

    Wonderful, superb, simple.

  2.   Shane Ritchie — January 10, 2011 @ 8:31 am    Reply

    Hi, this article has been very helpful for me and I have this working nicely in my project. However, in my situation, very often I just need to return a string. I take it that would be the Single Entity you mention in your article. I can’t seem to get this working. Can you post a snippet of how you would do this using your example above please? Many Thanks.

  3.   Thanga — January 11, 2011 @ 7:13 am    Reply

    GREAT WORK. Was really useful

  4.   Wei — March 13, 2011 @ 10:03 am    Reply

    Your example is great and creative, which is much better than the articles I obtained on internet before. Thanks a lot.

  5.   Manoj Nair — April 18, 2011 @ 8:16 am    Reply

    Thank you very much for this article. It gives me some insight into the inner workings of Domain Services that has been a black box.

  6.   msp.netdev — June 21, 2011 @ 9:10 am    Reply

    Very well done!

  7.   Saskia — March 1, 2012 @ 3:37 am    Reply

    This is by far the best introduction to this topic that I have found. Thank you so much!

  8.   Jason — May 25, 2012 @ 3:51 pm    Reply

    Thank you for this very informative tutorial. All of the “Out of the Box” and “Textbook Examples” do not include good information for RIA using POCO DTO defined in another assembly. After reading through this, all seems amazingly simple. Prior to reading this I have gone through countless examples that return EF objects.

  9.   SimonRoper — May 29, 2012 @ 3:10 pm    Reply

    Excellent

    Source code AND pictures. And none of the high-level terminology that seems designed to confuse people. This was just what I needed. Thanks

    Now … Do you have something similar covering deployment?

RSS feed for comments on this post. TrackBack URI

Leave a comment

© 2019 Deborah's Developer MindScape   Provided by WPMU DEV -The WordPress Experts   Hosted by Microsoft MVPs