无法在核心管道的中间件中实现可调用的 try-catch 捕获 [英] Can't implement invokable catch of try-catch in middleware in Core pipeline

查看:25
本文介绍了无法在核心管道的中间件中实现可调用的 try-catch 捕获的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已将自定义中间件添加到我的 Startup 类(遵循示例 此处).

I've added a custom middleware to my Startup class (following the example 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"));
}

据我所知,在控制器中的方法中抛出异常应该在自定义中间件的 try-catch 中捕获.但是 .NET Core 似乎与我的期望不一致.通过断点,我可以看到 return next() 被调用 但是 在控制器的方法抛出异常之后,异常未被捕获并且黄色标记跳过中间件全部放在最后的花括号中.

It was my understanding that throwing an exception in my method in a controller should be caught in try-catch of the custom middleware. But .NET Core seems to diagree with my expectations. By the breakpoints I can see that return next() is invoked but after the controller's method throws an exception, the exception isn't caught and the yellow marker jumps past the middleware alltoghether and lands at the end curly brace of it.

我错过了什么?

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

If it's of any significance or interest, my aim is to move out the exception handling from my methods to the cross-cut middy in orde to simplify the code (and I want not to apply filters, since I'm targetting pure WebApi without MVC). So the controller and the method look something like this.

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

推荐答案

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

The problem here is that request delegates, the executable parts of a middleware, run asynchronously. If you look at the type of next you can see that it is actually a Func<Task>, so it’s a function that returns a task. Or in other words: It’s an asynchronous function without a return value.

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

That means that in order to be able to catch exceptions, you need to keep the asynchronous context. So your custom middleware should execute asynchronously as well. If you do that, you will notice that you can catch exceptions and then respond to them accordingly, for example by writing out a plain text response (as an example):

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!");
    }
});

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

Now, if an exception is raised further down the middleware pipeline, then your custom pipeline will be able to catch it and respond to it.

这篇关于无法在核心管道的中间件中实现可调用的 try-catch 捕获的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆