ASP.NET MVC 3 JSONP:这可以与 JsonValueProviderFactory 一起使用吗?

发布于 2024-10-14 01:42:14 字数 3413 浏览 2 评论 0原文

Phil Haack 有一个出色的 博客发布关于如何使用 JSON、数据绑定和数据验证的文章

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

是否有内置的 MVC 3 方法可以做到这一点,或者我是否需要遵循 这样的帖子< /a>?可以发内容吗?我问这个问题是因为我的同事实现了 JsonPfilterAttribute 以及其他东西来使这项工作正常进行。如果 MVC 3 中已经存在某些内容,显然最好避免这种情况。

编辑:

摘要:除了访问 POST 变量之外,一切正常,即,如何做我在上下文中访问 POST 变量?(在代码的最后一部分中对其进行注释标记)

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

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

这会产生此响应:

randomFunctionName([{"firstField":"111","secondField":"222"}]);

以及所有这些如果我使用 GET,效果会很好。但是,我仍然无法让它作为 POST 工作。这是 Nathan Bridgewater 此处。此行找不到 POST 数据:

context.HttpContext.Request["callback"];

要么我应该以某种方式访问​​ 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;
        }
    }
}

Phil Haack has an excellent blog post on how to use JSON, data binding, and data validation.

Enter the browser's "same origin policy security restriction." and JSONP where you use $.getJSON() to retrieve the content.

Is there a built in MVC 3 way to do this, or do I need to follow the advice of posts like this? Can you post content? I ask because my colleague implemented a JsonPfilterAttribute among other things to make this work. It's obviously preferred to avoid that if something already exists in MVC 3.

Edit:

Summary: everything works with the exception of accessing a POST variable, i.e., how do I access the POST variable in the context? (comment marking it in the last section of code)

I elected to use this format to call the server:

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

Which produces this response:

randomFunctionName([{"firstField":"111","secondField":"222"}]);

And all this works very well if I use a GET. However, I still cannot get this to work as a POST. Here's the original code posted by Nathan Bridgewater here. This line doesn't find the POST data:

context.HttpContext.Request["callback"];

Either I should be accessing Form in some way, or the MVC data validators are stripping out the POST variables.

How should context.HttpContext.Request["callback"]; be written to access the POST variable or is MVC stripping out these values for some reason?

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

时光匆匆的小流年 2024-10-21 01:42:15

就接收 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(")");
        }
    }
}

然后在您的控制器操作中:

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

可以使用 $.getJSON()

$.getJSON('http://example.com/home/foo?jsoncallback=?', function(data) {
    alert(data.Prop1);
});

As far as receiving a JSON string and binding it to a model is concerned the JsonValueProviderFactory does this job out of the box in ASP.NET MVC 3. But there is nothing built-in for outputting JSONP. You could write a custom 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(")");
        }
    }
}

And then in your controller action:

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

which could be consumed from another domain with $.getJSON():

$.getJSON('http://example.com/home/foo?jsoncallback=?', function(data) {
    alert(data.Prop1);
});
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文