Silverlight to WCF Cross Domain SecurityException

In debugging a fairly simple Silverlight control that calls into a WCF service I ran into an often encountered security exception having to do with cross-domain policy. Silverlight generally does not allow cross domain access unless that access is explicitly granted via a clientaccesspolicy.xml file. Given that I had to read through several sources (see References below) to formulate a solution to this problem, I decided to pull those sources of information together here for future reference.

The Problem

I originally ran into the following dialog when trying to debug my main solution which consists of a couple of nested WCF services and a Silverlight application hosted in a web app (the control makes a call to one of the services which in turn makes a call to the other service).

Here is the exception:

CommunicationException

And the text:

Communication exception was unhandled by user code

An error occurred while trying to make a request to URI ‘http://localhost:7249/Service1.svc’. This could be due to attempting to access a service in a cross-domain way without a proper cross-domain policy in place, or a policy that is unsuitable for SOAP services. You may need to contact the owner of the service to publish a cross-domain policy file and to ensure it allows SOAP-related HTTP headers to be sent. This error may also be caused by using internal types in the web service proxy without using the InternalsVisibleToAttribute attribute. Please see the inner exception for more details.

Examining the inner exception, I found:

{System.Security.SecurityException —> System.Security.SecurityException: Security error.
at System.Net.Browser.BrowserHttpWebRequest.InternalEndGetResponse(IAsyncResult asyncResult)
at System.Net.Browser.BrowserHttpWebRequest.<>c__DisplayClass5.<EndGetResponse>b__4
(Object sendState)
at System.Net.Browser.AsyncHelper.<>c__DisplayClass2.<BeginOnUI>b__0(Object sendState)
— End of inner exception stack trace —
at System.Net.Browser.AsyncHelper.BeginOnUI(SendOrPostCallback beginMethod, Object state)
at System.Net.Browser.BrowserHttpWebRequest.EndGetResponse(IAsyncResult asyncResult)
at System.ServiceModel.Channels.HttpChannelFactory.HttpRequestChannel.
HttpChannelAsyncRequest.CompleteGetResponse(IAsyncResult result)}

Given the somewhat complicated structure of the overall application, I decided to take a step back and create a very simple solution that contains a Silverlight app, its associated web hosting app, and a WCF service called “Service1”. I then added a service reference to “Service1” to the Silverlight app and ran the project. That got me back to the above CommunicationException. Good.

The Solution

There’s a lot of potential solutions to this problem (or so it seemed as I was working through it). What worked for me was adding a “clientaccesspolicy.xml” file to the root of the WCF service project. Here’s the contents of that file (and note that the name of the file is important as that is what Silverlight will look for by default):

<?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>

This grants access across the board with no restrictions.

When I re-run the application it works as expected.

But, wait, there’s more…

One other issue I had was with the VS Dev Web Server using a virtual path like:

http://localhost:7249/MyService/Service1.svc

This can happen if you have folders inside your solution, for example. The problem is that Silverlight is looking for clientaccesspolicy.xml in the root folder of the service but it now exists in MyService. Fortunately, there’s an easy way to correct this.

Thanks to Tim Heuer for the solution which is to examine Properties on the WCF service project:

image

The solution then is to remove the folder designation so the virtual path contains the root slash only:

image

 

I re-ran again and everything works.