Using the ADO.NET Data Services Silverlight client in x-domain and out of browser scenarios – I

DB Blogs

With the release of ADO.NET Data Services v1.5 CTP2, you can now use the Silverlight Astoria client library to access Cross-Domain services
and applications written with the new client library can go out of browser.

The new Client Http networking stack introduced in SL3 supports the standard and custom HTTP Verbs(GET/PUT/POST/DELETE/MERGE)
as well as access to the response status codes required for a full fidelity REST-based client experience in Silverlight.
Working with the SL networking team, we modified the Astoria client library to use the networking stack
in cross-domain and out-of-browser scenarios.
With this change, we are now able to support Cross-Domain calls allowed by ClientAccessPolicy.xml files
and applications written with the Silverlight Astoria client library can go Out Of Browser.

I have an existing SL app based on the Astoria client library , what do I need to do to enable my application to
access X-Domain Data Services and go Out Of Browser ?

1. Recompile your application with a reference to the new Silverlight client library .
2. Update the URI of the Data Service to point to the absolute URI of the Data Service in its new location.
3. Drop a ClientAccessPolicy.xml file into the root of the Webserver Hosting your Data Service.
4. Deploy the newly created application to the Webserver.
5. In your Silverlight application code, find all the places that you call EndExecute/EndSaveChanges/EndExecuteBatch
and check if the call is being marshaled back to the UI thread , else Silverlight will throw an invalid Cross-Thread Access Exception.
To fix this, always dispatch the call to EndExecute to the UI thread using Dispatcher.BeginInvoke.
As an example:

nwContext.BeginExecute<Customers>(new Uri("Customers"),
(asResult) =>
{
 Dispatcher.BeginInvoke(
   () =>{
   CustomersGrid.ItemsSource = nwContext.EndExecute<Customers>(asResult).ToList();
   }
   );                     
}, someUserState);

.csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, “Courier New”, courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; }

Now , let’s walk through a demo application that illustrates how to build a Silverlight application
that accesses an ADO.NET Data Service from a different domain than the Silverlight application and can also run Out-Of-Browser.

We have a sample Silverlight application that looks like this :

Now , let’s walk through a demo application that illustrates how to build a Silverlight application
that accesses an ADO.NET Data Service from a different domain than the Silverlight application and can also run Out-Of-Browser.

We have a sample Silverlight application that looks like this :

clip_image002

1. SilverlightApplicationHost is the Web application hosting your Silverlight XAP , think of this as UI.Foo.Com.
2. DataServiceHost is the web application hosting the ADO.NET Data Service , think of this as API.Foo.Com

3. DataServicesXDomainSLClient is the Silverlight application that runs in UI.Foo.Com and consumes the Data Service from API.Foo.Com.

Since the DataServiceHost site hosts the Data Service, it also hosts the ClientAccessPolicy.xml file which allows apps from the
domain hosting the Silverlight app to access resources hosted at API.Foo.com

clip_image002[8]

The Silverlight application, DataServicesXDomainSLClient, has a Service Reference to the Data Service hosted at DataServiceHost.
It has two buttons which download an Entity Set called “Publications” from the Data Service and looks like this.

clip_image001

The “Load Publications Via Uri” downloads Entities from the “Publications” entity set and the Click handler looks like this :

void btnLoadPublications_Click(object sender, RoutedEventArgs e)
{
object userState = null;
//download the Publications and sort the Publications in descending order of Name
publicationContext.BeginExecute<Publication>(
  new Uri("/Publications?$expand=PublishedFrom&$orderby= Name desc", UriKind.Relative),
(asResult) =>
  {
  //Dispatch the EndExecute call to the UI thread
  Dispatcher.BeginInvoke(
   () =>
   {
     var IEnumerableOfPublications = publicationContext.EndExecute<Publication>(asResult);
     PublicationsGrid.ItemsSource = IEnumerableOfPublications.ToList();
   }
   );
   }, userState);
}

The “Load Publications Via Linq” downloads entities via a Linq Query and the Click Handler looks like this :

void btnLoadPublicationsLinq_Click(object sender, RoutedEventArgs e)
{
 object userState = null;
 //download the Publications and sort the Publications in ascending order of Name
 var publicationLinqQuery = (from pub in 
publicationContext.CreateQuery<Publication>("Publications")
.Expand("PublishedFrom") orderby pub.Name ascending select pub) as DataServiceQuery<Publication>; publicationLinqQuery.BeginExecute( (asResult) => { //Dispatch the EndExecute call to the UI thread Dispatcher.BeginInvoke( () => { var IEnumerableOfPublications = publicationLinqQuery.EndExecute(asResult); PublicationsGrid.ItemsSource = IEnumerableOfPublications.ToList(); }); }, userState); }

.csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, “Courier New”, courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; }

.csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, “Courier New”, courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; }

.csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, “Courier New”, courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; }

Clicking the “Install Me” button installs the app and launches it Out Of Browser.
Here is what the “Install Me” button click handler looks like :

/// <summary>
/// Installs the Silverlight application as an Out Of Browser application
/// </summary>
void InstallApplication(object sender, RoutedEventArgs e)
{
  //Install the app
  App.Current.Install();
  //Hide the "Install Me" button
  btnInstallOOBApp.Visibility = Visibility.Collapsed;
 }

.csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, “Courier New”, courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; }

.csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, “Courier New”, courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; }

The buttons which do a Linq Query and a URI query still work , without any changes to the code .
clip_image001[8]

Debugging Out Of Browser Silverlight Applications

To debug your Out Of Browser Silverlight apps , follow these steps.

1.  Open the properties of the Silverlight application.

clip_image002[10]

2. Select the Out Of Browser application which has the name of the project with the Page hosting the SL application.
Which , in this case , is SilverlightApplicationHost.

clip_image002[12]

3. Hit F5 and select yes when this prompt comes up.
This prompt is warning you that you have a Service Reference to a Data Service.

In In-Browser Silverlight apps , running the SL app directly will launch it off of the file system ( i.e c:ProjectsyourProjectPath),

and you wont be able to make calls to data services  as this would constitute a Cross-Scheme request and isn’t allowed.

While debugging your Out Of Browser Silverlight application, you can ignore this prompt.

clip_image004

Is the SL3 Client HTTP stack used by the ADO.NET Data Services v1.5 CTP2 client library for all requests?

No, the SL3 Client Http Stack is only used for Out-Of-Browser and Cross-domain network access.
The XmlHttp based stack is still used for In Browser, Same Domain network access to preserve backward compatibility.

You can customize this by setting a new property on the client library called HttpStack.

HttpStack which has 3 possible values:

1. Auto: Client library decides when to switch networking stacks.

2. XmlHttp: The classic networking stack based on XmlHttpRequest

3. ClientHttp: The new SL3 Client HTTP  stack

The Default value is Auto, and you should leave it as it is, unless you need to customize the networking stack we use.
When the HttpStack is set to Auto, the client library automatically switches the networking stack it uses to talk to

the Data Service.

Should I set the HttpStack on the DataServiceContext instance so that I get X-Domain and OOB data access?

Nope, you can just leave the HttpStack property at Auto and we will figure out which stack to use and when.

We use XmlHttp only in a scenario where the Silverlight XAP and the Data Service are hosted in the same domain.

For other scenarios we use the ClientHttpStack. The below table is helpful in understanding when we automatically switch stacks.

 

Silverlight App

Data Service

Out Of Browser

Networking stack

http://foo.com

http://foo.com

False

XmlHttp                    

http://foo.com

http://foo.com

True

ClientHttp

http://UI.foo.com

http://API.foo.com

False/True

ClientHttp

Features VS Networking Stack

Feature

XmlHttp

ClientHttp

Cross Domain Data Access

No

Yes

Out Of Browser Data Access

No

Yes

NTLM Based Authentication

Yes

No*

Same Domain Data Access

Yes

Yes

Cookie Based Authentication

Yes

Yes

Cookie store shared with browser

Yes

No*

*We are working over the next few releases of Silverlight to extend the ClientHttp stack such that it supports
all possible scenarios.

Authentication Schemes supported

With the new networking stack, in X-Domain and OOB scenarios, the client library is now restricted to the same options as any other application that uses the SL3 networking stack.
The main concern is that NTLM based authentication schemes such as Windows Authentication or BASIC Authentication are not supported in X-Domain and Out Of Browser scenarios.

The only authentication schemes that are supported are cookie-based authentication schemes such as ASP.NET Forms Authentication.

An example of using the new client library with ASP.NET Forms Authentication will be shown in Part II of this blog post.

You can download the sample application shown here at the bottom of the post.

Phani Raj
Engineer, ADO.NET Data Services .

0 comments

Discussion is closed.

Feedback usabilla icon