AspNetCore.Docs/aspnetcore/fundamentals/middleware/write.md

3.7 KiB

title author description ms.author ms.custom ms.date uid
Write custom ASP.NET Core middleware rick-anderson Learn how to write custom ASP.NET Core middleware. riande mvc 02/14/2019 fundamentals/middleware/write

Write custom ASP.NET Core middleware

By Rick Anderson and Steve Smith

Middleware is software that's assembled into an app pipeline to handle requests and responses. ASP.NET Core provides a rich set of built-in middleware components, but in some scenarios you might want to write a custom middleware.

Middleware class

Middleware is generally encapsulated in a class and exposed with an extension method. Consider the following middleware, which sets the culture for the current request from a query string:

[!code-csharp]

The preceding sample code is used to demonstrate creating a middleware component. For ASP.NET Core's built-in localization support, see xref:fundamentals/localization.

You can test the middleware by passing in the culture. For example, http://localhost:7997/?culture=no.

The following code moves the middleware delegate to a class:

[!code-csharp]

::: moniker range="< aspnetcore-2.0"

The middleware Task method's name must be Invoke. In ASP.NET Core 2.0 or later, the name can be either Invoke or InvokeAsync.

::: moniker-end

Middleware extension method

The following extension method exposes the middleware through xref:Microsoft.AspNetCore.Builder.IApplicationBuilder:

[!code-csharp]

The following code calls the middleware from Startup.Configure:

[!code-csharp]

Middleware should follow the Explicit Dependencies Principle by exposing its dependencies in its constructor. Middleware is constructed once per application lifetime. See the Per-request dependencies section if you need to share services with middleware within a request.

Middleware components can resolve their dependencies from dependency injection (DI) through constructor parameters. UseMiddleware<T> can also accept additional parameters directly.

Per-request dependencies

Because middleware is constructed at app startup, not per-request, scoped lifetime services used by middleware constructors aren't shared with other dependency-injected types during each request. If you must share a scoped service between your middleware and other types, add these services to the Invoke method's signature. The Invoke method can accept additional parameters that are populated by DI:

public class CustomMiddleware
{
    private readonly RequestDelegate _next;

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

    // IMyScopedService is injected into Invoke
    public async Task Invoke(HttpContext httpContext, IMyScopedService svc)
    {
        svc.MyProperty = 1000;
        await _next(httpContext);
    }
}

Additional resources