处理对 ASP.NET MVC 操作的 CORS 预检请求 [英] Handling CORS Preflight requests to ASP.NET MVC actions
问题描述
我正在尝试对 ASP.NET MVC 控制器操作执行跨域 POST 请求.此控制器动作接受 &使用各种参数.问题是当预检请求发生时,控制器动作实际上试图执行 &因为 OPTIONS 请求没有传递任何数据,所以控制器操作会抛出 500 HTTP 错误.如果我去掉使用参数的代码,或者参数本身,整个请求链就成功完成了.
I'm trying to perform a cross-domain POST request to an ASP.NET MVC controller action. This controller action accepts & uses various parameters. The problem is that when the preflight request happens, the controller action actually attempts to execute & because the OPTIONS request doesn't pass any data, the controller action throws out a 500 HTTP error. If I remove the code that uses the parameter, or the parameter itself, the entire request chain is completed successfully.
这是如何实现的示例:
控制器动作
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"参数为空,因为 OPTIONS 请求没有传递任何值.
Now, whenever the preflight request happens, it returns a 500 HTTP code, because the "data" parameter is null, seeing as the OPTIONS request doesn't pass any values.
服务器应用程序已在我本地 IIS 的 8100 端口上设置 &运行客户端代码的页面设置在端口 8200 上以模拟跨域调用.
The server application has been set up in my local IIS on port 8100 & the page running the client-side code is set up on port 8200 to mimic the cross-domain calls.
我还使用以下标头配置了主机(在 8100 上):
I have also configured the host (on 8100) with the following headers:
Access-Control-Allow-Headers: Content-Type
Access-Control-Allow-Methods: POST, GET
Access-Control-Allow-Origin: http://localhost:8200
我发现的一种解决方法是检查执行操作的 HTTP 方法 &如果是 OPTIONS 请求只返回空白内容,否则执行操作代码.像这样:
One workaround I had found, was to check the HTTP method that executes the action & if it's a OPTIONS request to just return blank content, otherwise execute the action code. Like so:
public ActionResult GetData(string data)
{
if (Request.HttpMethod == "OPTIONS") {
return new ContentResult();
} else {
return new JsonResult
{
Data = data.ToUpper(),
JsonRequestBehavior = JsonRequestBehavior.AllowGet
};
}
}
但是我觉得这种方法很笨拙.我考虑将这种逻辑添加到 Attribute
中,但即使这样也意味着装饰将使用 CORS 调用的每个操作.
But this approach feels very clunky to me. I considered adding this sort of logic to an Attribute
, but even this would mean decorating every action that will get called using CORS with it.
是否有更优雅的解决方案来使此功能发挥作用?
Is there a more elegant solution to getting this functionality to work?
推荐答案
所以我找到了一个有效的解决方案.对于每个请求,我检查它是否是 CORS 请求 &请求是否带有 OPTIONS 动词,表明它是预检请求.如果是,我只是发送一个空响应(当然它只包含在 IIS 中配置的标头),从而否定控制器操作的执行.
So I have found a solution that works. For each request, I check whether it's a CORS request & whether the request is coming in with the OPTIONS verb, indicating that it's the preflight request. If it is, I just send an empty response back (which only contains the headers configured in IIS of course), thus negating the controller action execution.
然后,如果客户端根据预检返回的标头确认允许执行请求,则执行实际的 POST &控制器动作被执行.以及我的代码示例:
Then if the client confirms it's allowed to perform the request based on the returned headers from preflight, the actual POST is performed & the controller action is executed. And example of my code:
protected void Application_BeginRequest()
{
if (Request.Headers.AllKeys.Contains("Origin", StringComparer.OrdinalIgnoreCase) &&
Request.HttpMethod == "OPTIONS") {
Response.Flush();
}
}
如前所述,这对我有用,但如果有人知道更好的方法或我当前实施中的任何缺陷,我将不胜感激.
As mentioned, this worked for me, but if anyone knows of a better way, or of any flaws in my current implementation, I would appreciate to hear about them.
这篇关于处理对 ASP.NET MVC 操作的 CORS 预检请求的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!