简体   繁体   中英

ASP.NET Core returns 404 instead of 500 when using ExceptionHandler PipeLine

I have this controller

[Route("api/[controller]")]
public class ValuesController : Controller
{
    // GET api/values
    [HttpGet]
    public IEnumerable<string> Get()
    {
        Console.WriteLine("GET Index");
        throw new Exception();
    }

    // POST api/values
    [HttpPost]
    public void Post()
    {
        Console.WriteLine("POST Index");
        throw new Exception();
    }
}

Both the GET and POST request returns a statuscode of 500. This is the expected behavior.

But when I add app.UseExceptionHandler("/api/debug/error"); In the Startup.cs file, the POST request does no longer return a statuscode of 500, instead it returns 404. The GET request is still working as it should by returning a statuscode of 500.

DebugController

[Route("api/[controller]")]
public class DebugController : Controller
{


    [HttpGet("error")]
    public IActionResult Index()
    {
        return StatusCode(500,"Hello, World! From debug controller");
    }
}

Any idé why adding app.UseExceptionHandler("/api/debug/error"); would make the POST request behave this way?

A repo to reproduce this behavior can be found Here .

When using ExceptionHandlerMiddleware with an ExceptionHandlingPath, as in your example, the main outcome is that the request path gets rewritten to instead use your new path ( /api/debug/error in your case). You can see how this works in the source :

if (_options.ExceptionHandlingPath.HasValue)
{
    context.Request.Path = _options.ExceptionHandlingPath;
}

If you continue to browse through the source, you'll see that the StatusCode gets set to 500 , but the original request is left mostly intact.

In practical terms, this means you are being sent to a POST action on your DebugController , but you have only provided a GET action.

A simple way to fix this would be to make your Index action support both GET and POST , like so:

[HttpGet("error")]
[HttpPost("error")]
public IActionResult Index()
{
    return StatusCode(500,"Hello, World! From debug controller");
}

If you want to do something different for POST errors, you can just create a new action, decorated with [HttpPost("error")] .


Update: Some of this explanation now exists in the docs :

The exception handling middleware re-executes the request using the original HTTP method. If an error handler endpoint is restricted to a specific set of HTTP methods, it runs only for those HTTP methods. For example, an MVC controller action that uses the [HttpGet] attribute runs only for GET requests. To ensure that all requests reach the custom error handling page, don't restrict them to a specific set of HTTP methods.

To handle exceptions differently based on the original HTTP method:

  • For Razor Pages, create multiple handler methods. For example, use OnGet to handle GET exceptions and use OnPost to handle POST exceptions.
  • For MVC, apply HTTP verb attributes to multiple actions. For example, use [HttpGet] to handle GET exceptions and use [HttpPost] to handle POST exceptions.

I think I've been having a similar problem. I made an API controller callable from JavaScript. Everything works fine on development. I have noticed for a while that the API on the live site often returns a 404 error, even though the route is obviously there.

I think I have tracked down the issue which was 500 errors caused by subtle differences on the live site, most notably using a different version of the SQL database on live and dev. So basically my API's GET method was returning a 404 when it should have been returning 500. It sounds as if the solution is to ensure my API methods have both [HttpGet] and [HttpPost] attributes.

One other issue I have noticed is that API calls are sometimes cached if you use:

app.UseResponseCaching();

in Startup.cs. This very much depends on your hosting environment. I append a random number to my API route that resolves this.

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