预检请求返回 404 Not Found for Controllers in a Area

Posted

技术标签:

【中文标题】预检请求返回 404 Not Found for Controllers in a Area【英文标题】:Preflight request returns 404 Not Found for Controllers in an Area 【发布时间】:2014-09-16 12:03:15 【问题描述】:

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

    获取 nuget 包:Install-Package Microsoft.AspNet.WebApi.Cors。 在 WebApiConfig.cs 中添加了 config.EnableCors();。 已将[EnableCors(origins: "*", headers: "*", methods: "*")] 添加到我的控制器中。

我的控制器位于根 Controllers 文件夹中,并且位于区域内。

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

两个控制器都有[EnableCors(...)] 属性。

我的问题是只有 ValuesController 有效。

使用 Fiddler 检查OtherStuffController 的请求,我可以看到客户端发送了一个预检 OPTIONS 请求,但服务器响应为 404 未找到而不是 200 OK,但 ValuesController 工作正常。

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

这两个控制器除了名称没有什么不同,而且它在一个区域中。

附加信息

路线:

// 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 请求(预照明失败):

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

【问题讨论】:

你能发布你试图查询的 URI,没有域吗?。 路由配置会有所帮助。 @Machinarius:添加了附加信息。 您是否检查过 TestAreaAreaRegistration.cs 是否正在被调用以注册其路由?也许您还想使用MapHttpRoute 而不是MapRoute @Sabacc:是的,MapHttpRoute 与 MapRoute 是个问题,谢谢。在将额外信息添加到我的帖子并并排查看两个路线定义后,我解决了这个问题。 【参考方案1】:

我找到了问题。

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

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

但是,此代码不适用于 ApiController。正确的路线注册码是:

public override void RegisterArea(AreaRegistrationContext context) 

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

事实证明这与 CORS 无关。

【讨论】:

【参考方案2】:

我通过在configuration\system.webServer\handlers 下的Web.config 文件中删除以下行来解决此问题:

<remove name="OPTIONSVerbHandler" />

【讨论】:

以上是关于预检请求返回 404 Not Found for Controllers in a Area的主要内容,如果未能解决你的问题,请参考以下文章

请求用户电子邮件时返回 404 Not Found [ASP.NET Web API]

404 NOT FOUND!

Autodesk Forge 数据管理 API 获取***文件夹请求现在返回 404 Not Found 今天始终如一,但上周工作

打开网页显示404 Not Found 如何解决

spring boot api不时返回404 Not Found

将所有 Apache 2.2 403 Forbidden 重定向到 404 Not Found