Cross-domain JSONP with jQuery call step-by-step guide
I’ve been banging my head all day to accomplish this, it’s like a puzzle.. but since i get it to work i thought i could write this post for you and myself.
What we want to accomplish?
Simple way to communicate cross-domain with ASMX .NET 3.5 Web Service
How can we do it?
1. Implement a web service method like the following
[ScriptService]
public class JSONP_EndPoint : System.Web.Services.WebService
{
[WebMethod]
[ScriptMethod(UseHttpGet = true,ResponseFormat = ResponseFormat.Json)]
public string Sum(string x,string y)
{
return x + y;
}
}
2. Add New class library with a name ContentTypeHttpModule
The reason for this is no matter how you specify the content-type of your ajax call ASP.NET send the request with Content-Type text/xml; charset=utf-8 this is security feature explained here by ScottGu
3. Add the following code to your Class (Code by Jason i just did a simple modification)
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Web;
namespace ContentTypeHttpModule
{
public class ContentTypeHttpModule : IHttpModule
{
private const string JSON_CONTENT_TYPE = "application/json; charset=utf-8";
#region IHttpModule Members
public void Dispose()
{
}
public void Init(HttpApplication app)
{
app.BeginRequest += OnBeginRequest;
app.ReleaseRequestState += OnReleaseRequestState;
}
#endregion
public void OnBeginRequest(object sender, EventArgs e)
{
HttpApplication app = (HttpApplication)sender;
HttpRequest resquest = app.Request;
if (!resquest.Url.AbsolutePath.Contains("JSONP-EndPoint.asmx")) return;
if (string.IsNullOrEmpty(app.Context.Request.ContentType))
{
app.Context.Request.ContentType = JSON_CONTENT_TYPE;
}
}
public void OnReleaseRequestState(object sender, EventArgs e)
{
HttpApplication app = (HttpApplication)sender;
HttpResponse response = app.Response;
if (app.Context.Request.ContentType != JSON_CONTENT_TYPE) return;
response.Filter = new JsonResponseFilter(response.Filter);
}
}
public class JsonResponseFilter : Stream
{
private readonly Stream _responseStream;
private long _position;
public JsonResponseFilter(Stream responseStream)
{
_responseStream = responseStream;
}
public override bool CanRead { get { return true; } }
public override bool CanSeek { get { return true; } }
public override bool CanWrite { get { return true; } }
public override long Length { get { return 0; } }
public override long Position { get { return _position; } set { _position = value; } }
public override void Write(byte[] buffer, int offset, int count)
{
string strBuffer = Encoding.UTF8.GetString(buffer, offset, count);
strBuffer = AppendJsonpCallback(strBuffer, HttpContext.Current.Request);
byte[] data = Encoding.UTF8.GetBytes(strBuffer);
_responseStream.Write(data, 0, data.Length);
}
private string AppendJsonpCallback(string strBuffer, HttpRequest request)
{
return request.Params["callback"] +"(" + strBuffer + ");";
}
public override void Close()
{
_responseStream.Close();
}
public override void Flush()
{
_responseStream.Flush();
}
public override long Seek(long offset, SeekOrigin origin)
{
return _responseStream.Seek(offset, origin);
}
public override void SetLength(long length)
{
_responseStream.SetLength(length);
}
public override int Read(byte[] buffer, int offset, int count)
{
return _responseStream.Read(buffer, offset, count);
}
}
}
4. Register the HttpModule in the service project
4.1 Add referance to the HttpModule assembly to the service project
4.2 Add this code to web.config to register the module
<add name="ContentTypeHttpModule"
type="ContentTypeHttpModule.ContentTypeHttpModule, ContentTypeHttpModule" />
This goes under system.web / httpmodules section
5. Add a web project for testing the application
5.1 add the following libs
jquery-1.3.1.js
json2.js
5.2 add new script file caller.js
function test() {
$.ajax({ url: "http://localhost:1690/JSONP-EndPoint.asmx/Sum",
data: { x: JSON.stringify("Now i am getting jsop string"), y: JSON.stringify("2nd param") },
dataType: "jsonp",
success: function(json) {
alert(json.d);
},
error: function() {
alert("Hit error fn!");
}
});
}
5.3 Add referances to jquery-1.3.1.js and json2.js
5.4 Add Default.aspx page with input button that has onclick=”return test();”
6. Remarks
6.1 I use the JSON.stringify function to serialize the string data parameters.
6.2 .d is a security features on ASP.NET 3.5