I am having some troubles with understanding the circumstances under which Silverlight downloads a clientaccesspolicy.xml file. I have a few complications to the runtime environment that need explaining.
This is an Azure web app, running in full IIS mode in dev fabric. There are two sites defined, App and Admin. Since they are both on port :80, they are accessed via host headers, app.dev.com and admin.dev.com, both of which have entries in my HOSTS file pointing back to 127.0.0.1. Accessing both of the client apps is working fine. Silverlight loads, and hits the RIA services defined, no problem.
Things get tricky when the Silverlight client tries to access a blob from dev storage. The problem has been explained before so I won’t go too deep–bottom line, you can’t put the XML file in the root of the web because of how dev storage works (it goes to http://127.0.0.1:10000/devstoreaccount1/clientaccesspolicy.xml). The solution is a reverse proxy to remap the URL–I’ve done it with a Fiddler rule. What this does is “if a request comes in for 127.0.0.1:11000, modify that request to :10000 and GET that instead,” etc.
if (oSession.host == "127.0.0.1:11000") {
oSession.host = "127.0.0.1:10000";
}
if (oSession.url == "127.0.0.1:10000/clientaccesspolicy.xml") {
oSession.url = "127.0.0.1:10000/devstoreaccount1/clientaccesspolicy.xml";
}
This works as far as remapping is concerned; I can hit http://127.0.0.1:11000/clientaccesspolicy.xml in my browser and get the file actually living at 127.0.0.1:10000/devstoreaccount1/clientaccesspolicy.xml:
<?xml version="1.0" encoding="utf-8"?>
<access-policy>
<cross-domain-access>
<policy>
<allow-from http-methods="*" http-request-headers="*">
<domain uri="*" />
</allow-from>
<grant-to>
<resource path="/" include-subpaths="true" />
</grant-to>
</policy>
</cross-domain-access>
</access-policy>
Then this fails from a Silverlight client accessed at http://app.dev.com:81/default.aspx (which to remind you, is remapped to 127.0.0.1 in HOSTS)
private void DownloadFile()
{
var sampleUri = new Uri("http://127.0.0.1:11000/devstorageaccount1/mycontainer/myblob.bin");
var client = new WebClient();
client.OpenReadCompleted += blobDownloaded;
client.OpenReadAsync(sampleUri);
}
void blobDownloaded(object sender, OpenReadCompletedEventArgs e)
{
if (e.Error != null) throw e.Error;
//throws
}
with exception
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)
Looking in Fiddler, the clientaccesspolicy.xml file was NOT downloaded! I have no idea why, or how to debug it. I can download the blob from my browser. Can anyone explain why this would throw before even downloading the XML file?
Then I tried updating those Fiddler rules:
if (oSession.host == "app.dev.com:10000") {
oSession.host = "127.0.0.1:10000";
}
if (oSession.url == "127.0.0.1:10000/clientaccesspolicy.xml") {
oSession.url = "127.0.0.1:10000/devstoreaccount1/clientaccesspolicy.xml";
}
and changing the URL to download to
var sampleUri = new Uri("http://app.dev.com:10000/devstorageaccount1/mycontainer/myblob.bin");
And this one succeeds! The Fiddler capture shows the clientaccesspolicy.xml file downloaded first and the blob second.
Can anyone help explain what’s going on here? In both cases the Silverlight app is being access at http://app.dev.com:81/default.aspx. When it tries to download a blob from http://127.0.0.1:11000 it fails with a SecurityException without first downloading clientaccesspolicy.xml. But when it downloads a blob from http://app.dev.com:10000 it succeeds, first downloading clientaccesspolicy.xml and then the blob.
Thanks for the help, this one has me stumped.
Traffic to 127.0.0.1 usually skips the proxy, so I would imagine Fiddler simply wasn’t getting the chance to rewrite the URL. You could probably point Silverlight at ipv4.fiddler instead and get it to work.