Skip to main content
Various ASP.NET Core Diagnostics Middleware

Various ASP.NET Core Diagnostics Middleware

Middleware is the heart of an ASP.NET Core application. You can think of middleware as small connectors which makes a pipeline to accept requests and send responses. Anything which your ASP.NET core application does is performed by middleware. Middleware are small application components that can be incorporated into an HTTP request pipeline like HttpHandlers and HttpModules. But middleware are different from HttpModules. In this post, we take a look at various ASP.NET Core Diagnostics middleware examples which are used for error logging and handling, exception handling and runtime environment information.
03.03.2017: Updated to ASP.NET Core 1.0 version

ASP.NET Core Diagnostics Middleware

ASP.NET Core comes with many built-in and ready to use middleware, and you add them to your application in the Startup.Configure method. These built-in middleware can be classified in the following categories.

Built-in Middleware

Authentication Provides authentication support.
CORS Configures Cross-Origin Resource Sharing.
Routing Define and constrain request routes.
Session Provides support for managing user sessions.
Routing Provides support for serving static files, and directory browsing.
Diagnostics Includes support for error pages and runtime information.

In this post, we are interested in Diagnostics middleware. And some of the built-in diagnostics middleware are,

In any ASP.NET Core 1.0 RTM web application, you will find many built-in middleware are already added to the HTTP request pipeline. You can verify this in Startup.cs file -> configure() method. Highlighted lines in below code, are built-in Middleware with ASP.NET Core 1.0.

public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
    loggerFactory.AddConsole(Configuration.GetSection("Logging"));
    loggerFactory.AddDebug();

    app.UseApplicationInsightsRequestTelemetry();

    if (env.IsDevelopment())
    {
        app.UseBrowserLink();
        app.UseDeveloperExceptionPage();
    }
    else
    {
        app.UseExceptionHandler("/Home/Error");

        // For more details on creating database during deployment see http://go.microsoft.com/fwlink/?LinkID=615859
        try
        {
            using (var serviceScope = app.ApplicationServices.GetRequiredService<IServiceScopeFactory>()
                .CreateScope())
            {
                serviceScope.ServiceProvider.GetService<ApplicationDbContext>()
                        .Database.Migrate();
            }
        }
        catch { }
    }

    app.UseIISPlatformHandler(options => options.AuthenticationDescriptions.Clear());
    app.UseStaticFiles();
    app.UseIdentity();

    // To configure external authentication please see http://go.microsoft.com/fwlink/?LinkID=532715

    app.UseMvc(routes =>
    {
        routes.MapRoute(
            name: "default",
            template: "{controller=Home}/{action=Index}/{id?}");
    });
}

Let’s take a look at diagnostics middleware.

app.UseDeveloperExceptionPage() Back to List

As you can see in the configure method, this middleware is already added and it will come into picture the hosting environment is development. And by default, hosting environment is development. I shall show you later how you can change it. So as the name UseDeveloperExceptionPage() says all that it’s going to execute on when an exception occurs and since it’s in a development mode it should show you the culprit line of code. You can say that it’s a replacement for yellow screen of death.

So let’s go ahead and add code which throws an exception. And the most common exception I could think of is “Object reference not set to an instance of an object”. So let’s add the following code in Index action method of home controller so that when we run the app, an exception occurs.

public IActionResult Index()
{
    string sMessage = null;
    if (sMessage.Length > 0)
    {
        var sResult = sMessage.Substring(0);
    }
    return View();
}

Self explanatory code. And now when you run the application you should see following.

Asp.net core middleware UseDeveloperExceptionPage

As you can see there are 4 tabs (Stack, Query, Cookie and Headers). Stack tab has information for culprit code (highlighted) and provides complete stack trace. Query tab has query string information (if any). Cookie tab tells you a list of all the cookies created by your application and the Headers tab has HTTP request header information.

On some blog post, you may find app.UseErrorPage() to handle errors, that was present in beta stage. In RC 1, it’s not available. With app.UseErrorPage, you had the option to choose which tab to show and which to hide.

app.UseDatabaseErrorPage() Back to List

Till RC1, this middleware was available in Microsoft.AspNetCore.Diagnostics package so it was available out of the box as this package is available by default for the ASP.NET Core project. With RTM release, it is now available with "Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore" nuget package.

This is similar to UseDeveloperExceptionPage() but it is used to display database related error details. The default ASP.NET Core application uses EF Code first approach to create a database and it provides functionality like user registration and login. It creates various DB tables and one of them is AspNetUsers. So for demo purpose, I renamed this table to AspNetUsers_ so that login button fails and display the error. You should see the following error on-screen with DB error “SqlException: Invalid object name ‘AspNetUsers’.

UseDataBaseErrorPage_00

If we don’t add UseDatabaseErrorPage() middleware and use UseDeveloperExceptionPage() to handle even DB errors, then you should see the following screen.

UseDeveloperException_In case of DB errors

app.UseExceptionHandler() Back to List

This middleware is also added by default to HTTP request pipeline in configure method and it will be executed only when the environment is not development. Which makes sense as on production environment you don’t want to show the error stack trace or DB related errors which is meant only for development purpose.

As you can see in below code, it is configured to accept the error handling path. So, in case of any exception, go to Home Controller -> Error action method and executes Error() action method to display the “Shared->error.cshtml” view.

if (env.IsDevelopment())
{
    app.UseBrowserLink();
    app.UseDeveloperExceptionPage();
    app.UseDatabaseErrorPage();
}
else
{
    app.UseExceptionHandler("/Home/Error");
}

But let’s first change the environment to Production. To change it, right-click on your Project Files -> Select Properties -> go to the Debug tab. You should see “Environment Variables” section. You can change the value from here.

ChangingEnvironmentSettings

Now when any exception occurs, you should see following. You can test it with same code which we used in Home Controller to show “Object reference not set to an instance of an object” exception.

Asp.net core middleware UseExceptionHandler

app.UseStatusCodePages() Back to List

This middleware can be used to handle the response status code is between 400 and 600. This middleware allows to return a generic error response or allows you to also redirect to any controller action or another middleware. To use this, add it to configure method.

app.UseStatusCodePages();

This by default returns simple text-only handlers for common status codes. Below is the result of 404 error.

Asp.net core middleware UseStatusCodePages

Please read How to handle 404 error in ASP.NET Core 1.0 to learn more about UseStatusCodePages middleware.

app.UseRuntimeInfoPage() Removed in 1.0 release Back to List

This middleware adds an endpoint and provide details of the application’s environment. Again, it should be used in development environment otherwise you would be exposing your application’s production environment which you must not do. Use following code to add this,

if (env.IsDevelopment())
{
    app.UseBrowserLink();
    app.UseDeveloperExceptionPage();
    app.UseDatabaseErrorPage();
    app.UseRuntimeInfoPage();
}
else
{
    app.UseExceptionHandler("/Home/Error");
}

And now run the application and add /runtimeinfo to the URL and you should see your application environment. It will display your runtime architecture, .NET runtime version, list of all the packages and location from where they are loaded.
Asp.net core middleware UseRuntimeInfoPage

app.UseWelcomePage() Back to List

This middleware adds a welcome page when your application starts. Use “UseWelcomePage()” to add this.

app.UseWelcomePage();

Once added, it will handle all the requests with a cool welcome page which uses embedded images and fonts to display a rich view.

Asp.net core middleware UseWelcomePage

There would be no links available on the page to go to other parts of the application. And even when you try to go to another page via URL, then also you would be redirected to this welcome page. Welcome page is a good option, when application’s work is in progress.

You can also configure this middleware to handle request for certain path.

app.UseWelcomePage("/welcome"));

So when you hit the URL http://localhost:49883/welcome, then only welcome page will come.

app.UseElmPage() and app.UseElmCapture() Back to List

Till RC1, this middleware was available in Microsoft.AspNetCore.Diagnostics package so it was available out of the box as this package is available by default for the ASP.NET Core project. With RTM release, it is now available with "Microsoft.AspNetCore.Diagnostics.Elm" nuget package.

ELMAH
(Error Logging Modules and Handlers) is an application-wide error logging facility that is completely pluggable. It can be dynamically added to a running ASP.NET web application, or even all ASP.NET web applications on a machine, without any need for re-compilation or re-deployment. ELMAH does not work with ASP.NET Core 1.0 as ELMAH is currently compiled for .NET 1.x and 2.0; run on .NET 1.x, 2.0. 3.x and 4.0. There is a middleware in the ASP.NET Core called “ELM” (Error Logging Middleware) that has some features similar to ELMAH.

To use ELM, we need to add 2 middlewares. One which capture the errors and other adds an endpoint to see the error log.

app.UseElmPage();
app.UseElmCapture();

And with RTM changes, also need to add ElmLoggerProvider service in ConfigureServices method.

public void ConfigureServices(IServiceCollection services)
{
    services.AddApplicationInsightsTelemetry(Configuration);
    services.AddElm();
    services.AddMvc();
}

Now when you add /elm to URL, then you should see something similar.

Asp.net core middleware UseElmPage

Here you have the option to filter the logs based on error, warning, information and other parameters.

These 2 needs to be used together. If you use only UseElmPage(), then only the endpoint is added but no information. And if you use only UseElmCapture(), then you are capturing information, but no place to display it.

You may also find this useful app.Use vs app.Run in ASP.NET Core middleware while adding middleware.

Summary

Middleware are great as it allows to have complete control on the request pipeline. In this post, you saw various diagnostics middleware examples to handle errors/exceptions, database errors, how to do error logging, handling of HTTP status codes and see run-time information. These are quite useful and save time at the time of development.

Thank you for reading. Keep visiting this blog and share this in your network. Please put your thoughts and feedback in the comments section.

2 thoughts on “Various ASP.NET Core Diagnostics Middleware

Leave a Reply

Your email address will not be published. Required fields are marked *

two × three =