【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)); //全局异常过滤
});
相关文章
|
2月前
|
开发框架 .NET C#
C#|.net core 基础 - 删除字符串最后一个字符的七大类N种实现方式
【10月更文挑战第9天】在 C#/.NET Core 中,有多种方法可以删除字符串的最后一个字符,包括使用 `Substring` 方法、`Remove` 方法、`ToCharArray` 与 `Array.Copy`、`StringBuilder`、正则表达式、循环遍历字符数组以及使用 LINQ 的 `SkipLast` 方法。
|
2月前
.NET 4.0下实现.NET4.5的Task类相似功能组件
【10月更文挑战第29天】在.NET 4.0 环境下,可以使用 `BackgroundWorker` 类来实现类似于 .NET 4.5 中 `Task` 类的功能。`BackgroundWorker` 允许在后台执行耗时操作,同时不会阻塞用户界面线程,并支持进度报告和取消操作。尽管它有一些局限性,如复杂的事件处理模型和不灵活的任务管理方式,但在某些情况下仍能有效替代 `Task` 类。
|
2月前
|
API
使用`System.Net.WebClient`类发送HTTP请求来调用阿里云短信API
使用`System.Net.WebClient`类发送HTTP请求来调用阿里云短信API
39 0
|
4月前
|
缓存 程序员
封装一个给 .NET Framework 用的内存缓存帮助类
封装一个给 .NET Framework 用的内存缓存帮助类
|
4月前
|
开发框架 .NET 编译器
总结一下 C# 如何自定义特性 Attribute 并进行应用
总结一下 C# 如何自定义特性 Attribute 并进行应用
114 1
|
4月前
|
XML 存储 API
电商商品详情页面的获取,详情图属性sku价格的采集,API接口系列
在电商平台上,商品详情页面的获取,包括详情图、属性、SKU(Stock Keeping Unit,库存量单位)、价格等信息的采集,通常可以通过多种方式实现,其中之一是利用电商平台提供的API接口。以下是一个基于通用流程的概述,用于说明如何通过API接口系列来采集这些信息。
|
4月前
|
开发框架 前端开发 API
使用代码生成工具快速开发应用-结合后端Web API提供接口和前端页面快速生成,实现通用的业务编码规则管理
使用代码生成工具快速开发应用-结合后端Web API提供接口和前端页面快速生成,实现通用的业务编码规则管理
|
5月前
|
开发框架 前端开发 应用服务中间件
部署基于.netcore5.0的ABP框架后台Api服务端,以及使用Nginx部署Vue+Element前端应用
部署基于.netcore5.0的ABP框架后台Api服务端,以及使用Nginx部署Vue+Element前端应用
|
5月前
|
JavaScript API
前后端数据交互.js文件的axios的写法,想要往后端发送数据,页面注入API,await的意思是同步等待服务器数据,并返回,axios注入在其他页面,其他页面调用的时候,同步作用
前后端数据交互.js文件的axios的写法,想要往后端发送数据,页面注入API,await的意思是同步等待服务器数据,并返回,axios注入在其他页面,其他页面调用的时候,同步作用
|
3月前
|
开发框架 前端开发 JavaScript
ASP.NET MVC 教程
ASP.NET 是一个使用 HTML、CSS、JavaScript 和服务器脚本创建网页和网站的开发框架。
48 7