# Wednesday, August 19, 2009

Microsoft’s Silverlight 3.0 is a great new platform for building line of business applications. With every new technology advancement, we always seem to lose something. With Silverlight we lose the dirt simple data access since Silverlight does not support System.Data.SQLClient and talking to a database directly. This forces us into a service oriented architecture and an asynchronous model. While this is definitely a best practice, it sometimes takes a little getting used to.

With Silverlight we have to wrap up our data access layer into WCF services. (Or Astoria, RIA Services, or something similar.) It is also pretty standard to use some kind of ORM like the Entity Framework or Telerik OpenAccess to map to your database tables and then expose those entities as part of your WCF service. Mapping tables to entities may save you time, however, the part that bothers me is that there is a lot of generic “plumbing” code that has to get written for the WCF service to function.

That is why Telerik created the OpenAccess WCF Wizard. The Telerik OpenAccess WCF Wizard is a tool that will automatically create the C# “plumbing” code and necessary project files for using OpenAccess entities with the following services:

  • Astoria (ADO .NET Data Services)
  • WCF
  • REST Collection Services (WCF REST Starter Kit)
  • ATOM Publishing Services (WCF REST Starter Kit)

Using the wizard is pretty easy. If you already have a project with OpenAccess mapped entities in it, all you have to do is point the wizard to that location and have it generate the scv and .cs files of the WCF service (or Astoria, REST Collection or ATOM Pub service) as shown below. This will eliminate the need for you to write all of the WCF plumbing code.

image

 

We’ll map the Northwind tables and run the wizard and then create a WCF service project. Once you create the service, replace the .cs file with the one generated by the wizard and then create a new Silverlight project (or any project that wants to communicate with your OpenAccess enabled WCF service.) Then set a Service Reference to the WCF service and you can start to consume the it. Your projects in the solution will look like this:

image

Where:

  • OA.WCFWizard.Demo.DAL is the project containing your OpenAccess entities (mapped to Northwind tables).
  • OA.WCFWizard.Demo.SL is the project containing your Silverlight project, including the service reference to your WCF service. (First arrow.)
  • OA.WCFWizard.Demo.WCFService is the project containing the WCF service created by the WCF wizard (second arrow.)
  • OA.WCFWizard.Demo.Web is the asp.net site hosting your Silverlight application

Writing some Silverlight code to consume the WCF service

Consuming the service is pretty easy once you have the service reference set up. We’ll start with some basic XAML, but I will spare you the major XAML details since I am not a XAML expert. Here is my datagrid in XAML, notice that I am using data binding and predefined columns to make life a little easier:

<data:DataGrid x:Name="dataGridCustomers" Grid.ColumnSpan="2" AutoGenerateColumns="False" ItemsSource="{Binding}">
     <data:DataGrid.Columns>
         <data:DataGridTextColumn Binding="{Binding Path=CompanyName}" Header="Company Name"></data:DataGridTextColumn>
         <data:DataGridTextColumn Binding="{Binding Path=ContactName}" Header="Contact Name"></data:DataGridTextColumn>
     </data:DataGrid.Columns>
</data:DataGrid>

When filled, it looks like this:

image

Pretty basic stuff, if you want more advanced looking grids and controls, talk to a designer. :)

Ok, so how can we easily consume this service and bring this data from Northwind via OpenAccess and WCF to the Silverlight grid? Once you have a service reference set up (NorthwindWCFService) in your Silverlight project, you have to do a few things to call it. I created a LoadData() method to contain the code to fill the grid. We can call this on the page load event as well as on the UI with a “refresh” button, or after any “save” method.

Inside of the LoadData() method, first you have to create an instance of the proxy or the “client” as shown in line 4 of the first code block below. Once you have this set up, you then have to register an event for the method you are going to call, as shown on line 6 below. This means that when you call your ReadCustomers method asynchronously the client_ReadCustomersCompleted event handler will fire when the ReadCustomers method is done. This is where you put your binding code (more on that in a second.)  Lastly we have to call our ReadCustomers method, we can only call the asynchronous version of this method as shown in line 9.

   1:  private void LoadData()
   2:  {
   3:      //ref to our service proxy
   4:      NorthwindWCFService.SampleWCFServiceClient wcf = new NorthwindWCFService.SampleWCFServiceClient();
   5:      //register the event handler-can move this up if you want
   6:      wcf.ReadCustomersCompleted += new EventHandler<NorthwindWCFService.ReadCustomersCompletedEventArgs>(client_ReadCustomersCompleted);
   7:      //make an async call to ReadCustomer method of our WCF serice
   8:      //get only the first 100 records (default)
   9:      wcf.ReadCustomersAsync(0, 100);
  10:  }

 

The code for the event handler is pretty straightforward, we just set the datagrid’s DataContext to the e.Result of the event handler. This will contain an ObservableCollection<Customers> that was defined automatically for you via the proxy when you created your service reference.

   1:  void client_ReadCustomersCompleted(object sender, OA.WCFWizard.Demo.SL.NorthwindWCFService.ReadCustomersCompletedEventArgs e)
   2:  {
   3:      dataGridCustomers.DataContext = e.Result; 
   4:  }

 

That is it! I will soon post a video here showing how to do this in more detail as well as an update method since our grid is editable (it is super easy.) Next week I will show some examples using ADO .NET Data Services (Astoria) where the wizard will also automatically create the IObjectScope OpenAccess and Astoria plumbing code for you.