Have you ever absolutely needed to do an AJAX call to another domain? Here is a way to do it (non-secure). Basically, we create a new IHttpHandler
that listens for a request. It takes a single QueryString
parameter, "url
". It then passes the request on to the given destination. It supports all HTTP Methods (GET
, PUT
, HEAD
, POST
, etc.).
First, create a new class that implements IHttpHandler
as follows:
CrossDomainHandler.ashx.cs
using System;
using System.Globalization;
using System.IO;
using System.Net;
using System.Web;
namespace CrossDomain
{
public class CrossDomainHandler : IHttpHandler
{
public CrossDomainHandler()
{
}
public void ProcessRequest(HttpContext context)
{
try
{
string url = context.Request.QueryString["url"];
HttpWebRequest request = WebRequest.Create(url) as HttpWebRequest;
request.Headers.Clear();
foreach (string key in context.Request.Headers.AllKeys)
{
string value = context.Request.Headers[key];
if (string.Compare(key, "Connection", true, CultureInfo.InvariantCulture) == 0)
{
if (string.Compare(value, "Keep-Alive", true, CultureInfo.InvariantCulture) == 0)
{
request.KeepAlive = true;
}
else if (string.Compare(value, "Close", true,
CultureInfo.InvariantCulture) == 0)
{
request.KeepAlive = false;
}
else
{
request.Connection = value;
}
}
else if (string.Compare(key, "Content-Length", true,
CultureInfo.InvariantCulture) == 0)
{
int length = Convert.ToInt32(value);
if (length > 0)
{
request.ContentLength = length;
}
}
else if (string.Compare(key, "Accept", true,
CultureInfo.InvariantCulture) == 0)
{
request.Accept = value;
}
else if (string.Compare(key, "Content-Type", true,
CultureInfo.InvariantCulture) == 0)
{
request.ContentType = value;
}
else if (string.Compare(key, "Date", true,
CultureInfo.InvariantCulture) == 0)
{
}
else if (string.Compare(key, "Expect", true,
CultureInfo.InvariantCulture) == 0)
{
request.Expect = value;
}
else if (string.Compare(key, "Host", true,
CultureInfo.InvariantCulture) == 0)
{
}
else if (string.Compare(key, "If-Modified-Since",
true, CultureInfo.InvariantCulture) == 0)
{
request.IfModifiedSince = DateTime.Parse(value);
}
else if (string.Compare(key, "Proxy-Connection", true,
CultureInfo.InvariantCulture) == 0)
{
}
else if (string.Compare(key, "Range", true,
CultureInfo.InvariantCulture) == 0)
{
}
else if (string.Compare(key, "Referer", true,
CultureInfo.InvariantCulture) == 0)
{
request.Referer = value;
}
else if (string.Compare(key, "Transfer-Encoding", true,
CultureInfo.InvariantCulture) == 0)
{
request.TransferEncoding = value;
}
else if (string.Compare(key, "User-Agent", true,
CultureInfo.InvariantCulture) == 0)
{
request.UserAgent = value;
}
else
{
request.Headers.Add(key, value);
}
}
request.Method = context.Request.HttpMethod;
if (context.Request.ContentLength > 0)
{
CopyStream(context.Request.InputStream,
request.GetRequestStream(), 512);
}
using (HttpWebResponse response =
request.GetResponse() as HttpWebResponse)
{
context.Response.ClearHeaders();
context.Response.ClearContent();
foreach (string key in response.Headers.AllKeys)
{
context.Response.AddHeader(key, response.Headers[key]);
}
if (response.ContentLength > 0)
{
CopyStream(response.GetResponseStream(),
context.Response.OutputStream, 512);
}
}
}
catch (Exception ex)
{
context.Response.Write(ex);
}
}
public bool IsReusable
{
get
{
return false;
}
}
private static void CopyStream(Stream input,
Stream output, int bufferSize)
{
byte[] buffer = new byte[bufferSize];
int count = 0;
while ((count = input.Read(buffer, 0, buffer.Length)) > 0)
{
output.Write(buffer, 0, count);
}
}
}
}
CrossDomainHandler.ashx
<%@ WebHandler Class="CrossDomain.CrossDomainHandler,CrossDomain" %>
Use it as follows:
if (typeof XMLHttpRequest == "undefined") XMLHttpRequest = function() {
try { return new ActiveXObject("Msxml2.XMLHTTP.6.0") } catch(e) {}
try { return new ActiveXObject("Msxml2.XMLHTTP.3.0") } catch(e) {}
try { return new ActiveXObject("Msxml2.XMLHTTP") } catch(e) {}
try { return new ActiveXObject("Microsoft.XMLHTTP") } catch(e) {}
throw new Error("This browser does not support XMLHttpRequest.")
};
var req = new XMLHttpRequest();
req.open('GET', 'CrossDomainHandler.ashx?url=http%3A%2F%2Fwww.google.com%2F', false);
alert(req.responseText);
Or, extend the Prototype JS Framework:
CrossDomainAjax.js
Ajax.CrossDomainRequest = Class.create(Ajax.Request, {
initialize: function($super, url, handlerUrl, options) {
this.handlerUrl = handlerUrl;
$super(url, options);
},
request: function($super, url) {
this.url = url;
if (!this.isSameOrigin())
url = this.handlerUrl + '?url=' + encodeURIComponent(url);
$super(url);
}
});
To use:
<script type="text/javascript">
var mine = new Ajax.CrossDomainRequest('http://www.google.com/',
'CrossDomainHandler.ashx', {
method: 'head',
onSuccess: function(transport) {
$('mine').value = transport.getAllResponseHeaders();
}
});
</script>
Hope this helps…