手机版

ASP .净核心应用错误处理之DeveloperExceptionPageMiddleware中间件中间件中间件呈现"开发者异常页面"

时间:2021-08-29 来源:互联网 编辑:宝哥软件园 浏览:

前言

在《ASP.NET Core应用的错误处理[1]:三种呈现错误页面的方式》 中,我们通过几个简单的实例演示了如何呈现一个错误页面,这些错误页面的呈现分别由三个对应的中间件来完成,接下来我们将对这三个中间件进行详细介绍。在开发环境呈现的异常页面是通过一个类型为DeveloperExceptionPageMiddleware中间件中间件中间件实现的。

公共类developerxceptionpage中间件{ public developerxceptionpage中间件(request delegate next,ioptiondeveloperxceptionpage选项,ILoggerFactory loggerFactory,IHostingEnvironment托管环境,诊断源诊断源);公共任务调用(HttpContext上下文);}如上面的代码片段所示,当我们创建一个DeveloperExceptionPageMiddleware中间件中间件对象的时候需要以参数的形式提供一个IOptionsDeveloperExceptionPageOptions选项选项对象,而DeveloperExceptionPageOptions选项选项对象携带我们为这个中间件指定的配置选项,具体的配置选项体现在如下另个属性(文件提供程序和SourceCodeLineCount)。

公共类开发人员异常页面选项{ public IFileProvider文件提供程序{ get设置;} public int SourceCodeLineCount { get;设置;} }一般来说我们总是通过调用ApplicationBuilder的扩展方法UseDeveloperExceptionPage方法来注册这个DeveloperExceptionPageMiddleware中间件中间件中间件,这两个扩展方法重载采用如下的方式创建并注册这个DeveloperExceptionPageMiddleware中间件中间件中间件。

公共静态类开发人员异常页面扩展{公共静态IApplicationBuilder usedeveloper exception page(此IApplicationBuilder应用程序){返回应用程序.usemiddlewareddeveloper exceptionpagemiddleware();}公共静态IApplicationBuilder usedeveloper exception page(此IApplicationBuilder应用程序,DeveloperExceptionPageOptions选项){返回应用程序.usemiddlewareddeveloper异常页面中间件(选项。创建(选项));} }在《ASP.NET Core应用的错误处理[1]:三种呈现错误页面的方式》 实例演示中,我们并不曾使用过DeveloperExceptionPageOptions选项选项这个对象,对于定义在这个类型中的这两个属性,我想很多人都不知道它们究竟可以用作哪方面的配置。要很清楚地解答这个问题,就需要从DeveloperExceptionPageMiddleware中间件中间件中间件处理的两种异常类型说起。总的来说,该中间件处理的异常大体上可以分为两类,它们分别是"运行时异常"和"编译异常",后者类型实现了ICompilationException接口,如下的代码片段基本上体现了异常处理在DeveloperExceptionPageMiddleware中间件中间件中间件中的实现。

公共类DeveloperExceptionPageMiddleware中间件中间件{私有请求委托_下一个公共异步任务调用(HttpContext上下文){ try { await _ next(context);} catch(异常ex) { context .响应。clear();语境回应。status code=500 ICompilationException compilationException=ex as ICompilationException;if (null!=compilationException){ await DisplayCompilationException(上下文,compilationException);} else { await DisplayRuntimeException(context,ex);} } }私有任务显示运行时异常(HttpContext上下文例外(ex);私有任务DisplayCompilationException(HttpContext上下文,ICompilationException compilationException);}一、处理编译异常

我想很多人会感到困惑:当我们编写一个ASP.NET Core应用程序时,我们应该首先将它编译成一个程序集,然后部署它并开始执行它。为什么运行过程中还会出现“编译异常”?从ASP.NET核心的应用层面来说,我们采用的是“预编译”,也就是说我们部署的是编译后的程序集,而不是源代码,所以在运行过程中不存在“编译异常”。但是不要忘记,在ASP.NET核心MVC应用程序中,视图文件(。cshtml)支持“动态编译”。也就是说,我们可以直接部署视图源文件,应用程序可以在执行过程中动态编译它们。换句话说,因为视图文件支持动态编译,所以我们可以在部署环境中直接修改视图文件。

对于developerxception pageMeddleware中间件,对于普通的运行时异常,它将以HTML文档的形式呈现异常本身的细节和当前请求的信息,我们前面的例子已经很好地说明了这一点。如果应用程序在动态编译视图文件中有编译异常,错误页面将有不同的结构和内容。我们可以通过一个简单的例子来演示如何处理编译异常。

我们用下面显示的代码启动了一个ASP.NET Core MVC应用程序,并通过调用ApplicationBuilder的扩展方法UseDeveloperExceptionPage注册了DeveloperExceptionPage中间件。在HomeController中定义的动作方法索引负责呈现相应的视图。

公共类Program { public static void Main(){ new WebHostBuilder()。UseKestrel()。UseContentRoot(目录。GetCurrentDirectory())。configureSerVices(SVC=SVC。AddMvc())。配置(app=app。UseDeveloperExceptionPage()。UseMvc())。构建()。run();} }公共类HomeController : Controller {[HttpGet('/')]公共IActionResult Index(){ return View();}}按照惯例,Action方法Index呈现的视图文件对应的路径应该是“~/view/home/Index . cshtml”,所以我们在这个路径下创建这个视图文件。为了在动态编译期间生成编译异常,我们在这个视图文件中编写了以下三行代码,Foobar是一个尚未创建的类型。

@ { var value=new Foobar();}当我们使用浏览器访问HomeController的Action方法Index时,应用程序会动态编译目标视图。因为视图文件使用了未定义的类型,所以动态编译将失败,并且响应错误消息将出现在浏览器中,如图7所示。可以看出,错误页面显示的内容和结构与前面的例子完全不同。我们不仅可以从这个错误页面得到导致编译失败的视图文件(“view/Home/index . cshtml”)的路径,还可以直接看到导致编译失败的代码行。不仅如此,这个错误页还会直接参与编译源代码(而不是。cshtml文件,但C#代码由转换处理生成)。毫无疑问,这个详细的错误页面对于相信开发人员的纠错非常有价值。

一般来说,动态编译的整个过程包括两个步骤。首先,源代码(模板文件喜欢。cshtml)被转换成特定的代码。NET语言(如C#),然后进一步编译成IL代码。动态编译期间引发的异常类型通常实现ICompilationException接口。如下面的代码片段所示,接口值有一个唯一的属性CompilationFailures,它返回一个元素类型为CompilationFailure的集合。CompilationFailure的相关信息封装在CompilationFailure对象中,可用于获取SourceFilePath和内容,以及源代码转换后交付编译的内容。如果在内容转换过程中出现错误,SourceFileContent属性可能会返回Null。

公共接口ICompilationException { IEnumerableCompilationFailure CompilationFailures { get;} }公共类CompilationFailure { public string source file content { get;}公共字符串SourceFilePath { get} public string CompiledContent { get;} public IEnumerableDiagnosticMessage { get;} … }CompilationFailure类型还有一个名为Messages的只读属性,它返回一个元素类型为DiagnosticMessage的集合,DiagnosticMessage对象携带一些描述编译错误的诊断信息。借助于DiagnosticMessage对象的相关属性,我们不仅可以得到描述编译错误的消息(Message和FormattedMessage),还可以得到出现编译错误的SourceFilePath和范围。StartLine、StartColumn、EndLine和EndColumn属性分别指示在源文件中导致编译错误的源代码的行和列(行数和列数分别从1和0开始)。

公共类diagnostic message { public string source filepath { get;} public int StartLine { get} public int StartColumn { get} public int EndLine { get} public int EndColumn { get}公共字符串Message { get}公共字符串FormattedMessage { get} .}从上图可以看出,错误页面会直接显示导致编译失败的相关源代码。具体来说,它不仅会实现直接导致失败的源代码,还会同时显示相邻的源代码。至于相邻的源代码中应该显示多少行,实际上是由DeveloperExceptionPageOptions的SourceCodeLineCount属性控制的。

公共类Program { public static void Main(){ new WebHostBuilder()。UseKestrel()。UseContentRoot(目录。GetCurrentDirectory())。configureSerVices(SVC=SVC。AddMvc())。配置(app=app。UseDeveloperExceptionPage(新的developer exceptionpage options { SourceCodeLineCount=3 })。UseMvc())。构建()。run();}}对于上面显示的例子,如果我们希望在错误页面上显示三行相邻的代码,我们可以用上面的方法为注册的developerxceptionpagemidware中间件指定一个developerxceptions对象,并将其SourceCodeLineCount属性设置为3。同时,我们将视图文件(index.cshtml)重写为以下形式,即在导致编译失败的代码行前后添加了四行代码。

1: 2: 3: 4: 5: @ { var value=new Foobar();} 6: 7: 8: 93360对于视图文件中定义的总共9行代码,根据注册developerxception page middleware中间件时指定的规则,错误页面上的最终显示应该是第2行到第8行。如果我们使用浏览器访问同一个地址,我们会看到这7行代码会以下图的形式出现在错误页面上。值得一提的是,如果我们不显式设置SourceCodeLineCount属性,它的默认值是6。

第二,处理运行时异常

对于developerException pagemedleware中间件,任何类型的不实现ICompilationException接口的异常都被视为“运行时异常”。通过ASP.NET核心应用的错误处理[1]演示的例子:错误页的三种呈现方式,我们已经知道developerxception page middleware中间件不仅在处理运行时异常时在错误页上显示异常的详细信息,还包含与当前请求相关的信息,包括查询字符串、Cookie和请求头集。现在我们关心的是另一个问题。使用DeveloperExceptionPageOptions提供的这个FileProvider对象的目的是什么?

对于描述错误页面上出现的异常的详细信息,除了类型和消息等基本信息之外,异常的堆栈跟踪也会出现在页面上。此外,如果堆栈跟踪包含源代码信息(如源文件路径和相应源代码所在的行和列),developerxception page middleware中间件还会尝试加载源文件并完整显示导致异常的源代码。

公共类Program { public static void Main(){ new WebHostBuilder()。UseKestrel()。配置(app=app。UseDeveloperExceptionPage()。运行(调用))。构建()。run();}私有静态任务调用(HttpContext上下文){引发新的InvalidOperationException('手动引发的异常');}}我们将上面显示的代码改写成上面的形式,在本地以Debug模式运行程序,会得到如下图所示的错误页面。我们可以看到异常的堆栈跟踪信息包含了源代码的相关信息(源文件路径和行号),所以导致异常的行号可以原封不动的显示出来。与编译异常处理方法一样,也会显示与其相邻的代码。至于将显示多少行相邻代码,自然是由DeveloperExceptionPageOptions的SourceCodeLineCount属性控制的。

DeveloperExceptionPageOptions的文件提供程序提供文件提供程序对象来帮助读取源文件的内容,或者它为我们的纠错和调试提供源文件。如果我们在创建developerxception pageMeddleware中间件时没有明确提供这样一个文件提供程序,那么默认情况下将使用指向ContentRoot目录的PhysicalFileProvider。值得一提的是,如果源文件的路径出现在异常跟踪栈中,developerException PageMeddleware中间件总是会先尝试从本地文件系统加载文件,只有在本地文件加载失败时,才会使用指定的FileProvider读取文件。

摘要

以上就是本文的全部内容。希望本文的内容对大家的学习或工作有一定的参考价值。有问题可以留言交流。谢谢你的支持。

版权声明:ASP .净核心应用错误处理之DeveloperExceptionPageMiddleware中间件中间件中间件呈现"开发者异常页面"是由宝哥软件园云端程序自动收集整理而来。如果本文侵犯了你的权益,请联系本站底部QQ或者邮箱删除。