首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >ASP.net MVC返回JSONP

ASP.net MVC返回JSONP
EN

Stack Overflow用户
提问于 2009-04-17 03:18:43
回答 7查看 38.6K关注 0票数 72

我希望跨域返回一些JSON,我知道这样做的方法是通过JSONP,而不是纯JSON。

我使用的是Jsonp,所以我在考虑只扩展JsonResult类型,然后扩展控制器,这样它也实现了一个ASP.net方法。

这是最好的方法吗?或者有没有内置的ActionResult可能更好?

Solution:我已经这么做了。仅供参考,我添加了一个新的结果:

public class JsonpResult : System.Web.Mvc.JsonResult
{
    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 (Data != null)
        {
            // The JavaScriptSerializer type was marked as obsolete prior to .NET Framework 3.5 SP1
        #pragma warning disable 0618
            HttpRequestBase request = context.HttpContext.Request;

            JavaScriptSerializer serializer = new JavaScriptSerializer();
            response.Write(request.Params["jsoncallback"] + "(" + serializer.Serialize(Data) + ")");
        #pragma warning restore 0618
        }
    }
}

还有几个方法到我所有控制器的超类中:

protected internal JsonpResult Jsonp(object data)
{
    return Jsonp(data, null /* contentType */);
}

protected internal JsonpResult Jsonp(object data, string contentType)
{
    return Jsonp(data, contentType, null);
}

protected internal virtual JsonpResult Jsonp(object data, string contentType, Encoding contentEncoding)
{
    return new JsonpResult
    {
        Data = data,
        ContentType = contentType,
        ContentEncoding = contentEncoding
    };
}

就像一种护身符。

EN

回答 7

Stack Overflow用户

发布于 2013-03-20 09:13:03

如果您不想定义操作过滤器,这里有一个简单的解决方案

使用jQuery的客户端代码:

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

MVC控制器操作。返回内容结果,JavaScript代码执行查询字符串提供的回调函数。还为响应设置JavaScript MIME类型。

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

Stack Overflow用户

发布于 2010-12-15 01:50:24

我没有使用Jsonp()方法对我的控制器进行子类化,而是选择了扩展方法路线,因为它让我感觉更干净。JsonpResult的好处是您可以像测试JsonResult一样对它进行测试。

我做到了:

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};
    }
}

这样,您就不必担心创建所有不同的Jsonp()重载,只需将您的JsonResult转换为Jsonp即可。

票数 13
EN

Stack Overflow用户

发布于 2013-11-08 22:51:19

Ranju's blog post (也就是“我发现的这篇博客文章”)非常优秀,阅读它可以让你进一步了解下面的解决方案,这样你的控制器就可以在相同的控制器操作中优雅地处理同域JSON和跨域JSONP请求,而无需在操作中添加额外的代码。

无论如何,对于“给我代码”类型,这里是它,以防博客再次消失。

在您的控制器中(此代码片段是新的/非博客代码):

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

this excellent blog post上找到JsonpResult

/// <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
        }
    }
}

备注:在对comments to the OP by @Ranju and others的后续研究中,我认为值得将的博客文章中的“最低限度”功能代码作为社区维基发布。尽管可以肯定地说,Ranju在他的博客上添加了上述代码和其他代码以供自由使用,但我不打算在这里复制他的话。

票数 10
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/758879

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档