ASP.NET MVC 3 JSONP:这适用于JsonValueProviderFactory吗?

Zac*_*ott 7 jsonp model-binding asp.net-mvc-3

Phil Haack有一篇关于如何使用JSON,数据绑定和数据验证的优秀博客文章.

输入浏览器的"同源策略安全限制".和JSONP,您使用$ .getJSON()来检索内容.

是否有内置的MVC 3方法来做到这一点,还是我需要遵循这样的帖子的建议?你可以发布内容吗?我问,因为我的同事实现了JsonPfilterAttribute以及其他工作.如果MVC 3中已存在某些内容,显然最好避免这种情况.

编辑:

总结:除访问POST变量外,一切都有效,即如何POST在上下文中访问变量?(注释在代码的最后部分标记)

我选择使用这种格式来调用服务器:

$.ajax({
    type: "GET",
    url: "GetMyDataJSONP",
    data: {},
    contentType: "application/json; charset=utf-8",
    dataType: "jsonp",
    jsonpCallback: "randomFunctionName"
});
Run Code Online (Sandbox Code Playgroud)

产生这种反应:

randomFunctionName([{"firstField":"111","secondField":"222"}]);
Run Code Online (Sandbox Code Playgroud)

如果我使用的话,这一切都很有效GET.但是,我仍然无法将其作为一个工作POST.这是Nathan Bridgewater 在这里发布的原始代码.此行找不到POST数据:

context.HttpContext.Request["callback"];
Run Code Online (Sandbox Code Playgroud)

要么我应该Form以某种方式访问,要么MVC数据验证器正在剥离POST变量.

如何context.HttpContext.Request["callback"];编写访问POST变量或MVC是否出于某种原因剥离这些值?

namespace System.Web.Mvc
{   public class JsonpResult : ActionResult
    {   public JsonpResult() {}

        public Encoding ContentEncoding { get; set; }
        public string ContentType { get; set; }
        public object Data { get; set; }
        public string JsonCallback { get; set; }

        public override void ExecuteResult(ControllerContext context)
        {   if (context == null)
               throw new ArgumentNullException("context");

            this.JsonCallback = context.HttpContext.Request["jsoncallback"];

            // This is the line I need to alter to find the form variable:

            if (string.IsNullOrEmpty(this.JsonCallback))
                this.JsonCallback = context.HttpContext.Request["callback"];

            if (string.IsNullOrEmpty(this.JsonCallback))
                throw new ArgumentNullException(
                    "JsonCallback required for JSONP response.");

            HttpResponseBase response = context.HttpContext.Response;

            if (!String.IsNullOrEmpty(ContentType))
               response.ContentType = ContentType;
            else
               response.ContentType = "application/json; charset=utf-8";

            if (ContentEncoding != null)
                response.ContentEncoding = ContentEncoding;

            if (Data != null)
            {   JavaScriptSerializer serializer = new JavaScriptSerializer();
                response.Write(string.Format("{0}({1});", this.JsonCallback,
                    serializer.Serialize(Data)));
    }   }   }

    //extension methods for the controller to allow jsonp.
    public static class ContollerExtensions
    {
        public static JsonpResult Jsonp(this Controller controller, 
               object data)
        {
            JsonpResult result = new JsonpResult();
            result.Data = data;
            result.ExecuteResult(controller.ControllerContext);
            return result;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

Dar*_*rov 39

就接收JSON字符串并将其绑定到模型而言JsonValueProviderFactory,ASP.NET MVC 3中的这项工作是开箱即用的.但是没有任何内置输出JSONP.你可以写一个自定义JsonpResult:

public class JsonpResult : JsonResult
{
    public override void ExecuteResult(ControllerContext context)
    {
        if (context == null)
        {
            throw new ArgumentNullException("context");
        }
        var request = context.HttpContext.Request;
        var response = context.HttpContext.Response;
        string jsoncallback = (context.RouteData.Values["jsoncallback"] as string) ?? request["jsoncallback"];
        if (!string.IsNullOrEmpty(jsoncallback))
        {
            if (string.IsNullOrEmpty(base.ContentType))
            {
                base.ContentType = "application/x-javascript";
            }
            response.Write(string.Format("{0}(", jsoncallback));
        }
        base.ExecuteResult(context);
        if (!string.IsNullOrEmpty(jsoncallback))
        {
            response.Write(")");
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

然后在你的控制器动作中:

public ActionResult Foo()
{
    return new JsonpResult
    {
        Data = new { Prop1 = "value1", Prop2 = "value2" },
        JsonRequestBehavior = JsonRequestBehavior.AllowGet
    };
}
Run Code Online (Sandbox Code Playgroud)

可以从另一个域使用$.getJSON():

$.getJSON('http://domain.com/home/foo?jsoncallback=?', function(data) {
    alert(data.Prop1);
});
Run Code Online (Sandbox Code Playgroud)

  • @Dr.Zim,`JSONP`仅适用于jQuery实现的GET请求.这里没有什么神奇之处,jQuery只是将一个`<script>'标签注入到指向远程服务器的主机页面的DOM中,因为你知道`<script>`标签只能向这个远程资源发送一个GET请求.所以,甚至不要尝试`$ .ajax({type:'POST'});`,使用JSONP,这是永远不会有用的.事实上,你可以通过使用隐藏的iframe和隐藏的表单来使它工作,但这不是jQuery用来实现JSONP的. (2认同)