Silverlight Networking - Using a proxy to overcome cross-domain-scripting troubles

This is already my fifth article on Silverlight Networking, with only the Credentials in mind. Please read my other articles first:

I ended my last post with the trouble we get by using Javascript for the networking. Javascript doesn't support calling outside the document's domain. I've read through some hacking around this, but the hacks tend to work for a small time because they make use of bugs/holes inside the browsers that will be closed someday. But there's a solution that will work for Javascript.

A proxy is the solution

It's the best solution available for Javascript I think and it works. I'm talking about using some kind of proxy that will fully forward the request and fully return the response. One of the things I think is important to forward is the set of HTTP Headers. I've looked at some proxy code in both .NET and PHP. Some of them just don't forward the Headers. This is important in scenario's where the authorization header is used.

Also I've found some solutions that are fully customized for a specific situation, but I would rather like a more generic solution that can handle any request and response not just the two requests I need now.

I've tested this proxy, written in PHP. It works for me because I've got a Webhost that supports PHP and no ASP.NET. I've looked around to find a possible solution written for ASP.NET. This solution looks promising but you'll have to change it a little bit to forward the Headers also.

The nicest thing about the proxies I've found, is their working. They all work with some kind of querystring parameter. I've changed build a new implementation of the IWebRequestExecutor a to support a proxy. It's a very small class that doesn't do much. It only changes the Uri in a JavascriptWebRequest. A very small addition I think with a lot of effect. You can use ProxyWebRequestExecutor instead of the JavascriptWebRequestExecutor as follows.

1 IWebRequestExecutor requestExecutor = 2 new ProxyWebRequestExecutor("http://.../proxy.php?url={0}"); 3 4 5 var request = new JavascriptWebRequest 6 { 7 Uri = "http://localhost:2851/Test.xml", 8 Method = "GET" 9 }; 10 11 requestExecutor.Execute(request, OnResponse);

This is the implementation of the ProxyWebRequestExecutor.

1 public class ProxyWebRequestExecutor : IWebRequestExecutor 2 { 3 private readonly IWebRequestExecutor innerWebRequestExecutor; 4 private readonly string proxyPattern; 5 6 public ProxyWebRequestExecutor(string proxyPattern) : 7 this(new JavascriptWebRequestExecutor(), proxyPattern) 8 { 9 } 10 11 public ProxyWebRequestExecutor(IWebRequestExecutor innerWebRequestExecutor, 12 string proxyPattern) 13 { 14 if (!proxyPattern.Contains("{0}")) 15 throw new ArgumentException( 16 "The proxyPattern should containt {0} which will be filled with the original request-url.", 17 "proxyPattern"); 18 19 this.innerWebRequestExecutor = innerWebRequestExecutor; 20 this.proxyPattern = proxyPattern; 21 } 22 23 #region IWebRequestExecutor Members 24 25 public void Execute(JavascriptWebRequest request, 26 EventHandler<JavascriptResponseEventArgs> functionToCallOnResponse) 27 { 28 if (!string.IsNullOrEmpty(proxyPattern)) 29 { 30 request.Uri = 31 string.Format(proxyPattern, HttpUtility.UrlEncode(request.Uri)); 32 } 33 innerWebRequestExecutor.Execute(request, functionToCallOnResponse); 34 } 35 36 public void Execute(JavascriptWebRequest request) 37 { 38 Execute(request, null); 39 } 40 41 #endregion 42 }

What's next?

So we now have something that can be used to bypass the limitations of the Silverlight Networking features. At least I have the code, and most of them is published through the different posts. I'm thinking about putting this functionality onto an Open Source site. Please leave a comment if you're interested.