Search code examples
c#.nethttpiis

How can I solve the CORS error when trying to access a folder on server using. net core API


I am able to upload images to a folder on my server without any issues. When I want to access it I get the same folder I get a CORS error. I am using IIS 10 and my application is in .net core API

using PortalApp.Contracts.Data.Dtos.Custom;
using PortalApp.Data;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.FileProviders;
using Microsoft.IdentityModel.Tokens;
using System.Net.Sockets;
using System.Net;
using System.Text;
using Microsoft.AspNetCore.Cors.Infrastructure;

var builder = WebApplication.CreateBuilder(args);
var MyAllowSpecificOrigins = "_myAllowSpecificOrigins";

builder.Services.AddOptions<AppPortalSettings>().BindConfiguration("AppPortalSettings");
builder.Services.AddDbContext<AppPortalDatabaseContext>(options =>
    options.UseSqlServer(builder.Configuration.GetConnectionString("DefaultConnection")));
builder.Services.AddDbContext<AppPortalDatabaseContext>();
builder.Services.AddCustomServices();
builder.Services.AddMapper();
builder.Services.AddCors();
builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme).AddJwtBearer(options =>
{
    var key = builder.Configuration["AppPortalSettings:Key"];
    var issuer = builder.Configuration["AppPortalSettings:Issuer"];
    var audience = builder.Configuration["AppPortalSettings:Issuer"];

    options.TokenValidationParameters = new TokenValidationParameters
    {
        ValidateIssuer = true,
        ValidateAudience = true,
        ValidateIssuerSigningKey = true,
        ValidateLifetime = true,
        ValidIssuer = issuer,
        ValidAudience = audience,
        IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(key))
    };
});
builder.Services.AddControllers();
builder.Services.AddCors(options =>
{

    options.AddPolicy(name:"Policy1",
       builder =>
        {
            builder.SetIsOriginAllowed(origin => new Uri(origin).Host == "localhost")
                .AllowAnyHeader().AllowAnyMethod();

        });

    options.AddPolicy("MyCorsPolicy",
       builder => builder
          .SetIsOriginAllowedToAllowWildcardSubdomains()
          .WithOrigins("https://*.", "http://*.")
          .AllowAnyMethod()
          .AllowCredentials()
          .AllowAnyHeader()
          .Build()
       );
    options.AddPolicy(name: MyAllowSpecificOrigins,
      builder => builder
         .SetIsOriginAllowedToAllowWildcardSubdomains()
         .WithOrigins("http://15x.xxx.xxx.xxx:6065/", "http://*.")
         .AllowAnyMethod()
         .AllowCredentials()
         .AllowAnyHeader()
         .Build()
      );

});

builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
builder.Services.AddHttpContextAccessor();
builder.Services.AddMemoryCache(); 

var app = builder.Build();
app.UseSwagger();
app.UseSwaggerUI();
#region Use Static Files
try
{
    app.UseStaticFiles();
    app.UseStaticFiles(new StaticFileOptions
{
    FileProvider = new PhysicalFileProvider(
           Path.Combine(builder.Environment.ContentRootPath, "Uploads")),
    RequestPath = "/Uploads"
});
}
catch (Exception ex)
{
    Console.WriteLine(ex.Message + ex.StackTrace);
}
#endregion
app.UseHttpsRedirection();
app.UseCors();
app.UseCors(x => x.AllowAnyOrigin().AllowAnyMethod().AllowAnyHeader());

app.UseAuthentication();
app.UseAuthorization(); 
app.MapControllers();
app.Run();

Web Config On The Server

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <location path="." inheritInChildApplications="false">
    <system.webServer>
    <modules> 
          <remove name="WebDAVModule" /> 
         </modules> 
      <handlers>
        <add name="aspNetCore" path="*" verb="*" modules="AspNetCoreModuleV2" resourceType="Unspecified" />
         </handlers>        
      <aspNetCore processPath="dotnet" arguments=".\App.Api.dll" stdoutLogEnabled="false" stdoutLogFile=".\logs\stdout" hostingModel="inprocess"/>
   

    </system.webServer>
  </location>
</configuration>
<!--ProjectGuid: f75f628c-d8f8-41eb-b53c-9b9ec6e5a000-->

Solution

  • As per UseCors and UseStaticFiles order section of the docs:

    Typically, UseStaticFiles is called before UseCors. Apps that use JavaScript to retrieve static files cross site must call UseCors before UseStaticFiles.

    If other CORS request work then it seems that it is your case, so you can try changing the middleware order:

    app.UseCors(x => ...);
    app.UseStaticFiles(...);
    

    Or you can try leveraging the OnPrepareResponse property of StaticFileOptions to apply the CORS:

    app.UseStaticFiles(new StaticFileOptions
    {
        OnPrepareResponse = ctx => {
            ctx.Context.Response.Headers.Append("Access-Control-Allow-Origin", "*");
            ctx.Context.Response.Headers.Append("Access-Control-Allow-Headers", 
                "Origin, X-Requested-With, Content-Type, Accept");
        }
    });
    

    Or by using solution from this blog post:

    app.UseStaticFiles(new StaticFileOptions
    {
        ServeUnknownFileTypes = true,
        OnPrepareResponse = (ctx) =>
        {
            var policy = corsPolicyProvider.GetPolicyAsync(ctx.Context, "CorsPolicyName")
                .ConfigureAwait(false)
                .GetAwaiter().GetResult();
    
            var corsResult = corsService.EvaluatePolicy(ctx.Context, policy);
    
            corsService.ApplyResult(corsResult, ctx.Context.Response);
        }
    });
    

    P.S.

    Also in general you should avoid AllowAnyOrigin (though maybe it is just part of you attempts to solve the issue).