预检请求为区域中的控制器返回404 Not Found

时间:2014-07-24 19:13:26

标签: 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: "*")]添加到我的控制器。
  4. 我的控制器位于根Controllers文件夹中,并位于区域内。

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

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

    我的问题是只有ValuesController有效。

    使用Fiddler检查OtherStuffController的请求我可以看到客户端发送了预检OPTIONS请求,但服务器响应时找不到404而不是200 OK,而ValuesController效果很好。

    我做错了什么?为什么TestArea区域中的控制器不能处理CORS请求,而值控制器呢?

    除了名称之外,两个控制器没有什么不同,并且它位于区域中。

    附加信息

    路线:

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

    我用来访问操作方法的网址:

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

2 个答案:

答案 0 :(得分:4)

我找到了问题。

通过添加&gt;在项目中创建区域时区域上下文菜单,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无关。

答案 1 :(得分:0)

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

<remove name="OPTIONSVerbHandler" />