【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…

Andorid之打包出现Proguard returned with erro code 1.See console解决办法

1、错误 我们进行签名操作的时候&#xff0c;提示下面错误 Proguard returned with erro code 1.See console 然后在console里面提示这个 you should check if you need to specify additional program jars 2、原因 找不到引用包导致 2、解决办法 我们可以在proguard-projec…

CCF-CSP认证201312-1(出现次数最多的数)

CCF-CSP认证201312-1&#xff08;出现次数最多的数&#xff09; 问题描述   给定n个正整数&#xff0c;找出它们中出现次数最多的数。如果这样的数有多个&#xff0c;请输出其中最小的一个。 输入格式   输入的第一行只有一个正整数n(1 ≤ n ≤ 1000)&#xff0c;表示数字…

Java的原始数据类型一共就8个

Java的原始数据类型一共就8个&#xff0c;分别是&#xff1a;byte、short、int、long、boolean、char、float、double。注意这些是大小写敏感的&#xff0c;而Boolean是boolean的封装类(wrapper class)。 在java中一个类只能有一个直接父类&#xff0c;但是可以实现多个接口&a…

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 课程的分…

LeetCode之Search Insert Position

1、问题 Given a sorted array and a target value, return the index if the target is found. If not, return the index where it would be if it were inserted in order. You may assume no duplicates in the array. Here are few examples. [1,3,5,6], 5 → 2 [1,3,5,6]…

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上。 本文为你介…

(算法)最长递增子序列

问题&#xff1a; Given an array of N integer, find the length of the longest increasing subsequence. For example, given [1,-5,4,5,10,-1,-5,7], the longest increasing subsequence is length 4.(1,4,510) 思路&#xff1a; 1、枚举 枚举数组所有的子序列&#xff0c…

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

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

Android之在一个类里面注册Handler发送消息在另外一个类里面接收消息

1、问题 我们要在一个类里面变量或者函数变化需要改变另外一个类里面的东西,这个时候java里面除了接口回调之外,我们还可以用注册Handler来实现 2、代码实现 1、MainActivity.java文件 package com.example.handlercallback;import android.app.Activity; import android.o…

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

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

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

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

linux 命令-- touch

linux中文件元数据中有三个时间戳1.atime&#xff1a;最后一次访问时间2.mtime&#xff1a;最后一次修改文件内容的时间3.ctime&#xff1a;最后一次修改文件元数据的时间。&#xff08;最后一次改变文件状态的时间&#xff0c;上面atime 和 mtime的变化、文件权限的变化等都会…