WCF RIA Services – Hands On Lab | John Papa

John Papa

Evangelist on the loose

WCF RIA Services – Hands On Lab

...

At the keynote for the Silverlight 4 Launch alongside Scott Guthrie I demonstrated image(minute 28 to minute 38) how to build a Silverlight 4 application using WCF RIA Services and the new Visual Studio 2010 tooling.

The application I built is an online book store to rival the big boys … OK, well, maybe not the big boys but you get the idea. As promised I am elaborating on the presentation and breaking down the steps to create the application here.

I included the starter solution and the completed solution for this presentation so you can try this out for yourself or simply run the completed solution if that interests you more. In this post I will go through the steps to create the application so you can try this as well.

image 

Here is the completed application that I will show how to build. You can select a book category and the books for that category will appear in the book list in the middle. You can sort by title or author or you can filter the book list by title or author. If you log into the application (as RIA Services integrates well with ASP.NET authentication) I show how to set up permissions to edit the book information too. OK, so this was a stretch as you really don’t want to allow book information to be edited by buyers, but work with me on this :-)

image

imageWhere Do We Start?

Let’s start by examining what is already in the project. Open the starter project and notice that there are already a Silverlight project and a Web project created. imageThe application starts out with a SQL Server database containing information about the books. This image shows the Entity Framework model that maps to the SQL Server database. We will be talking to the EF model which in turn talks to SQL Server. Of course this model can be a 1-1 model to table mapping or it could be much more complex. Also, this could have been an nHibernate model or a custom model … RIA Services will sit on top of a variety of models.

So the lower tier architecture contains a SQL Server database which stores the book information and an Entity Framework model which maps to that SQL Server database. RIA Services will operate on the Entity Framework model for both retrieving and modifying data using LINQ to Entities in this application.

imageCreate the Domain Service

To create the domain service you then add a new Domain Service Class to the Web project and name it BookClubService.cs.

image 

imageConfigure the Domain Service

When you configure the domain service RIA Services can see all of the entities that the Entity Framework model exposes. You can select which entities you want the domain service to imageexpose and if they should be editable through this dialog. I’m going to select the Book, BookOfDay and Category and enable editing of the Book. This tells RIA Services to generate methods in the domain service class to return the entities and to create methods to save changes to the Book entity.

I will also check the box to “Generate associated classes for metadata”. This creates a BookClubService.metadata.cs class. This is where you can define validation and business rules that you want to share between the server and the client. The code in this class will be copied to the Silverlight client when the application is compiled.

  ont>

imageReturning Object Graphs

When we get the book of the day we want to get the BookOfDay entity and its child entity, Book. By default when asking for a BookOfDay entity from a domain service it will only return BookOfDay entities, and no child entities. Since this is not what we want we can decorate the Book property of the BookOfDayMetadata class with the Include attribute. We’ll also have to configure the domain service method for getting the BookOfDay entities to include the Book entities too … but we’ll do that in the next step.

   1: internal sealed class BookOfDayMetadata

   2: {

   3:     // Metadata classes are not meant to be instantiated.

   4:     private BookOfDayMetadata()

   5:     {

   6:     }

   7:     //Include the book for the object graph

   8:     [Include]

   9:     public Book Book { get; set; }

  10:     public int BookID { get; set; }

  11:     public DateTime Day { get; set; }

  12: }

imageCustomize the Domain Service Methods

The BookClubService class (generated in step 3) contains a series of methods that will be exposed to the Silverlight client. You should see a series of methods to retrieves the entities and a few methods to insert, update and delete Book entities. While this code is generated we can modify the code without risk of it being overwritten. (The domain service generated class is not one that is regenerated on the fly.) So we can edit the GetBooks method to return the books in sequence by title.

   1: public IQueryable<Book> GetBooks()

   2: {

   3:     return this.ObjectContext.Books.OrderBy(b => b.Title);

   4: }

Then change the GetCategories method to order the Category entities by the CategoryName.

   1: public IQueryable<Category> GetCategories()

   2: {

   3:     return this.ObjectContext.Categories.OrderBy(c => c.CategoryName);

   4: }

Now change the GetBookOfDays method to include the Book entity and return the most recent BookOfDay entity and its Book.

   1: public IQueryable<BookOfDay> GetBookOfDays()

   2: {

   3:     return this.ObjectContext.BookOfDays.Include("Book").OrderByDescending

   4:         (b => b.Day).Take(1);

   5: }

Build the application and the services will be exposed, the models shared, and the metadata shared to the Silverlight client.

imageConfigure the Data Sources to use ListBox Controls

Now let’s go to the Silverlight client in Visual Studio 2010. Open the Home.xaml View in the designer. Styles have already been applied to the View by my Designer, which yields a nice limageooking control. But we have to hook the functionality (data, buttons, actions, behaviors) up. Let’s start by opening the Data Sources window and verifying that we see the Book, BookOfDay and Category show up under the BookClubContext. These can be dragged to the design surface which then creates a Domain Data Source (DDS) and a DataGrid in the View’s XAML. The DDS calls the GetBooks method in the domain service in the web project and binds the results to the DataGrid. image

We don’t want a DataGrid, though. So lets change the type of control to a ListBox. Click the arrow to the right of the Book in the Data Source window and select Customize. When the Customize Control Binding dialog appears scroll to ListBox, select it, and click the Set Default button. This tells the Data Sources window that we want the ListBox to be the default option when dragging and dropping to the design surface.

Now, go back to the Data Sources window and the Book should now show a different icon that represents the ListBox.

 image

imageDrag the Data Sources to the Design Surface

Drag the Category from the Data Source window to the rectangular Grid panel below the Book Categories title. Then right click the ListBox and choose Reset Layout | All. This makes the ListBox consume all of the space inside of the Grid.

image

Drag the BookOfDay to the BookOfDay Grid and reset the layout to “all”. Then drag the Book to the Book Grid and reset the layout to “all”.

The ListBox controls are now created, aligned, and bound to the newly created DDS controls. The Silverlight client is also now wired up to retrieve the data for these bindings from the domain service class we created in the previous steps.

Now drag the Book from the Data Sources window onto the DataPager control. This binds the DataPager to the same DDS that the Book ListBox is bound to, thus enabling paging.

imageApply the DataTemplates

Now it is time to apply the DataTemplates for the 3 ListBox controls. These DataTemplates were created in advance by our designer as resources and are quite simple. For example, the DataTemplate for Book looks like this:

   1: <DataTemplate x:Key="BookItemTemplate">

   2:     <StackPanel Orientation="Horizontal">

   3:         <TextBlock Text="{Binding Title}" Margin="8,0"/>

   4:         <TextBlock Text="(by "/>

   5:         <TextBlock Text="{Binding Author}"/>

   6:         <TextBlock Text=")"/>

   7:     </StackPanel>

   8: </DataTemplate>

We can apply the DataTemplates to the ListBoxes using the new Visual Studio 2010 tooling for imageapplying resources. Select the Category ListBox in the designer, go to the Properties window, and find the ItemTemplate property. Click the gray arrow in the right hand side of the ItemTemplate’s value box and the following dialog should appear. This shows all of the matching options, which in this case are the DataTemplates within scope that can be applied to this ListBox’s ItemTemplate property. Select the CategoryItemTemplate. Now repeat the process and apply the BookOfDayItemTemplate and the BookItemTemplate to their respective ListBox controls. Our ListBox controls are now laid out, styled, bound and templated.

imageApply Filters

We want to filer the books by the selected category and by the title or author (whichever is selected in the combobox and value typed into the TextBox above the Book’s ListBox). We can do this through the Visual Studio 2010 tooling by first going to the Document Outline window and selecting the bookDomainDataSource. Open the Properties window, find the FilterDescriptors property, and click the button (the one with the 3 dots).

When the Collection Editor for the FilterDescriptors appears click the Add button to add a new filter. This filter will make sure the books are filtered by the selected category. Set the PropertyPath to the string “CategoryID” (without quotes). Then click the square next to the Value property, click the Apply Data Binding options, and the binding dialog appears. For the Source select the ElementName binding and the categorylistBox, as shown below.

image

Now for the Path select the SelectedItem property as shown below. We just created a filter so only books for the selected category will appear.

image

Now we need to create a filter by the partial name entered for the author or title. Add another filter descriptor and set the Operator to Contains (we want to do partial matching of the title or author). Bind the PropertyPath to the cboSort combobox’s SelectedItem.Content property, as shown below.

image

Then bind the TextBox named txtFilter and to its Text property, as shown below.

image

These steps created the filters but there are 2 additional steps we need to take. First, we need to go to the XAML of the filter for the category and set the Path to SelectedItem.CategoryID. (The tooling does not support the free form entry of the CategoryID in the filter dialog.) Next, I want the FallBackValue for the same filter to be set to 1. This way if a category is not selected the filter will be applied to the first category. When you are done, your XAML for the filters  should look like this:

   1: <riaControls:DomainDataSource.FilterDescriptors>

   2:     <riaControls:FilterDescriptor Operator="IsEqualTo" PropertyPath="CategoryID" Value="{Binding ElementName=categoryListBox, Path=SelectedItem.CategoryID, FallbackValue=1}" />

   3:     <riaControls:FilterDescriptor Operator="Contains" PropertyPath="{Binding Path=SelectedItem.Content, ElementName=cboSort}" Value="{Binding ElementName=txtFilter, Path=Text}" />

   4: </riaControls:DomainDataSource.FilterDescriptors>

imageApply Sorting

The next step is to apply the sorting. Select the bookDomainDataSource from the Document Outline window, go to the Properties window, and find the Sort Descriptors property. Click the button and when the sort dialog opens, add a new SortDescriptor. Here we want to sort by the selected value in the cboSort combobox. Click the PropertyPath’s binding icon and select the Apply Data Binding option. Set the Source to cboSort and set the Path to SelectedItem.Content.

image

Your XAML for the SortDescriptor should look like this:

   1: <riaControls:DomainDataSource.SortDescriptors>

   2:     <riaControls:SortDescriptor PropertyPath="{Binding Path=SelectedItem.Content, ElementName=cboSort}" />

   3: </riaControls:DomainDataSource.SortDescriptors>

imageBind the Book Control

The next step is to bind the selected book (from the ListBox) to the BookControl. The BookControl is already created (in a separate XAML file in my project). It contains the layout to display and edit the book’s property values. All it needs is a book for its DataContext to bind to.

Select the BookControl, go to the Properties window, and find the DataContext property. Click the binding button next to the DataContext property and choose the Apply Data Binding option. use the binding picker to bind to the ElementName of bookListBox and the Path of SelectedItem. Now our BookControl is bound to the selected book.

image

imageBind the Submit Button

We can support saving changes made by the user by binding the Submit button control to the bookDomainDataSource control’s SubmitChanges method. Select the btnSubmit control, go to the properties window, and find the Command property. Click the binding button next to the property and choose the Apply Data Binding option. Set the Source to the bookDomainDataSource and set the Path to the SubmitChangesCommand. (This command is part of the DDS you created when you dragged the Book from the Data Sources window onto the design surface.)

image

image

Now it is time to run the application. Click the login link and register a username and a password.You will need this information to log into the application so you can edit the book details.

This will take advantage of the authentication that is set up by default by WCF RIA Services. This includes an auth database, services to log in and register users, log in controls, and wiring up the services to the Silverlight client.

image

image

Once you log in you can use the application to:

  • choose different categories and watch the books get filtered
  • change the sorting for the books
  • filter the books by partial name of the author or title
  • select a book and view the book details in the book control
  • page through the books
  • edit details of a book
  • submit the changes for the book

You might notice when you edit the book details that some fields are in bold. These fields have validation attributes applied to them for required fields. If you remove the text from the ASIN TextBox the control will be highlighted in red. This means the validation condition not been met. If you hover over the upper right corner of the TextBox on the red triangle you will see a message that explains the problem.

image 

image

This application stepped you through creating the fictitious Online Book Shelf application using RIA Services. if you have 10 minutes, you can watch me follow these steps (rather quickly with some variations) from the keynote from the Silverlight 4 launch using the following link. I begin 28 minutes in and spend about 9 1/2 minutes on the demo.

You can download the source for the completed version of the application or the starter from these links:

NOTE: After you download the zip files, make sure you unblock them. Also, I recommend cleaning the solution before you start working through the steps.

image

Several people contributed heavily to this keynote demo and application including Deepesh Mohnani, Jeff Handley, Dinesh Kulkarni, and Nikhil Kothari. Thank you all for your huge contributions!

Now for something Different …

If you made it this far in the post, you can even watch a pre-keynote warmup (tongue in cheek) from me and Ward Bell.

 

tags: Silverlight
  • http://www.ubervu.com/conversations/johnpapa.net/silverlight/wcf-ria-services-hands-on-lab/ Anonymous

    This post was mentioned on Twitter by jitukrish: RT @John_Papa: Posting … WCF RIA Services – Hands On Lab: At the keynote for the Silverlight 4 Launch alongside Scott Guthrie I… http://bit.ly/dxCsce

  • http://blog.cwa.me.uk/2010/04/26/the-morning-brew-587/ Anonymous

    Pingback from The Morning Brew – Chris Alcock » The Morning Brew #587

  • http://www.sparklingclient.com/this-week-in-silverlight-april-23-2010/ Anonymous

    Pingback from This Week In Silverlight April 23 2010

  • http://johnpapa.net/tutorials/ Anonymous

    This is a list of Silverlight tutorials I’ve worked on recently. &#160; WCF RIA Services Wiring Up WCF RIA Services 101

  • Anonymous

    I just installed all of studio 2010 enterprise (release version). The sample fails with:
    "The imported project "C:\Program Files\MSBuild\Microsoft\Silverlight\v4.0\Microsoft.Silverlight.CSharp.targets" was not found."
    I believe this was installed w/the beta version but not release. Any advise?

  • Anonymous

    Thanks for this article/tutorial, good work.
    However, it should be said that this is not the way we build/want to build our applications. The moment we drag those controls from the Data Sources window and generated those Domain Data Sources, we literally chopped of our own hands when it comes to having control of our application and its behavior.
    Some of us know that you do not need to stoop to this compromising way of working when using WCF RIA Services. It is not necessary to rely on the declarative Domain Data Source which makes refactoring a living nightmare. Those demos are what will get people hooked – demos like these scare us off.
    I dare you to do a poll on what kind of approach people are interested in when it comes to WCF RIA Services development: code driven or declarative.
    I think you guys pretty much need to do this because this is a really interesting technology, but 90% of the demos makes the majority (just my guess) cringe.
    Why do we cringe? No, not because we want to come across as pompous code fascists, but because we know that coding as opposed to drag n’ drop leads to a more easily maintained code base (well, that and the fact that most of us never really got over the dreaded declarative data sources in ASP.NET).
    Thanks for listening, and again I don’t mean to put down the tutorial, its a good one, but many would agree it promotes bad practices.

  • Anonymous

    it seems that with VS2010 official, i cannot work with the database you supply. what version of the sql should i use? i have sqlserver2008
    thganks,
    Eli

  • http://hankwallace.wordpress.com/2010/04/27/interesting-finds-april-27-2010/ Anonymous

    Pingback from Interesting Finds: April 27, 2010 « Hank Wallace

  • http://johnpapa.net JohnPapa

    Dan – It was written with the RTM version. I’m not getting that error though.
    Truthteller – I understand your points and I won’t argue the merits of the DDS with you. I prefer the code techniques myself but after digging into the DDS I have found it to buck against the trends of the average drag/drop control. It is powerful and can be extended and tapped into, which is where most in the past have failed. That all said, I still prefer the code approach (call it old habits). I’ll be producing some other demos here and on Silverlight TV, too that show alternative methods.

  • http://progg.ru/WCF-RIA-Services-Hands-On-Lab Anonymous

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

  • Anonymous

    Hi, John.
    I get an error "An EntityKey value cannot be null" when I try to add a record.
    The problem – in generated_code:
    public override object GetIdentity()
    {
    return EntityKey.Create(this._codigo, this._codigoEmpresa, this._codigoFilial, this._tipo);
    }
    The field "_tipo" is null on insert.
    I’m using VS2010 RTM with the latest SL4 tools, but I’m having this problem, which occurs when the primary key contains a field of type string.
    In this fórum forums.silverlight.net/…/404476.aspx "mathewc" explain wich problem is the CodeGen (the generator), but where I can update then?
    Thanks.

  • http://www.appsolo.com/index.php/2010/05/11/ria-services-resources/ Anonymous

    Pingback from RIA Services Resources « Appsolo – News from Appsolo Ltd.

  • Rahul

    It is shocking to see such demos (drag ‘n drop of controls) which is as far removed from real-world design and development as can be.
    I fail to understand why most of the presenters resort to these PROTOTYPING techniques.
    Stop using DomainDataSource in the UI !!

  • Rick

    Where do I go to correct this type of error?
    base type ‘Papa.Common.NotifiableObject’ is not CLS-compliant

  • haiyun

    Question: How to assign a value to a variable in RIA Bussiness application?

%d bloggers like this: