使用ExceptionHandler PipeLine时,ASP.NET Core返回404而不是500

时间:2018-02-07 15:55:52

标签: c# asp.net asp.net-mvc asp.net-core

我有这个控制器

[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();
    }
}

GET和POST请求都返回500的状态代码。这是预期的行为。

但是当我添加app.UseExceptionHandler("/api/debug/error");时 在Startup.cs文件中,POST请求不再返回状态代码500,而是返回404.通过返回状态代码500,GET请求仍然可以正常工作。

DebugController

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


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

为什么添加app.UseExceptionHandler("/api/debug/error");会使POST请求以这种方式运行?

可以找到重现此行为的仓库Here

2 个答案:

答案 0 :(得分:6)

ExceptionHandlerMiddleware与ExceptionHandlingPath一起使用时,如示例所示,主要结果是请求路径被重写为使用新路径(在您的情况下为/api/debug/error)。您可以在source

中查看其工作原理
if (_options.ExceptionHandlingPath.HasValue)
{
    context.Request.Path = _options.ExceptionHandlingPath;
}

如果您继续浏览来源,则会看到StatusCode gets set to 500,但原始请求大部分保持不变。

实际上,这意味着您将被DebugController发送到POST操作,但您只提供了GET操作。

解决此问题的一种简单方法是让Index动作支持GETPOST,如下所示:

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

如果您想为POST错误做一些不同的,您可以创建一个用[HttpPost("error")]修饰的新动作。

答案 1 :(得分:0)

我想我遇到了类似的问题。我制作了一个可从 JavaScript 调用的 API 控制器。在开发中一切正常。一段时间以来,我注意到实时站点上的 API 经常返回 404 错误,即使路由明显存在。

我想我已经找到了由实时站点上的细微差异引起的 500 个错误的问题,最明显的是在实时站点和开发站点上使用了不同版本的 SQL 数据库。所以基本上我的 API 的 GET 方法在应该返回 500 时返回了 404。听起来好像解决方案是确保我的 API 方法同时具有 [HttpGet] 和 [HttpPost] 属性。

我注意到的另一个问题是 API 调用有时会被缓存,如果您使用:

app.UseResponseCaching();

在 Startup.cs 中。这在很大程度上取决于您的托管环境。我在解决此问题的 API 路由中附加了一个随机数。