1
votes

I use asp.net core 2.1 to build web API and use ajax on my web to request the api.

First I got problem on the GET method, I use a chrome plugin to solve the problem.

But I still can't work on the post method.

On the webpage

POST https://localhost:5001/api/chatbot 400 (Bad Request)

The Visual Studio show the Exception.

[40m[32minfo[39m[22m[49m: Microsoft.AspNetCore.Hosting.Internal.WebHost1 Request starting HTTP/1.1 OPTIONS https://localhost:5001/api/chatbot
Microsoft.AspNetCore.Hosting.Internal.WebHost:Information: Request starting HTTP/1.1 OPTIONS https://localhost:5001/api/chatbot
Microsoft.AspNetCore.Cors.Infrastructure.CorsService:Information: Policy execution failed. [40m[32minfo[39m[22m[49m: Microsoft.AspNetCore.Cors.Infrastructure.CorsService[5] Policy execution failed. [40m[32minfo[39m[22m[49m: Microsoft.AspNetCore.Cors.Infrastructure.CorsService[7] Request method POST not allowed in CORS policy. Microsoft.AspNetCore.Cors.Infrastructure.CorsService:Information: Request method POST not allowed in CORS policy. [40m[32minfo[39m[22m[49m: Microsoft.AspNetCore.Hosting.Internal.WebHost[2] Request finished in 21.587ms 204

And I already use cors in Startup.cs - ConfigureServices()

options.AddPolicy("CorsPolicy", policy =>
            {
                policy.AllowAnyOrigin()
                      .AllowAnyHeader()
                      .AllowAnyMethod()
                      .AllowCredentials();
            });

Startup.cs - Configure()

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
    {
        string swwwRootPath = env.WebRootPath; 
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
        }
        else
        {
            app.UseHsts();
        }
        app.UseStaticFiles();

        app.UseAuthentication();

        //app.UseHttpsRedirection();
        app.UseExceptionHandler("/Error");
        //app.UseCors(builder => 
        //builder.WithOrigins("file:///").AllowAnyHeader());

        app.UseCors("CorsPolicy");

        app.UseCors(builder => {
            builder.WithOrigins("file:///").AllowAnyHeader();
        });

        app.UseMvc();
    }

And my ajax function

var json = {"channel":"web", "message":"", "messagetype":"text", "userid":"xxx", "nodeid":nodeid};
$.ajax({
        method: 'POST',
        url: "https://localhost:5001/api/chatbot",
        data: json,
        datatype: "json",
        contentType: "application/json; charset=utf-8",
        success:...

My Controller

[ApiController]
[Route("api/[controller]")]
public class ChatbotController : Controller
{
    [HttpPost]
    [EnableCors("CorsPolicy")]
    [Produces("application/json")]
    public ActionResult<string> Post([FromBody]RequestModel request)
    {...

RequestModel

public class RequestModel
{
    public string channel { get; set; }
    public string message { get; set; }
    public string messagetype { get; set; }
    public string userid { get; set; }
    public string nodeid { get; set; }
}

Both GET and POST Method I can get the correct response when I using Postman.

Does anyone know how to fix it? Thanks.

2
By the way, the Access-Control-Allow-* headers must be sent by the server in response to an OPTIONS request, not be the client in a request as it seems you are trying here...marekful

2 Answers

0
votes

Edit: now that you provided more code it is clear. This

    app.UseCors(builder => {
        builder.WithOrigins("file:///").AllowAnyHeader();
    });

overrides the initial global cors-settings and this is why it is not working. Enabling cors for a function or a controller doesn't sound like a good idea. CORS is for safety within browsers. You file:/// doesn't make sense here and is not necessary.

Adjust the method call app.UseCors(); to app.UseCors("CorsPolicy");. You have to provide the name you have defined.

0
votes

I had a similar issue, I had to add this line of code above my controller as well, to allow that actual call. Please note that you can alter the headers and method attributes as this will allow everything...

[EnableCors(origins: "http://yoursitenamehere.org", headers: "*", methods: "*")]
public class SampleController : ApiController
{}

Or you can replace the "http://yoursitenamehere.org" with * inorder to again allow everything. Dont forget to change this before releasing to prod, lol.