Jez
Jez

Reputation: 29973

Can't enable CORS for specific API controllers in ASP.NET Core WebApp targeting netcoreapp3.0

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?

Upvotes: 2

Views: 4702

Answers (1)

Jota.Toledo
Jota.Toledo

Reputation: 28434

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

Upvotes: 6

Related Questions