Asp.Net WebApi2使CORS不能与AspNet.WebApi.Cors 5.2.3一起使用

ibe*_*dev 71 c# rest cors asp.net-web-api2

我尝试按照http://enable-cors.org/server_aspnet.html中的步骤 使我的RESTful API(使用ASP.NET WebAPI2实现)与跨源请求(CORS Enabled)一起工作.除非我修改web.config,否则它无法正常工作.

我安装了WebApi Cors依赖:

install-package Microsoft.AspNet.WebApi.Cors -ProjectName MyProject.Web.Api
Run Code Online (Sandbox Code Playgroud)

然后在我App_Start的课程中我得到WebApiConfig如下:

public static class WebApiConfig
{
    public static void Register(HttpConfiguration config)
    {
        var corsAttr = new EnableCorsAttribute("*", "*", "*");
        config.EnableCors(corsAttr);

        var constraintsResolver = new DefaultInlineConstraintResolver();

        constraintsResolver.ConstraintMap.Add("apiVersionConstraint", typeof(ApiVersionConstraint));
        config.MapHttpAttributeRoutes(constraintsResolver); 
        config.Services.Replace(typeof(IHttpControllerSelector), new NamespaceHttpControllerSelector(config));
        //config.EnableSystemDiagnosticsTracing(); 
        config.Services.Replace(typeof(ITraceWriter), new SimpleTraceWriter(WebContainerManager.Get<ILogManager>())); 
        config.Services.Add(typeof(IExceptionLogger), new SimpleExceptionLogger(WebContainerManager.Get<ILogManager>()));
        config.Services.Replace(typeof(IExceptionHandler), new GlobalExceptionHandler()); 
    }
}
Run Code Online (Sandbox Code Playgroud)

但之后我运行应用程序,我请求Fiddler的资源,如: http:// localhost:51589/api/v1/persons ,在响应中,我看不到我应该看到的HTTP头,例如:

  • Access-Control-Allow-Methods: POST, PUT, DELETE, GET, OPTIONS
  • Access-Control-Allow-Origin: *

我错过了一步吗?我在控制器上尝试了以下注释:

[EnableCors(origins: "http://example.com", headers: "*", methods: "*")]

相同的结果,没有启用CORS.

但是,如果我在web.config中添加以下内容(甚至没有安装AspNet.WebApi.Cors依赖项),它的工作原理如下:

<system.webServer>

<httpProtocol>
  <!-- THESE HEADERS ARE IMPORTANT TO WORK WITH CORS -->
  <!--
  <customHeaders>
    <add name="Access-Control-Allow-Origin" value="*" />
    <add name="Access-Control-Allow-Methods" value="POST, PUT, DELETE, GET, OPTIONS" />
    <add name="Access-Control-Allow-Headers" value="content-Type, accept, origin, X-Requested-With, Authorization, name" />
    <add name="Access-Control-Allow-Credentials" value="true" />
  </customHeaders>
  -->
</httpProtocol>
<handlers>
  <!-- THESE HANDLERS ARE IMPORTANT FOR WEB API TO WORK WITH  GET,HEAD,POST,PUT,DELETE and CORS-->
  <!--

  <remove name="WebDAV" />
  <add name="ExtensionlessUrlHandler-Integrated-4.0" path="*." verb="GET,HEAD,POST,PUT,DELETE" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" />
  <remove name="ExtensionlessUrlHandler-Integrated-4.0" />
  <remove name="OPTIONSVerbHandler" />
  <remove name="TRACEVerbHandler" />
  <add name="ExtensionlessUrlHandler-Integrated-4.0" path="*." verb="*" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" />
-->
</handlers>
Run Code Online (Sandbox Code Playgroud)

任何帮助将非常感激!

谢谢.

Sha*_*tin 89

我已经为你创建了一个简化的演示项目.

您可以尝试使用本地Fiddler 上面的API链接来查看标题.这是一个解释.

Global.ascx

所有这一切都是打电话给WebApiConfig.它只不过是代码组织.

public class WebApiApplication : System.Web.HttpApplication
{
    protected void Application_Start()
    {
        WebApiConfig.Register(GlobalConfiguration.Configuration);
    }
}
Run Code Online (Sandbox Code Playgroud)

WebApiConfig.cs

你这里的关键方法是EnableCrossSiteRequests方法.这是所有你需要做的.这EnableCorsAttribute是一个全局范围的CORS属性.

public static class WebApiConfig
{
    public static void Register(HttpConfiguration config)
    {
        EnableCrossSiteRequests(config);
        AddRoutes(config);
    }

    private static void AddRoutes(HttpConfiguration config)
    {
        config.Routes.MapHttpRoute(
            name: "Default",
            routeTemplate: "api/{controller}/"
        );
    }

    private static void EnableCrossSiteRequests(HttpConfiguration config)
    {
        var cors = new EnableCorsAttribute(
            origins: "*", 
            headers: "*", 
            methods: "*");
        config.EnableCors(cors);
    }
}
Run Code Online (Sandbox Code Playgroud)

值控制器

Get方法接收EnableCors我们全局应用的属性.该Another方法覆盖了全局EnableCors.

public class ValuesController : ApiController
{
    // GET api/values
    public IEnumerable<string> Get()
    {
        return new string[] { 
            "This is a CORS response.", 
            "It works from any origin." 
        };
    }

    // GET api/values/another
    [HttpGet]
    [EnableCors(origins:"http://www.bigfont.ca", headers:"*", methods: "*")]
    public IEnumerable<string> Another()
    {
        return new string[] { 
            "This is a CORS response. ", 
            "It works only from two origins: ",
            "1. www.bigfont.ca ",
            "2. the same origin." 
        };
    }
}
Run Code Online (Sandbox Code Playgroud)

Web.config文件

您无需在web.config中添加任何特殊内容.实际上,这就是demo的web.config看起来的样子 - 它是空的.

<?xml version="1.0" encoding="utf-8"?>
<configuration>
</configuration>
Run Code Online (Sandbox Code Playgroud)

演示

var url = "https://cors-webapi.azurewebsites.net/api/values"

$.get(url, function(data) {
  console.log("We expect this to succeed.");
  console.log(data);
});

var url = "https://cors-webapi.azurewebsites.net/api/values/another"

$.get(url, function(data) {
  console.log(data);
}).fail(function(xhr, status, text) {
  console.log("We expect this to fail.");
  console.log(status);
});
Run Code Online (Sandbox Code Playgroud)
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
Run Code Online (Sandbox Code Playgroud)

  • 我按照你的答案和从这里开始的所有步骤:http://www.asp.net/web-api/overview/security/enabling-cross-origin-requests-in-web-api#enable-cors.尝试了各种组合,除了问题中的`Web.config`->`<customHeaders>`之外,没有任何东西可以启用CORS.我正在使用最新的软件包(与问题中的相同).有什么建议在哪里寻找问题?基本上,由于某些原因,这对我来说并不能解决同样的问题. (17认同)
  • 在浪费3个小时试图让它工作之后我只是将3个标头添加到Web配置中以实际让它工作http://stackoverflow.com/a/21458845/286121 (12认同)
  • "固定它".出于某种原因,它在生产中(在真实的IIS上)设置CORS头,但在从VisualStudio运行时不在localhost上.我不知道为什么,我猜这是有条件的. (7认同)
  • @ShaunLuttin我认为我错了,它确实有效.似乎框架检查原点并仅在原点位于允许的原点列表中时发送标题.当原点不在列表中时,框架不会发送任何标题(我错误地将其解释为错误行为,因为我希望在标题中看到任何响应的允许来源).我将对此进行测试并报告结果. (4认同)
  • 在我的本地IIS上,我有不同的端口号的应用程序.Shaun的解决方案在没有Web.Config补丁的情况下无法工作直到......我注意到Shaun使用"*"作为WebApiConfig的起源.所以我将``*'`作为源自控制器中的EnableCorsAttribute,现在它可以在没有WebConfig的情况下工作.我阅读如何指定Origins让我相信端口号无效但我没有发现"*"没问题.此外,大多数示例调用`config.EnableCors(cors);`没有参数.例如:(http://enable-cors.org/server_aspnet.html) (2认同)

小智 14

你只需要改变一些文件.这适合我.

Global.ascx

public class WebApiApplication : System.Web.HttpApplication {
    protected void Application_Start()
    {
        WebApiConfig.Register(GlobalConfiguration.Configuration);
    } }
Run Code Online (Sandbox Code Playgroud)

WebApiConfig.cs

所有请求都必须调用此代码.

public static class WebApiConfig {
    public static void Register(HttpConfiguration config)
    {
        EnableCrossSiteRequests(config);
        AddRoutes(config);
    }

    private static void AddRoutes(HttpConfiguration config)
    {
        config.Routes.MapHttpRoute(
            name: "Default",
            routeTemplate: "api/{controller}/"
        );
    }

    private static void EnableCrossSiteRequests(HttpConfiguration config)
    {
        var cors = new EnableCorsAttribute(
            origins: "*", 
            headers: "*", 
            methods: "*");
        config.EnableCors(cors);
    } }
Run Code Online (Sandbox Code Playgroud)

一些控制器

没什么可改变的.

Web.config文件

您需要在web.config中添加处理程序

<configuration> 
  <system.webServer>
    <handlers>
      <remove name="ExtensionlessUrlHandler-Integrated-4.0" />
      <remove name="OPTIONSVerbHandler" />
      <remove name="TRACEVerbHandler" />
      <add name="ExtensionlessUrlHandler-Integrated-4.0" path="*." verb="*" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" />
    </handlers>   
  </system.webServer> 
</configuration>
Run Code Online (Sandbox Code Playgroud)


Nee*_*raj 12

在CORS请求的情况下,所有现代浏览器都使用OPTION动词进行响应,然后实际请求通过.这应该用于在CORS请求的情况下提示用户进行确认.但是如果您想要跳过此验证过程,则在API的情况下,将以下代码段添加到Global.asax

        protected void Application_BeginRequest(object sender, EventArgs e)
        {
            HttpContext.Current.Response.AddHeader("Access-Control-Allow-Origin", "*");
            if (HttpContext.Current.Request.HttpMethod == "OPTIONS")
            {
                HttpContext.Current.Response.AddHeader("Access-Control-Allow-Methods", "POST, PUT, DELETE");

                HttpContext.Current.Response.AddHeader("Access-Control-Allow-Headers", "Content-Type, Accept");
                HttpContext.Current.Response.AddHeader("Access-Control-Max-Age", "1728000");
                HttpContext.Current.Response.End();
            }
        }
Run Code Online (Sandbox Code Playgroud)

这里我们只是通过检查OPTIONS动词来通过检查.


Mat*_*ter 8

我刚刚在Web.config中添加了自定义标题,它就像一个魅力.

在配置 - system.webServer:

<httpProtocol>
  <customHeaders>
    <add name="Access-Control-Allow-Origin" value="*" />
    <add name="Access-Control-Allow-Headers" value="Content-Type" />
  </customHeaders>
</httpProtocol>
Run Code Online (Sandbox Code Playgroud)

我有相同解决方案的前端应用程序和后端.为此,我需要将Web服务项目(Backend)设置为默认设置.

我正在使用ReST,没有尝试过其他任何东西.