在ASP Net Core Web API v3.0中启用CORS的问题

时间:2019-11-27 14:31:51

标签: asp.net-core cors asp.net-core-3.0 .net-core-3.0

我在我的Web API项目中使用asp net core 3.0。我创建了各种API,并且都可以通过Swagger或Postman访问。但是,当尝试通过其他任何客户端(如React)访问同一对象时,会收到方法不允许(405错误代码)。在进一步投资时,我发现首先是从React应用程序收到OPTION请求,并且网络核心Web API应用程序给出了405状态代码。此外,我发现我需要启用所有方法以及来自网络核心应用程序的来源以接受所有类型的请求,否则它将不接受OPTION请求。为此,我在startup.cs文件中启用了CORS策略,但是仍然没有运气。以下是我的startup.cs文件:

public class Startup
{
    public Startup(IConfiguration configuration)
    {

        Configuration = configuration;

        var elasticUri = Configuration["ElasticConfiguration:Uri"];

        Log.Logger = new LoggerConfiguration()
            .Enrich.FromLogContext()
            .Enrich.WithExceptionDetails()
            .WriteTo.Elasticsearch(new ElasticsearchSinkOptions(new Uri(elasticUri))
            {
                MinimumLogEventLevel = LogEventLevel.Verbose,
                AutoRegisterTemplate = true,
            })
        .CreateLogger();


    }

    public IConfiguration Configuration { get; }

    // This method gets called by the runtime. Use this method to add services to the container.
    public void ConfigureServices(IServiceCollection services)
    {
        services.Configure<IISServerOptions>(options =>
        {
            options.AutomaticAuthentication = false;
        });
        services.Configure<ApiBehaviorOptions>(options =>
        {
            //To handle ModelState Errors manually as ApiController attribute handles those automatically
            //and return its own response.
            options.SuppressModelStateInvalidFilter = true;
        });

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

        services.AddControllers(options =>
        {
            //To accept browser headers.
            options.RespectBrowserAcceptHeader = true;
        }).
         AddNewtonsoftJson(options =>
         {
             // Use the default property (Pascal) casing
             options.SerializerSettings.ContractResolver = new DefaultContractResolver();
             options.SerializerSettings.NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore;

         }).
        AddJsonOptions(options =>
         {
             //Not applying any property naming policy
             options.JsonSerializerOptions.PropertyNamingPolicy = null;
             options.JsonSerializerOptions.IgnoreNullValues = true;

         }).
        AddXmlSerializerFormatters().
        AddXmlDataContractSerializerFormatters();
    }

    // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
    public void Configure(IApplicationBuilder app, IWebHostEnvironment env, ILoggerFactory loggerFactory)
    {
        app.UseCors("CorsPolicy");

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

        // Enable middleware to serve generated Swagger as a JSON endpoint.
        app.UseSwagger();

        // Enable middleware to serve swagger-ui (HTML, JS, CSS, etc.),
        // specifying the Swagger JSON endpoint.
        app.UseSwaggerUI(c =>
        {
            c.SwaggerEndpoint("/swagger/v1/swagger.json", "My API V1");
        });

        app.UseRouting();

        app.UseAuthentication();

        app.UseAuthorization();

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

        //Configuring serilog
        loggerFactory.AddSerilog();

    }
}

我尝试使用POSTMAN的OPTIONS方法测试相同的API。它还给出了Http状态码405。但是当尝试使用POST方法访问相同的请求时,我成功收到了响应。

上面的代码是否有问题,或者在Configure()中调用中间件的顺序有问题?

2 个答案:

答案 0 :(得分:0)

尝试添加扩展方法并修改您的启动类:

扩展方法:

public static void AddApplicationError(this HttpResponse response, string 
    message)
{
    response.Headers.Add("Application-Error", message);
    response.Headers.Add("Access-Control-Expose-Headers", "Application-Error");
    response.Headers.Add("Access-Control-Allow-Origin", "*");
}

Startup.cs:

        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
        }
        else
        {
            app.UseExceptionHandler(builder =>
            {
                builder.Run(async context =>
                {
                    context.Response.StatusCode = (int) 
                 HttpStatusCode.InternalServerError;

                    var error = context.Features.Get<IExceptionHandlerFeature>();
                    if (error != null)
                    {
                        context.Response.AddApplicationError(error.Error.Message);
                        await context.Response.WriteAsync(error.Error.Message);
                    }
                });
            });
        }

P.S。在我的情况下,我的场景也返回了405状态错误,原因是,我使用的类似操作方法存在冲突

例如:

    [HttpGet]
    public ActionResult GetAllEmployees()

    [HttpGet]
    public ActionResult GetCustomers()

希望这至少有助于显示确切的错误消息

答案 1 :(得分:0)

您需要在您的 web api 项目下的 Startup.cs 文件中添加 Cors

  1. Startup.cs
  2. 中添加此变量
<块引用>

只读字符串 MyAllowSpecificOrigins = "_myAllowSpecificOrigins";

  1. 在文件 Startup.cs 的方法 ConfigureServices 中的 services.AddControllers() 之前添加 services.AddCors
<块引用>
services.AddCors(options =>
{
    options.AddPolicy(MyAllowSpecificOrigins,
    builder =>
    {
       builder.WithOrigins("http://localhost:4000",
       "http://www.yourdomain.com")
       .AllowAnyHeader()
       .AllowAnyMethod();
    });
});

services.AddControllers();

*** 在 WithOrigins 方法中,您只能通过 * 来允许所有,而不是通过 http://localhost:4000","http://www.yourdomain.com

  1. 在文件 Startup.cs 中的 Configure 方法中的 app.UseAuthentication() 之前添加 app.UseCors
<块引用>

app.UseCors(MyAllowSpecificOrigins);

Check this Microsoft help