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
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 project4.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 libsjquery-1.3.1.jsjson2.js5.2 add new script file caller.jsfunction 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.js5.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