Skip to content

Commit

Permalink
Conventional middleware class requirements. (#12895)
Browse files Browse the repository at this point in the history
  • Loading branch information
serpent5 authored and guardrex committed Jun 17, 2019
1 parent 3d60f12 commit 035fdc8
Show file tree
Hide file tree
Showing 2 changed files with 25 additions and 19 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ public class Startup
{
public void Configure(IApplicationBuilder app)
{
app.Use((context, next) =>
app.Use(async (context, next) =>
{
var cultureQuery = context.Request.Query["culture"];
if (!string.IsNullOrWhiteSpace(cultureQuery))
Expand All @@ -24,7 +24,7 @@ public void Configure(IApplicationBuilder app)
}

// Call the next delegate/middleware in the pipeline
return next();
await next();
});

app.Run(async (context) =>
Expand Down
40 changes: 23 additions & 17 deletions aspnetcore/fundamentals/middleware/write.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,10 @@
title: Write custom ASP.NET Core middleware
author: rick-anderson
description: Learn how to write custom ASP.NET Core middleware.
monikerRange: '>= aspnetcore-2.1'
ms.author: riande
ms.custom: mvc
ms.date: 02/14/2019
ms.date: 06/17/2019
uid: fundamentals/middleware/write
---
# Write custom ASP.NET Core middleware
Expand All @@ -21,33 +22,28 @@ Middleware is generally encapsulated in a class and exposed with an extension me

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`.
Test the middleware by passing in the culture. For example, request `https://localhost:5001/?culture=no`.

The following code moves the middleware delegate to a class:

[!code-csharp[](index/snapshot/Culture/RequestCultureMiddleware.cs)]

::: moniker range="< aspnetcore-2.0"
The middleware class must include:

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`.
* A public constructor with a parameter of type <xref:Microsoft.AspNetCore.Http.RequestDelegate>.
* A public method named `Invoke` or `InvokeAsync`. This method must:
* Return a `Task`.
* Accept a first parameter of type <xref:Microsoft.AspNetCore.Http.HttpContext>.

Additional parameters for the constructor and `Invoke`/`InvokeAsync` are populated by [dependency injection (DI)](xref:fundamentals/dependency-injection).

::: moniker-end
## Middleware dependencies

## Middleware extension method

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

[!code-csharp[](index/snapshot/Culture/RequestCultureMiddlewareExtensions.cs)]

The following code calls the middleware from `Startup.Configure`:

[!code-csharp[](index/snapshot/Culture/Startup.cs?name=snippet1&highlight=5)]

Middleware should follow the [Explicit Dependencies Principle](/dotnet/standard/modern-web-apps-azure-architecture/architectural-principles#explicit-dependencies) by exposing its dependencies in its constructor. Middleware is constructed once per *application lifetime*. See the [Per-request dependencies](#per-request-dependencies) section if you need to share services with middleware within a request.
Middleware should follow the [Explicit Dependencies Principle](/dotnet/standard/modern-web-apps-azure-architecture/architectural-principles#explicit-dependencies) by exposing its dependencies in its constructor. Middleware is constructed once per *application lifetime*. See the [Per-request middleware dependencies](#per-request-middleware-dependencies) section if you need to share services with middleware within a request.

Middleware components can resolve their dependencies from [dependency injection (DI)](xref:fundamentals/dependency-injection) through constructor parameters. [UseMiddleware&lt;T&gt;](/dotnet/api/microsoft.aspnetcore.builder.usemiddlewareextensions.usemiddleware#Microsoft_AspNetCore_Builder_UseMiddlewareExtensions_UseMiddleware_Microsoft_AspNetCore_Builder_IApplicationBuilder_System_Type_System_Object___) can also accept additional parameters directly.

## Per-request dependencies
## Per-request middleware 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:

Expand All @@ -70,6 +66,16 @@ public class CustomMiddleware
}
```

## Middleware extension method

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

[!code-csharp[](index/snapshot/Culture/RequestCultureMiddlewareExtensions.cs)]

The following code calls the middleware from `Startup.Configure`:

[!code-csharp[](index/snapshot/Culture/Startup.cs?name=snippet1&highlight=5)]

## Additional resources

* <xref:fundamentals/middleware/index>
Expand Down

0 comments on commit 035fdc8

Please sign in to comment.