3 Ways To Create Middleware In ASP.NET Core
Tags: aspnet, aspnetcore, dotnet, csharp
Published: 2023-09-10 07:52:27

---
title: 3 Ways To Create Middleware In ASP.NET Core
published: true
date: 2022-10-01 00:00:00 UTC
tags: aspnet,aspnetcore,dotnet,csharp
canonical_url: https://www.milanjovanovic.tech/blog/3-ways-to-create-middleware-in-asp-net-core
cover_image: https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6imb1p6pkokf1r8305ql.png
---

In this newsletter, we'll be covering three ways to create middleware in **ASP.NET Core** applications.

**Middleware** allows us to introduce additional logic before or after executing an HTTP request.

You are already using many of the built-in middleware available in the framework.

I'm going to show you three approaches to how you can define custom middleware:

- With Request Delegates
- By Convention
- Factory-Based

Let's go over each of them and see how we can implement them in code.

## Adding Middleware With Request Delegates

The first approach to defining a middleware is by writing a **Request Delegate**.

You can do that by calling the `Use` method on the `WebApplication` instance and providing a lambda method with two arguments. The first argument is the `HttpContext` and the second argument is the actual next request delegate in the pipeline `RequestDelegate`.

Here's what this would look like:

```csharp
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();

app.Use(async (context, next) =>
{
    // Add code before request.

    await next(context);

    // Add code after request.
});
```

By awaiting the `next` delegate, you are continuing the request pipeline execution. You can _short-circuit_ the pipeline by not invoking the `next` delegate.

This overload of the `Use` method is the one suggested by **Microsoft**.

## Adding Middleware By Convention

The second approach requires us to create a class that will represent our middleware. We have to follow the convention when creating this class so that we can use it as middleware in our application.

I'm first going to show you what this class looks like, and then explain what is the convention we are following here.

Here's how this class would look like:

```csharp
public class ConventionMiddleware
{
    private readonly RequestDelegate _next;
    private readonly ILogger _logger;

    public ConventionMiddleware(
        RequestDelegate next,
        ILogger logger)
    {
        _next = next;
    }

    public async Task InvokeAsync(HttpContext context)
    {
        _logger.LogInformation("Before request");

        await next(context);

        _logger.LogInformation("After request");
    }
}
```

The convention we are following has a few rules:

- We need to inject a `RequestDelegate` in the constructor
- We need to define an `InvokeAsync` method with an `HttpContext` argument
- We need to invoke the `RequestDelegate` and pass it the `HttpContext` instance

There's one more thing that's required, and that is to tell our application to use this middleware.

We can do that by calling the `UseMiddleware` method:

```csharp
app.UseMiddleware<ConventionMiddleware>();
```

And with this, we have a functioning middleware.

## Adding Factory-Based Middleware

The third and last approach requires us to also create a class that will represent our middleware.

However, this time we're going to implement the `IMiddleware` interface. This interface has only one method - `InvokeAsync`.

Here's what this class would like:

```csharp
public class FactoryMiddleware : IMiddleware
{
    private readonly ILogger _logger;

    public FactoryMiddleware(ILogger logger)
    {
        _logger = logger;
    }

    public async Task InvokeAsync(
        HttpContext context,
        RequestDelegate next)
    {
        _logger.LogInformation("Before request");

        await next(context);

        _logger.LogInformation("After request");
    }
}
```

The `FactoryMiddleware` class will be resolved at runtime from dependency injection.

Because of this, we need to register it as a service:

```csharp
builder.Services.AddTransient<FactoryMiddleware>();
```

And like the previous example, we need to tell our application to use our factory-based middleware:

```csharp
app.UseMiddleware<FactoryMiddleware>();
```

With this, we have a functioning middleware.

## A Word On Strong Typing

I'm a big fan of **strong typing** whenever possible. Out of the three approaches I just showed you, the one using the`IMiddleware` interface satisfies this constraint the most. This is also my **preferred** way to implement **middleware**.

Since we're implementing an interface, it's very easy to create a generic solution to never forget to register your middleware.

You can use reflection to scan for classes implementing the `IMiddleware` interface and add them to dependency injection, and also add them to the application by calling `UseMiddleware`.

* * *

**P.S. Whenever you're ready, there are 2 ways I can help you:**

1. [**Pragmatic Clean Architecture:**](https://www.milanjovanovic.tech/pragmatic-clean-architecture?utm_source=dev.to&utm_medium=website&utm_campaign=cross-posting) This comprehensive course will teach you the system I use to ship production-ready applications using Clean Architecture. Learn how to apply the best practices of modern software architecture. [**Join 950+ students here.**](https://www.milanjovanovic.tech/pragmatic-clean-architecture?utm_source=dev.to&utm_medium=website&utm_campaign=cross-posting)

2. [**Patreon Community:**](https://www.patreon.com/milanjovanovic) Think like a senior software engineer with **access to the source code** I use in my YouTube videos and **exclusive discounts** for my courses. [**Join 820+ engineers here.**](https://www.patreon.com/milanjovanovic)