Tuesday, March 1, 2011

Debugging Silverlight web-resources that connect to CRM Online.

Debugging Silverlight web-resources in CRM 2011 can be pretty tedious when you have to constantly re-upload your XAP file to the CRM server and then manually attach the debugger to the IE process. If you run the Silverlight application from your own development machine (using the ASP.NET Development server) you can quickly start debugging by hitting F5 in Visual Studio, but the app won't be able to make any requests to the CRM server because of Silverlight's cross-domain restrictions.

If you have an on-premise CRM server you can get around the cross-domain restrictions by putting a ClientAccessPolicy.xml file in the root of the CRM web application (See Markus Konrad's post on creating the policy file), but CRM online won't let you upload a ClientAccessPolicy, so you have to be a little more clever.  One method is to just create a proxy to pass all the requests to the CRM server.

Creating a proxy for CRM SOAP requests
A quick note: This works for the SOAP Organization service and the example at the end of this post only uses the SOAP service. I'm not sure if a similar proxy would work for the REST endpoint  (Given the REST endpoint's limitation I rarely use it anyway).

To get web-service requests to go from a Silverlight application w just need a few things:
1. Create an aspx page in the web project that's hosting the Silverlight app that will act as our proxy.
2. Program the proxy page to forward all posted requests to the CRM Online web-service endpoint.
3. Authenticate against CRM Online and attach the LiveId security token to each request.
4. Configure the Silverlight app to point to the proxy page.

Steps 1 and 2 are actually pretty straightforward once you pull out fiddler and figure out what the soap requests work like. Step 3 is the complicated bit but the sample code in the CRM SDK provides an example of authenticating against CRM Online (see sdk\samplecode\cs\wsdlbasedproxies\online). Once you've authenticated and have the security token you can just inject the token right into the header of the SOAP request.

I've built an example application which you can download here.  It's just a simple Silverlight application that makes create, retrieve, update, delete, and execute request to CRM Online using the proxy described above.

To try it out just update the constants defined at the top of Proxy.aspx.cs:
//Update these constants to match your CRM Online account
const string host = "orgName.api.crm.dynamics.com";
const string userName = "erik.pool@example.com";
const string password = "Password";

Also note the GetOrganizationService method in the Silverlight app. If the current page is running on "localhost" it assumes you're debugging and points the org service url at the proxy.aspx page.  This way the same silverlight app works on my dev machine and when it's deployed to CRM Online.

if (href.Contains("localhost"))
   Uri baseUrl = new Uri(href, UriKind.Absolute);
   orgServiceUrl = new Uri(baseUrl, "SoapProxy/Proxy.aspx");
   orgServiceUrl = new Uri(location.GetProperty("protocol") + "//" + location.GetProperty("host") + "/xrmservices/2011/organization.svc/web");

Download the source code here.