2

I'm trying to enable CORS for a specific API controller in an ASP.NET Core application. First, I install the NuGet package, and this is added to my .csproj:

<PackageReference Include="Microsoft.AspNetCore.Cors" Version="2.2.0" />

Then, I add the following in my ConfigureServices:

services.AddCors(options => {
    options.AddPolicy("AllowAll", builder => builder.AllowAnyOrigin().AllowAnyMethod().AllowAnyHeader());
});

After that, if I add this in my Configure, it works:

app.UseCors("AllowAll");

However, this enables CORS for all controllers. I just want to enable it for SessionApiController. If I instead add the EnableCorsAttribute to the controller:

[Route("api/session")]
[EnableCors("AllowAll")]
[ApiController]
public class SessionApiController : Controller {
    [...]

    [Route("init")]
    public JsonResult InitSession() {
        [...]
    }
}

... it doesn't work, and Chrome gives me a CORS error when I try to access the /api/session/init endpoint ("No 'Access-Control-Allow-Origin' header is present on the requested resource."). What am I missing here?

Jota.Toledo
  • 27,293
  • 11
  • 59
  • 73
Jez
  • 27,951
  • 32
  • 136
  • 233
  • 1
    the CORS has to be activated on API-Side, you could accept all headers but it has to be done on the server side via `Access-Control-Allow-Headers: *` – A.A. Aug 21 '19 at 13:34
  • Code LGTM. What happens if you instead decorate the controller method? could you provide a reproduction of your setup? – Jota.Toledo Aug 21 '19 at 13:54
  • @Jota.Toledo Decorating the controller method still doesn't add the CORS headers. I can come up with a minimal reproduction, I guess. – Jez Aug 22 '19 at 10:31
  • @Jota.Toledo I've setup a minimal reproduction based on the .NET Core WebAPI template available to be cloned from my Github account: https://github.com/jez9999/CorsTest – Jez Aug 27 '19 at 10:41
  • @Jota.Toledo If you put the example JS on the webpage of another origin (after including jQuery in the page), it won't work because of CORS policy not kicking in, even though there is a `[EnableCors("AllowAll")]` attribute on the controller. The same applies if the attribute is on the method. If you then uncomment `app.UseCors("AllowAll");` in the startup instead, it works. – Jez Aug 27 '19 at 10:43
  • @Jez your demo project is targeting `netcoreapp3.0`. Is that intentional? are you using the preview sdk in your original project? – Jota.Toledo Aug 27 '19 at 11:34
  • Yes I am using it in the original. – Jez Aug 27 '19 at 11:58
  • I was able to solve your issue, Ill add an answer. – Jota.Toledo Aug 27 '19 at 12:28

1 Answers1

6

Considering the following an ASP.NET Core WebApp:

App.csproj:

<Project Sdk="Microsoft.NET.Sdk.Web">
  <PropertyGroup>
    <TargetFramework>netcoreapp3.0</TargetFramework>
  </PropertyGroup>
  <ItemGroup>
    <PackageReference Include="Microsoft.AspNetCore.Cors" Version="2.2.0" />
  </ItemGroup>
</Project>

Extract from Startup.cs:

    public void ConfigureServices(IServiceCollection services) {
        services.AddCors(options => {
            options.AddPolicy("AllowAll", builder => builder.AllowAnyOrigin().AllowAnyMethod().AllowAnyHeader());
        });

        services.AddControllers();
    }

    // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
    public void Configure(IApplicationBuilder app, IWebHostEnvironment env) {
        app.UseCors();  // Doesn't work
        //app.UseCors("AllowAll");  // Works

        if (env.IsDevelopment()) {
            app.UseDeveloperExceptionPage();
        }

        app.UseHttpsRedirection();

        app.UseRouting();

        app.UseAuthorization();

        app.UseEndpoints(endpoints => {
            endpoints.MapControllers();
        });
    }

Extract from a controller in which you want to apply the AllowAll policy:

[EnableCors("AllowAll")]
[ApiController]
[Route("[controller]")]
public class WeatherForecastController : ControllerBase

In order to correctly apply CORS in it, you need to apply the following changes into the code as described in the migration MS docs:

  1. Remove deprecated Microsoft.AspNetCore.* packages, in your case Microsoft.AspNetCore.Cors. This results in your .csproj looking like:
 <Project Sdk="Microsoft.NET.Sdk.Web">
    <PropertyGroup>
      <TargetFramework>netcoreapp3.0</TargetFramework>
    </PropertyGroup>
  </Project>
  1. Carefully follow the middleware migration advice in the msdocs as the order is important!. This results in Startup#Configure looking as follows:

    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
        app.UseRouting();
    
        // AFAIK in netcoreapp2.2 this was not required
        // to use CORS with attributes.
        // This is now required, as otherwise a runtime exception is thrown
        // UseCors applies a global CORS policy, when no policy name is given
        // the default CORS policy is applied
        app.UseCors(); 
    
        if (env.IsDevelopment()) {
            app.UseDeveloperExceptionPage();
        }
    
        app.UseHttpsRedirection();
    
        app.UseAuthorization();
    
        app.UseEndpoints(endpoints => {
            endpoints.MapControllers();
        });
    }
    
Jota.Toledo
  • 27,293
  • 11
  • 59
  • 73
  • 1
    Yep, solved the problem too. Basically the 2 issues were: I needed to remove the `Microsoft.AspNetCore.Cors` package reference - this is apparently built-in in .NET Core 3.0 - and I needed to move `app.UseCors()` to be *after* `app.UseRouting()` - as you said, order matters. – Jez Aug 27 '19 at 13:20