我创建了一个简单的MVC Controller操作,该操作需要一些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=3500(内部服务器错误)XMLHttpRequest无法加载http://somedomain.com/Ajax/AddPerson。Access- Control-Allow-Headers不允许请求标头字段Content-Type。
怎么了
我一直在寻找可能的解决方案达数小时之久,这似乎与使用OPTIONS的jquery有关(而不是我期望的POST)。
如果确实存在问题,我该如何解决?
我建议您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); } });