【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)); //全局异常过滤
});
相关文章
|
1月前
|
开发框架 JavaScript 前端开发
揭秘:如何让你的asp.net页面变身交互魔术师——先施展JavaScript咒语,再引发服务器端魔法!
【8月更文挑战第16天】在ASP.NET开发中,处理客户端与服务器交互时,常需先执行客户端验证再提交数据。传统上使用ASP.NET Button控件直接触发服务器事件,但难以插入客户端逻辑。本文对比此法与改进方案:利用HTML按钮及JavaScript手动控制表单提交。后者通过`onclick`事件调用JavaScript函数`SubmitForm()`来检查输入并决定是否提交,增强了灵活性和用户体验,同时确保了服务器端逻辑的执行。
39 5
|
24天前
|
SQL 存储 关系型数据库
C#一分钟浅谈:使用 ADO.NET 进行数据库访问
【9月更文挑战第3天】在.NET开发中,与数据库交互至关重要。ADO.NET是Microsoft提供的用于访问关系型数据库的类库,包含连接数据库、执行SQL命令等功能。本文从基础入手,介绍如何使用ADO.NET进行数据库访问,并提供示例代码,同时讨论常见问题及其解决方案,如连接字符串错误、SQL注入风险和资源泄露等,帮助开发者更好地利用ADO.NET提升应用的安全性和稳定性。
58 6
|
20天前
|
算法 Java 中间件
C#/.NET/.NET Core优质学习资料,干货收藏!
C#/.NET/.NET Core优质学习资料,干货收藏!
|
20天前
|
人工智能 开发框架 算法
C#/.NET/.NET Core技术前沿周刊 | 第 2 期(2024年8.19-8.25)
C#/.NET/.NET Core技术前沿周刊 | 第 2 期(2024年8.19-8.25)
|
20天前
|
缓存 开发框架 算法
C#/.NET这些实用的编程技巧你都会了吗?
C#/.NET这些实用的编程技巧你都会了吗?
|
20天前
|
传感器 应用服务中间件 Linux
C#/.NET/.NET Core技术前沿周刊 | 第 3 期(2024年8.26-8.31)
C#/.NET/.NET Core技术前沿周刊 | 第 3 期(2024年8.26-8.31)
|
20天前
|
人工智能 算法 C#
C#/.NET/.NET Core技术前沿周刊 | 第 1 期(2024年8.12-8.18)
C#/.NET/.NET Core技术前沿周刊 | 第 1 期(2024年8.12-8.18)
|
30天前
|
JSON C# 开发者
💡探索C#语言进化论:揭秘.NET开发效率飙升的秘密武器💼
【8月更文挑战第28天】C#语言凭借其强大的功能与易用性深受开发者喜爱。伴随.NET平台演进,C#持续引入新特性,如C# 7.0的模式匹配,让处理复杂数据结构更直观简洁;C# 8.0的异步流则使异步编程更灵活高效,无需一次性加载全部数据至内存。通过示例展示了模式匹配简化JSON解析及异步流实现文件逐行读取的应用。此外,C# 8.0还提供了默认接口成员和可空引用类型等特性,进一步提高.NET开发效率与代码可维护性。随着C#的发展,未来的.NET开发将更加高效便捷。
43 1
|
1月前
|
开发框架 .NET Docker
【Azure 应用服务】App Service .NET Core项目在Program.cs中自定义添加的logger.LogInformation,部署到App Service上后日志不显示Log Stream中的问题
【Azure 应用服务】App Service .NET Core项目在Program.cs中自定义添加的logger.LogInformation,部署到App Service上后日志不显示Log Stream中的问题
|
1月前
|
监控 前端开发 Serverless
现代化 Web 应用构建问题之观测站点的PV、UV和API异常等指标如何解决
现代化 Web 应用构建问题之观测站点的PV、UV和API异常等指标如何解决
31 2