Error Logging Middleware in ASP.NET Core
Tags: dotnet, csharp, middleware, aspnetcore
Published: 2019-06-07 06:09:55

---
title: Error Logging Middleware in ASP.NET Core
published: true
description: Using middleware in ASP.NET Core, implementing custom error logging have never been easier. Learn how to log all crashes on your website to your log files or elmah.io using the request pipeline available in Core. Avoid common pitfalls when implementing and installing middleware.
tags: dotnet, csharp, middleware, aspnetcore
canonical_url: https://blog.elmah.io/error-logging-middleware-in-aspnetcore/
---

This post is about the concept of middleware in ASP.NET Core. The post is named *Error Logging Middleware in ASP.NET Core* because I want to use error logging as an example of utilizing middleware. The concepts around middleware shown in the examples throughout this post aren't bound to error logging in any way and can be used as a foundation for building all types of middleware.

Middleware are code components executed as part of the request pipeline in Core. If you have a background in ASP.NET and think this sounds familiar, you're right. Middleware is pretty much HTTP modules as you know it from ASP.NET. The biggest difference between modules and middleware is really how you configure it. Modules are configured in `web.config` and since Core doesn't use the concept of a `web.config`, you configure middleware in C#. If you know Express for Node.js, you will find that configuring middleware heavily borrow a lot of concepts from that.

Let's wait with more babbling about middleware and look at an example. Middleware in its most simple form is a C# class. Let's create some error logging middleware:

```csharp
public class ErrorLoggingMiddleware
{
    private readonly RequestDelegate _next;

    public ErrorLoggingMiddleware(RequestDelegate next)
    {
        _next = next;
    }

    public async Task Invoke(HttpContext context)
    {
        try
        {
            await _next(context);
        }
        catch (Exception e)
        {
            System.Diagnostics.Debug.WriteLine($"The following error happened: {e.Message}");
            throw;
        }
    }
}
```

In order for our middleware to work, we need to implement two things. A constructor accepting a `RequestDelegate` and an `Invoke` method. The contructor is called a single time, but the underlying delegate will change from request to request. All middleware components are responsible for either executing the next link in the pipeline (`_next`) or terminate the pipeline by not calling `_next`. In our case, we want to execute the rest of the pipeline in order to catch any exceptions happening while processing the HTTP request. When an exception is caught, we log a message to `System.Diagnostics.Debug`. In real life, you probably want to log somewhere better, but for the demo, we want the exception to show up inside Visual Studio only.

Notice that the `catch`-block throw the exception after logging it to `System.Diagnostics`. Throwing the exception makes sure that other pieces of middleware handling exceptions still work.

To tell Core about our new and shiny piece of middleware, configure it in `Startup.cs`:

```csharp
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory fac)
{
    ...
    app.UseMiddleware<ErrorLoggingMiddleware>();
    ...
}
```

Make sure to call the `UseMiddleware`-method after installing other pieces of middleware handling exceptions (like `UseExceptionHandler`). Some middleware classes "swallow" the exception, which results in your catch block not being triggered. By adding your middleware as the last piece, the class is invoked closer to the failing code.

To test the middleware, make the `Index`-method in `HomeController` throw an exception:

```csharp
public class HomeController : Controller
{
    public IActionResult Index()
    {
        throw new Exception("Some error yo");
    }
}
```

When starting the project, the exception is now logged to the Output window in Visual Studio:

![Debug message in output](https://blog.elmah.io/content/images/old/debug_message_in_output.png)

Success! We just implemented our first piece of functional middleware for Core.

While calling the `UseMiddleware<>` method in `Startup.cs` definitely work, it is considered the good practice to create a custom `Use`-method:

```csharp
public static class ErrorLoggingMiddlewareExtensions
{
    public static IApplicationBuilder UseErrorLogging(this IApplicationBuilder builder)
    {
        return builder.UseMiddleware<ErrorLoggingMiddleware>();
    }
}
```

Call the static method in `Startup.cs`:

```csharp
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory fac)
{
    ...
    app.UseErrorLogging();
    ...
}
```

For an example on how to implement fully featured error logging middleware for Core, check out our [elmah.io support for ASP.NET Core](https://docs.elmah.io/logging-to-elmah-io-from-aspnet-core/) on <a href="https://github.com/elmahio/Elmah.Io.AspNetCore/blob/master/Elmah.Io.AspNetCore/ElmahIoMiddleware.cs" target="_blank">GitHub</a>.

## Would your users appreciate fewer errors?

elmah.io is the easy error logging and uptime monitoring service for .NET. Take back control of your errors with support for all .NET web and logging frameworks.

➡️ [Error Monitoring for .NET Web Applications](https://elmah.io/?utm_source=devto&utm_medium=social&utm_campaign=devtoposts) ⬅️

This article first appeared on the elmah.io blog at https://blog.elmah.io/error-logging-middleware-in-aspnetcore/