.net5 core Razor 进阶之三:异常和日志处理

异常和日志是软件开发中不可或缺的一部分,总是成对出现,

程序运行过程中出现了异常,就需要用日志将此异常信息记录下来,为后续 debug 做参考。

在.NET5 Core Razor 中,日志和异常的处理比较简单,我们只需要做一些配置和少许编码就可以了,具体步骤如下。

注:

.NET5 Core自带的日志处理接口可以将日志信息输出到控制台、事件管理器等终端上,

但目前还不支持输出到文件,这里我们使用第三方包 Serilog.Extensions.Logging.File 来实现。

----------------------------------------------------------------------

第1步:引用 Serilog.Extensions.Logging.File 包并配置使用环境 。

具体参考这篇文章:https://www.cnblogs.com/pfm33/p/14336356.html

 

第2步:扑捉异常信息并调用相应的 Logger 方法写日志文件。

代码一般是这样的(还是以之前的学生成绩管理为例):

    public class ScoreMngModel : PageModel
    {
        private ILogger<ScoreMngModel> _logger; //定义日志对象
        private readonly ScoreContext _context;

        //在构造函数中做依赖注入
        public ScoreMngModel(ILogger<ScoreMngModel> logger, ScoreContext context)
        {
            _logger = logger; //注入日志实例
            _context = context; //注入 AuthDbContext 实例
        }

        public void OnGet()
        {
            try
            {
                _context.Database.ExecuteSqlRaw("UPDATE t_student SET class_name={0} WHERE stu_id={1}", "五(1)班", 1);
                //使用日志对象 _logger 的 LogInformation() 方法将信息写入日志文件
                _logger.LogInformation("UPDATE t_student SET class_name={0} WHERE stu_id={1}", "五(1)班", 1);
                
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, ex.Message); //使用日志对象 _logger 的 LogError() 方法将异常信息写入日志文件
            }
        }

        // 其他代码......   

    }

运行后会在解决方案的根目录下生成对应的日志文件,如下:

.net5 core Razor 进阶之三:异常和日志处理

除了 try-catch 这种方式外,还可以以  【Filter】 或 【中间件】 的方式来处理异常和记录日志 ,其区别是:

1. try-catch 方式需要在每个方法中使用 try {} catch {} 语句将代码包起来,工作量很大,不便于集中维护。

2. Filter 方式只需要实现相关的接口并做配置就可以了,非常适合捕获发生在操作中的异常,但 xxx.cshtml 中的异常无法捕获 。

3. 中间件 方式最灵活,其代码更简洁,后期维护也更方便,这是推荐的方式。

下面我们分别实现第2种和第3种方式。

 

一、Filter 方式的步骤如下:

第1步:在解决方案根目录中新建一个 Filters 的文件夹用来存放相关的类文件。

.net5 core Razor 进阶之三:异常和日志处理

第2步:在 Filters 的文件夹下新增一个自定义 Filter 类 CustomExceptionFilter ,实现 IExceptionFilter 接口,如下:

.net5 core Razor 进阶之三:异常和日志处理

代码如下:

namespace AuthManagement.Filters
{
    public class CustomExceptionFilter : IExceptionFilter
    {
        private ILogger<CustomExceptionFilter> _logger; //定义日志处理对象
        public CustomExceptionFilter(ILogger<CustomExceptionFilter> logger)
        {
            _logger = logger; //在构造函数中注入日志处理实例
        }

        // 实现 IExceptionFilter 接口的 Onexception() 方法
        public void OnException(ExceptionContext context)
        {
            //使用日志对象 _logger 的 LogError() 方法将异常信息写入日志文件
            _logger.LogError(context.Exception, context.Exception.Message); 
        }
    }
}

第3步:在 Startup.cs 的 ConfigureServices() 方法中配置 Filter,代码如下:

public void ConfigureServices(IServiceCollection services)
{ 
    services.AddScoped<CustomExceptionFilter>(); //将自定义的 ExceptionFilter 注入到容器
     
    //......          
}

删除 Logs 文件夹下之前产生的日志文件,在 .cs 文件中抛出一个 Exception , 如下:

public void OnGet()
{ 
    throw new Exception("test exception ....");
}

编译并运行程序,可以看到 Logs 文件夹下新增了一个日志文件:

.net5 core Razor 进阶之三:异常和日志处理

 

二、中间件 方式的步骤如下:

第1步:在解决方案下新增一个文件夹 Middlewares

.net5 core Razor 进阶之三:异常和日志处理

第2步:在该文件夹下新增一个 ExceptionMiddleware.cs 的中间件

.net5 core Razor 进阶之三:异常和日志处理

代码如下:

using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace AuthManagement.Middlewares
{
    // You may need to install the Microsoft.AspNetCore.Http.Abstractions package into your project
    public class ExceptionMiddleware
    {
        private ILogger<ExceptionMiddleware> _logger; //定义日志处理对象
        private readonly RequestDelegate _next;

        public ExceptionMiddleware(ILogger<ExceptionMiddleware> logger,RequestDelegate next)
        {
            _logger = logger; //在构造函数中注入日志处理对象的实例
            _next = next;
        }

        public async Task Invoke(HttpContext httpContext)
        {
            try
            {
                await _next(httpContext);
            }
            catch (Exception ex) // 用 try-catch 来捕获异常。
            {
                _logger.LogError(ex, "##异常来源:{0}", httpContext.Request.Path); //调用日志处理对象的实例记录日志
            }
        }
    }


    // Extension method used to add the middleware to the HTTP request pipeline.
    public static class ExceptionMiddlewareExtensions
    {
        public static IApplicationBuilder UseExceptionMiddleware(this IApplicationBuilder builder)
        {
            return builder.UseMiddleware<ExceptionMiddleware>();
        }
    }
}

ExceptionMiddlewareExtensions 是新增中间件时自动生成的扩展方法类,用于异常中间件的启用,所以不需要在 Startup.cs 中做设置。

测试:

在 xxx.cshtml 文件中抛出异常:

@page
@model AuthManagement.Pages.Auth.ScoreMngModel
@using AuthManagement.DbUtil.Entity2;
@{
    throw new Exception("test ()()()$$$$$$$$$$$$$");
}

或者在 xxx.cshtml.cs 文件中抛出异常:

public void OnGet()
{  
    throw new Exception("test()()()77777......");
}

编译后运行程序,都可以在 /Logs 文件夹下看到生成的日志文件,如下:

.net5 core Razor 进阶之三:异常和日志处理

这里虽然将异常记录到了日志文件中,实际项目中还需要做一下完善,

比如根据不同的异常类型跳转到一个自定义的错误页面。

 

.net5 core Razor 进阶之三:异常和日志处理

上一篇:JSTL用 <c:forEach> 遍历对象集合,而对象内含有集合属性


下一篇:关于JS类型隐式转换的完整总结