我试图对ASP.NET MVC控制器操作执行跨域POST请求。这个控制器动作接受&使用各种参数。问题是当预检请求发生时,控制器动作实际上尝试执行&因为OPTIONS请求不传递任何数据,控制器操作抛出一个500 HTTP错误。如果我删除使用参数的代码或参数本身,整个请求链已成功完成。
一个如何实现的示例:
控制器操作
public ActionResult GetData(string data) { return new JsonResult { Data = data.ToUpper(),JsonRequestBehavior = JsonRequestBehavior.AllowGet }; }
客户端代码
<script type="text/javascript"> $(function () { $("#button-request").click(function () { var ajaxConfig = { dataType: "json",url: "http://localhost:8100/host/getdata",contentType: 'application/json',data: JSON.stringify({ data: "A string of data" }),type: "POST",success: function (result) { alert(result); },error: function (jqXHR,textStatus,errorThrown) { alert('Error: Status: ' + textStatus + ',Message: ' + errorThrown); } }; $.ajax(ajaxConfig); }); }); </script>
现在,每当预检请求发生时,它返回一个500 HTTP代码,因为“data”参数为null,因为OPTIONS请求不传递任何值。
服务器应用程序已经在我的本地IIS中设置在端口8100&运行客户端代码的页面在端口8200上设置,以模拟跨域调用。
我还配置了主机(在8100)与以下标题:
Access-Control-Allow-Headers: Content-Type Access-Control-Allow-Methods: POST,GET Access-Control-Allow-Origin: http://localhost:8200
我发现一个解决方法是检查HTTP方法执行操作&如果它是一个OPTIONS请求只返回空白内容,否则执行动作代码。像这样:
public ActionResult GetData(string data) { if (Request.HttpMethod == "OPTIONS") { return new ContentResult(); } else { return new JsonResult { Data = data.ToUpper(),JsonRequestBehavior = JsonRequestBehavior.AllowGet }; } }
解决方法
所以我找到了一个解决方案工作。对于每个请求,我检查它是否是CORS请求&该请求是否带有OPTIONS动词,表明它是预检请求。如果是,我只是发送一个空的响应(当然只包含在IIS中配置的头),从而否定控制器动作执行。
然后,如果客户端确认允许基于从预检检测返回的报头执行请求,则执行实际的POST,执行控制器动作。和我的代码示例:
protected void Application_BeginRequest() { if (Request.Headers.AllKeys.Contains("Origin") && Request.HttpMethod == "OPTIONS") { Response.Flush(); } }
如前所述,这对我有用,但如果有人知道更好的方法,或我目前的实施中的任何缺陷,我将感激听到他们。