David Kennedy’s Tech Ramblings

Just another WordPress.com weblog

Silverlight Adventures Part 2 August 26, 2008

Filed under: Silverlight Tutorials — dotnetdave @ 12:29 am

The Grid

Ok, for this exercise we start with a new Silverlight project (you can create this in either Expression Blend or Visual Studio). Next, we want to add a reference to system.windows.controls.data (to make the datagrid control accessible) before dragging the new Silverlight Datagrid control onto the page, producing xaml as follows:

<UserControl xmlns:my="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Data" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" x:Class="SilverGridClient.Page" Width="640" Height="480"> <Grid x:Name="LayoutRoot" Background="White"> <my:DataGrid x:Name="dg" AutoGenerateColumns="True"></my:DataGrid> </Grid> </UserControl>

Next, we want to add a WCF Service project to the solution within VS. As a data source for our grid I’ve opted for a simple LinQ to SQL dbml, so add a new ‘LINQ to SQL Classes’ item to the WCF project. From server explorer, define a connection to any DB that has some data in it, and drag a populated table onto the designer. Since we are passing this type via our WCF service, we need to decorate the generated LinQ classes (in the designer.cs file) with the DataContract attribute. Open the Web.config for the WCF service & ensure that the service endpoint is defined with basicHttpBinding as the binding attribute. Finally, we need to define a method to return data for our grid. In my case I was using a table specifiying documents from a recent project I was involved with, so I added a method as follows:

public List<FreestyleDocument> GetAllDocuments() { SilverLinqDataContext linq = new SilverLinqDataContext("Server=.;Database=Data_DavesJuly;Integrated Security=true"); return linq.FreestyleDocuments.Take(500).ToList(); }

Now build the WCF service.

Next we need to generate a proxy for our service, so we want to add a service reference to our WCF service from the Silverlight project. Kick up the WCF service (or host it in IIS if you prefer) and navigate to the service endpoint from the ‘Add Service Reference’ context option. This will create our proxy as well as a ServiceReferences.ClientConfig file defining the endpoint. Finally, we want to include the call via the proxy to our WCF service method which we have defined in order to populate the grid view. Do this in the Page.xaml.cs file; in my case the code looked like this:

public Page() { //InitializeComponent(); SilverProxy.Service1Client webService = new SilverProxy.Service1Client(); webService.GetAllDocumentsCompleted += new EventHandler<SilverProxy.GetAllDocumentsCompletedEventArgs>(webService_GetUsersCompleted); webService.GetAllDocumentsAsync(); } void webService_GetUsersCompleted(object sender, SilverProxy.GetAllDocumentsCompletedEventArgs e) { dg.ItemsSource = e.Result; }

At this stage it would be possible for the Silverlight application to directly access our WCF service if it weren’t for the browser-side sand-boxing which prevent cross domain calls. Attempting to run the application now will result in something similar to the following error:

An error occurred while trying to make a request to URI ‘http://localhost/SilverService/Service1.svc’. This could be due to a cross domain configuration error. Please see the inner exception for more details.

According to online documentation, this problem should be averted by including one or both of the following configuration override files in the root of the hosting web server (in my case I hosted the service in IIS to make this process simpler):

crossdomain.xml:

<?xml version="1.0"?> <!DOCTYPE cross-domain-policy SYSTEM "http://www.macromedia.com/xml/dtds/cross-domain-policy.dtd"> <cross-domain-policy> <allow-http-request-headers-from domain="*" headers="*"/> </cross-domain-policy>

clientaccesspolicy.xml

<?xml version="1.0" encoding="utf-8" ?> <access-policy> <cross-domain-access> <policy> <allow-from http-request-headers="*"> <domain uri="*"/> </allow-from> <grant-to> <resource path="/" include-subpaths="true"/> </grant-to> </policy> </cross-domain-access> </access-policy>

In my case neither of these files made any difference; I continued to receive the cross domain call error. Failing this approach, the next step is to institute an intermediate proxy on the server side of our Silverlight project, thus negating the cross domain call from the browser. After moving the Linq2Sql ORM & WCF service into the main ASP.NET site which included the Silverlight application the datagrid was bound to the data as expected.

Advertisements
 

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s