【问题标题】:Enable CORS in Web API 2在 Web API 2 中启用 CORS
【发布时间】:2013-09-08 07:17:33
【问题描述】:

我有客户端和服务器在不同的端口上运行。服务器正在运行 Web API 2 (v5.0.0-rc1)

我尝试安装Microsoft ASP.NET Web API Cross-Origin Support package 并在WebApiConfig.cs 中启用它。它给了我EnableCors() 函数,所以包安装正确。

在这里你可以在WebApiConfig.cs中看到我的Register()函数:

public static void Register(HttpConfiguration config)
{
    config.MapHttpAttributeRoutes();

    var cors = new EnableCorsAttribute("*", "*", "*");
    config.EnableCors(cors);
}

GET 请求工作正常。但是在发送POST 时,我得到以下信息:

OPTIONS http://localhost:19357/api/v1/rooms? 404 (Not Found) angular.js:10159
OPTIONS http://localhost:19357/api/v1/rooms? Origin http://localhost:8000 is not allowed by Access-Control-Allow-Origin. angular.js:10159
XMLHttpRequest cannot load http://localhost:19357/api/v1/rooms. Origin http://localhost:8000 is not allowed by Access-Control-Allow-Origin.

根据 Fiddler 的说法,它只发送 OPTIONS 请求。之后它不会发出POST

所以我猜WebApiConfig.cs 中的config.EnableCors(cors); 没有做任何事情,这导致服务器拒绝客户端/浏览器发送POST 请求。

你知道如何解决这个问题吗?

编辑 05.09.13 这已在 5.0.0-rtm-130905 中修复

【问题讨论】:

  • 感谢您的问答,它已在 5.0.0-rtm 中修复。我在哪里可以获得 RTM 版本?
  • Tools -> Library Package Manager -> Package Manager Settings 并在Package Sources 下添加以下网址:myget.org/F/aspnetwebstacknightly

标签: c# asp.net-web-api cors


【解决方案1】:

CORS 在Microsoft.AspNet.WebApi.Cors 5.2.2 版中运行良好。以下步骤配置 CORS 对我来说就像一个魅力:

  1. Install-Package Microsoft.AspNet.WebApi.Cors -Version "5.2.2" // 从包管理器控制台运行
  2. 在 Global.asax 中,添加以下行:在任何 MVC 路由注册之前

    GlobalConfiguration.Configure(WebApiConfig.Register);
    
  3. WebApiConfig注册方法中,有如下代码:

    public static void Register(HttpConfiguration config)
    {
        config.EnableCors();
        config.MapHttpAttributeRoutes();
    }
    

在 web.config 中,以下处理程序必须是管道中的第一个处理程序:

<add name="ExtensionlessUrlHandler-Integrated-4.0" path="*." verb="*" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" />

在派生自ApiController的控制器中,添加EnableCorsAttribute

[EnableCors(origins: "*", headers: "*", methods: "*")] // tune to your needs
[RoutePrefix("")]
public class MyController : ApiController

这应该很好地设置你!

【讨论】:

  • 就像我说的,它已在 5.0.0-rtm-130905 中修复 :)
  • 当然,我只是添加了完整的步骤:)
  • 只是想添加,我想启用 CORS,但仅限于控制器\操作级别。我不希望它在全球范围内开放。但是直到我在 WebApiConfig 中添加了 config.EnableCors() 之前,什么都没有。基本上启用它,但参数为 0。但后来它让我在各个 Controller\Action 级别使用 [System.Web.Http.Cors.EnableCors(origins: "", headers: "", methods: "*")]。
  • 我们如何使用 .net 4.6.2 做到这一点?
  • 我正在使用 ajax 调用 web api 2,并且我在本地运行的 web api 项目中使用相同的上述代码。看到它不起作用。
【解决方案2】:

我不需要安装任何软件包。只需对您的 WebAPI 项目的 web.config 进行简单的更改,效果就很好:

<system.webServer>
    <httpProtocol>
        <customHeaders>
            <add name="Access-Control-Allow-Origin" value="*" />
        </customHeaders>
    </httpProtocol>
</system.webServer>

归功于:Using CORS in ASP.NET WebAPI Without Being a Rocket Scientist

【讨论】:

  • 这可以解决问题,但如果您想在控制器/路由的基础上指定 CORS,则它不起作用。
  • 正如您建议我在项目中使用的相同技巧,+1!并且讨厌 nuget 包,它完全没有必要!Happy Coding bro!
  • 此方法的另一个警告:使用 OWIN/Katana,您可能不在 IIS 中托管,在这种情况下,没有 web.config - 这就是 Microsoft.AspNet.WebApi.Cors 包的原因要走的路。
  • 这种方法的另一个缺点是它会导致标头包含在服务器的每个响应中。 Microsoft.AspNet.WebApi.Cors 只有在请求包含 Origin: 标头时才知道包含它。
  • 这似乎是最简单的,但并不总是有效,就像所有的 cors 方法一样。
【解决方案3】:

如果您使用DelegatingHandler 拦截消息管道,则使用[EnableCors()] 方法作为参考将不起作用。在我的情况下,检查请求中的 Authorization 标头并在调用路由之前对其进行相应处理,这意味着我的请求在管道中更早地得到处理,因此 [EnableCors()] 无效。

最后找到了一个示例CrossDomainHandler classshaunxuGist它在管道中为我处理 CORS,使用它就像添加另一个一样简单管道的消息处理程序。

public class CrossDomainHandler : DelegatingHandler
    {
        const string Origin = "Origin";
        const string AccessControlRequestMethod = "Access-Control-Request-Method";
        const string AccessControlRequestHeaders = "Access-Control-Request-Headers";
        const string AccessControlAllowOrigin = "Access-Control-Allow-Origin";
        const string AccessControlAllowMethods = "Access-Control-Allow-Methods";
        const string AccessControlAllowHeaders = "Access-Control-Allow-Headers";

        protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
        {
            bool isCorsRequest = request.Headers.Contains(Origin);
            bool isPreflightRequest = request.Method == HttpMethod.Options;
            if (isCorsRequest)
            {
                if (isPreflightRequest)
                {
                    return Task.Factory.StartNew(() =>
                    {
                        HttpResponseMessage response = new HttpResponseMessage(HttpStatusCode.OK);
                        response.Headers.Add(AccessControlAllowOrigin, request.Headers.GetValues(Origin).First());

                        string accessControlRequestMethod = request.Headers.GetValues(AccessControlRequestMethod).FirstOrDefault();
                        if (accessControlRequestMethod != null)
                        {
                            response.Headers.Add(AccessControlAllowMethods, accessControlRequestMethod);
                        }

                        string requestedHeaders = string.Join(", ", request.Headers.GetValues(AccessControlRequestHeaders));
                        if (!string.IsNullOrEmpty(requestedHeaders))
                        {
                            response.Headers.Add(AccessControlAllowHeaders, requestedHeaders);
                        }

                        return response;
                    }, cancellationToken);
                }
                else
                {
                    return base.SendAsync(request, cancellationToken).ContinueWith(t =>
                    {
                        HttpResponseMessage resp = t.Result;
                        resp.Headers.Add(AccessControlAllowOrigin, request.Headers.GetValues(Origin).First());
                        return resp;
                    });
                }
            }
            else
            {
                return base.SendAsync(request, cancellationToken);
            }
        }
    }

要使用它,请将其添加到已注册的消息处理程序列表中

config.MessageHandlers.Add(new CrossDomainHandler());

浏览器的任何预检请求都会被处理和传递,这意味着我不需要在控制器上实现[HttpOptions]IHttpActionResult 方法。

【讨论】:

  • 这让我遇到了 ASP .NET Web API CORS 策略的问题,即相关响应不会回来。原来它是一个基于 FilterAttribute 的实现,并且早在管道的DelegatingHandler 阶段就没有参与。因此,如果处理程序提前返回,您必须手动提供 CORS 标头响应(并根据您的策略)。
【解决方案4】:

我肯定会用属性路由打this issue。从 5.0.0-rtm-130905 开始,The issuefixed。但是,您仍然可以尝试nightly builds,它肯定会解决问题。

要将 nightlies 添加到 NuGet 包源,请转到 Tools -&gt; Library Package Manager -&gt; Package Manager Settings 并在 Package Sources 下添加以下 URL:http://myget.org/F/aspnetwebstacknightly

【讨论】:

    【解决方案5】:

    确保您通过 HTTPS 访问 WebAPI。

    我还在 WebApi.config 中启用了 cors。

    var cors = new EnableCorsAttribute("*", "*", "*");
    config.EnableCors(cors);
    

    但直到我使用 HTTPS 网址,我的 CORS 请求才起作用。

    【讨论】:

      【解决方案6】:
       var cors = new EnableCorsAttribute("*","*","*");
       config.EnableCors(cors);
      
       var constraints = new {httpMethod = new HttpMethodConstraint(HttpMethod.Options)};
       config.Routes.IgnoreRoute("OPTIONS", "*pathInfo",constraints);
      

      【讨论】:

        【解决方案7】:

        迟到的回复以供将来参考。对我有用的是通过 nuget 启用它,然后将自定义标头添加到 web.config 中。

        【讨论】:

        • 谢谢!通过包管理控制台安装对我来说不起作用,所以我通过 NuGet 界面进行了尝试,它自动更新了项目引用,现在可以正常工作了。
        【解决方案8】:

        要启用 CORS, 1.转到 App_Start 文件夹。 2.添加命名空间'using System.Web.Http.Cors'; 3.打开WebApiConfig.cs文件,在静态方法中输入以下内容。

        config.EnableCors(new EnableCorsAttribute("https://localhost:44328",headers:"*", methods:"*"));

        【讨论】:

          【解决方案9】:

          以下代码对我有用,

          App_Start -> WebApiConfig

          EnableCorsAttribute cors = new EnableCorsAttribute("\*", "\*", "GET,HEAD,POST");
          config.EnableCors(cors);
          

          【讨论】:

            【解决方案10】:

            据我了解,服务器必须有一个标头,指定允许从源访问,即可以响应来自同一服务器的请求。

            我使用了以下代码:

            // create a response object of your choice
            var response = Request.CreateResponse(HttpStatusCode.OK);
            
            //add the header
            //replace the star with a specific name if you want to restrict access
            response.Headers.Add("Access-Control-Allow-Origin", "*");
            
            //now you could send the response and it should work...
            return response;
            

            【讨论】:

              猜你喜欢
              • 2014-10-20
              • 1970-01-01
              • 1970-01-01
              • 2017-11-22
              • 2023-04-03
              • 2017-04-22
              • 2017-05-03
              • 2019-02-11
              • 2019-01-24
              相关资源
              最近更新 更多