If you are writing some sort of service or application that needs to be able to return
data to clients that originate from a different domain, then JSONP is your friend.
Here is an example jQuery function that makes a request to a server on another domain
expecting a jsonp response back, and using Knockout.js to handle data binding:
$(function () {
$.ajax({
dataType: 'jsonp',
url: 'http;//otherdomain.com/Home/GetEmployees', //Normally this would be a url to an application on a different domain for JSONP
success: function (data) {
var viewModel = {
FirstName: ko.observable(data[0].FirstName),
LastName: ko.observable(data[0].LastName),
Address: ko.observable( data[0].Address),
City: ko.observable (data[0].City),
Region: ko.observable(data[0].Region)
};
ko.applyBindings(viewModel);
}
});
});
jQuery is already set up to handle JSONP requests and results easily, and has supported
JSONP since version 1.2.
One of the easiest ways to handle the return of JSONP - style data in your MVC
applications is to create a "JsonpResult" ActionResult class:
using System;
using System.Text;
using System.Web;
using System.Web.Mvc;
using System.Web.Script.Serialization;
namespace JSONPExample.ActionResults
{
public class JsonpResult : ActionResult
{
public string CallbackFunction { get; set; }
public Encoding ContentEncoding { get; set; }
public string ContentType { get; set; }
public object Data { get; set; }
public JsonpResult(object data) : this(data, null) { }
public JsonpResult(object data, string callbackFunction)
{
Data = data;
CallbackFunction = callbackFunction;
}
public override void ExecuteResult(ControllerContext context)
{
if (context == null) throw new ArgumentNullException("context");
HttpResponseBase response = context.HttpContext.Response;
response.ContentType = string.IsNullOrEmpty(ContentType) ? "application/x-javascript" : ContentType;
if (ContentEncoding != null) response.ContentEncoding = ContentEncoding;
if (Data != null)
{
HttpRequestBase request = context.HttpContext.Request;
var callback = CallbackFunction ?? request.Params["callback"] ?? "callback";
var serializer = new JavaScriptSerializer();
response.Write(string.Format("{0}({1});", callback, serializer.Serialize(Data)));
}
}
}
}
In your Action Method in the controller, you simply go get your data in whatever way your app does this, and then return the data as a JsonpResult rather than as a JsonResult:
public ActionResult GetEmployees()
{
var data = GetDataSomehow();
//constructor overload for overriding callback function:
//return new JsonpResult(data, "callback function");
return new JsonpResult(data);
}
private List<Employee> GetDataSomehow()
{
// Surrogate for getting some data from your database or other store
List<Employee> emps = new List<Employee>();
Employee emp = new Employee()
{
Address = "123 High st.",
BirthDate = DateTime.Parse("2/2/1980"),
FirstName = "Joe",
LastName = "Blow",
City = "Yuma",
Region ="AZ",
Country = "US",
EmployeeID = 1,
HomePhone = "999-999-9999"
};
emps.Add(emp);
return emps;
}
What the ExecuteResult method does is to simply wrap your serialized JSON data in
a javascript function with the name of the requested callback. This returned
script block is then injected direcly into the DOM of the client page, and since
the JSON it contains is legal javascript, it is executed by the browser. jQuery
handles all the dirty work transparently behind the scenes so that as far as
you the developer are concerned, it behaves exactly like any other jQuery $.ajax
call.
You can download the complete Visual Studio 2010 ASP.NET MVC 3 solution, which also has an example of using Knockout.js for databinding.