Want to get 405 (Method Not Allowed) instead of 404
Asked Answered
B

1

5

I am trying to get 405 errors when a valid route is supplied but the HTTP method is not found. Currently, the application returns 404s as it requires both the route and method to match on the function (expected behaviour in MVC).

[HttpGet("api/action")]
public IActionResult ActionGet()
{
    // code
}

[HttpPost("api/action")]
public IActionResult ActionPost()
{
    //code
}

In this example, if I do a DELETE or PUT request it won't route to either of those functions and just return a 404.

My current solution is to create a function in every controller which has all the routes hardcoded to catch the request no matter what HTTP method is used. This will then just throw a 405 error.

[Route("api/action", Order = 2)]
public IActionResult Handle405()
{
    return StatusCode(405);
}

However, I don't really like this way too much as it duplicates the code over several controllers and the hardcoded route list needs to be updated every time a new action is created in the controller.

Is there a cleaner solution available to handle the routes in the way I want? Such as using attributes or filters?

Brahmani answered 19/4, 2019 at 9:45 Comment(1)
Try the ProducesResponseType attributeGunnery
M
7

Since ASP.NET Core 2.2, the MVC services support your desired behavior by default. Make sure that the compatibility version of the MVC services is set to Version_2_2 within the ConfigureServices method.

Startup.cs

// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
    services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
}

Example

For demonstration purposes, I have created an API controller similar to yours.

ActionsController.cs

[Route("api/[controller]")]
[ApiController]
public class ActionsController : ControllerBase
{
    [HttpGet("action")]
    public IActionResult ActionGet()
    {
        return Ok("ActionGet");
    }

    [HttpPost("action")]
    public IActionResult ActionPost()
    {
        return Ok("ActionPost");
    }
}

GET Request

GET /api/actions/action HTTP/1.1
Host: localhost:44338

200 ActionGet

POST Request

POST /api/actions/action HTTP/1.1
Host: localhost:44338

200 ActionPost

PUT Request

PUT /api/actions/action HTTP/1.1
Host: localhost:44338

405 Method Not Allowed

Martial answered 19/4, 2019 at 11:45 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.