JumpIntoTheWater
JumpIntoTheWater

Reputation: 1336

405 (Method Not Allowed) and blocked by CORS policy

I have Asp.Net Core(3) WebApi project with UI based on Angular(7.2.1) on Client side. When using Postman or just using the URL I can use GET and POST without any particular errors. When trying the same by Angular(Chrome\FireFox\IE Browser) I'm getting the following errors.

zone.js:3243 OPTIONS http://localhost:8888/api/PaymentDetails 405 (Method Not Allowed) ccess to XMLHttpRequest at 'http://localhost:8888/api/PaymentDetails' from origin 'http://localhost:4200' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.

I'll try to share as much as code I can to demonstrate the flow.

WebApi Startup.cs:

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.AddCors(options =>
    {
        options.AddPolicy("CorsPolicy",
            builder =>
            builder.AllowAnyOrigin()
                   .AllowAnyMethod()
                   .AllowAnyHeader()

                );
    });
    services.AddControllers()
        .AddJsonOptions(options =>
        {
            options.JsonSerializerOptions.PropertyNameCaseInsensitive = true;
            options.JsonSerializerOptions.PropertyNamingPolicy = null;
        });

    services.AddDbContext<PaymentDetailContext>(options => options.UseSqlServer("Server=DESKTOP-KT0N2RN\\SQLEXPRESS;DataBase=PaymentDetailDB;Trusted_Connection=True;MultipleActiveResultSets=True;"));
}

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

    app.UseAuthorization();

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

    app.UseCors("CorsPolicy");
}

WebAPi GET method:

[HttpGet]
public async Task<ActionResult<IEnumerable<PaymentDetail>>> GetPaymentDetails()
{
    return await _context.PaymentDetails.ToListAsync();
}

Client Side:

rootUrl: string = "http://localhost:8888/api";

getPaymentDetail()
{
    
    console.log(`${this.rootUrl}/PaymentDetails`)
    const headers = new HttpHeaders().set('Content-Type','application/json');
    // headers.append('Access-Control-Allow-Origin', '*');
    // headers.append('Access-Control-Allow-Headers','Origin, X-Requested-With, Content-Type, Accept');
    return this._http.get(`${this.rootUrl}/PaymentDetails`,{headers:headers});
}

Upvotes: 7

Views: 12910

Answers (2)

Omer Faruk KAYA
Omer Faruk KAYA

Reputation: 396

Sometimes it occurs because of WebDAVModule.

<system.webServer>
  <modules runAllManagedModulesForAllRequests="false">
    <remove name="WebDAVModule" />
  </modules>
</system.webServer>

https://www.ryadel.com/en/error-405-methods-not-allowed-asp-net-core-put-delete-requests/

Upvotes: 0

Kevin
Kevin

Reputation: 2404

I think changing the following in Startup Configure should work. Note the order: as per the docs

With endpoint routing, the CORS middleware must be configured to execute between the calls to UseRouting and UseEndpoints. Incorrect configuration will cause the middleware to stop functioning correctly.

app.UseRouting();

app.UseAuthorization();

app.UseCors("CorsPolicy");

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

I think a really quick summary of CORs might be helpful to eexplain why postman requests were working for you.

CORS is used in browsers by default to check which origins servers will accept requests from.

if your request to the server was from the same origin (all parts of the origin must match) your CORS request would not fail because its not cross origin. In your case the ports to not match so even though both the server and web app are running from your localhost, it counts as cross origin because the ports don't match

When you send a request the browser will first send an Options request (a preflight request) which will show supported supported methods and check if your origin (your front end web app) has permission to send requests to the server. This functionality is built into most main browsers by default (Chrome, Firefox, Edge etc).

Your postman request works because postman does not send a preflight request.

Further reading:

Enabling CORS

https://learn.microsoft.com/en-us/aspnet/core/security/cors?view=aspnetcore-3.1

What is CORS

https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS

Upvotes: 14

Related Questions