Wednesday, August 24, 2011

How to create a simple proxy in ASP.NET

A common obstruction when developing Silverlight web applications is cross domain access. Silverlight has built-in security that prevents communication to servers that do not explicitly granted access using with either a client access policy or cross domain file. Even though a server has services intended for public use, if the server does not have a cross domain file then Silverlight apps will be denied access.

This post presents a convenient and legitimate way to overcome this restriction with a simple proxy service in three easy steps!

Step 1 – In Visual Studio 2010, create a new ASP.NET Web Application project called WebApplication1

How to create a simple proxy in ASP.NET

Step 2 – Add a new generic handler called proxy.ashx

How to create a simple proxy in ASP.NET

Step 3 – Copy and paste this code into proxy.ashx.cs.

using System;
using System.IO;
using System.Net;
using
System.Web;

namespace
WebApplication1 {
   
public class proxy : IHttpHandler
{
       
public void ProcessRequest(HttpContext
context) {
           
HttpResponse
response = context.Response;

           
// Check for query string
            string uri = Uri
.UnescapeDataString(context.Request.QueryString.ToString());
           
if (string
.IsNullOrWhiteSpace(uri)) {
                response.StatusCode = 403;
                response.End();
               
return
;
            }

           
// Filter requests
            if (!uri.ToLowerInvariant().Contains("
wikimedia.org")) {
                response.StatusCode = 403;
                response.End();
               
return
;
            }

           
// Create web request
            WebRequest webRequest = WebRequest.Create(new Uri
(uri));
            webRequest.Method = context.Request.HttpMethod;

           
// Send the request to the server
            WebResponse serverResponse = null
;
           
try
{
                serverResponse = webRequest.GetResponse();
            }
           
catch (WebException
webExc) {
                response.StatusCode = 500;
                response.StatusDescription = webExc.Status.ToString();
                response.Write(webExc.Response);
                response.End();
               
return
;
            }

           
// Exit if invalid response
            if (serverResponse == null
) {
                response.End();
               
return
;
            }

           
// Configure reponse
            response.ContentType = serverResponse.ContentType;
           
Stream
stream = serverResponse.GetResponseStream();

           
byte[] buffer = new byte
[32768];
           
int
read = 0;

           
int
chunk;
           
while
((chunk = stream.Read(buffer, read, buffer.Length - read)) > 0) {
                read += chunk;
               
if (read != buffer.Length) { continue
; }
               
int
nextByte = stream.ReadByte();
               
if (nextByte == -1) { break
; }

               
// Resize the buffer
                byte[] newBuffer = new byte
[buffer.Length * 2];
               
Array
.Copy(buffer, newBuffer, buffer.Length);
                newBuffer[read] = (
byte
)nextByte;
                buffer = newBuffer;
                read++;
            }

           
// Buffer is now too big. Shrink it.
            byte[] ret = new byte
[read];
           
Array
.Copy(buffer, ret, read);

            response.OutputStream.Write(ret, 0, ret.Length);
            serverResponse.Close();
            stream.Close();
            response.End();
        }
       
public bool
IsReusable {
           
get { return false; }
        }
    }
}

You are done! To test, press F5 to run the web application in debug mode. Your default web browser will display the Default.aspx page from your project.

How to create a simple proxy in ASP.NET

Without closing the web browser, append the name of the proxy service and the web resource (highlighted below) that you need access to. For example:
http://localhost:51220/proxy.ashx?http://upload.wikimedia.org/wikipedia/en/f/f0/New-esri-logo.jpg

This is the result.

How to create a simple proxy in ASP.NET

In summary, this post described how to crate a simple proxy web service. The proxy can be used by Silverlight web application to access resources that are restricted due to a missing cross domain file. To prevent malicious use of the proxy it is advisable to add some sort of access restriction, for example, in this exercise the proxy was configured to only accept requests for content from the wikimedia.org domain.

5 comments:

  1. hi,

    thanks for code.

    how can i send post data to a page on this proxy service.

    ReplyDelete
  2. the solution is that :

    Stream newStream = webRequest.GetRequestStream();
    StreamReader sr = new StreamReader(HttpContext.Current.Request.InputStream);
    byte[] bytes = sr.CurrentEncoding.GetBytes(sr.ReadToEnd());

    newStream.Write(bytes, 0, bytes.Length);
    newStream.Close();
    sr.Close();

    webRequest.ContentType = "text/xml";

    ReplyDelete
  3. @trda. Thanks for the clarification.

    ReplyDelete
  4. Hi,

    Thank you for a highly interesting plog post. I read the question of trda ”How can i send post data to a page on this proxy service.” and your answer. However I cannot interpret your answer and I have some questions I would be most happy if you please could answer:

    (1) What does the new code allow the proxy to do?

    (2) Were in your original published code goes the modification?

    (3) In my application the proxy shall add (optimal) post data. Is that what the code in the Answer does?

    (4) If not, how can this (3) be accomplished?

    (5) Are there any special (know) limitation what calls cannot be made throw the proxy? What about https?

    Most grateful for answers to these questions,

    Ulf L

    ReplyDelete
  5. PS. Sorry, I meant to write “optional” and “known”.

    ReplyDelete