Business Apps Example for Silverlight 3 RTM and .NET RIA Services July Update: Part 8: WCF Based Data Source

More updates on my Mix09 talk “building business applications with Silverlight 3”.

You can watch the original  video of the full session

The demo requires (all 100% free and always free):

  1. VS2008 SP1 (Which includes Sql Express 2008)
  2. Silverlight 3 RTM
  3. .NET RIA Services July '09 Preview

Also, download the full demo files

In the original demo I showed getting your data from a database directly from the web tier.  Many enterprise customers have found that it their systems are more maintainable and secure if they isolate the database access behind a set of web services possibly in a DMZ.  This means that no apps talk directly to the database.   Yet there is often a need to add application specific validation and application logic as well as data shaping and aggregation in the web-tier.  

To show this, I have refactored the example application from the first part of this walk through to access its data from a WCF service rather than EF directly.   Notice that all the other UI bits stayed the same,



Defining the Service

Let’s start by defining the WCF service.  In a real word application this service is likely defined by another group and you are only allowed to access it, not modify it. 


Right click on the solution and add a new project… WCF Service Application.  I called it MyApp.Service, but you can choose anything you’d like.



First we create an Entity Framework model for our database.. this is done exactly the same way as part 2, but this time it is part of our Service rather than in the web-tier.   The demo would work exactly the same no mater what source of data you use… EF was just easy for me to get going, it is not required for this scenario as we are encapsulating everything behind a the WCF services layer. 

Next, we define the interface for our service

public interface ISuperEmployeeService
    IEnumerable<SuperEmployee> GetSuperEmployees(int page);
     SuperEmployee GetSuperEmployee(int empId);
    void UpdateEmployee(SuperEmployee emp);

Then we implement it…

public IEnumerable<SuperEmployee> GetSuperEmployees(int page)
    using (var context = new NORTHWNDEntities()) {
    var q = context.SuperEmployeeSet
        .Skip(page * PageSize).Take(PageSize);
    return q.ToList();



Notice here we are implementing paging by taking a page parameter…  After a brief inventory of real world services on the net, i find this a very common pattern.    It is very easy with EF to access just the page of data we want. 


Consuming the Service

Now let’s consume this service from the web-tier. The reason we do this here is to get all the benefits of the RIA Services in terms of validation logic, etc and be able to customize and arrogate the data so the view is just right for the client.

First, we define a SuperEmployee type that is shaped just right for the client.   In this simple example I left it pretty much the same as the service returned, but you can use any shape you’d like. 

Notice we are using attributes to specify the different validation we want to have done on this data on the client AND the web-tier. 

public class SuperEmployee
        public int EmployeeID { get; set; }
            ErrorMessage = "Gender must be 'Male' or 'Female'")]
        public string Gender {get;set;}
        [Range(0, 10000,
            ErrorMessage = "Issues must be between 0 and 1000")]
        public Nullable<int> Issues {get;set;}
        public Nullable<DateTime> LastEdit {get;set;}
        public string Name {get;set;}
        public string Origin {get;set;}
        public string Publishers {get;set;}
        public string Sites {get;set;}


Now, let’s add a reference to the service we just created.

Right click on the project and select Add Service Reference..



Now we modify our DomainService…


   1: public class SuperEmployeeDomainService : DomainService
   2:   {
   3:       SuperEmployeeServiceClient Context = new SuperEmployeeServiceClient();
   5:       public IQueryable<SuperEmployee> GetSuperEmployees(int pageNumber)
   6:       {
   7:           return this.Context.GetSuperEmployees(pageNumber)
   8:                      .Where(emp => emp.Issues > 100)
   9:                      .OrderBy(emp => emp.EmployeeID)
  10:                      .Select(emp =>
  11:                          new MyApp.Web.SuperEmployee()
  12:                          {
  13:                              EmployeeID = emp.EmployeeID,
  14:                              Gender = emp.Gender,
  15:                              Issues = emp.Issues,
  16:                              LastEdit = emp.LastEdit,
  17:                              Name = emp.Name,
  18:                              Origin = emp.Origin,
  19:                              Publishers = emp.Publishers,
  20:                              Sites = emp.Sites,
  21:                          }).AsQueryable();
  22:       }

Notice in line 1, we no longer need to derive from EFDomainService as there is no DAL access code in this web-tier now… we have factored all that into the service.

In line 3, we create an instance of the WCF web Service Proxy..

In line 5, you can see we are taking a page number – we will need to pass that from the client.

In line 7 we are creating a simple LINQ query to change the shape of the data we get back from the service. 



In the Silverlight Client

Now, to consume that in the silverlight client is very easy..   We just make a few tweaks to the Home.xaml we created in part 2..

   1: <riaControls:DomainDataSource x:Name="dds" 
   2:         AutoLoad="True"
   3:         QueryName="GetSuperEmployeesQuery"
   4:         LoadSize="20">
   6:     <riaControls:DomainDataSource.QueryParameters>
   7:         <datagroup:ControlParameter ParameterName="pageNumber"
   8:                                     ControlName="pager"
   9:                                     RefreshEventName="PageIndexChanged"
  10:                                     PropertyName="PageIndex">                            
  11:         </datagroup:ControlParameter> 
  13:     </riaControls:DomainDataSource.QueryParameters>
  15:     <riaControls:DomainDataSource.DomainContext>
  16:         <App:SuperEmployeeDomainContext/>
  17:     </riaControls:DomainDataSource.DomainContext>
  19:     <riaControls:DomainDataSource.GroupDescriptors>
  20:         <datagroup:GroupDescriptor PropertyPath="Publishers" />
  21:     </riaControls:DomainDataSource.GroupDescriptors>
  25: </riaControls:DomainDataSource>

Notice in line 7 we are getting the page number from the GetSuperEmployees() method from the DataPager… This is set up such that as the DataPager changes pages, the DDS request data from the server.

If you are paying close attention to the whole blog series, you will notice I removed the sorting and filtering for this example.  I did this because you are basically limited by the expressiveness of your back-end data… If your back end data does not support sorting and filtering, then it is tough to do that on the client!  You could do caching on the web tier but that is a subject for another day.  

As an fun exercise, assume you could change the WCF Service definition, how would you add filtering?   You could follow the exact pattern we use for paging.  Add an argument to the WCF Service, add the same one to the GetSuperEmployees() query method on the server, then add another ControlParamater to the DDS getting its data from a control on the form.  Pretty easy!  Let me know if you try it.

The final step is to bind the DataPager to a shim collection, just to make it advance.  

   1: <data:DataPager x:Name="pager" PageSize="1" Width="379" 
   2:                 HorizontalAlignment="Left"
   3:                 DisplayMode="FirstLastPreviousNext"
   4:                 IsEnabled="True"
   5:                 IsTotalItemCountFixed="False"
   6:                 Margin="0,0.2,0,0">
   7:     <data:DataPager.Source>
   8:         <paging:PagingShim PageCount="-1"></paging:PagingShim>
   9:     </data:DataPager.Source>
  10: </data:DataPager>

You can find the implementation of PagingShim in the sample.  (thanks to David Poll for his help with it). 

Hit F5, and we have something cool!  It looks pretty much the same as the previous app, but this one gets all its data via WCF!


Comments (19)

  1. Steve says:

    Excellent – thanks Brad.  I personally think this is a common scenario – so it’s good to see post on it.

    Loving the series, thanks again

  2. Mike says:

    Thanks for the serie!

    But, Where is the part 7? or, I’m lost…?

  3. BradA says:

    > But, Where is the part 7? or, I’m lost…?

    Mike — Ahh, yes.. mysterious  post 7… well, I sort of screwed up and posted 8 before 7…  Not sure how I will resolve that yet.. i might just post 7 as 9 and shift everything down.. thoughts?

  4. Steve says:

    Post 7 as 7  🙂  Leave 8 as 8 and 9 will just have to stay 9

  5. Hi,

    This article is very nice. I have to try this .



  6. Mark says:

    Great series.

    Could you provide an example of how to hookup master-detail (Customers-Orders) using data binding with the Silverlight DomainDataSource and a pair of DataGrids. Specifically how do you reference, say the customer number for the SelectedItem in the Customers grid to use as a parameter value in the Orders grid.

    Can you have more that one DomainDataSource for the same DataContext? I can see how to do this in code but not xaml.

    Any thoughts would be appreciated.


  7. Steve says:

    Brad, I’d liked to see your sample done with Prism – showing Prism with DomainServices would be a good topic in your series  🙂

  8. BradA says:

    >  Could you provide an example of how to hookup > master-detail (Customers-Orders) using data  

    > binding with the Silverlight DomainDataSource

    Mark — I will look into an example like that — in the mean time, here is the section from the RIAServices overview doc that includes information on the IncludeAttribute..    That should help.

    4.8 Using the IncludeAttribute

    The IncludeAttribute can be applied to association members to shape the generated client entities as well as to influence serialization. Below we explore two uses of this attribute.

    4.8.1 Returning Related Entities

    When querying entity Types with associations to other entities, often you’ll want to return the associated entities along with the top level entities returned by the query. For example, assume your DomainService exposes Products, and for each Product returned you also want to return its associated ProductSubCategory. The first thing to do is ensure that the associated entities are actually returned from the data source when Products are queried. The mechanism used to load the associated entities is a DAL specific thing. In this LINQ to SQL example, the code would be:

       public IQueryable<Product> GetProducts()


           DataLoadOptions loadOpts = new DataLoadOptions();

           loadOpts.LoadWith<Product>(p => p.ProductSubcategory);

           this.Context.LoadOptions = loadOpts;

           return this.Context.Products;


    With this code, all ProductSubCategories are returned from the DAL when Products are queried. The next step is to indicate to .NET RIA Services that a ProductSubCategory entity should be code generated, as should the bi-directional association between the two Types. To do this you need to apply the IncludeAttribute to the association member.

    IncludeAttribute has both serialization semantics and data-shape semantics.  For both serialization of results to the client as well as the client object model we code-gen, .NET RIA Services will only ever expose data and types from the service that you have explicitly exposed from your service.

    • If a Type is exposed via a query method from the service a corresponding proxy class will be generated on the client for that Type. In addition any associations referencing that Type from other exposed types will also be generated.

    • If a Type is not exposed by a query method, but there is an association on another exposed Type that is marked with IncludeAttribute, a corresponding proxy class will be generated on the client for that Type.

    Those points define what types are defined on the client and their shapes. In addition to these data shape semantics, IncludeAttribute also has serialization semantics : during serialization, only associations marked with IncludeAttribute will actually be traversed. All of this ensures that only information you’ve explicitly decided to expose is exposed.

    Therefore, we need to apply the IncludeAttribute to the Product.Category association member. We do this by adding the attribute to the buddy metadata class:

       internal sealed class ProductMetadata



           public ProductSubcategory ProductSubcategory;


    With this in place we’ll get a ProductSubCategory entity generated on the client, as well as the Product.ProductSubCategory association member. This works the same way for collection associations. For example, to include all Products when querying a ProductSubCategory, you’d put the IncludeAttribute on the ProductSubCategory.Products member.

    4.8.2 Denormalizing Associated Data

    IncludeAttribute can also be used for another purpose – data denormalization. For example, assume that in the above scenario we don’t really need the entire ProductSubCategory for each Product, we only want the Name of the category.

       internal sealed class ProductMetadata


           [Include("Name", "SubCategoryName")]

           public ProductSubcategory ProductSubcategory;


    The above attribute results in a “SubCategoryName” member being generated on the client Product entity. When querying Products, only the category Name is sent to the client, not the entire category. Note that the ProductSubCategory must still be loaded from the DAL as it was in the previous example.

  9. MarkZ says:

    Brad:  How do you deal with authentication delegation here, specifically within a Windows-auth domain model?  

    For example:  

    Client (web browser) is on Machine A.

    Web Tier is on Machine B.

    Database (via EF) (or wcf service on database) is on Machine C.

    Only with Active Directory delegation can the user credentials make it all the way from Machine A to Machine C since they’ll be going via Machine B.

    What’s the recommended security model if you can’t setup delegation in this case?  Does the database need to be connected via SQL logins?  How do you deal with web services on other machines that require Windows-auth?

    We’ve really been struggling with this since we’re not able to setup delegation in our domain.

  10. Tazul says:


      I created a sample application using the pattern you described in tihs post. When i page it gets me data till 6th page and after that it spins for a while with activity bar shown eventually it stops with System.TimeoutException.

      When i debugged i found that in the generated class it never makes a call to the WCF service.

           public EntityQuery<ZipCode> GetZipCodesQuery(int pageNumber)


               Dictionary<string, object> parameters = new Dictionary<string, object>();

               parameters.Add("pageNumber", pageNumber);

               return base.CreateQuery<ZipCode>("GetZipCodes", parameters, false, true);


    I had a breakpoint in the WCF service

           IEnumerable<ZipCode> IZipCodeService.GetZipCodes(int page)


               var context = new Mid_MarketEntities();

               var q = context.ZipCode.OrderBy(zip => zip.ZipID).

                   Skip(page * PageSize).Take(PageSize);

               return q.ToList();


    but it never made into this function after the 6th page.

    Not sure what am I missing. Is there a way to add trace to RIA services to troubleshoot such kind of problems.



  11. BradA says:

    I did see this a couple of times and I attributed it to the development-web server in VS…  Are you using that or IIS?  Can you let me know if this happens under IIS as well?

  12. Tazul says:

    Thanks for the reply. I am using development web server. I haven’t tried in IIS. Do you think this will not occur in IIS?  

  13. Tazul says:

    I tried after deploying both the WCF service and Web project on IIS and I am having same problem. I used 20 records in DDS  and same in the WCF service.

                   <riaControls:DomainDataSource x:Name="dds"





                           <datagroup:ControlParameter ParameterName="pageNumber"










                           <datagroup:GroupDescriptor PropertyPath="Publishers" />



    WCF Service:

           const int PageSize = 20;

           public IEnumerable<SuperEmployee> GetSuperEmployees(int page)


               var context = new NORTHWINDEntities();

               var q = context.SuperEmployeeSet

                   .OrderBy(emp => emp.EmployeeID)

                   .Skip(page * PageSize).Take(PageSize);

               return q.ToList();


    After the 5th page (100 records) when i click next, it does the same thing. I tried changing

    the pagesize and the load size but after fetching around 100-150 records it fails.

  14. Tazul says:

    I found the problem and fixed it. It was with WCF service. Domain Service was not closing the channel and was open. By default WCF has 10 max concurrent sessions. While paging Domain service makes calls to the WCF service to fetch next batch but doesn’t close the channel. So I made a change to the WCF function to close the channel after the call is done.

    WCF Service:

          const int PageSize = 20;

          public IEnumerable<SuperEmployee> GetSuperEmployees(int page)


              var context = new NORTHWINDEntities();

              var q = context.SuperEmployeeSet

                  .OrderBy(emp => emp.EmployeeID)

                  .Skip(page * PageSize).Take(PageSize);

              context.Close(); //This fixed the problem.

              return q.ToList();


  15. BradA says:

    Excellent!  thanks… I will fix my sample.

  16. Hi BradA,

    In your code you have Update and Insert functions

    public void InsertSuperEmployee(SuperEmployee superEmployee)




           public void UpdateSuperEmployee(SuperEmployee currentSuperEmployee)




    but you never called these on client.

    Your these functions are not generated on client as they are not IQuerable nor they carry the Attribute Query with them, i mean they donot fulfill the requirements of getting gnerated on the client, neither are they generating in your code.

    My question is in this scenario what are your plans on how to call these domain methods from the client code.

  17. BradA says:

    Aashish Gupta  – Those are called when you are add a new SuperEmployee or update data on an super employee.  They are part of the changeset processing.  

  18. Sony Grace says:


    It would be great if you can shed any light on this…

    The  sort properties on a domaindatasource are lost after a paging operation

    The properties are there , but they are not present in the final query on the sql server and thus the data is no longer sorted..

    any ideas on how to fix this ???

    I have already created a thread here on forum

    appreciate any kind of help  

  19. Thanks for this series Brad – I’m really learning alot.

    Some feedback – I find anything that’s not strictly presentation living in the Xaml to be extremely confusing and hard to follow.  I’m sure there are other ways to do the same thing (that are probably less demo-friendly), but more straightforward.  Xaml in general is very difficult to read if you’re not an expert – especially if its written in one of the many abbreviated ways it allows.

    I’ve been trying to take one of these MyApp drops and steal from it piece by piece to get a simple app of my own up and running.  Things like this in the Xaml are very difficult to understand:





       <datagroup:GroupDescriptor PropertyPath="Publishers" />


    I know there’s some kind of context object that RIA Service is generating for me, but it’s really difficult for me to understand how to change this to get it working with my service.  This feels like that whole ObjectDataSource thing from ASP.NET that I refused to take part in.  Please tell me there are ways to do this in the code behind with more of a MVP or MV-VM pattern?

    Thanks for all this content!

Skip to main content