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

查看:124
本文介绍了无法在Core管道的中间件中实现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.

我想念什么?

如果它有任何意义或兴趣,我的目标是将异常处理从我的方法移到orde中的横切Middy上,以简化代码(并且我不想应用过滤器,因为我的目标是纯粹的没有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<Task>,因此它是一个返回任务的函数.换句话说:这是一个没有返回值的异步函数.

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.

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

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