When we built the client library for Silverlight in Silverlight 2.0 , the underlying Network Stack provided by Silverlight core libraries was very limited in terms of the Status Codes and Request Verbs that it supported.Our options were : a) Use the System.Net libraries provided by the agClr and give a limited subset of the functionality available on the desktop. b) Cook up our own Network stack and provide all the functionality provided on the desktop , in Silverlight.
We went with Option (b) and built a network stack that uses the browser’s underlying XmlHttpRequest object. This means that the cross domain access available in Silverlight networking stack is not available in our networking stack. Forums user Ben Hayat asked a question about the guidelines for Cross-Domain access using our Silverlight Client Library .
Now , this is not supported out of the box . But ,you can use the same solution as you would for an Ajax application , which is building a server-side proxy that talks to the remote service and is completely transparent to the client library. Below is a sample Server-Side proxy that would help one talk to Data Services hosted on a different domain than the Silverlight application. There are a couple of issues that a Server-Side proxy needs to solve for an ADO.NET Data Service , a) Appear totally transparent b) Resolve Identities of resources to appear as they would from the Proxy service and not the original Data Service. Issue a) is easy , Issue b) is a little more involved. When the client library receives a Payload back as part of a query ,we construct the entity’s identity based on the following rules, ex: If you browse to http://ServiceEndpoint/Northwind.svc/Customers('ALFKI') ,the response looks like this :
<entry xml:base="http://ServiceEndpointNorthwind.svc/" xmlns:d="http://schemas.microsoft.com/ado/2007/08/dataservices" xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata" xmlns="http://www.w3.org/2005/Atom"> <link rel="edit" title="Customers" href="Customers('ALFKI')" /> <id>http://ServiceEndpointNorthwind.svc/Customers('ALFKI')</id> <content type="application/xml"> <m:properties> Properties go here </m:properties> </content> </entry>
When we get the above payload back as a response , we create a Customer object and its identity is the value of the <id> field in the payload. When you make any edits to this Customer object, the edits are sent to the URI specified in the <link rel=”edit”> value of the payload. Which means that the proxy server has to modify the payload it recieves from the real Data Service to make sure that all links , Id and Edit point to the proxy Data Service and not the real Data Service. The easiest way to do this is to do a String.Replace replacing all occurrences of the the original Service end point with the Proxy Service end point in the payload.
Without further stalling , here is the Proxy Handler.
The Cross Domain Proxy is a generic AShx handler which receives the requests from the Client library and forwards them onto the original Data Service , gets the response , changes the ID and Edit Links and returns the response to the Silverlight Client .
The source available for download contains “CrossDomainHandlerBase” which is the class that contains the functionality required for recieving requests from clients and forwarding the requests onto the Data Service.
2. This will create a Generic Handler which implements IHttpHandler.
3. Remove the code stubs for IHttpHandler methods and properties . 4. Replace IHttpHandler with “CrossDomainHandlerBase”.
[WebService(Namespace = "http://tempuri.org/")] [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)] public class CrossDomainHandler : CrossDomainHandlerBase { public CrossDomainHandler() : base() { this.DataServiceURI = "URI FOR THE DATA SERVICE"; this.ProxyServiceURI = "URI FOR THE PROXY SERVICE"; } }
4.From this point on , for all purposes , the Proxy Handler service IS the Data Service
DataProvider dataProvider = new DataProvider( new Uri("RELATIVE URI FOR THE PROXY SERVICE", UriKind.RelativeOrAbsolute) );
To do in the near future :
PingBack from http://castironbakeware.info/story.php?title=with-great-power-comes-great-response-write-ability-accessing
Hi,
Thanks for posting the workaround. I am able to use the workaround to get the data. But, I am receiving error when i insert data. Error is 'The expected content type for a batch requests is "multipart/mixed;boundary=batch" not "application/atom+xml; charset=utf-8'.
I am using following call to insert object
context.BeginSaveChanges(SaveChangesOptions.Batch , new AsyncCallback(Save_Complete), null);
In my Save_Complete method, it throws error at following point
DataServiceResponse response = (DataServiceResponse)context.EndSaveChanges(result);
Any idea how to make it work?
Hi Govind,
With the release of CTP2 , this workaround is no longer needed.
Please refer to this blog post :
http://blogs.msdn.com/astoriateam/archive/2009/09/03/using-the-ado-net-data-services-silverlight-client-in-x-domain-and-out-of-browser-scenarios-i.aspx
PhaniRaj