惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

阮一峰的网络日志
阮一峰的网络日志
Jina AI
Jina AI
GbyAI
GbyAI
D
DataBreaches.Net
人人都是产品经理
人人都是产品经理
Hugging Face - Blog
Hugging Face - Blog
V
Visual Studio Blog
P
Proofpoint News Feed
The Cloudflare Blog
H
Help Net Security
MyScale Blog
MyScale Blog
T
The Blog of Author Tim Ferriss
量子位
博客园 - 聂微东
Apple Machine Learning Research
Apple Machine Learning Research
T
Tailwind CSS Blog
博客园 - 三生石上(FineUI控件)
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
MongoDB | Blog
MongoDB | Blog
Last Week in AI
Last Week in AI
大猫的无限游戏
大猫的无限游戏
小众软件
小众软件
月光博客
月光博客

博客园 - 试试手气

Web Worker 入门 若依Ruoyi分离版替换 MyBatis-Plus 若依前端菜单管理中路由地址、组件路径、权限字符的使用 Idea clone 项目推送到自有仓库 Spring Boot —— Spring Security Spring Boot —— 集成文档工具 Spring Boot —— Filter 过滤器 Spring Boot —— Cors 跨域 Spring Boot —— 集成 Druid Spring Boot —— 集成 MyBatis-Plus Spring Boot —— 集成 Springdoc Navicat 使用笔记 Datagrip连接SQLServer失败 Asp.net Core 笔记 mybatis 笔记 SQLServer 笔记 Asp.net Core 全局异常处理 SqlSugar 实践笔记 Asp.net Core 基于Cookie的身份认证
Asp.net mvc 笔记
试试手气 · 2023-08-23 · via 博客园 - 试试手气

捕捉处理全局异常

  1. 自定义异常处理类如LogErrorAttribute继承HandleErrorAttribute并重写OnException实现处理逻辑
  2. LogErrorAttribute加入启动时的Filter注册使之在管道中生效
  3. 在需要捕捉异常的Controller、Action上使用它

自定义异常处理类

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using NLog;
using EmpowerApiService.Entity;
using Newtonsoft.Json;

namespace EmpowerApiService.Filter
{
    public class LogErrorAttribute : HandleErrorAttribute
    {
        private static NLog.Logger logger = NLog.LogManager.GetCurrentClassLogger();

        public override void OnException(ExceptionContext filterContext)
        {
            // 如果发现被处理过,则不进行处理
            if (filterContext.ExceptionHandled) { return; }

            // 可获取一些关键参数待用
            var controllerName = (string)filterContext.RouteData.Values["controller"];
            var actionName = (string)filterContext.RouteData.Values["action"];

            // 将http上下文关键信息写入日志
            if (filterContext.HttpContext != null && filterContext.HttpContext.Request != null)
            {
                var requestUrl = filterContext.HttpContext.Request.Url.ToString();
                var requestParams = filterContext.HttpContext.Request.Params;
                var requestParamsStr = HttpUtility.UrlDecode(requestParams.ToString());

                // 写日志
                logger.Error(
                    filterContext.Exception,
                    "url: {0}, params: {1}",
                    new Object[] { requestUrl, requestParamsStr });
            }

            // build http response result
            filterContext.Result = new JsonResult
            {
                ContentType = "applicaltion/json",
                ContentEncoding = System.Text.Encoding.UTF8,
                Data = BuildErrorData(filterContext.Exception),
                JsonRequestBehavior = JsonRequestBehavior.AllowGet
            };

            filterContext.ExceptionHandled = true;
        }

        private object BuildErrorData(Exception error)
        {
            if(error == null) { return null; }

            var ar = new AjaxResult();

            if (error is ArgumentException)
            {
                ar.Code = AjaxResult.Err_Code_BadRequest;
                ar.Message = error.Message;
            }
            else if (error is System.Runtime.InteropServices.COMException)
            {
                ar.Code = AjaxResult.Err_Code_InternalServer;
                try
                {
                    ar.Message = EmpowerUtils.EmpowerProject.TkErrorDescription(error.HResult);
                }
                catch
                {
                    ar.Message = "Toolkit error";
                }
            }
            else
            {
                ar.Code = AjaxResult.Err_Code_InternalServer;
                ar.Message = error.Message ?? AjaxResult.Err_Msg_InternalServer;
            }

            ar.Data = error.HResult.ToString("X");
            return ar;
        }
    }
}

关于自定义响应结果,需要注意的两点:

  1. 修改HttpContext.Response.StatusCode,asp.net mvc 将根据响应码自动匹配并返回对应的错误信息页面,如下图
    image
    设置ExceptionContext.Result,可返回自定义的ActionResult类型的结果,比如一个Json结构的错误消息,如下图
    image

  2. HttpContext.Response.StatusCodeExceptionContext.Result会冲突,不能同时设置这两个属性,或者说修改了StatusCode后,Result将不再起作用。

注册LogErrorAttribute

注册自定义的处理类,使之生效,替换默认的错误处理,修改APP_Start中的FilterConfig.cs

namespace EmpowerApiService
{
    public class FilterConfig
    {
        public static void RegisterGlobalFilters(GlobalFilterCollection filters)
        {
            //filters.Add(new HandleErrorAttribute());
            filters.Add(new EmpowerApiService.Filter.LogErrorAttribute());
        }
    }
}

使用[LogError]特性

在需要使用错误处理的ControllerAction上使用特性,就可以捕捉并处理异常

using EmpowerApiService.Filter;

namespace EmpowerApiService.Controllers{

   [LogError]
   public class xxxController : Controller 
   { ... }
}

使用日志组件 NLog

先从Nuget安装NLog,网文说要同时安装NLog.Config,经实测不安装也可以,测试版本是5.2.3
右键点击目标项目,新增项,选择新增配置文件,起名NLog.config
image

编辑文件如下

<?xml version="1.0"?>
<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd"
	  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	  xsi:schemaLocation="http://www.nlog-project.org/schemas/NLog.xsd"
	  autoReload="true"
	  throwException="false"
	  internalLogLevel="Off" internalLogFile="c:\temp\nlog-internal.log">

	<variable name="appName" value="EmpowerApiService" />
	
	<targets>
		<target name="logfile" 
				xsi:type="File"
				fileName="${basedir}/logs/${appName}-${shortdate}.log"
				layout="${longdate}|${uppercase:${level}}|${message}${newline}${callsite}(${callsite-filename:includeSourcePath=False}:${callsite-linenumber})|${exception:format=ToString}"
				maxArchiveFiles="999"
				archiveFileName="${basedir}/logs/${appName}-${shortdate}-${###}.log"
				createDirs="true"
				archiveAboveSize="5242880"
				archiveEvery="Day"
				archiveNumbering="Sequence"
				encoding="UTF-8"
				>
		</target>
	</targets>

	<rules>
		<logger name="*" minlevel="Debug" writeTo="logfile"/>
	</rules>
</nlog>

在需要使用日志的类中实例化日志组件即可使用
image

部署到IIS引发ComException组件异常

IIS 笔记 - Com组件异常

项目引入Com组件,VS调试运行正常,发布并部署到IIS运行报Com组件错误,解决方法:

  1. 打开应用程序池项高级设置中的允许32位应用程序