c# - 无法在核心管道中的中间件中实现try-catch的可调用catch

标签 c# asp.net-core .net-core middleware

我已将自定义中间件添加到我的 Startup 类中(按照示例 here )。

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
  app.Use((context, next) =>
  {
    try { return next(); }
    catch (Exception exception) { return new Task(() => { }); }
  });

  app.UseCors("Welcome All");
  app.UseMvc();
  app.UseSwagger();
  app.UseSwaggerUI(_ => _.SwaggerEndpoint("/swagger/v0.1/swagger.json", "Version 0.1"));
}

据我了解,在 Controller 中的方法中抛出异常应该在自定义中间件的 try-catch 中捕获。但.NET Core 似乎与我的期望不一致。通过断点,我可以看到 return next() 被调用但是在 Controller 的方法抛出异常之后,异常没有被捕获并且黄色标记跳过中间件全部放在一起并落在它的大括号末尾。

我错过了什么?

如果它具有任何意义或兴趣,我的目标是将异常处理从我的方法移至横切中间,以简化代码(并且我不想应用过滤器,因为我的目标是纯没有 MVC 的 WebApi)。所以 Controller 和方法看起来像这样。

[Route("api/test")]
public class TestController : Controller
{
  public TestController(...) { ... }
  ...
  [HttpPost]
  public IActionResult CrashBoom([FromBody] Thing input)
  {
    if (input.isCrashworthy)
      throw new Exception("Boom")
    else
      return Ok();
  }
}

最佳答案

这里的问题是请求委托(delegate)(中间件的可执行部分)异步运行。如果你看 next 的类型你可以看到它实际上是一个 Func<Task> ,所以它是一个返回任务的函数。或者换句话说:它是一个没有返回值的异步函数。

这意味着为了能够捕获异常,您需要保留异步上下文。因此您的自定义中间件也应该异步执行。如果这样做,您会注意到您可以捕获异常,然后相应地响应它们,例如通过写出纯文本响应(作为示例):

app.Use(async (context, next) =>
{
    try
    {
        await next();
    }
    catch (Exception ex)
    {
        // let’s log the exception
        var logger = context.RequestServices.GetService<ILogger<Startup>>();
        logger.LogWarning(ex, "Encountered an exception");

        // write a response
        context.Response.StatusCode = 500;
        context.Response.ContentType = "text/plain";
        await context.Response.WriteAsync("Sorry, something went wrong!");
    }
});

现在,如果在中间件管道中进一步引发异常,那么您的自定义管道将能够捕获它并对其做出响应。

关于c# - 无法在核心管道中的中间件中实现try-catch的可调用catch,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48193220/

相关文章:

c# - 在.NET Core应用程序中使用NEST在ElasticSearch中的正确索引路径内进行批量收集

c# - 使用 SocketAsyncEventArgs 编写可扩展的套接字服务器

c# - 从 DN 获取用户信息

asp.net-core - 使用 Jwt 承载身份验证的自定义声明

asp.net-core - 如何在 Linux 上生成大小合理的 .NET Core 进程内存转储文件?

c# - EF Core EnsureDeleted 抛出 "failed to login with user ' sa'"

c# - .NET MVC Core 2.2 - 无法访问用户相关实体(外键)

c# - ASP.NET MVC 如何将 FilePath 传递给 PeopleDB?

msbuild - 在Linux上使用Mono构建VS 2017 MSBuild csproj项目

c# - 截取一帧视频文件(.Net core)