处理对 ASP.NET MVC 操作的 CORS 预检请求 [英] Handling CORS Preflight requests to ASP.NET MVC actions

查看:31
本文介绍了处理对 ASP.NET MVC 操作的 CORS 预检请求的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试对 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆