<span id="mktg5"></span>

<i id="mktg5"><meter id="mktg5"></meter></i>

        <label id="mktg5"><meter id="mktg5"></meter></label>
        最新文章專題視頻專題問(wèn)答1問(wèn)答10問(wèn)答100問(wèn)答1000問(wèn)答2000關(guān)鍵字專題1關(guān)鍵字專題50關(guān)鍵字專題500關(guān)鍵字專題1500TAG最新視頻文章推薦1 推薦3 推薦5 推薦7 推薦9 推薦11 推薦13 推薦15 推薦17 推薦19 推薦21 推薦23 推薦25 推薦27 推薦29 推薦31 推薦33 推薦35 推薦37視頻文章20視頻文章30視頻文章40視頻文章50視頻文章60 視頻文章70視頻文章80視頻文章90視頻文章100視頻文章120視頻文章140 視頻2關(guān)鍵字專題關(guān)鍵字專題tag2tag3文章專題文章專題2文章索引1文章索引2文章索引3文章索引4文章索引5123456789101112131415文章專題3
        問(wèn)答文章1 問(wèn)答文章501 問(wèn)答文章1001 問(wèn)答文章1501 問(wèn)答文章2001 問(wèn)答文章2501 問(wèn)答文章3001 問(wèn)答文章3501 問(wèn)答文章4001 問(wèn)答文章4501 問(wèn)答文章5001 問(wèn)答文章5501 問(wèn)答文章6001 問(wèn)答文章6501 問(wèn)答文章7001 問(wèn)答文章7501 問(wèn)答文章8001 問(wèn)答文章8501 問(wèn)答文章9001 問(wèn)答文章9501
        當(dāng)前位置: 首頁(yè) - 科技 - 知識(shí)百科 - 正文

        ASP.NET Core應(yīng)用錯(cuò)誤處理之DeveloperExceptionPageMiddleware中間件呈現(xiàn)“開(kāi)發(fā)者異常頁(yè)面”

        來(lái)源:懂視網(wǎng) 責(zé)編:小采 時(shí)間:2020-11-27 22:34:41
        文檔

        ASP.NET Core應(yīng)用錯(cuò)誤處理之DeveloperExceptionPageMiddleware中間件呈現(xiàn)“開(kāi)發(fā)者異常頁(yè)面”

        ASP.NET Core應(yīng)用錯(cuò)誤處理之DeveloperExceptionPageMiddleware中間件呈現(xiàn)開(kāi)發(fā)者異常頁(yè)面:前言 在《ASP.NET Core應(yīng)用的錯(cuò)誤處理[1]:三種呈現(xiàn)錯(cuò)誤頁(yè)面的方式》中,我們通過(guò)幾個(gè)簡(jiǎn)單的實(shí)例演示了如何呈現(xiàn)一個(gè)錯(cuò)誤頁(yè)面,這些錯(cuò)誤頁(yè)面的呈現(xiàn)分別由三個(gè)對(duì)應(yīng)的中間件來(lái)完成,接下來(lái)我們將對(duì)這三個(gè)中間件進(jìn)行詳細(xì)介紹。在開(kāi)發(fā)環(huán)境呈現(xiàn)的異常頁(yè)面是通過(guò)一個(gè)
        推薦度:
        導(dǎo)讀ASP.NET Core應(yīng)用錯(cuò)誤處理之DeveloperExceptionPageMiddleware中間件呈現(xiàn)開(kāi)發(fā)者異常頁(yè)面:前言 在《ASP.NET Core應(yīng)用的錯(cuò)誤處理[1]:三種呈現(xiàn)錯(cuò)誤頁(yè)面的方式》中,我們通過(guò)幾個(gè)簡(jiǎn)單的實(shí)例演示了如何呈現(xiàn)一個(gè)錯(cuò)誤頁(yè)面,這些錯(cuò)誤頁(yè)面的呈現(xiàn)分別由三個(gè)對(duì)應(yīng)的中間件來(lái)完成,接下來(lái)我們將對(duì)這三個(gè)中間件進(jìn)行詳細(xì)介紹。在開(kāi)發(fā)環(huán)境呈現(xiàn)的異常頁(yè)面是通過(guò)一個(gè)

        前言

        在《ASP.NET Core應(yīng)用的錯(cuò)誤處理[1]:三種呈現(xiàn)錯(cuò)誤頁(yè)面的方式》中,我們通過(guò)幾個(gè)簡(jiǎn)單的實(shí)例演示了如何呈現(xiàn)一個(gè)錯(cuò)誤頁(yè)面,這些錯(cuò)誤頁(yè)面的呈現(xiàn)分別由三個(gè)對(duì)應(yīng)的中間件來(lái)完成,接下來(lái)我們將對(duì)這三個(gè)中間件進(jìn)行詳細(xì)介紹。在開(kāi)發(fā)環(huán)境呈現(xiàn)的異常頁(yè)面是通過(guò)一個(gè)類型為DeveloperExceptionPageMiddleware中間件實(shí)現(xiàn)的。

         public class DeveloperExceptionPageMiddleware
         {
         public DeveloperExceptionPageMiddleware(RequestDelegate next, IOptions<DeveloperExceptionPageOptions> options, 
         ILoggerFactory loggerFactory, IHostingEnvironment hostingEnvironment, DiagnosticSource diagnosticSource);
         public Task Invoke(HttpContext context);
         }

        如上面的代碼片段所示,當(dāng)我們創(chuàng)建一個(gè)DeveloperExceptionPageMiddleware對(duì)象的時(shí)候需要以參數(shù)的形式提供一個(gè)IOptions<DeveloperExceptionPageOptions>對(duì)象,而DeveloperExceptionPageOptions對(duì)象攜帶我們?yōu)檫@個(gè)中間件指定的配置選項(xiàng),具體的配置選項(xiàng)體現(xiàn)在如下另個(gè)屬性(FileProvider和SourceCodeLineCount)。

         public class DeveloperExceptionPageOptions
         {
         public IFileProvider FileProvider { get; set; }
         public int SourceCodeLineCount { get; set; }
         }

        一般來(lái)說(shuō)我們總是通過(guò)調(diào)用ApplicationBuilder的擴(kuò)展方法UseDeveloperExceptionPage方法來(lái)注冊(cè)這個(gè)DeveloperExceptionPageMiddleware中間件,這兩個(gè)擴(kuò)展方法重載采用如下的方式創(chuàng)建并注冊(cè)這個(gè)DeveloperExceptionPageMiddleware中間件。

         public static class DeveloperExceptionPageExtensions
         { 
         public static IApplicationBuilder UseDeveloperExceptionPage(this IApplicationBuilder app)
         {
         return app.UseMiddleware<DeveloperExceptionPageMiddleware>();
         } 
         public static IApplicationBuilder UseDeveloperExceptionPage(this IApplicationBuilder app,DeveloperExceptionPageOptions options)
         {
         return app.UseMiddleware<DeveloperExceptionPageMiddleware>(Options.Create(options));
         }
         }

        在《ASP.NET Core應(yīng)用的錯(cuò)誤處理[1]:三種呈現(xiàn)錯(cuò)誤頁(yè)面的方式》實(shí)例演示中,我們并不曾使用過(guò)DeveloperExceptionPageOptions這個(gè)對(duì)象,對(duì)于定義在這個(gè)類型中的這兩個(gè)屬性,我想很多人都不知道它們究竟可以用作哪方面的配置。要很清楚地解答這個(gè)問(wèn)題,就需要從 DeveloperExceptionPageMiddleware中間件處理的兩種異常類型說(shuō)起。總的來(lái)說(shuō),該中間件處理的異常大體上可以分為兩類,它們分別是“運(yùn)行時(shí)異常”和“編譯異常”,后者類型實(shí)現(xiàn)了ICompilationException接口,如下的代碼片段基本上體現(xiàn)了異常處理在DeveloperExceptionPageMiddleware中間件中的實(shí)現(xiàn)。

         public class DeveloperExceptionPageMiddleware
         {
         private RequestDelegate _next;
         public async Task Invoke(HttpContext context)
         {
         try
         {
         await _next(context);
         }
         catch(Exception ex)
         {
         context.Response.Clear();
         context.Response.StatusCode = 500;
         
         ICompilationException compilationException = ex as ICompilationException;
         if (null != compilationException)
         {
         await DisplayCompilationException(context, compilationException);
         }
         else
         {
         await DisplayRuntimeException(context, ex);
         }
         }
         }
         
         private Task DisplayRuntimeException(HttpContext context, Exception ex);
         private Task DisplayCompilationException(HttpContext context,ICompilationException compilationException) ;
         }

        一、 處理編譯異常

        我想很多人會(huì)很疑惑:我們編寫一個(gè)ASP.NET Core應(yīng)用應(yīng)該是先編譯成程序集,然后再部署并啟動(dòng)執(zhí)行,為什么運(yùn)行過(guò)程中還會(huì)出現(xiàn)“編譯異常”呢?從ASP.NET Core應(yīng)用層面來(lái)說(shuō),我們采用的是“預(yù)編譯”,也就說(shuō)我們部署的不是源代碼而是編譯好的程序集,所以運(yùn)行過(guò)程中根本就不存在“編譯異常”一說(shuō)。但是不要忘了在一個(gè)ASP.NET Core MVC應(yīng)用中,視圖文件(.cshtml)是支持“動(dòng)態(tài)編譯”的。也就是說(shuō)我們可以直接部署視圖源文件,應(yīng)用在執(zhí)行過(guò)程中是可以動(dòng)態(tài)地編譯它們的。換句話說(shuō),由于視圖文件支持動(dòng)態(tài)編譯,我們是可以在部署環(huán)境直接修改視圖文件的。

        對(duì)于DeveloperExceptionPageMiddleware中間件來(lái)說(shuō),對(duì)于普通的運(yùn)行時(shí)異常,它會(huì)采用HTML文檔的形式將異常自身的詳細(xì)信息和當(dāng)前請(qǐng)求的信息以HTML文檔的形式呈現(xiàn)出來(lái),我們前面演示的實(shí)例已經(jīng)很好的說(shuō)明了這一點(diǎn)。如果應(yīng)用在動(dòng)態(tài)編譯視圖文件中出現(xiàn)了編譯異常,最終呈現(xiàn)出來(lái)的錯(cuò)誤頁(yè)面將具有不同的結(jié)構(gòu)和內(nèi)容,我們不防也通過(guò)一個(gè)簡(jiǎn)單的實(shí)例來(lái)演示一下DeveloperExceptionPageMiddleware中間件針對(duì)編譯異常的處理。

        我們通過(guò)如下所示的代碼啟動(dòng)了一個(gè)ASP.NET Core MVC應(yīng)用,并通過(guò)調(diào)用ApplicationBuilder的擴(kuò)展方法UseDeveloperExceptionPage注冊(cè)了DeveloperExceptionPageMiddleware中間件。對(duì)應(yīng)定義在HomeController中的Action方法Index來(lái)說(shuō),它會(huì)負(fù)責(zé)將對(duì)應(yīng)的視圖呈現(xiàn)出來(lái)。

         public class Program
         {
         public static void Main()
         {
         new WebHostBuilder()
         .UseKestrel()
         .UseContentRoot(Directory.GetCurrentDirectory())
         .ConfigureServices(svcs => svcs.AddMvc())
         .Configure(app => app
         .UseDeveloperExceptionPage()
         .UseMvc())
         .Build()
         .Run();
         }
         }
         
         public class HomeController : Controller
         {
         [HttpGet("/")]
         public IActionResult Index()
         {
         return View();
         }
        }

        根據(jù)約定,Action方法Index呈現(xiàn)出來(lái)的視圖文件對(duì)應(yīng)的路徑應(yīng)該是“~/views/home/index.cshtml”,我們?yōu)榇嗽谶@個(gè)路徑下創(chuàng)建這個(gè)視圖文件。為了能夠在動(dòng)態(tài)編譯過(guò)程中出現(xiàn)編譯異常,我們?cè)谶@個(gè)視圖文件中編寫了如下三行代碼,F(xiàn)oobar是一個(gè)尚未被創(chuàng)建的類型。

         @{ 
         var value = new Foobar();
         }

        當(dāng)我們利用瀏覽器訪問(wèn)HomeController的Action方法Index的時(shí)候,應(yīng)用會(huì)動(dòng)態(tài)編譯目標(biāo)視圖,由于視圖文件中使用了一個(gè)不曾不定義的類型,動(dòng)態(tài)編譯會(huì)失敗,響應(yīng)的錯(cuò)誤信息會(huì)以如圖7所示的形式出現(xiàn)在瀏覽器上。可以看出錯(cuò)誤頁(yè)面顯示的內(nèi)容和結(jié)構(gòu)與前面演示的實(shí)例是完全不一樣的,我們不僅可以從這個(gè)錯(cuò)誤頁(yè)面中得到導(dǎo)致編譯失敗的視圖文件的路徑(“Views/Home/Index.cshtml”),還可以直接看到導(dǎo)致編譯失敗的那一行代碼。不僅如此,這個(gè)錯(cuò)誤頁(yè)面還直接將參與編譯的源代碼(不是定義在.cshtml文件中的原始代碼,而是經(jīng)過(guò)轉(zhuǎn)換處理生成的C#代碼)。毫無(wú)疑問(wèn),這個(gè)如此詳盡的錯(cuò)誤頁(yè)面對(duì)于相信開(kāi)發(fā)人員的糾錯(cuò)針對(duì)是非常有價(jià)值的。

        一般來(lái)說(shuō),動(dòng)態(tài)編譯的整個(gè)過(guò)程由兩個(gè)步驟組成,它先是將源代碼(類似于.cshtml這樣的模板文件)轉(zhuǎn)換成針對(duì)某種.NET語(yǔ)言(比如C#)的代碼,然后進(jìn)一步地編譯成IL代碼。動(dòng)態(tài)編譯過(guò)程中拋出的異常類型一般會(huì)實(shí)現(xiàn)ICompilationException接口。如下面的代碼片段所示,該接口值具有一個(gè)唯一的屬性CompilationFailures,它返回一個(gè)元素類型為CompilationFailure的集合。編譯失敗的相關(guān)信息被封裝在一個(gè)CompilationFailure對(duì)象之中,我們可以利用它得到源文件的路徑(SourceFilePath)和內(nèi)容(SourceFileContent),以及源代碼轉(zhuǎn)換后交付編譯的內(nèi)容。如果在內(nèi)容轉(zhuǎn)換過(guò)程就已經(jīng)發(fā)生錯(cuò)誤,那么SourceFileContent屬性可能返回Null。

         public interface ICompilationException
         {
         IEnumerable<CompilationFailure> CompilationFailures { get; }
         }
         
         public class CompilationFailure
         {
         public string SourceFileContent { get; }
         public string SourceFilePath { get; }
         public string CompiledContent { get; }
         public IEnumerable<DiagnosticMessage> Messages { get; }
         …
         }

        CompilationFailure類型還具有一個(gè)名為Messages的只讀屬性,它返回一個(gè)元素類型為DiagnosticMessage的集合,一個(gè)DiagnosticMessage對(duì)象承載著一些描述編譯錯(cuò)誤的診斷信息。我們不僅可以借助DiagnosticMessage對(duì)象的相關(guān)屬性得到描述編譯錯(cuò)誤的消息(Message和FormattedMessage),還可以得到發(fā)生編譯錯(cuò)誤所在源文件的路徑(SourceFilePath)以及范圍,StartLine、StartColumn、EndLine和EndColumn屬性分別表示導(dǎo)致編譯錯(cuò)誤的源代碼在源文件中開(kāi)始和結(jié)束的行與列(行數(shù)和列數(shù)分別從1和0開(kāi)始計(jì)數(shù))。

         public class DiagnosticMessage
         {
         public string SourceFilePath { get; }
         public int StartLine { get; }
         public int StartColumn { get; } 
         public int EndLine { get; }
         public int EndColumn { get; }
         
         public string Message { get; } 
         public string FormattedMessage { get; } 
         …
         }

        從上圖可以看出,錯(cuò)誤頁(yè)面會(huì)直接將導(dǎo)致編譯失敗的相關(guān)源代碼顯示出來(lái)。具體來(lái)說(shuō),它不僅僅會(huì)將直接導(dǎo)致失敗的源代碼實(shí)現(xiàn)出來(lái),還會(huì)同時(shí)顯示前后相鄰的源代碼。至于相鄰源代碼應(yīng)該顯示多少行,實(shí)際上是通過(guò)DeveloperExceptionPageOptions的SourceCodeLineCount屬性控制的。

         public class Program
         {
         public static void Main()
         {
         new WebHostBuilder()
         .UseKestrel()
         .UseContentRoot(Directory.GetCurrentDirectory())
         .ConfigureServices(svcs => svcs.AddMvc())
         .Configure(app => app
         .UseDeveloperExceptionPage(new DeveloperExceptionPageOptions { SourceCodeLineCount = 3 })
         .UseMvc())
         .Build()
         .Run();
         }
         }

        對(duì)于前面演示的這個(gè)實(shí)例來(lái)說(shuō),如果我們希望前后相鄰的三行代碼被顯示在錯(cuò)誤頁(yè)面上,我們可以采用如上的方式為注冊(cè)的DeveloperExceptionPageMiddleware中間件指定一個(gè)DeveloperExceptionPageOptions對(duì)象,并將它的SourceCodeLineCount屬性設(shè)置為3。與此同時(shí),我們將視圖文件(index.cshtml)改寫成如下的形式,即在導(dǎo)致編譯失敗的那一行代碼前后分別添加了4行代碼。

         1:
         2:
         3:
         4:
         5:@{ var value = new Foobar();}
         6:
         7:
         8:
         9:

        對(duì)于定義在視圖文件中的共計(jì)9行代碼,根據(jù)在注冊(cè)DeveloperExceptionPageMiddleware中間件時(shí)指定的規(guī)則,最終顯示在錯(cuò)誤頁(yè)面上的應(yīng)該是第2行到第8行。如果利用瀏覽器訪問(wèn)相同的地址,我們會(huì)看到這7行代碼會(huì)以下圖的形式出現(xiàn)在錯(cuò)誤頁(yè)面上。值得一提的是,如果我們沒(méi)有對(duì)SourceCodeLineCount屬性作顯式設(shè)置,它的默認(rèn)值為6。

        二、處理運(yùn)行時(shí)異常

        對(duì)于DeveloperExceptionPageMiddleware中間件來(lái)說(shuō),任何類型沒(méi)有實(shí)現(xiàn)ICompilationException接口的異常都被視為“運(yùn)行時(shí)異常”。通過(guò)ASP.NET Core應(yīng)用的錯(cuò)誤處理[1]:三種呈現(xiàn)錯(cuò)誤頁(yè)面的方式》演示的實(shí)例我們已經(jīng)知道,DeveloperExceptionPageMiddleware中間件在處理運(yùn)行時(shí)異常時(shí)不僅僅會(huì)將異常的詳細(xì)信息顯示在錯(cuò)誤頁(yè)面中,該頁(yè)面中還會(huì)包含于當(dāng)前請(qǐng)求相關(guān)的信息,包括查詢字符串、Cookie和請(qǐng)求報(bào)頭集合。現(xiàn)在我們關(guān)心的是另一個(gè)問(wèn)題,我們利用DeveloperExceptionPageOptions的供的這個(gè)FileProvider對(duì)象就是出于什么目的呢?

        對(duì)于錯(cuò)誤頁(yè)面呈現(xiàn)的描述異常的詳細(xì)信息,除了類型和消息這些基本的信息之外,異常的堆棧追蹤(Stack Trace)也會(huì)出現(xiàn)在該頁(yè)面中。不僅如此,如果堆棧追蹤包含源代碼的信息(比如源文件路徑以及對(duì)應(yīng)源代碼所在的行和列),DeveloperExceptionPageMiddleware中間件還會(huì)試著加載源文件,并將導(dǎo)致異常的源代碼原封不動(dòng)的顯示出來(lái)。

         public class Program
         {
         public static void Main()
         {
         new WebHostBuilder()
         .UseKestrel()
         .Configure(app => app
         .UseDeveloperExceptionPage()
         .Run(Invoke))
         .Build()
         .Run();
         }
         private static Task Invoke(HttpContext context)
         {
         throw new InvalidOperationException("Manually thrown exception");
         }
         }

        我們將前面演示的代碼改寫成如上的形式,并在本地以Debug模式運(yùn)行該程序,將會(huì)得到如下圖所示的錯(cuò)誤頁(yè)面。我們會(huì)看到由于異常的堆棧追蹤信息中包含源代碼的相關(guān)信息(源文件路徑和行號(hào)),所以導(dǎo)致異常的那一行代碼可以原封不動(dòng)地顯示出來(lái)。與編譯異常處理方式一樣,一并顯示出來(lái)的還包括與之相鄰的代碼,至于具體會(huì)顯示多少行相鄰代碼,自然也是通過(guò)DeveloperExceptionPageOptions的SourceCodeLineCount屬性來(lái)控制的。

        DeveloperExceptionPageOptions的FileProvider提供FileProvider對(duì)象的目的就是幫助讀取源文件的內(nèi)容,或者說(shuō)它為我們的糾錯(cuò)調(diào)試提供源文件。如果我們?cè)趧?chuàng)建DeveloperExceptionPageMiddleware中間件的時(shí)候沒(méi)有顯式提供這么一個(gè)FileProvider,那么默認(rèn)情況下會(huì)使用指向ContentRoot目錄的這個(gè)PhysicalFileProvider。值得一提的是,如果異常的追蹤堆棧中出現(xiàn)了源文件的路徑,DeveloperExceptionPageMiddleware中間件總是會(huì)試圖先從本地文件系統(tǒng)去加載這個(gè)文件,只有在本地文件加載失敗的情況下它才會(huì)利用指定的FileProvider去讀取文件。

        總結(jié)

        聲明:本網(wǎng)頁(yè)內(nèi)容旨在傳播知識(shí),若有侵權(quán)等問(wèn)題請(qǐng)及時(shí)與本網(wǎng)聯(lián)系,我們將在第一時(shí)間刪除處理。TEL:177 7030 7066 E-MAIL:11247931@qq.com

        文檔

        ASP.NET Core應(yīng)用錯(cuò)誤處理之DeveloperExceptionPageMiddleware中間件呈現(xiàn)“開(kāi)發(fā)者異常頁(yè)面”

        ASP.NET Core應(yīng)用錯(cuò)誤處理之DeveloperExceptionPageMiddleware中間件呈現(xiàn)開(kāi)發(fā)者異常頁(yè)面:前言 在《ASP.NET Core應(yīng)用的錯(cuò)誤處理[1]:三種呈現(xiàn)錯(cuò)誤頁(yè)面的方式》中,我們通過(guò)幾個(gè)簡(jiǎn)單的實(shí)例演示了如何呈現(xiàn)一個(gè)錯(cuò)誤頁(yè)面,這些錯(cuò)誤頁(yè)面的呈現(xiàn)分別由三個(gè)對(duì)應(yīng)的中間件來(lái)完成,接下來(lái)我們將對(duì)這三個(gè)中間件進(jìn)行詳細(xì)介紹。在開(kāi)發(fā)環(huán)境呈現(xiàn)的異常頁(yè)面是通過(guò)一個(gè)
        推薦度:
        • 熱門焦點(diǎn)

        最新推薦

        猜你喜歡

        熱門推薦

        專題
        Top
        主站蜘蛛池模板: 在线jyzzjyzz免费视频| 国产精品福利在线观看免费不卡| a在线观看免费网址大全| 人人狠狠综合久久亚洲高清| 亚洲国产精品免费观看| 免费不卡视频一卡二卡| 久久精品亚洲综合专区| 男人都懂www深夜免费网站| 国产亚洲精品美女久久久| 1000部免费啪啪十八未年禁止观看| 精品国产_亚洲人成在线高清| eeuss影院www天堂免费| 伊人久久综在合线亚洲91| 91视频免费网站| 久热综合在线亚洲精品| 91精品啪在线观看国产线免费| 亚洲国产一区在线| 亚洲精品免费在线视频| 亚洲一级高清在线中文字幕| 大香人蕉免费视频75| 国产精品亚洲精品日韩电影| 亚洲AV无码乱码精品国产| 日韩免费高清播放器| 78成人精品电影在线播放日韩精品电影一区亚洲 | 免费v片在线观看视频网站| 亚洲黄色在线观看| 最新中文字幕电影免费观看| 亚洲风情亚Aⅴ在线发布| 亚洲?v无码国产在丝袜线观看 | 青草久久精品亚洲综合专区| 亚洲中文字幕无码专区| 久久精品免费电影| 亚洲区日韩精品中文字幕| 亚洲国产精品自在拍在线播放 | 亚洲w码欧洲s码免费| 亚洲性色AV日韩在线观看| 亚洲AV无码一区二区三区国产| 久久精品免费观看| 亚洲天堂免费在线| 久久久久一级精品亚洲国产成人综合AV区 | 日本高清免费网站|