ASP.net MVC returning JSONP ASP.net MVC returning JSONP json json

ASP.net MVC returning JSONP


Here is a simple solution, if you don't want to define an action filter

Client side code using jQuery:

  $.ajax("http://www.myserver.com/Home/JsonpCall", { dataType: "jsonp" }).done(function (result) {});

MVC controller action. Returns content result with JavaScript code executing callback function provided with query string. Also sets JavaScript MIME type for response.

 public ContentResult JsonpCall(string callback) {      return Content(String.Format("{0}({1});",          callback,           new JavaScriptSerializer().Serialize(new { a = 1 })),              "application/javascript"); }


Rather than subclassing my controllers with Jsonp() methods, I went the extension method route as it feels a touch cleaner to me. The nice thing about the JsonpResult is that you can test it exactly the same way you would a JsonResult.

I did:

public static class JsonResultExtensions{    public static JsonpResult ToJsonp(this JsonResult json)    {        return new JsonpResult { ContentEncoding = json.ContentEncoding, ContentType = json.ContentType, Data = json.Data, JsonRequestBehavior = json.JsonRequestBehavior};    }}

This way you don't have to worry about creating all the different Jsonp() overloads, just convert your JsonResult to a Jsonp one.


Ranju's blog post (aka "This blog post I found") is excellent, and reading it will allow you to further the solution below so that your controller can handle same-domain JSON and cross-domain JSONP requests elegantly in the same controller action without additional code [in the action].

Regardless, for the "give me the code" types, here it is, in case the blog disappears again.

In your controller (this snippet is new/non-blog code):

[AllowCrossSiteJson]public ActionResult JsonpTime(string callback){    string msg = DateTime.UtcNow.ToString("o");    return new JsonpResult    {        Data = (new        {            time = msg        })    };}

JsonpResult found on this excellent blog post:

/// <summary>/// Renders result as JSON and also wraps the JSON in a call/// to the callback function specified in "JsonpResult.Callback"./// http://blogorama.nerdworks.in/entry-EnablingJSONPcallsonASPNETMVC.aspx/// </summary>public class JsonpResult : JsonResult{    /// <summary>    /// Gets or sets the javascript callback function that is    /// to be invoked in the resulting script output.    /// </summary>    /// <value>The callback function name.</value>    public string Callback { get; set; }    /// <summary>    /// Enables processing of the result of an action method by a    /// custom type that inherits from <see cref="T:System.Web.Mvc.ActionResult"/>.    /// </summary>    /// <param name="context">The context within which the    /// result is executed.</param>    public override void ExecuteResult(ControllerContext context)    {        if (context == null)            throw new ArgumentNullException("context");        HttpResponseBase response = context.HttpContext.Response;        if (!String.IsNullOrEmpty(ContentType))            response.ContentType = ContentType;        else            response.ContentType = "application/javascript";        if (ContentEncoding != null)            response.ContentEncoding = ContentEncoding;        if (Callback == null || Callback.Length == 0)            Callback = context.HttpContext.Request.QueryString["callback"];        if (Data != null)        {            // The JavaScriptSerializer type was marked as obsolete            // prior to .NET Framework 3.5 SP1 #pragma warning disable 0618            JavaScriptSerializer serializer = new JavaScriptSerializer();            string ser = serializer.Serialize(Data);            response.Write(Callback + "(" + ser + ");");#pragma warning restore 0618        }    }}

Note: Following up on the comments to the OP by @Ranju and others, I figured it was worth posting the "bare minimum" functional code from Ranju's blog post as a community wiki. Though it's safe to say that Ranju added the above and other code on his blog to be used freely, I'm not going to copy his words here.