Share via

A Minimal API endpoint works using Bruno, but doesn't work from a Blazor app

Falanga, Rod, DOH 1,080 Reputation points
2026-06-15T19:12:21.76+00:00

I wrote a Minimal API project using .NET 9. It has several endpoints, which all work from a Blazor application (.NET 9) I also wrote, except for one. The endpoint that doesn't work is meant to delete a user. There are 2 endpoints which get called, one is to determine if the user has entered any data. If they have, then it shouldn't delete the user. This works fine. However, if the user hasn't entered data, then the call to the endpoint raises a "405 (Method Not Allowed)" error. What is frustrating is that if I use Bruno, the endpoint testing application, it works perfectly. I've successfully deleted 2 users using that. But if I try to delete a user with no data, it fails with that 405 error.

Here is the endpoint from the Minimal API:


app.MapDelete("/api/DeleteUser/{id}/{prodConn}", (string id, bool prodConn, IConfiguration _config, IMapper _mapper) =>
{
    TimetrackContext ctx = GetDbContext(_config, prodConn);

    //Finding the user by Employee ID
    var existingUser = ctx.PhdUsers.FirstOrDefault(u => u.PhdUserId == id);
    if (existingUser == null)
    {
        return Results.NotFound(new APIResponse<PhdUserDTO>
        {
            IsSuccess = false,
            Result = new PhdUserDTO(),
            StatusCode = System.Net.HttpStatusCode.NotFound,
            ErrorMessages = new List<string> { $"User with EmployeeId {id} not found." }
        });
    }
    //Remove the user
    ctx.PhdUsers.Remove(existingUser);
    ctx.SaveChanges();

    APIResponse<PhdUserDTO> response = new()
    {
        IsSuccess = true,
        Result = new PhdUserDTO(),
        StatusCode = System.Net.HttpStatusCode.OK
    };
    return Results.Ok(response);
})
    .WithName("DeleteUser")
    .WithOpenApi()
    .Produces<APIResponse<PhdUserDTO>>(StatusCodes.Status200OK)
    .Produces<APIResponse<PhdUserDTO>>(StatusCodes.Status404NotFound);

And here is the C# line from the Blazor app, where the error is raised:


var delResponse = await Http.GetFromJsonAsync<APIResponse<PhdUserDTO>>(string.Format(FPTimetrackCore.Models.ApiEndpoints.DeleteUser, empId, prodConn));

The ApiEndpoints.DeleteUser will return this:

"api/DeleteUser/{0}/{1}"

and that is the format we use for all the endpoints. The empId is a string and prodConn is a Boolean.

I have researched this error but the results weren't helpful. I'd appreciate some direction as to what's wrong, please.

Developer technologies | .NET | Blazor
0 comments No comments

Answer accepted by question author

MDFaizan-6337 80 Reputation points
2026-06-16T09:44:33.43+00:00

api/DeleteUser/12345/true var url = string.Format(FPTimetrackCore.Models.ApiEndpoints.DeleteUser, empId, prodConn);

Console.WriteLine(url)var url = string.Format(FPTimetrackCore.Models.ApiEndpoints.DeleteUser, empId, prodConn);

var response = await Http.DeleteAsync(url);

if (response.IsSuccessStatusCode)

{

var delResponse = await response.Content

    .ReadFromJsonAsync<APIResponse<PhdUserDTO>>();

// handle successful delete response

}

else

{

// handle 404, 405, or other erroapp.MapDelete("/api/DeleteUser/{id}/{prodConn}", ...)var url = string.Format(FPTimetrackCore.Models.ApiEndpoints.DeleteUser, empId, prodConn);

var response = await Http.DeleteAsync(url);

if (response.IsSuccessStatusCode)

{

var delResponse = await response.Content

    .ReadFromJsonAsync<APIResponse<PhdUserDTO>>();

// use delResponse

}

else

{

// hanvar delResponse = await Http.GetFromJsonAsync<APIResponse<PhdUserDTO>>(

string.Format(FPTimetrackCore.Models.ApiEndpoints.DeleteUser, empId, prodConn))app.MapDelete("/api/DeleteUser/{id}/{prodConn}", ...)https://learn.microsoft.com/api/mcp;dle error

}r responses

};

Was this answer helpful?

1 person found this answer helpful.

Answer accepted by question author

AI answer

2026-06-15T19:12:34.48+00:00

405 Method Not Allowed means the route is matched but the HTTP verb is wrong.

The Minimal API endpoint is mapped with:

app.MapDelete("/api/DeleteUser/{id}/{prodConn}", ...)

so it only accepts HTTP DELETE requests.

However, the Blazor code is calling it with:

var delResponse = await Http.GetFromJsonAsync<APIResponse<PhdUserDTO>>(
    string.Format(FPTimetrackCore.Models.ApiEndpoints.DeleteUser, empId, prodConn));

GetFromJsonAsync sends an HTTP GET request, not DELETE, so the server returns 405.

To fix this, send a DELETE request from Blazor, for example:

var url = string.Format(FPTimetrackCore.Models.ApiEndpoints.DeleteUser, empId, prodConn);
var response = await Http.DeleteAsync(url);

if (response.IsSuccessStatusCode)
{
    var delResponse = await response.Content
        .ReadFromJsonAsync<APIResponse<PhdUserDTO>>();
    // use delResponse
}
else
{
    // handle error
}

Or, if using an HttpClient extension that supports DELETE with JSON, use that instead of GetFromJsonAsync.

The reason it works in Bruno is that Bruno is correctly sending a DELETE request, matching the MapDelete endpoint.


References:

AI-generated content may be incorrect. Read our transparency notes for more information.

Was this answer helpful?

1 person found this answer helpful.

2 additional answers

Sort by: Most helpful
  1. MDFaizan-6337 80 Reputation points
    2026-06-22T20:05:36.7566667+00:00

    var delResponse = await response.Content

    .ReadFromJsonAsync<APIResponse<PhdUserDTO>>();
    

    // handle successful delete resp var url = string.Format(FPTimetrackCore.Models.ApiEndpoints.DeleteUser, empId, prodConn);

    var response = await Http.DeleteAsync(url);

    if (response.IsSuccessStatusCode)

    {

    var delResponse = await response.Content
    
        .ReadFromJsonAsync<APIResponse<PhdUserDTO>>();
    
    // use delResponse
    

    }

    else

    {

    // hanvar delResponse = await Http.GetFromJsonAsync<APIResponse<PhdUserDTO>>(
    
    string.Format(FPTimetrackCore.Models.ApiEndpoints.DeleteUser, empId, prodConn));dle error
    

    }onse

    Was this answer helpful?

    0 comments No comments

  2. Danny Nguyen (WICLOUD CORPORATION) 7,345 Reputation points Microsoft External Staff Moderator
    2026-06-16T03:23:11.83+00:00

    Hi @Falanga, Rod, DOH .

    The QA assist answer already points out the key issue correctly.

    In your Minimal API, the endpoint is registered with MapDelete:

    app.MapDelete("/api/DeleteUser/{id}/{prodConn}", ...)
    

    That means this route only accepts an HTTP DELETE request.

    However, the Blazor code is currently using:

    Http.GetFromJsonAsync<APIResponse<PhdUserDTO>>(...)
    

    GetFromJsonAsync sends an HTTP GET request, not a DELETE request. Since the route exists but does not allow GET, ASP.NET Core returns 405 Method Not Allowed.

    This also explains why the same endpoint works from Bruno. In Bruno, the request is likely being sent as DELETE, so it matches the Minimal API route.

    You can update the Blazor call to use DeleteAsync, for example:

    var url = string.Format(FPTimetrackCore.Models.ApiEndpoints.DeleteUser, empId, prodConn);
    
    var response = await Http.DeleteAsync(url);
    
    if (response.IsSuccessStatusCode)
    {
        var delResponse = await response.Content
            .ReadFromJsonAsync<APIResponse<PhdUserDTO>>();
    
        // handle successful delete response
    }
    else
    {
        // handle 404, 405, or other error responses
    }
    

    One small additional point: since prodConn is part of the route, it may also be worth checking the final URL generated by the Blazor app, for example:

    var url = string.Format(FPTimetrackCore.Models.ApiEndpoints.DeleteUser, empId, prodConn);
    Console.WriteLine(url);
    

    This helps confirm that the URL is being generated as expected, such as:

    api/DeleteUser/12345/true
    

    But based on the code shown, the main issue is the HTTP method mismatch: the API expects DELETE, while the Blazor client is currently sending GET. If you found the additional information helpful, I would greatly appreciate it if you could follow this guidance or provide feedback.

    Thank you.

    Was this answer helpful?

    0 comments No comments

Your answer

Answers can be marked as 'Accepted' by the question author and 'Recommended' by moderators, which helps users know the answer solved the author's problem.