跟着官网学ASP.NET Core 6.0之异常处理

跟着官网学ASP.NET Core 6.0之异常处理

我们写代码过程中,异常是较为常见的,如果用户直接看到我们未处理好的异常的话,用户体验是非常不好的,所以,我们需要了解一下如何来处理程序中的异常。

这里我新建了一个名为ExceptionController的控制器,加入几行简单的代码

1
2
3
4
5
6
7
8
9
[Route("api/[controller]")]
[ApiController]
public class ExceptionController : ControllerBase
{
[HttpGet]
public string Test() {
throw new ArgumentException("参数有误");
}
}

这时候来我们Debug模式看看程序是什么现象,

通过Swagger或者是浏览器直接访问,就可以看到上面这些错误提示,并且在控制台也会记录相关错误信息

如果我们正式部署之后,服务端默认只会返回Status Code500,其他信息则只能在后端控制台或者日志中才能看到。

这种方式显然是不友好的,所以,我们需要多异常进行处理

异常处理程序

当程序发生异常时,我们可以借助UseExceptionHandler中间件来路由到相应的错误。这里,我们分别对开发环境和非开发环境创建一个路由,如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
[Route("/error-local-development")]
public IActionResult ErrorLocalDevelopment(
[FromServices] IWebHostEnvironment webHostEnvironment)
{
if (webHostEnvironment.EnvironmentName != "Development")
{
throw new InvalidOperationException(
"This shouldn't be invoked in non-development environments.");
}

var context = HttpContext.Features.Get<IExceptionHandlerFeature>();

return Problem(
detail: context.Error.StackTrace,
title: context.Error.Message);
}

[Route("/error")]
public IActionResult Error() => Problem();

然后在Program.cs中使用UseExceptionHandler中间件

1
2
3
4
5
6
7
8
9
if (app.Environment.IsDevelopment())
{
app.UseSwagger();
app.UseSwaggerUI();
app.UseExceptionHandler("/error-local-development");
}
else {
app.UseExceptionHandler("/error");
}

这时候,我们再来访问一次,

这是开发模式

这是非开发模式

这样的相应格式,确实要比之前的要稍微直观一点,但是对于前端展示,还是一脸懵逼。

使用异常来修改响应

前面的方式,依然不够友好,官网说,可以通过Filter来处理我们的异常,那我们就依样画葫芦,先新建一个名为HttpExceptionFilter的类,然后继承IActionFilter, IOrderedFilter这两个接口,IActionFilter主要是处理异常,IOrderedFilter则处理Filter发处理顺序,因为框架中有其他的Filter要运行,要让我们自定义的Filter生效,那么就放置在最后,代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public class HttpExceptionFilter : IActionFilter, IOrderedFilter
{
public int Order { get; } = int.MaxValue - 10;

public void OnActionExecuted(ActionExecutedContext context)
{

context.Result = new ObjectResult("服务异常")
{
StatusCode = ((int)HttpStatusCode.BadGateway),
};
context.ExceptionHandled = true;

}

public void OnActionExecuting(ActionExecutingContext context)
{
}
}

Program.cs中添加Filter

1
builder.Services.AddControllers(options => options.Filters.Add(new HttpExceptionFilter()))



喏,这就是我们的实践成果,但是,对于WebApi来说,这种格式显然是要不得的,我们还需要统一一下返回格式,所以,我们对这个Filter改造一下

1
2
3
4
5
6
7
8
9
10
public void OnActionExecuted(ActionExecutedContext context)
{

context.Result = new ObjectResult(new { Code = 500, Msg = "服务端异常" })
{
StatusCode = ((int)HttpStatusCode.BadGateway),
};
context.ExceptionHandled = true;

}

这样子是要好一些了,但是所有的异常都提示这个,显然是不行的,所以,我们需要自定义错误类,这里新建一个名为BizException的类,继承Exception

1
2
3
4
5
6
7
8
9
public class BizException: Exception
{
public int Status { get; set; } = 201;
public string Tips { get; set; }

public BizException(string message) {
Tips = message;
}
}

控制器中的访问使用自定义的异常类

1
2
3
4
[HttpGet]
public string Test() {
throw new BizException("参数有误");
}

Filter中的OnActionExecuted方法中针对不同的异常来处理返回信息

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public void OnActionExecuted(ActionExecutedContext context)
{

if (context.Exception is BizException)
{
BizException bizException = (BizException)context.Exception;
context.Result = new ObjectResult(new { Code = bizException.Status, Msg = bizException.Tips })
{
StatusCode = ((int)HttpStatusCode.BadGateway),
};
}
else
{
context.Result = new ObjectResult(new { Code = 500, Msg = "服务端异常" })
{
StatusCode = ((int)HttpStatusCode.BadGateway),
};
}
context.ExceptionHandled = true;
}

这样一来,我们的异常则会统一处理了,前端是可以直观的看到信息提示了,那么后端也得把异常信息记录下来,不然到时候出错了,不是前端一脸懵逼了,该是后端开始懵逼了。处理使用Filter来处理异常,还可以使用自定义中间件来处理。

这里,我们简单的了解了通过Filter来处理异常,本文只是简单的示例,实际开发中则需要更强的逻辑,下面,我继续学习ASP.NET Core 中间件

跟着官网学ASP.NET Core 6.0之异常处理

https://blogs.52fx.biz/posts/913330324.html

作者

eyiadmin

发布于

2022-02-04

更新于

2024-05-31

许可协议

评论