ASP.NET Core 8 Method PATCH is not allowed by Access-Control-Allow-Methods in preflight response.

Copper Contributor
 

I created a PATCH method in an ASP.NET Core Web API like this:

#region Patch

/// <summary>
///     Patch TableName by id.
/// </summary>
// PATCH BY ID: /TableName/patch/{id}
[HttpPatch("[action]/{id}", Name = "PatchTableNameById")]
[ProducesResponseType(StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status404NotFound)]
[ProducesResponseType(StatusCodes.Status400BadRequest)]
[SwaggerOperation(
     Summary = "Patch Table Name by id",
     Description = "This can be used to modify any table name record",
     OperationId = "PatchTableNameById",
     Tags = new[] { "Patch" }
 )]
public async Task<IActionResult> Patch(string id, [FromBody] JsonPatchDocument<TableName> patchDoc)
{
     if (patchDoc != null)
     {
         var tablename =
             await context.TableName.SingleOrDefaultAsync(x => x.Id.ToString() == id);
         if (tablename == null)
             return NotFound();

         patchDoc.ApplyTo(tablename);
         context.Entry(tablename).State = EntityState.Modified;

         if (!ModelState.IsValid)
         {
             return BadRequest(ModelState);
         }

         await context.SaveChangesAsync();

         return new ObjectResult(tablename);
     }
     else
     {
         return BadRequest(ModelState);
     }
}

This works perfectly fine when I call it using Postman or directly using Swagger. However in my Blazor client I get an error when it is called. I have tried using httpclient, RestSharp and now Flurl.

The error returned when using the Developer Tools console to review the log is:

Access to fetch at 'http://localhost:5259/SharedServices/Commands/TableName/patch/2bd4e0f3-974a-4794-bb63-b0ce00ba5147' from origin 'http://localhost:5265' has been blocked by CORS policy: Method PATCH is not allowed by Access-Control-Allow-Methods in preflight response.

Here is my CORS policy in the Web API. It is called before anything else adding services.

builder.Services.AddCors(options =>
{
    options.AddPolicy("AllowSpecificOrigins",
        builder =>
        {
            builder.WithOrigins("http://localhost:56075", "http://localhost:5265",
                    "https://localhost:7235").AllowAnyHeader().WithMethods("PATCH");
        });
});

I have tried various combinations here including of allowing all methods, headers, and origins. In other words opening it wide up which isn't a great security tactic anyways.

Here is my client side code for the call.

public async Task Patch(string id, JsonPatchDocument<TableName> patchDoc)
{
    var url = "http://localhost:5259/SharedServices/Commands/TableName/patch/" +
              id;
    var resultStr = await url.WithHeader("Content-Type", "application/json-patch+json").PatchJsonAsync(patchDoc)
        .ReceiveString();
}

I have tried about every online suggestion to fix this. One problem is there are a lack of issue reports for later versions of asp.net -- post addition of addCORS. I have tried various browsers thinking this maybe a browser issue but no luck there either. Is this possibly a bug in asp.net core cors? I am also using Steeltoe. Is it possible it is interfering with this?

Is there any way to turn off a preflight request or modify it?

I tried to use various clients such as httpclient, restsharp, flurl. Also tried using a PUT and got the same issue. I have also tried various browsers. The expected result is a successful unblocked call to my web api method.

Thanks for any help you can give!

2 Replies

@Ben_Pierce 

I have tried to solve and summarise your issue for the PATCH method not being allowed in Blazor due to CORS restrictions, let me know if this helps.

Understanding the Issue:

  • CORS (Cross-Origin Resource Sharing): A browser security mechanism that restricts web pages from making requests to a different domain than the one that served the page.
  • Preflight Requests (for non-standard methods like PATCH): Browsers send an initial OPTIONS request to check allowed methods before making the actual PATCH request.
  • Access-Control-Allow-Methods Header: The server must explicitly list PATCH in this response header to grant permission.

Resolving the Issue in Blazor:

  1. Configure CORS in Startup.cs:

    • Add the CORS middleware:

 

services.AddCors(options =>
{
    options.AddPolicy("AllowPATCH",
        builder => builder.WithOrigins("http://localhost:5000") // Adjust origins as needed
                           .AllowAnyMethod() // Or explicitly list PATCH
                           .AllowAnyHeader();
});

 

  • Apply the policy in the app's middleware pipeline:

 

app.UseCors("AllowPATCH");

 

  • Enable CORS in ASP.NET Core Web API (if applicable):

    • Use EnableCors attribute on controllers or actions:

 

[EnableCors("AllowPATCH")]
[HttpPatch]
public IActionResult PatchData()
{
    // ...
}

 

@JaiminsoniThank you for the helpful suggestions. This turned out to be a conflict with Steeltoe. When using AddAllActuators the Steeltoe code is adding it's own CORS policy overriding anything that I was setting up. When adding each actuator separately then it works. This was a tough one to solve. I was only able to do that by looking at the CORS policy collection and noticing there was an additional one above mine.