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

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

问题描述:

我创建了一个简单的MVC控制器操作,该操作需要一些json数据 - 然后返回true或false。Ajax json发布到控制器跨域,“不允许”访问控制 - 允许标题

[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这个错误,跨域调用时:

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

这里有什么问题?

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

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

我推荐你JSONP,这是跨域AJAX唯一真正跨浏览器和可靠的解决方案。

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); 
    } 
}); 
所以,你可以通过编写自定义操作的结果,将包裹有回调JSON响应启动
+4

我爱你并想拥有你的宝宝。 – Kjensen

+0

这不是只能用于获取请求吗? –

+0

是的,JSONP的jQuery实现仅适用于GET请求。 –

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

Access-Control-Allow-Headers: Content-Type

基本上,任何“非简单”标题都需要包含在上面头部的逗号分隔列表中。退房CORS规范的更多详细信息:

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

“的Content-Type” 必须包括在内,因为 “应用/ JSON的” 不符合此定义的值:

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

+0

很好的答案!比JSONP好得多。 –