Introduction and Initial Problem
They say is part 13 of ASP.NET Core tutorial. In this video, we'll discuss developer exception page in ASP.NET Core and its use for us as a software developer.
Now, let's take a look at the code that we already have. In this configure method, we are going to use the default behavior that we get out of the box with this UseFileServer middleware. So to keep things simple, I'm going to stop passing FileServerOptions to our UseFileServer middleware. And then, let's throw an exception from this middleware that we are registering using this run method. So let's throw a new exception, and the exception message is 'some error processing the request'.
With all these changes in place, let's run our application. Notice we do not see the exception. Instead, our application's default document, default.html, is served.
Why the Exception Isn't Thrown
If you understand how the request processing pipeline works in ASP.NET Core, then you might already know the reason why we are not seeing the exception that we are throwing from the middleware that we have registered using run method. From our previous video in the series, we already discussed this UseFileServer middleware combines the functionality of UseDefaultFiles and UseStaticFiles. And if we take a look at the wwwroot folder, we see we already have default.html.
So when we issue a request to the application's root URL—in our case, we are running it on our local machine—so when we issue a request to localhost colon 15410, this is our root application URL. So this request is handled by our UseFileServer middleware. So at this point, the pipeline starts to reverse, and this middleware that we have registered using this run method will not get the opportunity to execute. So we do not see this exception. Instead, we see this default document served by our UseFileServer middleware.
Triggering and Exploring the Exception Page
Now, let's request a static HTML file with name abc.html. Notice now we see the exception that we are throwing. So let's understand what's going on here. First of all, we know we do not have a file with this name, abc.html, within our wwwroot folder or any of its subfolders. So this UseFileServer middleware will give up processing the request and passes that request to the next piece of middleware, and this middleware here is throwing an exception. And that's the reason we see this exception page.
If you have any experience with classic ASP.NET, then you must be familiar with this page. This is similar to that yellow screen of death. In classic ASP.NET, we call this page 'developer exception page' in ASP.NET Core. And as the name implies, this developer exception page contains exception details. Notice on the first tab, we have the complete stack trace, including the file name and the line number that caused this exception. On the second tab, we see query string parameters. At the moment, we don't have any query string parameters, and hence we see no query string data. But if we have query string parameters like a equals 10 and b equals 20, for example, we see both those query string parameters under the query tab. Similarly, this third tab contains cookies information, if any. And this last tab contains request headers. So this is all very useful information for a developer like us to understand the root cause of the exception and properly fix it.
How UseDeveloperExceptionPage Middleware Works
Now, who is serving this developer exception page? Well, if we take a look at the code in the Configure method, as the name implies, this UseDeveloperExceptionPage middleware is serving this developer exception page. So let's understand how this UseDeveloperExceptionPage middleware works.
If we take a look at our application's request processing pipeline, the first middleware component that is plugged in is this UseDeveloperExceptionPage. So now when we make a request, at the moment we are requesting for the file abc.html, this middleware, UseDeveloperExceptionPage, is not going to do anything with the incoming request. It will simply pass that request to the next piece of middleware, that is UseFileServer. And we know we do not have a file with name abc.html, so this middleware component is going to pass that request to the next piece of middleware, and this middleware is throwing an exception. So if this UseDeveloperExceptionPage detects that any other middleware that is registered after it in the pipeline produces an exception, it's going to take that exception and serve this exception page.
The Importance of Middleware Order
So the point that I'm trying to make is UseDeveloperExceptionPage middleware must be plugged into the request processing pipeline as early as possible so it can handle the exception and display this developer exception page if a subsequent middleware component in the pipeline raises an exception.
Now, let's see what's going to happen if we plug this UseDeveloperExceptionPage middleware later in our request processing pipeline. So I'm going to cut it from here and place it after this middleware that's actually throwing the exception. So let's paste it here and then build our solution. Notice now when we reload this web page, we do not see the developer exception page. We see very little information. All we see is localhost is currently unable to handle this request, and we see that the server has produced error 500. So the point that I'm trying to make is for this UseDeveloperExceptionPage component to work properly, it must be plugged in early in the pipeline. So let's move it to the front of the queue, build the solution, and reload this webpage. We are back with the developer exception page.
Customizing the Developer Exception Page
Now, like most of the middleware components in ASP.NET Core, we can also customize this UseDeveloperExceptionPage middleware. Whenever we want to customize a middleware, always remember we may have the respective options object. In this case, we want to customize developer exception page middleware, so from the IntelliSense, we can see we have DeveloperExceptionPageOptions object.
So let's create an instance of this DeveloperExceptionPageOptions class. Let's call the instance also developerExceptionPageOptions with the lowercase d. And we are going to use this property, SourceCodeLineCount, and I'm going to set this to 10. I'll explain what this property will do in just a bit. And then let's pass this developerExceptionPageOptions object to our UseDeveloperExceptionPage middleware and then build our solution.
Now, before we reload this page, take a look at this stack trace. We know line number 40 is the line which is actually throwing the exception. And notice the number of lines of source code that we have before and after this line which is actually throwing the exception. We have around five lines of code. And at the moment, we have set SourceCodeLineCount property to 10. So let's reload this webpage and see what happens to the number of lines that we have before and after the line that's actually throwing the exception. Notice it's increased to 10.
Now let's change the value of this SourceCodeLineCount property to one, build the solution, and reload our web page. Notice now we only have one line of source code before and after line number 44, which is actually throwing the exception. So this property, that is SourceCodeLineCount property, determines the number of lines of source code to display before and after the line that actually causes the exception.
Summary and Key Takeaways
Now, let's quickly recap the main points. To enable developer exception page, plug in UseDeveloperExceptionPage middleware. This middleware must be plugged in as early as possible in the pipeline. It contains all the valuable information that a developer would need, like stack trace, query string, cookies, and HTTP headers. Finally, if you want to customize this middleware, use DeveloperExceptionPageOptions object. That's it in this video. Thank you for watching.