c# - 预检请求返回 404 Not Found for Controllers in an Area

标签 c# asp.net-web-api cors asp.net-mvc-areas preflight

我有一个 WebAPI 项目,我按照以下步骤启用了 CORS:

  1. 获取 nuget 包:Install-Package Microsoft.AspNet.WebApi.Cors
  2. 添加 config.EnableCors(); 到 WebApiConfig.cs。
  3. 添加了 [EnableCors(origins: "*", headers: "*", methods: "*")] 到我的 Controller 。

我的 Controller 位于 Controllers 根文件夹中的一个区域中。

/Controllers/ValuesController
/Areas/TestArea/Controllers/OtherStuffController

两个 Controller 都有 [EnableCors(...)] 属性。

我的问题是只有 ValuesController 有效。

使用 Fiddler 检查对 OtherStuffController 的请求我可以看到客户端发送了预检 OPTIONS 请求,但服务器响应 404 not found 而不是 200 OK,但是 ValuesController 完美运行。

我做错了什么?为什么 TestArea 区域中的 Controller 不能处理 CORS 请求,而 Values Controller 可以?

这两个 Controller 除了名称之外没有什么不同,而且都在一个区域中。

附加信息

路线:

// In WebApiConfig.cs
config.Routes.MapHttpRoute("DefaultApi", "{controller}/{id}", 
    new {id = RouteParameter.Optional} );

// In Areas/TestArea/TestAreaAreaRegistration.cs
context.MapRoute("TestArea_default","TestArea/{controller}/{id}",
    new {id = UrlParameter.Optional});

我用来访问操作方法的 URL:

http://localhxst:57578/values
http://localhxst:57578/testarea/otherstuff

值请求(工作):

(REQUEST)
OPTIONS http://localhost:57578/values HTTP/1.1
Host: localhost:57578
User-Agent: Mozilla/5.0 (Windows NT 6.3; WOW64; rv:31.0) Gecko/20100101 Firefox/31.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-gb,en;q=0.5
Accept-Encoding: gzip, deflate
Origin: http://localhxst:12345
Access-Control-Request-Method: GET
Access-Control-Request-Headers: authorization
Connection: keep-alive

(RESPONSE)
HTTP/1.1 200 OK
Cache-Control: no-cache
Pragma: no-cache
Expires: -1
Server: Microsoft-IIS/8.0
Access-Control-Allow-Origin: *
Access-Control-Allow-Headers: authorization
X-AspNet-Version: 4.0.30319
X-SourceFiles: =?UTF-8?B?QzpcVXNlcnNcYmVuLmdvbGRlblxEb2N1bWVudHNcV29ya1xWb2ljZVNpbXBsaWZpZWRcQVBJXFZvaWNlU2ltcGxpZmllZC5QdWJsaWNBUElcdmFsdWVz?=
X-Powered-By: ASP.NET
Date: Thu, 24 Jul 2014 20:12:56 GMT
Content-Length: 0

其次是:

(REQUEST)
GET http://localhxst:57578/values HTTP/1.1
Host: localhost:57578
User-Agent: Mozilla/5.0 (Windows NT 6.3; WOW64; rv:31.0) Gecko/20100101 Firefox/31.0
Accept: application/json
Accept-Language: en-gb,en;q=0.5
Accept-Encoding: gzip, deflate
Authorization: Bearer HQkpyzeQ5NM1Va1Ow__6N6JzuRdMweDIJDneDQer1tL1uMhkrG4gsRYkXLQ1F4782L5vDTMOkoqvOEtO753n6TJ2BU-KNaxdXRAtf336c-r8MXMi_nWliw1vT1Xa7Wmt3eV5b9HmJR4Bnmt4gTavtoC0qwQVsoX_miV_VanJ98j_aaoNdNNZcnN5FsJ2eoLx7UebBDxXBMFmXEtOUTtWCsRp-g26mwKjbK3HeDoiUU2Ivh-VleUVImdh9ASwInbZ
Referer: http://localhxst:12345/
Origin: http://localhxst:12345
Connection: keep-alive    

(RESPONSE)
HTTP/1.1 200 OK
Cache-Control: no-cache
Pragma: no-cache
Content-Type: application/json; charset=utf-8
Expires: -1
Server: Microsoft-IIS/8.0
Access-Control-Allow-Origin: *
X-AspNet-Version: 4.0.30319
X-SourceFiles: =?UTF-8?B?QzpcVXNlcnNcYmVuLmdvbGRlblxEb2N1bWVudHNcV29ya1xWb2ljZVNpbXBsaWZpZWRcQVBJXFZvaWNlU2ltcGxpZmllZC5QdWJsaWNBUElcdmFsdWVz?=
X-Powered-By: ASP.NET
Date: Thu, 24 Jul 2014 20:12:56 GMT
Content-Length: 13

["ABC","DEF"]

OtherStuff 请求(prelight 失败):

(REQUEST)
OPTIONS http://localhxst:57578/testarea/otherstuff HTTP/1.1
Host: localhost:57578
User-Agent: Mozilla/5.0 (Windows NT 6.3; WOW64; rv:31.0) Gecko/20100101 Firefox/31.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-gb,en;q=0.5
Accept-Encoding: gzip, deflate
Origin: http://localhost:12345
Access-Control-Request-Method: GET
Access-Control-Request-Headers: authorization
Connection: keep-alive

(RESPONSE)
HTTP/1.1 404 Not Found
Cache-Control: private
Content-Type: text/html; charset=utf-8
Server: Microsoft-IIS/8.0
X-AspNet-Version: 4.0.30319
X-SourceFiles: =?UTF-8?B?QzpcVXNlcnNcYmVuLmdvbGRlblxEb2N1bWVudHNcV29ya1xWb2ljZVNpbXBsaWZpZWRcQVBJXFZvaWNlU2ltcGxpZmllZC5QdWJsaWNBUElcdGVzdGFyZWFcb3RoZXJzdHVmZg==?=
X-Powered-By: ASP.NET
Date: Thu, 24 Jul 2014 20:35:08 GMT
Content-Length: 3194
<!DOCTYPE html>
<html>
    <head>
        <title>The resource cannot be found.</title>
        <meta name="viewport" content="width=device-width" />
        <style>
         body {font-family:"Verdana";font-weight:normal;font-size: .7em;color:black;} 
         p {font-family:"Verdana";font-weight:normal;color:black;margin-top: -5px}
         b {font-family:"Verdana";font-weight:bold;color:black;margin-top: -5px}
         H1 { font-family:"Verdana";font-weight:normal;font-size:18pt;color:red }
         H2 { font-family:"Verdana";font-weight:normal;font-size:14pt;color:maroon }
         pre {font-family:"Consolas","Lucida Console",Monospace;font-size:11pt;margin:0;padding:0.5em;line-height:14pt}
         .marker {font-weight: bold; color: black;text-decoration: none;}
         .version {color: gray;}
         .error {margin-bottom: 10px;}
         .expandable { text-decoration:underline; font-weight:bold; color:navy; cursor:hand; }
         @media screen and (max-width: 639px) {
          pre { width: 440px; overflow: auto; white-space: pre-wrap; word-wrap: break-word; }
         }
         @media screen and (max-width: 479px) {
          pre { width: 280px; }
         }
        </style>
    </head>

    <body bgcolor="white">

            <span><H1>Server Error in '/' Application.<hr width=100% size=1 color=silver></H1>

            <h2> <i>The resource cannot be found.</i> </h2></span>

            <font face="Arial, Helvetica, Geneva, SunSans-Regular, sans-serif ">

            <b> Description: </b>HTTP 404. The resource you are looking for (or one of its dependencies) could have been removed, had its name changed, or is temporarily unavailable. &nbsp;Please review the following URL and make sure that it is spelled correctly.
            <br><br>

            <b> Requested URL: </b>/testarea/otherstuff<br><br>

            <hr width=100% size=1 color=silver>

            <b>Version Information:</b>&nbsp;Microsoft .NET Framework Version:4.0.30319; ASP.NET Version:4.0.30319.34009

            </font>

    </body>
</html>
<!-- 
[HttpException]: The controller for path &#39;/testarea/otherstuff&#39; was not found or does not implement IController.
   at System.Web.Mvc.DefaultControllerFactory.GetControllerInstance(RequestContext requestContext, Type controllerType)
   at System.Web.Mvc.DefaultControllerFactory.CreateController(RequestContext requestContext, String controllerName)
   at System.Web.Mvc.MvcHandler.ProcessRequestInit(HttpContextBase httpContext, IController& controller, IControllerFactory& factory)
   at System.Web.Mvc.MvcHandler.BeginProcessRequest(HttpContextBase httpContext, AsyncCallback callback, Object state)
   at System.Web.Mvc.MvcHandler.BeginProcessRequest(HttpContext httpContext, AsyncCallback callback, Object state)
   at System.Web.Mvc.MvcHandler.System.Web.IHttpAsyncHandler.BeginProcessRequest(HttpContext context, AsyncCallback cb, Object extraData)
   at System.Web.HttpApplication.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute()
   at System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously)
-->

ValuesController.cs

namespace MyAPIApp.PublicAPI.Controllers
{

    [EnableCors(origins: "*", headers: "*", methods: "*")]
    [Authorize]
    public class ValuesController : ApiController
    {
        private static readonly List<string> values = new List<string> { "ABC", "DEF" };

        public IEnumerable<string> Get() { return values; }
    }
}

OtherStuffController.cs

namespace MyAPIApp.PublicAPI.Areas.TestArea.Controllers
{
    [EnableCors(origins: "*", headers: "*", methods: "*")]
    [Authorize]
    public class OtherStuffController : ApiController
    {
        private static readonly List<string> values = new List<string> { "ABC", "DEF" };

        public IEnumerable<string> Get() { return values; }
    }
}

最佳答案

我发现了问题。

当您通过“添加”>“区域”上下文菜单在项目中创建区域时,Visual Studio 使用以下代码使用 AreaRegistration 模板创建区域:

public override void RegisterArea(AreaRegistrationContext context) {
    context.MapRoute(
        "TestArea_default",
        "TestArea/{controller}/{id}",
        new {id = UrlParameter.Optional}
        );
}

但是,此代码对于 ApiControllers 是不正确的。正确的路由注册码是:

public override void RegisterArea(AreaRegistrationContext context) {

    context.Routes.MapHttpRoute(
        "TestArea_default", 
        "TestArea/{controller}/{id}", 
        new { id = RouteParameter.Optional });
}

事实证明这与CORS无关。

关于c# - 预检请求返回 404 Not Found for Controllers in an Area,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24942076/

相关文章:

java - CORS 与 com.sun.net.httpserver

javascript - XMLHttpRequest无法加载XXX No'Access-Control-Allow-Origin' header

c# - 如何将多个 MethodCallExpressions 加入一个 Expression?

c# - 如何在 MongoDB 中使用小数类型

asp.net-web-api - 将WCF数据服务OData提供程序转换为Web API的最简单方法是什么?

c# - 加号登录 URL 获取请求

c# - 通过C#检查机器上是否安装了SQL Server

c# - 如果两个条件之一为真,则结束协程

c# - EntityFramework 6 中的 IDbCommandInterceptor 是线程安全的吗

ruby-on-rails - 如果用户未经授权,如何使用设计发送 CORS header (401 响应)