Error Handling for ASP. NET Core applications [2]: how to present the exceptionpagemiddleware middleware & ldquo; Developer exception page & rdquo ;,

Source: Internet
Author: User


Error Handling for ASP. NET Core applications [2]: How does the exceptionpagemiddleware middleware present the "Developer exception page ",


In ASP. NET Core application error handling [1]: three ways to render error pages, we demonstrated how to present an error page through a few simple examples, the presentation of these error pages is completed by three corresponding middleware. Next we will introduce these three middleware in detail. The exception page displayed in the development environment is implemented by using the exceptionpagemiddleware middleware. [This Article has been synchronized to ASP. NET Core framework secrets]


  1: public class DeveloperExceptionPageMiddleware

  2: {

  3:     public DeveloperExceptionPageMiddleware(RequestDelegate next, IOptions<DeveloperExceptionPageOptions> options,

  4:         ILoggerFactory loggerFactory, IHostingEnvironment hostingEnvironment, DiagnosticSource diagnosticSource);

  5:     public Task Invoke(HttpContext context);

  6: }

As shown in the code snippet above, when we create an exceptionpagemiddleware object, we need to provide an IOptions <exceptionpageoptions> object in the form of parameters, while the exceptionpageoptions object carries the configuration options we specified for this middleware, the specific configuration options are reflected in the following attributes (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 call the extended method UseDeveloperExceptionPage of ApplicationBuilder to register the exceptionpagemiddleware middleware. These two extended methods are reloaded using the following method to create and register the exceptionpagemiddleware middleware.


  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));

 10:     }

 11: }

In ASP.. NET Core application error handling [1]: Three Ways to Display error pages. In this example, we have never used the predictionpageoptions object. For the two attributes defined in this type, I don't think many people know what configuration they can use. To answer this question clearly, we need to start with the two exception types processed by the exceptionpagemiddleware middleware. Generally, the exceptions processed by the middleware can be divided into two types: "RunTime exception" and "Compilation exception". The latter type implements the ICompilationException interface, the following code snippets basically reflect the implementation of exception handling in the exceptionpagemiddleware 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:         }

 10:         catch(Exception ex)

 11:         {

 12:             context.Response.Clear();

 13:             context.Response.StatusCode = 500;

 14:  

 15:             ICompilationException compilationException = ex as ICompilationException;

 16:             if (null != compilationException)

 17:             {

 18:                 await DisplayCompilationException(context, compilationException);

 19:             }

 20:             else

 21:             {

 22:                 await DisplayRuntimeException(context, ex);

 23:             }

 24:         }

 25:     }

 26:  

 27:     private Task DisplayRuntimeException(HttpContext context, Exception ex);

 28:      private Task DisplayCompilationException(HttpContext context,ICompilationException compilationException) ;

 29: }

I. Handle compilation exceptions

I think many people will be confused: We compile an ASP. NET Core applications should be first compiled into an assembly, and then deployed and started for execution. Why is there a "Compilation exception" during the running process? From ASP. at the application level of NET Core, we adopt "pre-compilation", which means that we deploy the compiled Assembly instead of the source code. Therefore, there is no "Compilation exception" during the running process. But do not forget that in an ASP. NET Core MVC application, view files (. cshtml) support "dynamic compilation. That is to say, we can directly deploy view source files, and applications can dynamically compile them during execution. In other words, because view files support dynamic compilation, we can directly modify view files in the deployment environment.


For the exceptionpagemiddleware middleware, for normal runtime exceptions, it uses the HTML document to display the detailed information of the exception itself and the information of the current request in the form of an HTML document, the instance we demonstrated earlier demonstrates this well. If the application encounters a compilation exception in the dynamic compiling View File, the final error page will have different structures and contents, we also use a simple example to demonstrate how to handle compilation exceptions using the exceptionpagemiddleware middleware.


We started an ASP. NET Core MVC application using the code shown below, and registered the exceptionpagemiddleware middleware by calling the extended method UseDeveloperExceptionPage of ApplicationBuilder. For the Action method Index defined in HomeController, it is responsible for displaying 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

 10:                 .UseDeveloperExceptionPage()

 11:                 .UseMvc())

 12:             .Build()

 13:             .Run();

 14:     }

 15: }

 16:  

 17: public class HomeController : Controller

 18: {

 19:     [HttpGet("/")]

 20:     public IActionResult Index()

 21:     {

 22:         return View();

 23:     }

 24: }

According to the Convention, the path of the View File displayed by the Action Method Index should be "~ /Views/home/index. cshtml ", we create this view file in this path. To enable compilation exceptions during the dynamic compilation process, we have written the following three lines of code in this view file. Foobar is a type that has not been created yet.


  1: @{

  2:     var value = new Foobar();

  3: }

When we use a browser to access HomeController's Action Method Index, the application will dynamically compile the target view. Because the View File uses an undefined type, dynamic compilation will fail, the returned error message appears in the browser as shown in figure 7. It can be seen that the content and structure displayed on the error page are completely different from those shown in the previous example, we can not only obtain the path ("Views/Home/Index. cshtml), you can also directly see the line of code that causes compilation failure. In addition, this error page will directly involve the source code to be compiled (not the original code defined in the. cshtml file, but the C # code generated after conversion ). There is no doubt that such a detailed error page is very valuable for developers who believe that the error correction is targeted.




In general, the entire process of dynamic compilation is composed of two steps, which first put the source code (similar. cshtml and other template files. NET Language (such as C #) code, and then further compiled into IL code. The ICompilationException interface is generally implemented for the exception types thrown during the dynamic compilation process. As shown in the following code snippet, this interface value has a unique property CompilationFailures, which returns a set of element types: CompilationFailure. Compilation Failure Information is encapsulated in a CompilationFailure object. We can use it to obtain the path (SourceFilePath) and content (SourceFileContent) of the source file, and the content to be compiled after source code conversion. If an error occurs during content conversion, the SourceFileContent attribute may return Null.


  1: public interface ICompilationException

  2: {

  3:     IEnumerable<CompilationFailure> CompilationFailures { get; }

  4: }

  5:  

  6: public class CompilationFailure

  7: {

  8:     public string                             SourceFileContent {  get; }

  9:     public string                             SourceFilePath {  get; }

 10:     public string                             CompiledContent {  get; }

 11:     public IEnumerable<DiagnosticMessage>     Messages {  get; }

 12:     …

 13: }

The CompilationFailure type also has a read-only attribute named Messages, which returns a set of DiagnosticMessage element types. A DiagnosticMessage object carries diagnostic information describing compilation errors. We can not only get the Message describing the compilation error (Message and FormattedMessage) by using the relevant attributes of the DiagnosticMessage object, but also obtain the path (SourceFilePath) and range of the source file where the compilation error occurs, the StartLine, StartColumn, EndLine, and EndColumn attributes indicate the rows and columns that cause compilation errors in the source file (the number of rows and columns start from 1 and 0 respectively ).


  1: public class DiagnosticMessage

  2: {

  3:     public string     SourceFilePath {  get; }

  4:     public int        StartLine {  get; }

  5:     public int        StartColumn {  get; }

  6:     public int        EndLine {  get; }

  7:     public int        EndColumn {  get; }

  8:  

  9:     public string     Message {  get; }      

 10:     public string     FormattedMessage {  get; }

 11: …

 12: }

The error page shows the source code that causes compilation failure. Specifically, it will not only implement the source code that directly leads to the failure, but also display the adjacent source code. The number of lines to be displayed in the adjacent source code is controlled by the SourceCodeLineCount attribute of exceptionpageoptions.


  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

 10:                 .UseDeveloperExceptionPage(new DeveloperExceptionPageOptions { SourceCodeLineCount = 3 })

 11:                 .UseMvc())

 12:             .Build()

 13:             .Run();

 14:     }

 15: }

For the example shown above, if we want the adjacent three lines of code to be displayed on the error page, we can use the above method to specify a predictionpageoptions object for the registered exceptionpagemiddleware middleware, set its SourceCodeLineCount attribute to 3. At the same time, we rewrite the View File (index. cshtml) to the following form, that is, four lines of code are added before and after the line of code that causes compilation failure.


  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 nine lines of code defined in the View File, according to the rules specified when registering the exceptionpagemiddleware middleware, the rows displayed on the error page should be 2nd to 8th lines. If you use a browser to access the same address, we will see that the seven lines of code will appear on the error page. It is worth mentioning that if we do not explicitly set the SourceCodeLineCount attribute, its default value is 6.




Ii. Handling runtime exceptions

For the exceptionpagemiddleware middleware, exceptions of any type that do not implement the ICompilationException interface are considered as "RunTime exceptions ". Through ASP.. NET Core application error handling [1]: three methods for displaying error pages. We already know the examples demonstrated, exceptionpagemiddleware not only displays exception details on the error page when handling runtime exceptions, but also contains information about the current request, this includes a collection of query strings, cookies, and request headers. Now we are concerned about another issue. What is the purpose of the FileProvider object that we use the predictionpageoptions?


In addition to the basic information such as the type and message, Stack Trace of an exception is displayed on the error page. In addition, if the stack trace contains source code information (such as the source file path and the row and column of the corresponding source code), the exceptionpagemiddleware middleware will try to load the source file, and display the source code that causes exceptions.


  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))

 10:             .Build()

 11:             .Run();

 12:     }

 13:  

 14:     private static Task Invoke(HttpContext context)

 15:     {

 16:         throw new InvalidOperationException("Manually thrown exception");

 17:     }

 18: }

We will rewrite the code demonstrated above to the above form and run the program in Debug mode locally. The error page shown in will be displayed. We can see that the exception stack trace information contains the source code information (source file path and row number), so the line of code that causes the exception can be displayed intact. Similar to the compilation exception handling method, the adjacent code is also displayed. As to how many lines of adjacent code will be displayed, the SourceCodeLineCount attribute of exceptionpageoptions is also controlled.




The FileProvider of exceptionpageoptions provides the FileProvider object to help read the content of the source file, or to provide the source file for our error correction debugging. If we do not explicitly provide such a FileProvider when creating the exceptionpagemiddleware middleware, The PhysicalFileProvider pointing to the ContentRoot directory will be used by default. It is worth mentioning that if the path of the source file appears in the abnormal tracing stack, the exceptionpagemiddleware middleware always tries to load the file from the local file system first, only when the local file fails to be loaded can it use the specified FileProvider to read the file.


Error Handling for ASP. NET Core applications [1]: Three error page rendering Methods

Error Handling for ASP. NET Core applications [2]: exceptionpagemiddleware Middleware

Error Handling for ASP. NET Core applications [3]: ExceptionHandlerMiddleware Middleware

Error Handling for ASP. NET Core applications [4]: StatusCodePagesMiddleware Middleware




Related Article

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.