简体   繁体   中英

Asp.Net MVC WebApi CORS Request fails - no proposed solutions affecting the outcome

I have an Asp.Net NVC5 web application (running under Visual Studio 2017) on localhost:59569 (SiteApi). I have a second website (also running under Visual Studio 2017) on localhost:61527 (SiteClient) where a page once loaded makes the following api call to SiteApi:

$http({
    url: 'http://localhost:59569/api/V2/' + alias,
    method: 'POST',
    data: pm,
    xhrFields: { withCredentials: true },
    headers: { 'Content-Type': 'application/json; charset=utf-8' }
    })
    .then(th, ex);

NOTE: I have tried this with and without the xhrFields + withCredentials information using Microsoft IE, Microsoft Edge and Chrome.

Back on SiteApi the resulting preflight call for OPTIONS is intercepted by the following code in Global.asax which executes exactly as written and I can trace through the if statement when an inbound call for OPTIONS triggers it.

protected void Application_BeginRequest()
{
    if (Request.Headers.AllKeys.Contains("Origin") && Request.HttpMethod == "OPTIONS")
    {
        Response.Clear();
        Response.Headers.Add("Access-Control-Allow-Origin", "*");
        Response.Headers.Add("Access-Control-Allow-Headers", "Content-Type, Accept, X-Requested-With, Session");
        Response.Flush();
        Response.End();
    }
}

The intention being to send the desired headers back to the client to allow CORS to function properly - however immediately after this code is executed the web page back on SiteClient reports that the request has been blocked due to missing 'Access-Control-Allow-Origin' header is missing and I can see that none of the headers I have specified have made it back to the client.

In an attempt to have CORS work I have the following nuget packages installed on the SiteAPI project.

  • Microsoft.AspNet.Cors
  • Microsoft.AspNet.WebApi.Cors

I adjusted the WebApiConfig.Register() method to include:

   // Web API configuration and services
   config.EnableCors();

I have tried many variations of adding the filter attributes to my controller like so:

[EnableCors("*", "*", "*", SupportsCredentials = true)]

I have tried adding my own custom ActionFilterAttribute from solutions found in other CORS related questions on stackoverflow - for example (among various others):

    public override void OnActionExecuting(System.Web.Mvc.ActionExecutingContext filterContext)
    {
        filterContext.RequestContext.HttpContext.Response.AddHeader("Access-Control-Allow-Origin", "*");
        base.OnActionExecuting(filterContext);

I have the following to my web.config file:

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

I have ALL these solutions live in my project and in spite of this I still get CORS errors on the client side.

So the caveat here is that I also have a custom filter that looks up security on each API call - which works fine with ALL calls made from pages running on SiteApi. In the case of calls from SiteClient (CORS calls) the security filter never fires at all though I am getting 401 errors reported on the client in addition to the errors due to the missing CORS related headers.

I have cleared the caches of all browsers and the server itself. This is my first time working with CORS and I'm already exhausted from working with what really should be a simple solution. Looking for solutions here and would appreciate some help from those in the know.

Request Headers:

Accept: application/json, text/plain, */*
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.9
Connection: keep-alive
Content-Length: 2
Content-Type: application/json; charset=UTF-8
Host: localhost:59569
Origin: http://localhost:61527
Referer: http://localhost:61527/Home/Index
Sec-Fetch-Dest: empty
Sec-Fetch-Mode: cors
Sec-Fetch-Site: same-site
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.106 Safari/537.36 Edg/80.0.361.54

Response Headers:

Cache-Control: private
Content-Length: 6115
Content-Type: text/html; charset=utf-8
Date: Wed, 19 Feb 2020 00:46:06 GMT
Server: Microsoft-IIS/10.0
WWW-Authenticate: Negotiate
WWW-Authenticate: NTLM
X-Powered-By: ASP.NET
X-SourceFiles: =?UTF-8?B?QzpcVXNlcnNcbngyMDA4MjZcRGV2XFRlY2hJVFxFQVNJV2ViQXBwXGFwaVxWMlxHZXRDb21tYW5kcw==?=

This is the flow I use. Sometimes browsers don't like "*". Other times, browsers don't like localhost, either. This is the logic I use (modify the allow headers as you see fit). It could be the fact that you aren't allowing the access control headers in your allowed headers, too:

[Add this to Global.asax]

protected void Application_BeginRequest(object sender, EventArgs e)
{
        var originKey =
            Request.Headers.AllKeys.FirstOrDefault(
                a => a.Equals("origin", StringComparison.InvariantCultureIgnoreCase));

        if (originKey != null && Request.HttpMethod == "OPTIONS"))
        {
// Optional Whitelist check here can return without the headers below to reject CORS
            Response.Headers.Add("Access-Control-Allow-Origin", Request.Headers[originKey]);
            Response.Headers.Add("Access-Control-Allow-Credentials", "true");
            Response.Headers.Add("Access-Control-Allow-Methods", "GET, POST, PUSH, DELETE, OPTIONS");
            Response.Headers.Add("Access-Control-Allow-Headers",
                "Authorization, Content-Type, Access-Control-Allow-Headers, X-Requested-With, Access-Control-Allow-Method, Accept");

            Response.Flush();
            Response.End();
            return;
        }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM