在 ASP.NET Core 中记录异常信息

Author Image
admin Thursday, June 3, 2021 阅读数: 48
Share:

本文作者:梁桐铭- 微软最有价值专家(Microsoft MVP)
本文出自《从零开始学 ASP.NET Core 与 EntityFramework Core》目录
视频课程效果更佳:跨平台开发实战掌握 ASP.NET Core 与 EntityFramework Core

在 ASP.NET Core 中记录异常信息

在本章节中,我们将学习如何使用 ASP.NET Core 提供的 ILogger 接口记录我们自己的消息(Info),警告(Warnings)和异常(exceptions)信息。

当用户使用我们的应用程序时,如果有异常需要我们在某处记录异常。然后,开发人员可以查看异常日志,并在必要时提供修复。所以就需要记录异常信息,以了解在使用应用程序时生产服务器上发生了什么异常。

 public class ErrorController:Controller
    {
        private ILogger<ErrorController> logger;


       ///<summary>
       ///注入ASP.NET  Core ILogger服务。
       ///将控制器类型指定为泛型参数。
       ///这有助于我们进行确定哪个类或控制器产生了异常,然后记录它
       ///</summary>
       ///<param name="logger"></param>
        public ErrorController(ILogger<ErrorController> logger)
        {
            this.logger = logger;
        }

        [AllowAnonymous]
        [Route("Error")]
        public IActionResult Error()
        {
           //获取异常详情信息
            var exceptionHandlerPathFeature =
                    HttpContext.Features.Get<IExceptionHandlerPathFeature>();

           //LogError() 方法将异常记录作为日志中的错误类别记录
            logger.LogError($"路径 {exceptionHandlerPathFeature.Path} " +
                $"产生了一个错误{exceptionHandlerPathFeature.Error}");
            return View("Error");
        }

        [Route("Error/{statusCode}")]
        public IActionResult HttpStatusCodeHandler(int statusCode)
        {

            var statusCodeResult =
                HttpContext.Features.Get<IStatusCodeReExecuteFeature>();
            switch (statusCode)
            {
                case 404:
                    ViewBag.ErrorMessage = "抱歉,你访问的页面不存在";
               //LogWarning() 方法将异常记录作为日志中的警告类别记录
                    logger.LogWarning($"发生了一个404错误. 路径 = " +
                $"{statusCodeResult.OriginalPath} 以及查询字符串 = " +
                $"{statusCodeResult.OriginalQueryString}");
                    break;
            }
            return View("NotFound");
        }



    }

Error 和 NotFound 视图修改

因我们把消息信息改为记录到了日志中,所以我们调整我们的视图代码

Error 视图代码如下:

<h3>
  程序请求时发生了一个内部错误,我们会反馈给团队,我们正在努力解决这个问题。
</h3>
<h5>请通过 ltm@ddxc.org 与我们取得联系</h5>

NotFound 视图代码修改为以下:

@{ ViewBag.Title = "页面不存在"; }

<h1>@ViewBag.ErrorMessage</h1>

<a asp-action="index" asp-controller="home">
  点击此处返回首页
</a>

在 ASP.NET Core 中记录异常信息

两个简单的步骤来记录我们自己定义的消息(Info),警告(Warnings)和异常(exceptions)信息。

在需要日志记录功能的地方注入 ILogger 实例

可以指定 注入 ILogger 的类或控制器的类型作为 ILogger 泛型参数的参数。我们这样做是因为,可以将类或控制器的完整名称作为日志类别包含在日志输出中。

日志类别用于对日志消息进行分组。

由于我们已将 ErrorController 的类型指定为 ILogger 的泛型参数,因此 ErrorController 的完整名称也包含在下面的日志输出中。

private readonly ILogger<ErrorController> logger;

public ErrorController(ILogger<ErrorController> logger)
{
    this.logger = logger;
}

为了让我们进行日志内容的显示操作更加的方便,我们打开appsettings.json文件,在日志级别下面添加以下代码:

 "Logging": {
    "LogLevel": {
      "Default": "Warning",
      "Microsoft": "Information"
    }
  },

然后重新进入我们的程序调试模式,您可以下面的图片中的日志记录信息。 62-1

我们在当前的日志中,显示了 Microsoft 级别的日志信息,因为我们通过在appsettings.json文件中对日志级别进行了配置,通过配置的"Microsoft": "Information"显示了Microsoft的信息,我们也可以通过配置筛选过滤将"Microsoft": "Information"更改为"Microsoft": "Warning"

然后重新进入调式模式,运行后,我们的调试输出窗口为空白。这是我们人为进行了过滤不打印出这些内容。

LogError() 方法将异常记录到日志中的错误分组中。

   //LogError() 方法将异常记录到日志中的错误分组中。

            logger.LogError($"路径 {exceptionHandlerPathFeature.Path} " +
                $"产生了一个错误{exceptionHandlerPathFeature.Error}");

下面是 LogError() 方法生成的日志:

我们可以通过访问http://localhost:5160/home/details/1进行触发我们的Waring警告,因为我们在 Details.cshtml 中,写了一行抛出异常的代码。

public ViewResult Details(int? id)
{
    throw new Exception("在Details视图中抛出异常");

   //其他代码
}

触发后的结果如下:

62-2 62-3

我们可以获取到所有的完整错误日志信息,从我们的ErrorController中,帮我们拦截到了具体到哪个类文件,以及哪行代码出错,以及报错的信息。这样帮助我们进行程序的定位是很有效的。

而能看到这些错误信息是因为我们在ErrorController中的Error操作方法中,添加的

logger.LogError($"路径 {exceptionHandlerPathFeature.Path} " +
                $"产生了一个错误{exceptionHandlerPathFeature.Error}");

日志记录代码,帮助我们拦截到的错误信息。

StudentManagement.Controllers.ErrorController:Error: 路径/home/details/1 产生了一个错误System.Exception: 在Details视图中抛出异常
   at StudentManagement.Controllers.HomeController.Details(Int32 id) in D:\CodeManager\aiabpedu\ASP.NET -core-mvc-2019\src\new\StudentManage\Controllers\HomeController.cs:line 43
   at lambda_method(Closure , Object , Object[] )
   at Microsoft.Extensions.Internal.ObjectMethodExecutor.Execute(Object target, Object[] parameters)
   at Microsoft.AspNetCore.Mvc.Internal.ActionMethodExecutor.SyncActionResultExecutor.Execute(IActionResultTypeMapper mapper, ObjectMethodExecutor executor, Object controller, Object[] arguments)
   at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.InvokeActionMethodAsync()
   at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.InvokeNextActionFilterAsync()
   at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.Rethrow(ActionExecutedContext context)
   at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
   at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.InvokeInnerFilterAsync()
   at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.InvokeNextResourceFilter()
   at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.Rethrow(ResourceExecutedContext context)
   at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
   at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.InvokeFilterPipelineAsync()
   at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.InvokeAsync()
   at Microsoft.AspNetCore.Builder.RouterMiddleware.Invoke(HttpContext httpContext)
   at Microsoft.AspNetCore.StaticFiles.StaticFileMiddleware.Invoke(HttpContext context)
   at Microsoft.AspNetCore.Diagnostics.StatusCodePagesMiddleware.Invoke(HttpContext context)
   at Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddleware.Invoke(HttpContext context)

现在我们尝试访问一个 URL,这个 URL 和我们的路由完全不匹配如http://localhost:5160/market/food/1?eat=apple

运行后,我们可以看到因为是不存在的路由匹配,所以进入的是ErrorController中的HttpStatusCodeHandler操作方法,产生的日志记录信息为:

StudentManagement.Controllers.ErrorController:Warning: 发生了一个404错误. 路径 =/market/food/1 以及查询字符串 = ?eat=apple

提示错误级别为Warning级别的。这是因为我们的代码中指定该级别的错误为Waring,同时帮我们将按照我们自定义的规则给处理完毕,完整运行图片,参考下图。

62-4

文章说明

如果您觉得我的文章质量还不错,欢迎打赏,也可以订阅我的视频哦
未得到授权不得擅自转载本文内容,52abp.com 保留版权
感谢您对我的支持

关注微信公众号:角落的白板报

公众号:角落的白板报