在Web API 2中启用CORS

时间:2013-09-04 16:54:57

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

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

我尝试安装Microsoft ASP.NET Web API Cross-Origin Support package并在WebApiConfig.cs中启用了它。它为我提供了EnableCors()功能,因此正确安装了包。

在这里,您可以在Register()中看到我的WebApiConfig.cs功能:

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

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

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

编辑05.09.13 这已在5.0.0-rtm-130905

中修复

9 个答案:

答案 0 :(得分:53)

CORS在Microsoft.AspNet.WebApi.Cors版本5.2.2中运行得非常好。以下步骤为我配置CORS就像一个魅力:

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

    GlobalConfiguration.Configure(WebApiConfig.Register);
    
  4. WebApiConfig Register方法中,请输入以下代码:

    public static void Register(HttpConfiguration config)
    {
        config.EnableCors();
        config.MapHttpAttributeRoutes();
    }
    
  5. 在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
    

    那应该很好地帮助你!

答案 1 :(得分:32)

我不需要安装任何软件包。只需对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

答案 2 :(得分:6)

我肯定会使用属性路由命中this issue。自5.0.0-rtm-130905起,The issuefixed。但是,你仍然可以尝试nightly builds,这肯定会有修复。

要将夜莺添加到您的NuGet包来源,请转到Tools -> Library Package Manager -> Package Manager Settings并在Package Sources下添加以下网址:http://myget.org/F/aspnetwebstacknightly

答案 3 :(得分:4)

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

答案 4 :(得分:4)

如果使用[EnableCors()]拦截消息管道,使用DelegatingHandler方法进行参考将无效。在我的情况下,检查请求中的Authorization标头并在调用路由之前相应地处理它,这意味着我的请求在管道中的早期处理,因此[EnableCors()]没有效果。 / p>

最后找到了一个示例CrossDomainHandler class (归功于shaunxuGist,它为我在管道中处理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());

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

答案 5 :(得分:3)

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

 var constraints = new {httpMethod = new HttpMethodConstraint(HttpMethod.Options)};
 config.Routes.IgnoreRoute("OPTIONS", "*pathInfo",constraints);

答案 6 :(得分:2)

确保您正在通过HTTPS访问WebAPI。

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

#=> [{:name=>"John Doe", :number=>11222019}, {:name=>"Mark King", :number=>11232019}, {:name=>"Angle Darma", :number=>11242019}]

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

答案 7 :(得分:1)

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

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

答案 8 :(得分:-1)

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

我使用了以下代码:

// 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;