JSONP in ASP.NET MVC 3
When consuming a JSON REST API using AJAX the message is send as a XMLHttpRequest. Due to security reasons this is not allowed cross domain. Instead of returning the data as core JSON, JSONP is often used. The data will then not be parsed by the JSON parser but evaluated by the JavaScript interpreter.
Returning JSONP data does not come out of the box in ASP.NET MVC 3, but you can write a simple wrapper like this:
using System.Web.Mvc;
public class JsonpResult : JsonResult
{
private const string CALLBACK_QUERYSTRING = "callback";
private const string CALLBACK_CONTENTTYPE = "application/x-javascript";
public override void ExecuteResult(ControllerContext controllerContext)
{
if (controllerContext != null)
{
var request = controllerContext.HttpContext.Request;
object callback = request[CALLBACK_QUERYSTRING];
if (callback == null)
{
controllerContext.RouteData.Values.TryGetValue(CALLBACK_QUERYSTRING, out callback);
}
var hasCallback = !string.IsNullOrWhiteSpace(callback ==null ? "" : callback as string);
if (hasCallback)
{
SetContentTypeIfEmpty();
var response = controllerContext.HttpContext.Response;
response.Write(callback);
response.Write("(");
base.ExecuteResult(controllerContext);
response.Write(")");
}
else
{
base.ExecuteResult(controllerContext);
}
}
}
private void SetContentTypeIfEmpty()
{
if (string.IsNullOrWhiteSpace(base.ContentType))
{
base.ContentType = CALLBACK_CONTENTTYPE;
}
}
}
It is now possible to just replace the jsonresult with jsonpresult in the code. If no callback is given it will work as normal.
//return new JsonResult(); return new JsonpResult();
When sending the request GET http://localhost/Website/Products/All?callback=myCallbackFunction the data will be wrapped like this: (same method used in last blogpost)
Asp.NET MVC 3 and JSON
Creating a ASP.NET MVC 3 REST API returning JSON data is actually really simple.
If you have a MVC 3 Visual Studio project template and you add a Controller the default HomeController will be added:
public class HomeController : Controller { public ActionResult Index() { return View(); } }
If you want this Index to return Json data the only thing needed is return JsonResult instead of a View.
//return View(); return new JsonResult();
To give an example I have created a ProductsController returning 3 products with the properties ProductId, Name and Price.
[AcceptVerbs(HttpVerbs.Get)] public JsonResult All() { var data = GetProducts(); return new JsonpResult { Data = data, JsonRequestBehavior = JsonRequestBehavior.AllowGet }; }
Notice that you have to set JsonRequestBehavior.AllowGet. If forgotten you will get the self-explanatory errormessage:
This request has been blocked because sensitive information could be disclosed to third party web sites when this is used in a GET request. To allow GET requests, set JsonRequestBehavior to AllowGet.
When sending the request GET http://localhost/Website/Products/All, the method will return my three products:
(using Chrome with the extension JSONView)
As simple as that ![]()

