【C#/.NET】.NET6中全局异常处理

微信公众号:趣编程ACE
关注可了解每日一更的.NET日常实战开发技巧,欢迎公众号留言开发 获取源码;

.NET6中全局异常处理

异常处理是我们在程序开发中不可或缺的一环,下文我将会结合程序Sample讲解如何在.NET6中有效处理异常。

  1. Try-Ctach 块包裹

  2. 自定义异常中间件

Try-Catch 块

Try-Catch 是最基本的异常处理方法,下面我们看下例子。
创建一个基于.net6的Asp.Net Core Web Api项目

1using ExceptionHandling.Services;2using Microsoft.AspNetCore.Mvc;3namespace ExceptionHandling.Controllers;45[ApiController]6[Route("api/[controller]")]7public class UserController : Controller8{9    private readonly IUserService _userService;
10    private readonly ILogger<UserController> _logger;
11
12    /// <summary>
13    /// 依赖注入 IUserService ILogger<UserController>
14    /// </summary>
15    /// <param name="userService"></param>
16    /// <param name="logger"></param>
17    public UserController(IUserService userService, ILogger<UserController> logger)
18    {
19        _userService = userService;
20        _logger = logger;
21    }
22
23    [HttpGet]
24    public IActionResult GetUsers()
25    {
26
27       try
28       {
29           _logger.LogInformation("Get User Details");
30
31           var result = _userService.GetUsers();
32           if(result.Count==0)
33            throw new ApplicationException("Get User failed"); // 此处抛出一个获取用户出错异常
34
35           return Ok(result);
36       }
37       catch (System.Exception e)
38       {
39           _logger.LogError(e.Message);
40           return BadRequest("获取失败"); // 返回给前端
41       }
42    }
43}

我们在VsCode里面按照一个Postman插件PostCode 调用上面接口https://localhost:7218/api/User

909fba006c83470b58e086fa1eaac000.png

352aa64e9c784efd8e75aeb6566e516f.png

通过结果可知,当我们没有获取到用户的时候,代码将会抛出一个Get User failed的异常(见上图)。对于初学者来说,这是最常见最基础的方法,但是这个方法对于大项目来说也有一个缺点。

如果项目中有许多控制器和动作方法,然后我们需要对每一个动作方法都使用try-catch,那么在这种情况下,用try-catch就很累赘,也会增加代码行数。此时就需要自定义一个处理全局异常的中间件啦!

使用这个方法的好处就是我们可以在一个地方捕获未处理的异常,而不需要在每个动作方法中使用try-catch。

自定义中间件处理异常

在根目录下创建一个Middlewares文件夹,新建一个名为ExceptionHandlingMiddleware.cs

1using System.Net;2using System.Text.Json;3using ExceptionHandling.Models.Responses;45namespace ExceptionHandling.Middlewares;67public class ExceptionHandlingMiddleware8{9    private readonly RequestDelegate _next;  // 用来处理上下文请求  
10    private readonly ILogger<ExceptionHandlingMiddleware> _logger;
11    public ExceptionHandlingMiddleware(RequestDelegate next, ILogger<ExceptionHandlingMiddleware> logger)
12    {
13        _next = next;
14        _logger = logger;
15    }
16
17    public async Task InvokeAsync(HttpContext httpContext)
18    {
19        try
20        {
21            await _next(httpContext); //要么在中间件中处理,要么被传递到下一个中间件中去
22        }
23        catch (Exception ex)
24        {
25            await HandleExceptionAsync(httpContext, ex); // 捕获异常了 在HandleExceptionAsync中处理
26        }
27    }
28    private async Task HandleExceptionAsync(HttpContext context, Exception exception)
29    {
30        context.Response.ContentType = "application/json";  // 返回json 类型
31        var response = context.Response;
32
33        var errorResponse = new ErrorResponse
34        {
35            Success = false
36        };  // 自定义的异常错误信息类型
37        switch (exception)
38        {
39            case ApplicationException ex:
40                if (ex.Message.Contains("Invalid token"))
41                {
42                    response.StatusCode = (int) HttpStatusCode.Forbidden;
43                    errorResponse.Message = ex.Message;
44                    break;
45                }
46                response.StatusCode = (int) HttpStatusCode.BadRequest;
47                errorResponse.Message = ex.Message;
48                break;
49            case KeyNotFoundException ex:
50                response.StatusCode = (int) HttpStatusCode.NotFound;
51                errorResponse.Message = ex.Message;
52                break;
53            default:
54                response.StatusCode = (int) HttpStatusCode.InternalServerError;
55                errorResponse.Message = "Internal Server errors. Check Logs!";
56                break;
57        }
58        _logger.LogError(exception.Message);
59        var result = JsonSerializer.Serialize(errorResponse);
60        await context.Response.WriteAsync(result);
61    }
62}

这就是我们自定义的中间件,在ExceptionHandlingMiddleware中,我们首先通过依赖注入ILoggerRequestDelegate服务。委托类型_next用来处理上下文请求,要么将上下文放在中间件中处理,要么传递到下个中间链里的下一个中间件中去。

如果我们的请求发生异常,那么就会执行HandleExceptionAsync这个方法。这个方法里面会根据异常类型来返回不同的状态码并且记录到日志中去,不需要返回给调用的客户端,然后我们就可以通过检查日志来发现异常信息。

我们在Program.cs中添加自定义异常

1 app.UseMiddleware<ExceptionHandlingMiddleware>();

接着我们修改下控制器里GetUsers()这个方法,去掉try-catch,直接抛出异常

1[HttpGet]2    public IActionResult GetUsers()3    {45      _logger.LogInformation("Get User Details");67           var result = _userService.GetUsers();8           if(result.Count==0)9            throw new KeyNotFoundException("Get User failed"); // 此处抛出一个KeyNotFoundException异常
10
11           return Ok(result);
12    }

通过调试我们可以发现,当发生异常的时候,程序将会执行到HandleExceptionAsync()方法中去,接着根据类型KeyNotFoundException 返回404的状态码和异常信息。

5d583a2ac385762e5812e8208359638c.png


如需理解中间件管道执行过程可参考上篇文章:【C#/.NET】控制台上动态构建中间件管道

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/290741.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

JAVA学习笔记--初识容器类库

一、前言 JAVA中一切皆为对象&#xff0c;因而&#xff0c;持有对象显得尤为重要。 在JAVA中&#xff0c;我们可以通过创建一个对象的引用的方式来持有对象&#xff1a; HoldingObject holding; 也可以创建一个对象数组来持有一组特定类型的对象&#xff1a; HoldingObject hol…

如何保证执行异步方法时不会遗漏 await 关键字

前言在.NET Core 中已经广泛使用异步编程&#xff0c;代码中充斥着大量的 async 和 await 关键字。但有时候&#xff0c;调用一个异步方法时可能会忘了写 await。这会造成什么问题呢&#xff1f;问题重现示例代码如下&#xff1a;[HttpGet] public async Task<IEnumerable&l…

Avalonia跨平台入门第十二篇之动画效果

在前面分享的几篇中咱已经玩耍了Popup、ListBox多选、Grid动态分、RadioButton模板、控件的拖放效果、控件的置顶和置底、控件的锁定、自定义Window样式;今天趁着空闲时间接着去摸索简单的动画效果,毕竟有点动画的东西还是挺有意思的;最终实现的效果如下图:使用了Margin实现左右…

python之解析最简单的xml

1、person.xm文件如下 2、用xml.etree.ElementTree解析person.xml的实现 3、效果如下 4、总结 python里面的list []相当于java里面的list&#xff0c;然后可以改变其中的值。

mysql忘记密码,怎么办?

mysql忘记密码&#xff0c;怎么办&#xff1f;我们经常需要修改mySQL的密码&#xff0c;比如时间久了忘记了MySQL的密码&#xff0c;也或者是使用了一台别人使用过的电脑&#xff0c;不知道之前密码的情况下&#xff0c;又想使用MySQL&#xff0c;怎么办呢&#xff1f;准备工作…

三分钟学会缓存工具DiskLruCache

DiskLruCache是一个十分好用的android缓存工具&#xff0c;我们可以从GitHub上下载其源码&#xff1a;https://github.com/JakeWharton/DiskLruCache DiskLruCache所有的数据都存储在/storage/emulated/0/Android/data/应用包名/cache/XXX文件夹中(你也可以修改&#xff0c;但不…

【数据挖掘】知识总结——背景、定义、一般流程及应用(一)

数据挖掘知识总结&#xff08;一&#xff09; 1.数据挖掘产生的背景&&驱动力 DRIP&#xff08;Data Rich Information Poor&#xff09; 四种主要技术激发了人们对数据挖掘技术的开发、应用和研究的兴趣&#xff1a; 超大规模数据库的出现&#xff0c;如商业数据仓…

LinkedIn联合创始人:硅谷也就700万人,为什么能创建这么多瞩目的公司 ?

很多人不解&#xff1a;现在创业公司这么多&#xff0c;在世界任何地方都有很多人懂技术&#xff0c;营销&#xff0c;也有VC&#xff0c;可以组建团队&#xff0c;那为啥非要在硅谷做呢&#xff1f;作者董飞&#xff0c;整理了 Linkedin 创始人 Reid Hoffman 在CS183C 课程的分…

Docker容器安全的8大风险和33个最佳实践丨IDCF

作者&#xff1a;StackRox译者&#xff1a;冬哥原文&#xff1a;https://www.stackrox.io/blog/docker-security-101/容器以及例如Kubernetes等编排器开启了应用程序开发方法的新时代&#xff0c;支持微服务架构以及持续开发和交付。根据我们最新的容器状态和 Kubernetes 安全报…

iOS应用开发的五个Java开源工具

随着第三方工具的不断壮大&#xff0c;开发人员逐渐摆脱政策束缚&#xff0c;对于iOS系统的封闭性为其他语言&#xff08;如Java&#xff09;开发者诟病得到解脱&#xff0c;开始使用自己熟悉的语言来编写iOS本地应用&#xff0c;或将其他平台上的应用移植到iOS上。 本文为你介…

【Tensorflow】解决No module named ‘matplotlib‘/‘pandas‘

用Tensorflow出现No module named ‘matplotlib’/‘pandas’ 尝试网上方法打开终端pip install pandas 不成功&#xff0c;报一大堆红字错误。自己尝试了一种方法。 打开Anaconda Navigator&#xff1b;找到Environments&#xff0c;点击对应环境&#xff0c;我的是tensorfl…

人之将死其言也善?30年来死囚遗言分析

今天是感恩节&#xff0c;不知道这个话题合适不合适。我们经常会提到『死而无憾』这个词。这个词似乎是一种理想状态&#xff0c;几乎100%的人还是做不到的。那么我们的『憾』在哪里&#xff1f;这个问题看似不是难题&#xff0c;不过仔细想想是永远没答案的&#xff0c;人只有…

如何通过 C# 比较两幅图片的相似度?

咨询区 Byyo我在用 C# 实现一个可以查找重复图片的小工具&#xff0c;我目前是给每一个图片做一个 md5 码&#xff0c;然后通过 md5 值来判断图片是否相同。但现实情况要复杂的多&#xff0c;比如&#xff1a;图片被旋转了&#xff0c;比如&#xff1a;90图片大小不一致不同的压…

linux之用openssl命令Base64编码解码、md5/sha1摘要、AES/DES3加密解密

1、我们先看openssl help命令会输出什么? 2、我们用openssl命令实现字符串和文本的Base64编码和解码 openssl base64 openssl base64 -d 3、我们用openssl命令实现字符串和文本的md5/sha1摘要

陈松松:如何锁定细分领域,视频营销才更容易持续做下去

每个视频&#xff0c;都是你的金牌业务员这是我写的第33篇视频营销原创文章与其搜索十年&#xff0c;不如花一年的时间学习&#xff0c;去赚9年的高薪&#xff01;很多朋友都在探讨&#xff0c;视频营销越来越难了&#xff0c;得转行了&#xff01;我想说的是&#xff0c;自己不…

转:工作流服务Workflow Service(1):ReceiveActivity

转&#xff1a;http://www.cnblogs.com/carysun/archive/2009/01/11/receiveactivity.html 在.NET3.5中WF提供了和WCF的整合&#xff0c;就是工作流服务&#xff0c;即使用工作流创作的 WCF服务。服务协定的实现是通过一个或多个 ReceiveActivity 活动处理的。在WCF中提供了三种…

Echart..js插件渲染报错 data.length1?

问题 getJSON提交 返回数据正常&#xff0c;在传入参数进行序列化&#xff0c;渲染报表时报错 option.data.length < 1. 分析 1.可能情况一: . 可自己明明是getJSON()把渲染放在成功回调函数里面了&#xff0c;所以显然不是这个错误 2.可能情况二 &#xff1a; 序列化数据没…

《JavaScript专家编程》——第1章 对象和原型 1.1鸟瞰JavaScript

本节书摘来自异步社区《JavaScript专家编程》一书中的第1章&#xff0c;第1.1节&#xff0c;作者&#xff1a;【美】Mark Daggett&#xff08;达格特&#xff09;著&#xff0c;更多章节内容可以访问云栖社区“异步社区”公众号查看 第1章 对象和原型 练习不会造就完美&#xf…

c#使用PdfiumViewer展示、打印pdf文档

1:简介PdfiumViewer 是一个 WinForms 控件&#xff0c;它承载一个 PdfRenderer 控件并添加一个工具栏来保存或打印 PDF 文件2:兼容性除了常规的win7 win10 也支持xp win83:对比Spire.Pdf和Adobe PDF ReaderSpire.Pdf收费且免费版只能打印三页的pdfAdobe PDF Reader每台电脑都必…

apache 静态编译和动态编译参考

apache-2.2.22 编译安装笔记 一、静态编译 在使用./configure 编译的时候&#xff0c;即没有使用--enable-mods-shared[module]或者--enable-[module]shared这2个中的一个&#xff0c;那么所有的默认模块为静态。何谓静态&#xff1f; 其实就是编译的时候所有的模块自己编译进h…