26

I have a ASP.NET 5 Web API (Well, MVC now anyway) back-end which I am consuming in with the axios library in my JS app.

My CORS config in MVC is the following:

public void ConfigureServices(IServiceCollection services)
{
      services.AddMvc();
      services.AddCors();
} 


public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{ 
      app.UseCors(builder => {
          builder.AllowAnyOrigin().AllowAnyMethod().AllowAnyHeader();
      });
}

So in other words, I should be allowing every request possible. However, while this fixed preflight requests, a POST requests still gets rejected (I can see it executes on the server, but there's no header in the response so it results in a client side error).

Does anyone have any ideas why this wouldn't work ?

These are the headers that are returned by the MVC api:

  • For the OPTIONS preflight (this one passes): OPTIONS response
  • For the actual POST request (this one does NOT pass): POST response
Ian Kemp
  • 28,293
  • 19
  • 112
  • 138
valorl
  • 1,499
  • 2
  • 14
  • 30
  • 2
    Make sure your client send origin header to your server and your server receive the origin header, if no origin header, the cors middleware will not work. And if you use this way to configure cors, you don't need to add cors to the service collection. – Norgerman May 10 '16 at 12:45
  • I just checked the requests again and both of them are sending the origin header. – valorl May 10 '16 at 12:52
  • Can you show wheather the server receive the origin header when you use the post request? Additionally, the cors middleware will always intercept the options request. And can you show me the version of cors. RC1 works correctly in my app. – Norgerman May 10 '16 at 12:58
  • The MVC dependency I am using is RC1 final and could you tell me what's the best way to check whether the server received the header ? I put a breakpoint to the action and inspected the HttpContext but there is not "HeaderOrigin" or similar in the Headers so I can't really tell whether it's null or not – valorl May 10 '16 at 13:23
  • 1
    Just use debug have a look at the `HttpContext.Request.Headers's Results View` or just print `HttpContext.Request.Headers["Origin"]` to check the header field – Norgerman May 10 '16 at 13:30
  • Thanks. Yes `{[Origin, http://localhost:8080]}` is there. – valorl May 10 '16 at 13:51
  • Interesting. I just noticed there's an unrelated bug on the back-end that makes it return 500, and when I commented that part out, the POST request executes without problems. How can it reject due to same-origin policy only when it returns 500 ? – valorl May 10 '16 at 13:54
  • 2
    When exceptions happened, the default exception handler will clear all the response headers include the cors headers. – Norgerman May 10 '16 at 14:02
  • Oh ok. Thank you for the help with debugging ! :) – valorl May 10 '16 at 14:43

9 Answers9

18

You have to add Cors before MVC. The registration order of the middleware is important. If Cors is registered after mvc it will never be called. They are called in the order of registration.

Once cors process the request, it will pass it to next middleware (Mvc)

Tseng
  • 61,549
  • 15
  • 193
  • 205
  • 1
    I changed the order and it did not make any difference. OPTIONS preflight still passes, and the following POST request throws "No 'Access-Control-Allow-Origin' header is present on the requested resource." as before. I added the responses I am getting to to the original post. – valorl May 10 '16 at 12:23
  • 4
    If it helps, the order of my "Use" calls in configure is the following: `app.UseCors` , `app.UseJwtBearerAuthentication`, `app.UseIISPlatformHandler`, `app.UseStaticFiles`, `app.UseMvc` – valorl May 10 '16 at 12:30
15

@Norgerman mentioned this in the comments, but I think it is worthy of an answer because I've made this mistake myself several times:

The CORS middleware only works on actual cross-domain requests

It is not fired if you just access a same domain request like typing a URL into the browser.

This means if you are testing you have to either use an actual cross-domain request from an XHR client on another port or domain, or an HTTP client that can explicitly poke an origin header into the HTTP request.

Rick Strahl
  • 17,302
  • 14
  • 89
  • 134
  • I found this to be the case only when NOT running through IIS express. This caused lots of confusion for me because the CORS headers were present when debugging in IIS express, but not when running pure kestrel. – AJ Richardson Aug 25 '17 at 14:00
11

The problem was actually in the fact that there was an exception in the action processing the POST request and as Norgerman mentioned, the default exception handler cleared the CORS headers.

valorl
  • 1,499
  • 2
  • 14
  • 30
  • There's an extensive thread on [github](https://github.com/aspnet/CORS/issues/46) related to this. If you follow the links it appears the issue has been fixed in 2.2, and failures will no longer cause CORS to not send headers, but I haven't tested it. – Jordan Ryder Aug 14 '18 at 12:53
  • Updated link that @Jordan posted https://github.com/dotnet/aspnetcore/issues/2378 – Ian Kemp Feb 11 '20 at 13:12
9

For .net core 1.1:

public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{ 
    app.UseCors(x => x.AllowAnyOrigin().AllowAnyMethod().AllowAnyHeader().AllowCredentials());
}
scode102
  • 329
  • 4
  • 6
  • when you choose to be specific about the origin, you also need to include the scheme as well i.e. including 'http://' e.g. builder.WithOrigins("http:// localhost:52286") – sawe May 02 '18 at 05:50
  • 2
    You should never use `AllowAnyOrigin()` with `AllowCredentials()`. Use specific origins with credentials instead. – adam0101 Aug 28 '19 at 00:50
  • 5
    As of ASP.NET Core 2.2, you **cannot** use `AllowAnyOrigin()` with `AllowCredentials()`: https://trailheadtechnology.com/breaking-change-in-aspnetcore-2-2-for-signalr-and-cors/ relevant GitHub issue: https://github.com/dotnet/aspnetcore/issues/3106 – Ian Kemp Feb 11 '20 at 13:14
  • Yes, it was for .Net Core 1.1 – scode102 Jul 04 '20 at 21:17
7

Assuming that you are trying to create a truly PUBLIC endpoint, this worked for me:

Make sure that this:

app.UseCors(builder => {
    builder.AllowAnyOrigin()
    builder.AllowAnyMethod()
    builder.AllowAnyHeader()
});

Occurs before any of these:

app.UseHttpsRedirection();
app.UseDefaultFiles();
app.UseStaticFiles();
app.UseCookiePolicy();

app.useMvc();

Remember, we are dealing with a "pipeline". The cors stuff has to be first.

Also - (again, I'm assuming, "public endpoint") - make sure that your XHR call has... xhr.withCredentials = false;

... or just omit it. If you have it set to "true", you will get a CORS warning about the "Wildcard".

Tom Stickel
  • 19,633
  • 6
  • 111
  • 113
user1628627
  • 447
  • 1
  • 6
  • 8
5

If you're using UseHttpsRedirection, make sure your app is calling the https URL and not the http one or you'll get a CORS error even though the Accept-Header-Allow-Origin header is returned.

djeastm
  • 158
  • 2
  • 8
  • Thanks for the suggestion. after seeing this i commented my line from the api template and finally cors worked. now i know where to continue investigating to get things running on my little project – Joao Vasconcelos Dec 01 '20 at 17:55
1

This is what worked for me as I was having the same problem with CORS in conjunction with axios.

Assuming that you have set up the API correctly and you have decorated the class in the API Controller with:

[EnableCors("YourCorsPolicy")]

(you will need to add the statement "using Microsoft.AspNetCore.Cors;" to your class too)

Then you need to use the following in your axios-auth.js file:

axios.defaults.headers.common['Access-Control-Allow-Origin'] = '*'

This then worked fine for me over https. This is my complete axios-auth if you need a guide.

import axios from 'axios'

const instance = axios.create({
  baseURL: 'https://localhost:56799/api'
})

axios.defaults.headers.common['Access-Control-Allow-Origin'] = '*'
axios.defaults.headers.get['Accepts'] = 'application/json'
axios.defaults.headers.post['Content-Type'] = 'application/json; charset=utf-8'

export default instance

I hope this is useful.

JonSick
  • 156
  • 9
1

For me helps this:

services.AddCors(options =>{
  options.AddPolicy(AllowAllCorsPolicy, builder =>{
    builder
    .SetIsOriginAllowed(x =>_ = true)
    .AllowAnyMethod()
    .AllowAnyHeader()
    .AllowCredentials();
  });
});

Taken from .

Anton Semenov
  • 411
  • 5
  • 11
-3

Please notice that Windows Firewall and project's .vs\config\applicationhost.config must be properly set up besides enabling CORS in your project. The checklist below can help:

  1. Is the port used by your application/API open in the firewall? If not, open it.

  2. Open your project .vs\config\applicationhost.config file and search for <binding protocol="http" bindingInformation="*:NNNNN:localhost" /> (where NNNNN is the number of the IP port used by your application/API). Add a second line after that, <binding protocol="http" bindingInformation="*:NNNNN:*" />, so you allow any IP address to access your application.

Restart IIS Express and remember that running Visual Studio as Administrator is important most of times.

After that, continue your CORS set up and testing.

Ricardo Mendes
  • 407
  • 2
  • 4
  • 11
  • this just made the app run at on 2 different ports. And in turn causes the second site not to be able to connect to port because it is already in use. – Mike Jul 06 '18 at 15:19