简体   繁体   中英

Getting back a 405 Method Not Allowed from NotFound()

In an ASP.NET Core 2.2 MVC app, I have a View that makes an Ajax request back to a controller, the request goes through and gets to the controller where a condition is met that should return a NotFoundResult (404):

$.ajax({
    type: "POST",
    url: "/My/AjaxAction",
    data: {
        name: name
    }
})

[HttpPost]
public async Task<IActionResult> AjaxAction(string name)
{
    if (/* condition */)
    {
        return NotFound();
    }

    //....
}

When testing this I get back a 405 Method Not Allowed response instead of a 404. I debugged and verified that I am hitting the NotFound() line. However the EndpointMiddleware is changing the response to a 405 and I don't know why:

info: Microsoft.AspNetCore.Mvc.StatusCodeResult[1] Executing HttpStatusCodeResult, setting HTTP status code 404 info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2] Executed action MyProject.MyController.AjaxAction (MyProject) in 2071.1794ms info: Microsoft.AspNetCore.Routing.EndpointMiddleware[1] Executed endpoint 'MyProject.MyController.AjaxAction (MyProject)' info: Microsoft.AspNetCore.Routing.EndpointMiddleware[0] Executing endpoint '405 HTTP Method Not Supported'

Other Ajax actions using POST in the application still work fine, it's just this one that is the problem.

Update: If I don't satisfy the condition for NotFound() and instead return an Ok() as normal, then it returns the correct response as it should. It's only 404s are that being changed to 405s.

This is a long discussion on GitHub: https://github.com/aspnet/Mvc/issues/388

In resume you are always calling the url: /My/AjaxAction and you want to sometimes it returns 404 (This endpoint does not exist) and sometimes returns 200 . But it is the same route, so it will be a bit confusing for the consumers of your api. I believe that's why Asp.Net teams is doing this.

You can make a few changes to solve it.

One option is to add the name parameters on url so your url will not be always the same and you'll be able to return not found.

$.ajax({
    type: "POST",
    url: "/My/AjaxAction/"+name,
    data: {
        // other datainfo 
    }
})

[HttpPost]
public async Task<IActionResult> AjaxAction(string id) // Change name to id to asp.net route understand that this parameter is in your route and not on body.
{
    if (/* condition */)
    {
        return NotFound();
    }

    //....
}

Other option is to return other type of http error. like 400

$.ajax({
    type: "POST",
    url: "/My/AjaxAction",
    data: {
        name: name
    }
})

[HttpPost]
public async Task<IActionResult> AjaxAction(string name)
{
    if (/* condition */)
    {
        return BadRequest(); // You can also add an error message or an model;
    }

    //....
}

There is a problem with your calling. Can you change the url to "/My/AjaxAction/test" instead of "/My/AjaxAction"

$.ajax({
    type: "POST",
    url: "/My/AjaxAction/test",
    data: {
        name: name
    }
})

Also, you can try specifing the route in HttpPost like:

[HttpPost("/My/AjaxAction")]
public async Task<IActionResult> AjaxAction(string id) // Change name to id to asp.net route understand that this parameter is in your route and not on body.
{
    if (/* condition */)
    {
        return NotFound();
    }

    //....
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM