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.