Ajax json跨域发布到控制器,“不允许”访问控制允许标头

发布于 2024-12-06 07:30:17 字数 1779 浏览 1 评论 0原文

我创建了一个简单的 MVC 控制器操作,它接受一些 json 数据 - 然后返回 true 或 false。

    [AllowCrossSiteJson]
    public JsonResult AddPerson(Person person)
    {
            //do stuff with person object
           return Json(true);
    }

我从 javascript 调用它:

        function saveData(person) {
            var json = $.toJSON(person); //converts person object to json
            $.ajax({
                url: "http://somedomain.com/Ajax/AddPerson",
                type: 'POST',
                dataType: 'json',
                data: json,
                contentType: 'application/json; charset=utf-8',
                success: function (data) {
                    alert("ok");
                }
            });
        }

只要我在同一个域中,一切都会正常,但是一旦我从另一个域调用它,我就会遇到问题。

控制器上有一个操作过滤器“AllowCrossSiteJson”,它将标头“Access-Control-Allow-Origin”设置为“*”,允许任何源访问控制器操作。

public class AllowCrossSiteJsonAttribute : ActionFilterAttribute
{
    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        filterContext.RequestContext.HttpContext.Response.AddHeader("Access-Control-Allow-Origin", "*");
        base.OnActionExecuting(filterContext);
    }
}

但是 - 当跨域调用时,我在 firebug 中收到此错误:

选项http://somedomain.com/Ajax/AddPerson?packageId=3 500(内部服务器错误) XMLHttpRequest 无法加载 http://somedomain.com/Ajax/AddPerson。 Access-Control-Allow-Headers 不允许请求标头字段 Content-Type。

这里出了什么问题?

我几个小时以来一直在寻找可能的解决方案,这似乎与使用 OPTIONS 的 jquery 有关(而不是我期望的 POST)。

如果这确实是问题,我该如何解决?

I create a simple MVC Controller action, that takes some json data - then return true or false.

    [AllowCrossSiteJson]
    public JsonResult AddPerson(Person person)
    {
            //do stuff with person object
           return Json(true);
    }

I call it from javascript:

        function saveData(person) {
            var json = $.toJSON(person); //converts person object to json
            $.ajax({
                url: "http://somedomain.com/Ajax/AddPerson",
                type: 'POST',
                dataType: 'json',
                data: json,
                contentType: 'application/json; charset=utf-8',
                success: function (data) {
                    alert("ok");
                }
            });
        }

Everything works as long as I am on the same domain, but as soon as I call it from another domain, I run into problems.

On the controller is an action filter "AllowCrossSiteJson" that sets the header "Access-Control-Allow-Origin" to "*", allowing any origin to access the controller action.

public class AllowCrossSiteJsonAttribute : ActionFilterAttribute
{
    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        filterContext.RequestContext.HttpContext.Response.AddHeader("Access-Control-Allow-Origin", "*");
        base.OnActionExecuting(filterContext);
    }
}

However - I then get this error in firebug, when calling across domains:

OPTIONS http://somedomain.com/Ajax/AddPerson?packageId=3 500 (Internal Server Error)
XMLHttpRequest cannot load http://somedomain.com/Ajax/AddPerson. Request header field Content-Type is not allowed by Access-Control-Allow-Headers.

What is wrong here?

I have been looking through possible solutions for hours, and it seems to be something to do with jquery using OPTIONS (not POST as I would expect).

If that is indeed the problem, how can I fix that?

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

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

发布评论

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

评论(2

2024-12-13 07:30:17

要修复 Access-Control-Allow-Origin 错误,您需要在响应中包含以下标头:

Access-Control-Allow-Headers: Content-Type

基本上,任何“非简单”标头需要以逗号分隔的列表形式包含在上面的标题中。查看 CORS 规范以了解更多详细信息:

http://www.w3.org/TR/cors/

“内容-Type”需要包含在内,因为“application/json”与此处定义的值不匹配:

http://www. w3.org/TR/cors/#terminology

To fix the Access-Control-Allow-Origin error, you need to include the following header in your response:

Access-Control-Allow-Headers: Content-Type

Basically, any "non-simple" header needs to be included as a comma-delimited list in the header above. Check out the CORS spec for more details:

http://www.w3.org/TR/cors/

"Content-Type" needs to be included because "application/json" does not match the values defined here:

http://www.w3.org/TR/cors/#terminology

猫弦 2024-12-13 07:30:17

我推荐您 JSONP,它是唯一真正跨浏览器且可靠的跨域 AJAX 解决方案。因此,您可以首先编写一个自定义操作结果,该结果将用回调包装 JSON 响应:

public class JsonpResult : ActionResult
{
    private readonly object _obj;

    public JsonpResult(object obj)
    {
        _obj = obj;
    }

    public override void ExecuteResult(ControllerContext context)
    {
        var serializer = new JavaScriptSerializer();
        var callbackname = context.HttpContext.Request["callback"];
        var jsonp = string.Format("{0}({1})", callbackname, serializer.Serialize(_obj));
        var response = context.HttpContext.Response;
        response.ContentType = "application/json";
        response.Write(jsonp);
    }
}

然后:

public ActionResult AddPerson(Person person)
{
    return new JsonpResult(true);
}

最后执行跨域 AJAX 调用:

$.ajax({
    url: 'http://somedomain.com/Ajax/AddPerson',
    jsonp: 'callback',
    dataType: 'jsonp',
    data: { firstName: 'john', lastName: 'smith' },
    success: function (result) {
        alert(result);
    }
});

I'd recommend you JSONP, it's the only really cross browser and reliable solution for cross domain AJAX. So you could start by writing a custom action result that will wrap the JSON response with a callback:

public class JsonpResult : ActionResult
{
    private readonly object _obj;

    public JsonpResult(object obj)
    {
        _obj = obj;
    }

    public override void ExecuteResult(ControllerContext context)
    {
        var serializer = new JavaScriptSerializer();
        var callbackname = context.HttpContext.Request["callback"];
        var jsonp = string.Format("{0}({1})", callbackname, serializer.Serialize(_obj));
        var response = context.HttpContext.Response;
        response.ContentType = "application/json";
        response.Write(jsonp);
    }
}

and then:

public ActionResult AddPerson(Person person)
{
    return new JsonpResult(true);
}

and finally perform the cross domain AJAX call:

$.ajax({
    url: 'http://somedomain.com/Ajax/AddPerson',
    jsonp: 'callback',
    dataType: 'jsonp',
    data: { firstName: 'john', lastName: 'smith' },
    success: function (result) {
        alert(result);
    }
});
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文