How Developerexceptionpagemiddleware Middleware renders "developer Exception page"

Source: Internet
Author: User
Tags stack trace

How Developerexceptionpagemiddleware Middleware renders "developer Exception page"

In the error handling [1]: Three ways to render the error page in the ASP., we demonstrate how to render an error page with a few simple examples, the rendering of these error pages is done by three corresponding middleware, and we will introduce the three middleware in detail. The exception page rendered in the development environment is implemented by a type of developerexceptionpagemiddleware middleware. [This article has been synced to the "ASP. NET Core Framework"]

   1:public class Developerexceptionpagemiddleware
   2: {
   3:     
   4:         iloggerfactory loggerfactory, ihostingenvironment hostingenvironment, Diagnosticsource DiagnosticSource);
   5: Public     Task Invoke (HttpContext context);
   6:}

As shown in the code snippet above, when we create a Developerexceptionpagemiddleware object we need to provide a ioptions<developerexceptionpageoptions in the form of a parameter > objects, and the Developerexceptionpageoptions object carries the configuration options that we specify for this middleware, the specific configuration options are shown in the following other properties (Fileprovider and Sourcecodelinecount).

   1:public class Developerexceptionpageoptions
   2: {
   3: Public     ifileprovider     fileprovider {get; set;}
   4: Public     int               Sourcecodelinecount {get; set;}
   5:}

In general, we always register this developerexceptionpagemiddleware middleware by calling the Applicationbuilder extension method Usedeveloperexceptionpage method. These two extension method overloads create and register the Developerexceptionpagemiddleware middleware in the following manner.

   1:public Static Class Developerexceptionpageextensions
   2: {    
   3: Public     static Iapplicationbuilder Usedeveloperexceptionpage (this iapplicationbuilder app)
   4:     {
   5:         return app. Usemiddleware<developerexceptionpagemiddleware> ();
   6:     }    
   7: Public     static Iapplicationbuilder Usedeveloperexceptionpage (this iapplicationbuilder app, Developerexceptionpageoptions options)
   8:     {
   9:         return app. Usemiddleware<developerexceptionpagemiddleware> (Options.create (Options));
  Ten:     }
  11:}

In the error handling [1]: Three ways to render the error page in the ASP. Example, we did not use the Developerexceptionpageoptions object for the two properties defined in this type. I don't think many people know what kind of configuration they can use. To answer this question very clearly, you need to start with the two types of exceptions that Developerexceptionpagemiddleware middleware handles. In general, the exceptions handled by the middleware can be broadly divided into two categories, namely " Runtime exception " and " compile exception ", which implements the Icompilationexception interface. The code snippet below basically embodies the implementation of exception handling in Developerexceptionpagemiddleware middleware.

   1:public class Developerexceptionpagemiddleware
   2: {
   3:     private requestdelegate _next;
   4: Public     async Task Invoke (HttpContext context)
   5:     {
   6:         Try
   7:         {
   8:             await _next (context);
   9:         }
  Ten:         catch (Exception ex)
  One:         {
  :             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);
  29:}
One, handling compilation exceptions

I think a lot of people will be puzzled: we write an ASP. NET core application should be compiled into an assembly, and then deploy and start execution, why there will be a "compile exception" during the run? From the ASP. NET core application level, we are using "precompilation", which means that we are not deploying the source code but the compiled assembly, so there is no "compile exception" at all during the run. But don't forget that in an ASP. NET Core MVC application, the view file (. cshtml) is supported for "dynamic compilation." This means that we can deploy the view source files directly, and the application can compile them dynamically during execution. In other words, because the view file supports dynamic compilation, we can modify the view file directly in the deployment environment.

For Developerexceptionpagemiddleware middleware, for normal runtime exceptions, it renders the details of the exception itself and the information of the current request as an HTML document in the form of an HTML document. The example we demonstrated earlier illustrates this very well. If the application has a compilation exception in the dynamically compiled view file, the resulting error page will have a different structure and content, and we can also demonstrate a simple example of how the Developerexceptionpagemiddleware middleware handles compiler exceptions.

We launched an ASP. NET Core MVC application with the code shown below. The Developerexceptionpagemiddleware middleware is registered by calling Applicationbuilder's extension method usedeveloperexceptionpage. Corresponds to the action method defined in HomeController index, it is responsible for rendering the corresponding view.

   1:public class Program
   2: {
   3: Public     static void Main ()
   4:     {
   5:         New Webhostbuilder ()
   6:             . Usekestrel ()
   7:             . Usecontentroot (Directory.GetCurrentDirectory ())
   8:             . Configureservices (Svcs = Svcs. ADDMVC ())
   9:             . Configure (app = App
  Ten:                 . Usedeveloperexceptionpage ()
  One:                 . USEMVC ())
  A:             . Build ()
  :             . Run ();
  :     }
  15:}
  
  17:public class Homecontroller:controller
  18: {
  :     [HttpGet ("/")]
  : Public     Iactionresult Index ()
  :     {
  :         return View ();
  :     }
  24:}

According to the Convention, the action Method index renders the view file corresponding to the path should be "~/views/home/index.cshtml", we create this view file under this path. In order to be able to compile the exception during the dynamic compilation, we wrote the following three lines of code in this view file,Foobar is a type that has not yet been created .

   
   2:     var value = new Foobar ();
   3:}

When we use the browser to access the HomeController action method index, the application will dynamically compile the target view, because the view file uses a non-undefined type, dynamic compilation will fail, the response error message will appear in the form of 7 in the browser. You can see that the error page shows the content and structure is completely different from the example shown earlier, we can not only get the path of the view file that caused the compilation to fail ("views/home/index.cshtml") from this error page, but also directly see the line of code that caused the compilation to fail. Not only that, this error page will also direct the source code that participates in the compilation (not the original in the. cshtml file, but the C # code generated by the conversion process). There is no doubt that this so detailed error page is very valuable for believing that developers are correcting for errors.

In general, the entire process of dynamic compilation consists of two steps, first converting the source code (a template file like. cshtml) into code for a certain. NET language (such as C #), and then compiling it further into IL code. Exception types thrown during dynamic compilation generally implement the Icompilationexception interface. As shown in the following code fragment, the interface value has a unique property of Compilationfailures, which returns a collection of element types Compilationfailure. The information about the compilation failure is encapsulated in a Compilationfailure object that we can use to get the path (Sourcefilepath) and content (sourcefilecontent) of the source file, as well as the content of the source code after it is translated and delivered. If an error has occurred during the content conversion process, the Sourcefilecontent property may return null.

   1:public Interface Icompilationexception
   2: {
   3:     ienumerable<compilationfailure> compilationfailures {get;}
   4:}
   
   6:public class Compilationfailure
   7: {
   8: Public     string                             sourcefilecontent {  get;}
   9: Public     string                             sourcefilepath {  get;}
  Ten: Public     string                             compiledcontent {  get;}
  One: Public     ienumerable<diagnosticmessage>     Messages {  get;}
  A: ...     
  13:}

The Compilationfailure type also has a read-only property named messages, which returns a collection of element types Diagnosticmessage, and a Diagnosticmessage object that carries diagnostic information describing compilation errors. Not only can we get messages describing compilation errors (message and formattedmessage), but also the path (Sourcefilepath) and scope of the source file where the compilation error occurred, with the help of the Diagnosticmessage object's related properties. The StartLine, StartColumn, EndLine, and EndColumn properties, respectively, indicate that the source code that caused the compilation error starts and ends the rows and columns (counting the number of rows and columns, respectively, from 1 and 0) in the Origin file.

   1:public class Diagnosticmessage
   2: {
   3: Public     string     sourcefilepath {  get;}
   4: Public     int        StartLine {  get;}
   5: Public     int        StartColumn {  
   6: Public     int        EndLine {  get;}
   7: Public     int        EndColumn {  get;}
   
   9: Public     string     Message {  get;}      
  Ten: Public     string     formattedmessage {  
  11: ...
  12:}

As you can see, the error page directly displays the relevant source code that caused the compilation to fail. Specifically, it does not only implement the source code that directly causes the failure, but it also displays the source code that is adjacent to the front and back. As to how many rows the adjacent source code should display, it is actually controlled by the Sourcecodelinecount property of the developerexceptionpageoptions.

   1:public class Program
   2: {
   3: Public     static void Main ()
   4:     {
   5:         New Webhostbuilder ()
   6:             . Usekestrel ()
   7:             . Usecontentroot (Directory.GetCurrentDirectory ())
   8:             . Configureservices (Svcs = Svcs. ADDMVC ())
   9:             . Configure (app = App
  Ten:                 3 })
  One:                 . USEMVC ())
  A:             . Build ()
  :             . Run ();
  :     }
  15:}

For this example of the previous demo, if we want the next three lines of code to be displayed on the error page, We can specify a Developerexceptionpageoptions object for the registered Developerexceptionpagemiddleware middleware by using the method above, and set its Sourcecodelinecount property to 3. At the same time, we rewrite the view file (index.cshtml) as follows: 4 lines of code were added before and after the line that caused the compilation to fail.

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

For a total of 9 lines of code that are defined in the view file, according to the rules specified when registering the Developerexceptionpagemiddleware middleware, the final display on the error page should be line 2nd through 8th. If you use a browser to access the same address, we will see that the 7 lines of code will appear on the error page in the form. It is worth mentioning that if we do not explicitly set the Sourcecodelinecount property, its default value is 6.

second, handling the run-time exception

For Developerexceptionpagemiddleware Middleware, exceptions of any type that do not implement the Icompilationexception interface are considered "runtime exceptions." Error handling through ASP. NET core application [1]: Three examples of how error pages are rendered we already know that The Developerexceptionpagemiddleware middleware handles run-time exceptions by not only displaying the details of the exception on the error page, but also containing information about the current request, including the query string , a collection of Cookie and request headers . Now we are concerned with another question, what is the purpose of this Fileprovider object that we use Developerexceptionpageoptions for?

In addition to the basic information about the type and message, the exception's stack trace will appear on the page for the details of the exception that describes the error page rendering. Furthermore, if the stack trace contains information about the source code (such as the source file path and the row and column in which the source code is located), the Developerexceptionpagemiddleware middleware will try to load the source file and display the original source code that causes the exception to be displayed intact.

   1:public class Program
   2: {
   3: Public     static void Main ()
   4:     {
   5:         New Webhostbuilder ()
   6:             . Usekestrel ()
   7:             . Configure (app = App
   8:                 . Usedeveloperexceptionpage ()
   9:                 . Run (Invoke))
  Ten:             . Build ()
  One:             . Run ();
  :     }
  
  +:     private static Task Invoke (HttpContext context)
  :     {
  :         throw new InvalidOperationException ("Manually thrown exception");
  :     }
  18:}

We will rewrite the code shown above as above and run the program locally in debug mode, and we will get the error page as indicated. We will see that the line of code that caused the exception can be displayed intact because the stack trace information for the exception contains information about the source code (source file path and line number). As with the compiler exception handling, it also shows the adjacent code, as to how many lines of adjacent code will be displayed, naturally through the Developerexceptionpageoptions Sourcecodelinecount property control.

Developerexceptionpageoptions's Fileprovider provides a Fileprovider object to help read the contents of the source file, or it provides the source file for our error correction debugging. If we did not explicitly provide such a fileprovider when we created the Developerexceptionpagemiddleware middleware, The physicalfileprovider that points to the Contentroot directory is then used by default. It is worth mentioning that if the path of the source file appears in the trace stack of the exception, the Developerexceptionpagemiddleware middleware will always attempt to load the file from the local file system first. Only if the local file fails to load will it use the specified Fileprovider to read the file.

Error handling for ASP. NET core applications [1]: Three ways to render error pages
Error handling for ASP. NET core applications [2]:developerexceptionpagemiddleware middleware
Error handling for ASP. NET core applications [3]:exceptionhandlermiddleware middleware
Error handling for ASP. NET core applications [4]:statuscodepagesmiddleware middleware

Developerexceptionpagemiddleware middleware How to render "developer Exception page"

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.