Cookie Consent by Free Privacy Policy Generator 📌 How To Create Custom Middlewares in ASP.NET Core


✅ How To Create Custom Middlewares in ASP.NET Core


💡 Newskategorie: Programmierung
🔗 Quelle: dev.to

ASP.NET Core's middleware architecture offers a powerful way to build and configure the HTTP request pipeline in your applications.
In this post, you'll explore what middleware is and how to create a custom middlewares in ASP.NET Core.

What is Middleware in ASP.NET Core?

Middleware in ASP.NET Core is a software component that is a part of application pipeline that handles requests and responses.
In ASP.NET Core there are multiple middlewares that are combined in a chain with each other.

Each middleware component in the pipeline is responsible for invoking the next component in the sequence.
Any middleware can stop other middlewares from execution by short-circuiting the chain if necessary.
Middlewares in ASP.NET Core is a classic implementation of chain of responsibility design pattern.

ASP.NET Core has a lot of built-in middlewares and many provided by Nuget packages.
The order in which middlewares are added to the application pipeline is critical.
It defines how the incoming HTTP requests travel through the pipeline and in what sequence the responses are sent back.

Middlewares are executed in the order they are added to the pipeline in the WebApplication object.
If you want to learn more about common middlewares and their correct order - read my blog post.

How To Create Custom Middleware in ASP.NET Core

You can create a custom middleware in the following ways:

  • provide a delegate for Use method in WebApplication class
  • create a Middleware class by convention
  • create a Middleware class by inheriting from IMiddleware interface

With a Use Method in WebApplication Class

You can call a Use method on the WebApplication class to create a middleware:

var builder = WebApplication.CreateBuilder(args);

builder.Logging.AddConsole();

var app = builder.Build();

app.Use(async (context, next) =>
{
    Console.WriteLine("Request is starting...");

    await next();

    Console.WriteLine("Request has finished");
});

app.MapGet("/api/books", () =>
{
    var books = SeedService.GetBooks(10);
    return Results.Ok(books);
});

await app.RunAsync();

In this example when calling a /api/books endpoint, the middleware declared in the Use method is called first.
await next.Invoke() calls the books endpoint itself, but before and after we have a message logged to console:

Request is starting...
Request has finished

Middlewares are executed in the order they are added to the pipeline in the WebApplication object.
Each middleware can perform operations before and after the next middleware:

Before: executing operations before calling the next middleware can include tasks like logging, authentication, validation, etc.

After: operations after calling the next middleware can include tasks like response modification or error handling.

The real power of middlewares is that you can chain them freely in any order you want.
To stop the request from executing and short-cut the middleware chain (stop other middlewares from executing) - write a response directly into HttpContext instead of calling the await next.Invoke() method:

await context.Response.WriteAsync("Some response here");

With a Middleware Class by Convention

You can extract a middleware to a separate class that follows the specific convention:

public class LoggingMiddleware
{
    private readonly RequestDelegate _next;

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

    public async Task InvokeAsync(HttpContext context)
    {
        Console.WriteLine($"Request: {context.Request.Method} {context.Request.Path}");

        await _next(context);

        Console.WriteLine($"Response: {context.Response.StatusCode}");
    }
}

To add this middleware to the pipeline, call the UseMiddleware method on the WebApplication class:

app.Use(async (context, next) =>
{
    // Middleware from previous example
});

app.UseMiddleware<LoggingMiddleware>();

As a result of executing this middleware the following will be logged to the console when executing an /api/books endpoint:

Request is starting...
Request: GET /api/books

Response: 200
Request has finished

This approach is called by convention, because middleware class must follow these rules:

  • middleware class should have a InvokeAsync method with a required HttpContext argument
  • middleware class should inject a next RequestDelegate in the constructor
  • middleware class call the next RequestDelegate delegate and pass it the HttpContext argument

With a Middleware Class That Implements IMiddleware Interface

The previous approach has its drawbacks: the developer needs to create a middleware class that follows all mentioned above rules, otherwise a middleware won't work.
But there is a safer way to create a middleware: implement the IMiddleware interface:

public class ExecutionTimeMiddleware : IMiddleware
{
    public async Task InvokeAsync(HttpContext context, RequestDelegate next)
    {
        var watch = Stopwatch.StartNew();

        await next(context);

        watch.Stop();

        Console.WriteLine($"Request executed in {watch.ElapsedMilliseconds}ms");
    }
}

This approach is much safer as the compiler tells how the middleware class should look like.

For this approach you need to manually register ExecutionTimeMiddleware in the DI container:

builder.Services.AddScoped<ExecutionTimeMiddleware>();

To add this middleware to the pipeline, call the UseMiddleware method on the WebApplication class:

app.Use(async (context, next) =>
{
    // Middleware from previous example
});

app.UseMiddleware<LoggingMiddleware>();
app.UseMiddleware<ExecutionTimeMiddleware>();

As a result of executing this middleware the following will be logged to the console when executing an /api/books endpoint:

Request is starting...
Request: GET /api/books
Request executed in 68ms

Response: 200
Request has finished

Middlewares and Dependency Injection

Middlewares by convention have Singleton lifetime by default and all dependencies injected in constructor must be singletons too.
As we already know, middlewares run per each request, and you can inject scoped dependencies in the InvokeAsync method after HttpContext.
Here we are injecting a ILoggingService that is registered as scoped service in DI:

builder.Services.AddScoped<ILoggingService, ConsoleLoggingService>();
public class LoggingMiddleware
{
    private readonly RequestDelegate _next;

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

    public async Task InvokeAsync(HttpContext context, ILoggingService loggingService)
    {
        loggingService.LogRequest(context.Request.Method, context.Request.Path);

        await _next(context);

        loggingService.LogResponse(context.Response.StatusCode);
    }
}

This approach is suitable only for middleware classes created by convention.
To inject scoped services into middleware classes that implement IMiddleware interface, simply use the constructor:

public class ExecutionTimeMiddleware : IMiddleware
{
    private readonly ILoggingService _loggingService;

    public ExecutionTimeMiddleware(ILoggingService loggingService)
    {
        _loggingService = loggingService;
    }

    public async Task InvokeAsync(HttpContext context, RequestDelegate next)
    {
        // ...
    }
}

NOTE: when creating a middleware class that implements IMiddleware interface - you are responsible for selecting an appropriate DI lifetime for it.
You can create Singleton, Scoped or Transient middleware, select what suits the best in each use case.

Summary

You can create a custom middleware in the following ways:

  • provide a delegate for Use method in WebApplication class
  • create a Middleware class by convention
  • create a Middleware class by inheriting from IMiddleware interface

My preferred choice is to create a middleware by inheriting from the IMiddleware interface.
This approach offers a safer, more convenient way to create middlewares and a straightforward dependency injection strategy through a constructor.
And it also gives a full control over the middleware lifetime.

Hope you find this blog post useful. Happy coding!

Originally published at https://antondevtips.com.

After reading the post consider the following:

  • Subscribe to receive newsletters with the latest blog posts
  • Download the source code for this post from my github (available for my sponsors on BuyMeACoffee and Patreon)

If you like my content —  consider supporting me

Unlock exclusive access to the source code from the blog posts by joining my Patreon and Buy Me A Coffee communities!

...

✅ How To Create Custom Middlewares in ASP.NET Core


📈 64.94 Punkte

✅ Entendendo o que são middlewares em uma aplicação ASP.NET


📈 44.17 Punkte

✅ Visual Studio for Mac + ASP.NET Core – Getting started with ASP.NET Core using eShopOnWeb


📈 42.81 Punkte

✅ .NET Core, ASP.NET Core und Entity Framework Core 2.1 sind fertig


📈 38.98 Punkte

✅ Microsoft .NET Maze: Understand .NET Core Vs .NET Framework Vs ASP.NET


📈 38.91 Punkte

✅ Upcoming SameSite Cookie Changes in ASP.NET and ASP.NET Core


📈 36.95 Punkte

✅ Using SkipToken for Paging in Asp.Net OData and Asp.Net Core OData


📈 36.95 Punkte

✅ Differences between Asp.net and Asp.net Core


📈 36.95 Punkte

✅ Learn Live - Create web apps and services with ASP.NET Core, minimal API, and .NET 6


📈 34 Punkte

✅ ASP.NET Core updates in .NET Core 3.1 Preview 2


📈 33.11 Punkte

✅ ASP.NET Core and Blazor updates in .NET Core 3.0 Preview 6


📈 33.11 Punkte

✅ ASP.NET Core updates in .NET Core 3.1 Preview 1


📈 33.11 Punkte

✅ .NET Core und ASP.NET Core 2.2.0 Preview 3 verfügbar


📈 33.11 Punkte

✅ Microsoft ASP.NET Core/.NET Core Web Request denial of service


📈 33.11 Punkte

✅ ASP.NET Core 3.0 läuft nur noch auf .NET Core


📈 33.11 Punkte

✅ Microsoft ASP.NET Core/.NET Core Web Request privilege escalation


📈 33.11 Punkte

✅ Microsoft ASP.NET Core/.NET Core Web Request Denial of Service


📈 33.11 Punkte

✅ Microsoft ASP.NET Core/.NET Core Web Request spoofing


📈 33.11 Punkte

✅ Microsoft ASP.NET Core/.NET Core Web Request erweiterte Rechte


📈 33.11 Punkte

✅ ASP.NET Core and Blazor updates in .NET Core 3.0


📈 33.11 Punkte

✅ Microsoft ASP.NET Core/.NET Core Web Request Spoofing [CVE-2017-0256]


📈 33.11 Punkte

✅ Announcing a Microsoft .NET Core and ASP.NET Core Bug Bounty


📈 33.11 Punkte

✅ ASP.NET Core and Blazor updates in .NET Core 3.0 Release Candidate 1


📈 33.11 Punkte

✅ Microsoft legt Bug-Bounty-Programm für .NET Core und ASP.NET Core neu auf


📈 33.11 Punkte

✅ Microsoft ASP.NET Core/.NET Core System.IO.Pipelines denial of service


📈 33.11 Punkte

✅ ASP.NET Core and Blazor updates in .NET Core 3.0 Preview 9


📈 33.11 Punkte

✅ Microsoft legt Bug-Bounty-Programm für .NET Core und ASP.NET Core neu auf


📈 33.11 Punkte

✅ Updating an ASP.NET Core 2.2 Web Site to .NET Core 3.1 LTS


📈 33.11 Punkte

✅ 4021279 - Vulnerabilities in .NET Core, ASP.NET Core Could Allow Elevation of Privilege - Version: 1.1


📈 33.11 Punkte

✅ ASP.NET Core updates in .NET Core 3.1


📈 33.11 Punkte

✅ ASP.NET Core and Blazor updates in .NET Core 3.0 Preview 8


📈 33.11 Punkte

✅ ASP.NET Core updates in .NET Core 3.1 Preview 3


📈 33.11 Punkte

✅ ASP.NET Core and Blazor updates in .NET Core 3.0 Preview 7


📈 33.11 Punkte

✅ Middleware to Asp.net Core MVC Application + Custom Middleware


📈 29.55 Punkte











matomo

Datei nicht gefunden!