Simple ASP.NET MVC Ajax Proxy
February 24, 2009You may find, as you begin to combine the incredible power of jQuery, OpenLayers, and other JavaScript libraries capable of asynchronous (AJAX) behavior, that you want to serve some data to your client side code that doesn’t originate from your ASP.NET MVC application. Most commonly, I imagine, this need arises due to the fact that for security reasons browsers don’t allow AJAX calls to be made to domains external to the web app that served the original web page. The well known solution to this problem is to have your client side code make a request to your web application which will then make the request to the external resource and pass the result back to the client side AJAX request. There are other reasons, besides permitting cross domain AJAX calls, that you may want to use such a proxy. In our case we are hosting a GeoServer instance that serves web maps displaying proprietary, strategic customer spatial data. GeoServer has a relatively limited security model, at least in terms of remote administration, so we wanted to hide the GeoServer instance behind our firewall and layer our own, more sophisticated, role based security.
Whatever your motivations, this is a trivial feature to implement in almost any environment, and ASP.NET MVC is no exception. ASP.NET MVC’s flexible design also makes it possible to implement this kind of proxy in a very reusable, application-developer friendly way, reducing the code required on your controller to a single line. Of course, you could put your proxy in an HTTP (.axd) module and reduce the line count to zero lines of code if you wanted, but you may not want to open up a generic, free for all proxy mechanism to the client, for the same reasons that the cross domain restriction was created in the first place. I stole part of this solution from here. Here’s the code:
public class ProxyResult : ViewResult
{
public ProxyResult(Uri targetUri)
{
TargetUri = targetUri;
}
public ProxyResult(string baseUrl,string queryString)
{
TargetUri = new Uri(baseUrl + "?" + queryString);
}
public Uri TargetUri
{
get; set;
}
public override void ExecuteResult(ControllerContext context)
{
WebRequest proxy = WebRequest.Create(TargetUri);
using (WebResponse proxyResponse = proxy.GetResponse())
{
context.HttpContext.Response.ContentType = proxyResponse.ContentType;
using (Stream proxyResponseStream = proxyResponse.GetResponseStream())
{
StreamHelper.CopyStream(proxyResponseStream, context.HttpContext.Response.OutputStream);
}
}
}
}
public static class StreamHelper
{
public static void CopyStream(Stream input, Stream output)
{
var buffer = new byte[32768];
while (true)
{
int read = input.Read(buffer, 0, buffer.Length);
if (read < = 0)
return;
output.Write(buffer, 0, read);
}
}
}
To provide proxied access to a specific, known url to your client side code via your controller:
public class MapController : SecuredController
{
private readonly string _wmsServerUrl = ConfigurationManager.AppSettings["GeoServerUrl"] + "/wms";
private readonly string _wfsServerUrl = ConfigurationManager.AppSettings["GeoServerUrl"] + "/wfs";
public ActionResult Show()
{
return View("Map");
}
public ProxyResult WmsProxy()
{
return new ProxyResult(_wmsServerUrl, Request.QueryString.ToString());
}
public ProxyResult WfsProxy()
{
return new ProxyResult(_wfsServerUrl, Request.QueryString.ToString());
}
}
And in your client side javascipt code, you simply reference your local web app, and whatever query string would normally be required:
points = new OpenLayers.Layer.WMS(
"Units",
"/Map/WmsProxy",
{
layers: 'hsi:someprivatelayer',
styles: '',
srs: 'EPSG:4326',
format: 'image/png',
tiled: 'true',
tilesOrigin: "143.60260815000004,-43.851764249999995",
transparent: true
},
{
'opacity': 1,
'isBaseLayer': false,
'wrapDateLine': true
}
);






Recently I’ve been doing most of my web browsing using
continue my further explorations in a new tab expecting to go through all the tabs later to read what I want to read or to catalog my findings using
A while ago
philosophical about development practices in the small corner of the blogosphere that I follow. Jimmy Bogard started the ball rolling
So Agile attempts to adjust for this by addressing human need in an interactive way – assess the general outline of the need first, build a little something, see how it fits, make adjustments here and there, fill the general shape of the need, add the detail in layers as it is discovered. It brings to my mind an image of a potters wheel – the clay spins always, an iteration at a time, you shape a vessel first with your fingers, relying as much on tactile feedback as you do your logical understanding. Then you apply detail, little by little, and when it is finished you can fire it in the kiln and paint it, but not before. If you build the detail too soon, it will quickly get rubbed away as the true need emerges, or worse, it will remain because you’ve put the thing in the kiln too soon, but it won’t be appropriate to the piece you’re creating, so you cover it up with fresh clay and fire it again, and you end up with something structurally unsound, or ugly, or altogether useless.







Recent Comments