【C#】.net core2.1,自定义全局类对API接口和视图页面产生的异常统一处理

简介: 在开发一个网站项目时,异常处理和过滤功能是最基础的模块 本篇文章就来讲讲,如何自定义全局异常类来统一处理
作者:小5聊基础
简介:一只喜欢全栈方向的程序员,欢迎咨询,尽绵薄之力答疑解惑
编程原则:Write Less Do More
  • 流程图

image.png

【基本信息】

1)操作系统:windows11 <br/>
2)开发工具:VS 2017 <br/>
3)开发语言:C# <br/>
4)开发框架:.net core 2.1 <br/>
5)关键类:IAsyncExceptionFilter <br/>

【创建全局异常过滤类】

技术日新月异,同一个功能,版本肯定会在不停更新升级,除非已经弃用,因此,需要针对版本进行使用,否则可能会因为版本不用导致报错<br/>
1)继承接口类,IAsyncExceptionFilter <br/>
类来自的dll为,Microsoft.AspNetCore.Mvc.Abstractions.dll <br/>
版本:2.1.1 <br/>
2)实现接口方法,OnExceptionAsync <br/>
关键对象,ExceptionContext context,在实现方法类直接接收这个参数即可,这个参数会在目标方法发生异常后,赋值到这个参数里 <br/>

image.png

image.png

3)判断是否已经处理过异常 <br/>
如果有设置了多重嵌套过滤,那么可能会在第一层就已处理,或者根据业务需求进行灵活设定
context.ExceptionHandled==false; //未处理

4)请求协议 <br/>
可以根据http和https进行请求协议判断,也许在项目上需要对这两个请求协议做一个区别判断
context.HttpContext.Request.IsHttps

5)请求地址 <br/>
string url = http + context.HttpContext.Request.Host + context.HttpContext.Request.Path;

image.png

6)通过设置一个小技巧来判断,当前请求时api还是页面 <br/>
[Route("api/[controller]/[action]")] <br/>
bool isApi = url.IndexOf("/api/") > 0 ? true : false; <br/>
页面api标识来判断 <br/>

7)api和页面的post请求,响应json数据,页面get请求则返回页面信息

  • 类全部代码
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;
using Newtonsoft.Json;
using System;
using System.Text;
using System.Threading.Tasks;

namespace myweb.Class
{
    /// <summary>
    /// 异常处理 - 发生异常
    /// </summary>
    public class ExceptionFilter : IAsyncExceptionFilter
    {
        /// <summary>
        /// 重写OnExceptionAsync方法,定义自己的处理逻辑
        /// 测试方法-api:localhost:44345/api/LoginRegister/Test
        /// 测试方法-页面:localhost:44345/Home/Test
        /// </summary>
        /// <param name="context"></param>
        /// <returns></returns>
        public Task OnExceptionAsync(ExceptionContext context)
        {
            try
            {
                if (context.ExceptionHandled == false)
                {
                    //写入日志

                    //请求地址
                    string http = (context.HttpContext.Request.IsHttps ? "https://" : "http://");
                    string url = http + context.HttpContext.Request.Host + context.HttpContext.Request.Path;

                    bool isApi = url.IndexOf("/api/") > 0 ? true : false;
                    if (isApi)
                    {
                        var result = new 
                        {
                            message = context.Exception.Message.ToString(),
                            code = 198
                        };

                        context.Result = new ContentResult
                        {
                            StatusCode = StatusCodes.Status200OK,
                            ContentType = "application/json;charset=utf-8",
                            Content = JsonConvert.SerializeObject(result)
                        };
                    }
                    else
                    {
                        StringBuilder errorMessage = new StringBuilder();

                        //请求类型
                        var method = context.HttpContext.Request.Method;
                        int code = context.HttpContext.Response.StatusCode;
                        if (method.ToLower() == "Get".ToLower())
                        {
                            errorMessage.Clear();
                            errorMessage.Append($"<meta name=\"viewport\" content=\"width=device-width, height=device-height, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no\">");
                            errorMessage.Append($"<h1>请求页面发生异常</h1>");
                            errorMessage.Append($"<p>URL:{url}</p>");
                            errorMessage.Append($"<p>StatusCode:{code}</p>");
                            errorMessage.Append($"<p>GET</p>");

                            context.HttpContext.Response.ContentType = "text/html;charset=utf-8";
                            context.HttpContext.Response.StatusCode = 200;

                            using (var responseStream = context.HttpContext.Response.Body)
                            {
                                responseStream.Write(Encoding.Default.GetBytes(errorMessage.ToString()));
                            }
                        }
                        else
                        {
                            errorMessage.Clear();
                            errorMessage.Append($"请求页面发生异常,");
                            errorMessage.Append($"URL:{ url},");
                            errorMessage.Append($"StatusCode:{code},");
                            errorMessage.Append($"POST");

                            var result = new
                            {
                                message = errorMessage.ToString(),
                                code = 404
                            };

                            context.HttpContext.Response.ContentType = "application/json;charset=utf-8";
                            context.HttpContext.Response.StatusCode = 200;
                            using (var responseStream = context.HttpContext.Response.Body)
                            {
                                responseStream.Write(Encoding.Default.GetBytes(JsonConvert.SerializeObject(result)));
                            }
                        }
                    }
                }
            }
            catch (Exception exception)
            {
                //写入到txt
            }


            context.ExceptionHandled = true; //设置为true,表示异常已经被处理了

            return Task.CompletedTask;
        }
    }
}

【Startup启动类设置】

1)在ConfigureServices方法下设置 <br/>
因为是针对MVC方法进行异常过滤处理,所以需要在AddMvc方法进行设置

  • 部分代码
public IServiceProvider ConfigureServices(IServiceCollection services)
//===添加MVC组件===
services.AddMvc(options=> {
    options.Filters.Add(typeof(ExceptionFilter)); //全局异常过滤
});
相关文章
|
17天前
|
开发框架 .NET C#
C#|.net core 基础 - 删除字符串最后一个字符的七大类N种实现方式
【10月更文挑战第9天】在 C#/.NET Core 中,有多种方法可以删除字符串的最后一个字符,包括使用 `Substring` 方法、`Remove` 方法、`ToCharArray` 与 `Array.Copy`、`StringBuilder`、正则表达式、循环遍历字符数组以及使用 LINQ 的 `SkipLast` 方法。
|
2天前
|
编解码 监控 API
直播源怎么调用api接口
调用直播源的API接口涉及开通服务、添加域名、获取API密钥、调用API接口、生成推流和拉流地址、配置直播源、开始直播、监控管理及停止直播等步骤。不同云服务平台的具体操作略有差异,但整体流程简单易懂。
|
2天前
|
JSON C# 开发者
C#语言新特性深度剖析:提升你的.NET开发效率
【10月更文挑战第15天】C#语言凭借其强大的功能和易用性深受开发者喜爱。随着.NET平台的演进,C#不断引入新特性,如C# 7.0的模式匹配和C# 8.0的异步流,显著提升了开发效率和代码可维护性。本文将深入探讨这些新特性,助力开发者在.NET开发中更高效地利用它们。
9 1
|
13天前
|
存储 消息中间件 NoSQL
Redis 入门 - C#.NET Core客户端库六种选择
Redis 入门 - C#.NET Core客户端库六种选择
48 8
|
8天前
|
人工智能 开发框架 C#
C#/.NET/.NET Core技术前沿周刊 | 第 6 期(2024年9.16-9.22)
C#/.NET/.NET Core技术前沿周刊 | 第 6 期(2024年9.16-9.22)
|
8天前
|
人工智能 开发框架 Cloud Native
C#/.NET/.NET Core技术前沿周刊 | 第 9 期(2024年10.07-10.13)
C#/.NET/.NET Core技术前沿周刊 | 第 9 期(2024年10.07-10.13)
|
8天前
|
开发框架 前端开发 API
C#/.NET/.NET Core优秀项目和框架2024年9月简报
C#/.NET/.NET Core优秀项目和框架2024年9月简报
|
8天前
|
开发框架 NoSQL MongoDB
C#/.NET/.NET Core开发实战教程集合
C#/.NET/.NET Core开发实战教程集合
|
14天前
|
人工智能 自然语言处理 PyTorch
Text2Video Huggingface Pipeline 文生视频接口和文生视频论文API
文生视频是AI领域热点,很多文生视频的大模型都是基于 Huggingface的 diffusers的text to video的pipeline来开发。国内外也有非常多的优秀产品如Runway AI、Pika AI 、可灵King AI、通义千问、智谱的文生视频模型等等。为了方便调用,这篇博客也尝试了使用 PyPI的text2video的python库的Wrapper类进行调用,下面会给大家介绍一下Huggingface Text to Video Pipeline的调用方式以及使用通用的text2video的python库调用方式。
|
14天前
|
JSON JavaScript API
(API接口系列)商品详情数据封装接口json数据格式分析
在成长的路上,我们都是同行者。这篇关于商品详情API接口的文章,希望能帮助到您。期待与您继续分享更多API接口的知识,请记得关注Anzexi58哦!