Prepare IMiddleware for 6.0 (#25424)

pull/25429/head
Kirk Larkin 2022-03-25 14:23:25 +00:00 committed by GitHub
parent 959f2039d4
commit e26b4d6ed4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 112 additions and 43 deletions

View File

@ -11,11 +11,11 @@ uid: fundamentals/middleware/extensibility
---
# Factory-based middleware activation in ASP.NET Core
:::moniker range=">= aspnetcore-3.0"
:::moniker range=">= aspnetcore-6.0"
<xref:Microsoft.AspNetCore.Http.IMiddlewareFactory>/<xref:Microsoft.AspNetCore.Http.IMiddleware> is an extensibility point for [middleware](xref:fundamentals/middleware/index) activation.
<xref:Microsoft.AspNetCore.Builder.UseMiddlewareExtensions.UseMiddleware*> extension methods check if a middleware's registered type implements <xref:Microsoft.AspNetCore.Http.IMiddleware>. If it does, the <xref:Microsoft.AspNetCore.Http.IMiddlewareFactory> instance registered in the container is used to resolve the <xref:Microsoft.AspNetCore.Http.IMiddleware> implementation instead of using the convention-based middleware activation logic. The middleware is registered as a [scoped or transient service](xref:fundamentals/dependency-injection#service-lifetimes) in the app's service container.
<xref:Microsoft.AspNetCore.Builder.UseMiddlewareExtensions.UseMiddleware%2A> extension methods check if a middleware's registered type implements <xref:Microsoft.AspNetCore.Http.IMiddleware>. If it does, the <xref:Microsoft.AspNetCore.Http.IMiddlewareFactory> instance registered in the container is used to resolve the <xref:Microsoft.AspNetCore.Http.IMiddleware> implementation instead of using the convention-based middleware activation logic. The middleware is registered as a [scoped or transient service](xref:fundamentals/dependency-injection#service-lifetimes) in the app's service container.
Benefits:
@ -28,21 +28,21 @@ Benefits:
## IMiddleware
<xref:Microsoft.AspNetCore.Http.IMiddleware> defines middleware for the app's request pipeline. The [InvokeAsync(HttpContext, RequestDelegate)](xref:Microsoft.AspNetCore.Http.IMiddleware.InvokeAsync*) method handles requests and returns a <xref:System.Threading.Tasks.Task> that represents the execution of the middleware.
<xref:Microsoft.AspNetCore.Http.IMiddleware> defines middleware for the app's request pipeline. The [InvokeAsync(HttpContext, RequestDelegate)](xref:Microsoft.AspNetCore.Http.IMiddleware.InvokeAsync%2A) method handles requests and returns a <xref:System.Threading.Tasks.Task> that represents the execution of the middleware.
Middleware activated by convention:
[!code-csharp[](extensibility/samples/3.x/MiddlewareExtensibilitySample/Middleware/ConventionalMiddleware.cs?name=snippet1)]
:::code language="csharp" source="extensibility/samples/3.x/MiddlewareExtensibilitySample/Middleware/ConventionalMiddleware.cs" id="snippet1":::
Middleware activated by <xref:Microsoft.AspNetCore.Http.MiddlewareFactory>:
[!code-csharp[](extensibility/samples/3.x/MiddlewareExtensibilitySample/Middleware/FactoryActivatedMiddleware.cs?name=snippet1)]
:::code language="csharp" source="extensibility/samples/3.x/MiddlewareExtensibilitySample/Middleware/FactoryActivatedMiddleware.cs" id="snippet1":::
Extensions are created for the middlewares:
Extensions are created for the middleware:
[!code-csharp[](extensibility/samples/3.x/MiddlewareExtensibilitySample/Middleware/MiddlewareExtensions.cs?name=snippet1)]
:::code language="csharp" source="extensibility/samples/3.x/MiddlewareExtensibilitySample/Middleware/MiddlewareExtensions.cs" id="snippet1":::
It isn't possible to pass objects to the factory-activated middleware with <xref:Microsoft.AspNetCore.Builder.UseMiddlewareExtensions.UseMiddleware*>:
It isn't possible to pass objects to the factory-activated middleware with <xref:Microsoft.AspNetCore.Builder.UseMiddlewareExtensions.UseMiddleware%2A>:
```csharp
public static IApplicationBuilder UseFactoryActivatedMiddleware(
@ -55,11 +55,11 @@ public static IApplicationBuilder UseFactoryActivatedMiddleware(
The factory-activated middleware is added to the built-in container in `Startup.ConfigureServices`:
[!code-csharp[](extensibility/samples/3.x/MiddlewareExtensibilitySample/Startup.cs?name=snippet1&highlight=6)]
:::code language="csharp" source="extensibility/samples/3.x/MiddlewareExtensibilitySample/Startup.cs" id="snippet1" highlight="6":::
Both middlewares are registered in the request processing pipeline in `Startup.Configure`:
Both middleware are registered in the request processing pipeline in `Startup.Configure`:
[!code-csharp[](extensibility/samples/3.x/MiddlewareExtensibilitySample/Startup.cs?name=snippet2&highlight=12-13)]
:::code language="csharp" source="extensibility/samples/3.x/MiddlewareExtensibilitySample/Startup.cs" id="snippet2" highlight="12-13":::
## IMiddlewareFactory
@ -67,13 +67,82 @@ Both middlewares are registered in the request processing pipeline in `Startup.C
The default <xref:Microsoft.AspNetCore.Http.IMiddlewareFactory> implementation, <xref:Microsoft.AspNetCore.Http.MiddlewareFactory>, is found in the [Microsoft.AspNetCore.Http](https://www.nuget.org/packages/Microsoft.AspNetCore.Http/) package.
## Additional resources
* <xref:fundamentals/middleware/index>
* <xref:fundamentals/middleware/extensibility-third-party-container>
:::moniker-end
:::moniker range=">= aspnetcore-3.0 < aspnetcore-6.0"
<xref:Microsoft.AspNetCore.Http.IMiddlewareFactory>/<xref:Microsoft.AspNetCore.Http.IMiddleware> is an extensibility point for [middleware](xref:fundamentals/middleware/index) activation.
<xref:Microsoft.AspNetCore.Builder.UseMiddlewareExtensions.UseMiddleware%2A> extension methods check if a middleware's registered type implements <xref:Microsoft.AspNetCore.Http.IMiddleware>. If it does, the <xref:Microsoft.AspNetCore.Http.IMiddlewareFactory> instance registered in the container is used to resolve the <xref:Microsoft.AspNetCore.Http.IMiddleware> implementation instead of using the convention-based middleware activation logic. The middleware is registered as a [scoped or transient service](xref:fundamentals/dependency-injection#service-lifetimes) in the app's service container.
Benefits:
* Activation per client request (injection of scoped services)
* Strong typing of middleware
<xref:Microsoft.AspNetCore.Http.IMiddleware> is activated per client request (connection), so scoped services can be injected into the middleware's constructor.
[View or download sample code](https://github.com/dotnet/AspNetCore.Docs/tree/main/aspnetcore/fundamentals/middleware/extensibility/samples) ([how to download](xref:index#how-to-download-a-sample))
## IMiddleware
<xref:Microsoft.AspNetCore.Http.IMiddleware> defines middleware for the app's request pipeline. The [InvokeAsync(HttpContext, RequestDelegate)](xref:Microsoft.AspNetCore.Http.IMiddleware.InvokeAsync%2A) method handles requests and returns a <xref:System.Threading.Tasks.Task> that represents the execution of the middleware.
Middleware activated by convention:
:::code language="csharp" source="extensibility/samples/3.x/MiddlewareExtensibilitySample/Middleware/ConventionalMiddleware.cs" id="snippet1":::
Middleware activated by <xref:Microsoft.AspNetCore.Http.MiddlewareFactory>:
:::code language="csharp" source="extensibility/samples/3.x/MiddlewareExtensibilitySample/Middleware/FactoryActivatedMiddleware.cs" id="snippet1":::
Extensions are created for the middleware:
:::code language="csharp" source="extensibility/samples/3.x/MiddlewareExtensibilitySample/Middleware/MiddlewareExtensions.cs" id="snippet1":::
It isn't possible to pass objects to the factory-activated middleware with <xref:Microsoft.AspNetCore.Builder.UseMiddlewareExtensions.UseMiddleware%2A>:
```csharp
public static IApplicationBuilder UseFactoryActivatedMiddleware(
this IApplicationBuilder builder, bool option)
{
// Passing 'option' as an argument throws a NotSupportedException at runtime.
return builder.UseMiddleware<FactoryActivatedMiddleware>(option);
}
```
The factory-activated middleware is added to the built-in container in `Startup.ConfigureServices`:
:::code language="csharp" source="extensibility/samples/3.x/MiddlewareExtensibilitySample/Startup.cs" id="snippet1" highlight="6":::
Both middleware are registered in the request processing pipeline in `Startup.Configure`:
:::code language="csharp" source="extensibility/samples/3.x/MiddlewareExtensibilitySample/Startup.cs" id="snippet2" highlight="12-13":::
## IMiddlewareFactory
<xref:Microsoft.AspNetCore.Http.IMiddlewareFactory> provides methods to create middleware. The middleware factory implementation is registered in the container as a scoped service.
The default <xref:Microsoft.AspNetCore.Http.IMiddlewareFactory> implementation, <xref:Microsoft.AspNetCore.Http.MiddlewareFactory>, is found in the [Microsoft.AspNetCore.Http](https://www.nuget.org/packages/Microsoft.AspNetCore.Http/) package.
## Additional resources
* <xref:fundamentals/middleware/index>
* <xref:fundamentals/middleware/extensibility-third-party-container>
:::moniker-end
:::moniker range="< aspnetcore-3.0"
<xref:Microsoft.AspNetCore.Http.IMiddlewareFactory>/<xref:Microsoft.AspNetCore.Http.IMiddleware> is an extensibility point for [middleware](xref:fundamentals/middleware/index) activation.
<xref:Microsoft.AspNetCore.Builder.UseMiddlewareExtensions.UseMiddleware*> extension methods check if a middleware's registered type implements <xref:Microsoft.AspNetCore.Http.IMiddleware>. If it does, the <xref:Microsoft.AspNetCore.Http.IMiddlewareFactory> instance registered in the container is used to resolve the <xref:Microsoft.AspNetCore.Http.IMiddleware> implementation instead of using the convention-based middleware activation logic. The middleware is registered as a [scoped or transient service](xref:fundamentals/dependency-injection#service-lifetimes) in the app's service container.
<xref:Microsoft.AspNetCore.Builder.UseMiddlewareExtensions.UseMiddleware%2A> extension methods check if a middleware's registered type implements <xref:Microsoft.AspNetCore.Http.IMiddleware>. If it does, the <xref:Microsoft.AspNetCore.Http.IMiddlewareFactory> instance registered in the container is used to resolve the <xref:Microsoft.AspNetCore.Http.IMiddleware> implementation instead of using the convention-based middleware activation logic. The middleware is registered as a [scoped or transient service](xref:fundamentals/dependency-injection#service-lifetimes) in the app's service container.
Benefits:
@ -86,21 +155,21 @@ Benefits:
## IMiddleware
<xref:Microsoft.AspNetCore.Http.IMiddleware> defines middleware for the app's request pipeline. The [InvokeAsync(HttpContext, RequestDelegate)](xref:Microsoft.AspNetCore.Http.IMiddleware.InvokeAsync*) method handles requests and returns a <xref:System.Threading.Tasks.Task> that represents the execution of the middleware.
<xref:Microsoft.AspNetCore.Http.IMiddleware> defines middleware for the app's request pipeline. The [InvokeAsync(HttpContext, RequestDelegate)](xref:Microsoft.AspNetCore.Http.IMiddleware.InvokeAsync%2A) method handles requests and returns a <xref:System.Threading.Tasks.Task> that represents the execution of the middleware.
Middleware activated by convention:
[!code-csharp[](extensibility/samples/2.x/MiddlewareExtensibilitySample/Middleware/ConventionalMiddleware.cs?name=snippet1)]
:::code language="csharp" source="extensibility/samples/2.x/MiddlewareExtensibilitySample/Middleware/ConventionalMiddleware.cs" id="snippet1":::
Middleware activated by <xref:Microsoft.AspNetCore.Http.MiddlewareFactory>:
[!code-csharp[](extensibility/samples/2.x/MiddlewareExtensibilitySample/Middleware/FactoryActivatedMiddleware.cs?name=snippet1)]
:::code language="csharp" source="extensibility/samples/2.x/MiddlewareExtensibilitySample/Middleware/FactoryActivatedMiddleware.cs" id="snippet1":::
Extensions are created for the middlewares:
Extensions are created for the middleware:
[!code-csharp[](extensibility/samples/2.x/MiddlewareExtensibilitySample/Middleware/MiddlewareExtensions.cs?name=snippet1)]
:::code language="csharp" source="extensibility/samples/2.x/MiddlewareExtensibilitySample/Middleware/MiddlewareExtensions.cs" id="snippet1":::
It isn't possible to pass objects to the factory-activated middleware with <xref:Microsoft.AspNetCore.Builder.UseMiddlewareExtensions.UseMiddleware*>:
It isn't possible to pass objects to the factory-activated middleware with <xref:Microsoft.AspNetCore.Builder.UseMiddlewareExtensions.UseMiddleware%2A>:
```csharp
public static IApplicationBuilder UseFactoryActivatedMiddleware(
@ -113,11 +182,11 @@ public static IApplicationBuilder UseFactoryActivatedMiddleware(
The factory-activated middleware is added to the built-in container in `Startup.ConfigureServices`:
[!code-csharp[](extensibility/samples/2.x/MiddlewareExtensibilitySample/Startup.cs?name=snippet1&highlight=6)]
:::code language="csharp" source="extensibility/samples/2.x/MiddlewareExtensibilitySample/Startup.cs" id="snippet1" highlight="6":::
Both middlewares are registered in the request processing pipeline in `Startup.Configure`:
Both middleware are registered in the request processing pipeline in `Startup.Configure`:
[!code-csharp[](extensibility/samples/2.x/MiddlewareExtensibilitySample/Startup.cs?name=snippet2&highlight=13-14)]
:::code language="csharp" source="extensibility/samples/2.x/MiddlewareExtensibilitySample/Startup.cs" id="snippet2" highlight="13-14":::
## IMiddlewareFactory
@ -125,9 +194,9 @@ Both middlewares are registered in the request processing pipeline in `Startup.C
The default <xref:Microsoft.AspNetCore.Http.IMiddlewareFactory> implementation, <xref:Microsoft.AspNetCore.Http.MiddlewareFactory>, is found in the [Microsoft.AspNetCore.Http](https://www.nuget.org/packages/Microsoft.AspNetCore.Http/) package.
:::moniker-end
## Additional resources
* <xref:fundamentals/middleware/index>
* <xref:fundamentals/middleware/extensibility-third-party-container>
:::moniker-end

View File

@ -6,7 +6,7 @@ using MiddlewareExtensibilitySample.Models;
namespace MiddlewareExtensibilitySample.Middleware
{
#region snippet1
// <snippet1>
public class ConventionalMiddleware
{
private readonly RequestDelegate _next;
@ -35,5 +35,5 @@ namespace MiddlewareExtensibilitySample.Middleware
await _next(context);
}
}
#endregion
// </snippet1>
}

View File

@ -6,7 +6,7 @@ using MiddlewareExtensibilitySample.Models;
namespace MiddlewareExtensibilitySample.Middleware
{
#region snippet1
// <snippet1>
public class FactoryActivatedMiddleware : IMiddleware
{
private readonly AppDbContext _db;
@ -35,5 +35,5 @@ namespace MiddlewareExtensibilitySample.Middleware
await next(context);
}
}
#endregion
// </snippet1>
}

View File

@ -2,7 +2,7 @@ using Microsoft.AspNetCore.Builder;
namespace MiddlewareExtensibilitySample.Middleware
{
#region snippet1
// <snippet1>
public static class MiddlewareExtensions
{
public static IApplicationBuilder UseConventionalMiddleware(
@ -17,5 +17,5 @@ namespace MiddlewareExtensibilitySample.Middleware
return builder.UseMiddleware<FactoryActivatedMiddleware>();
}
}
#endregion
// </snippet1>
}

View File

@ -11,7 +11,7 @@ namespace MiddlewareExtensibilitySample
{
public class Startup
{
#region snippet1
// <snippet1>
public void ConfigureServices(IServiceCollection services)
{
services.AddDbContext<AppDbContext>(options =>
@ -22,9 +22,9 @@ namespace MiddlewareExtensibilitySample
services.AddMvc()
.SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
}
#endregion
// </snippet1>
#region snippet2
// <snippet2>
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
@ -43,6 +43,6 @@ namespace MiddlewareExtensibilitySample
app.UseStaticFiles();
app.UseMvc();
}
#endregion
// </snippet2>
}
}

View File

@ -6,7 +6,7 @@ using MiddlewareExtensibilitySample.Models;
namespace MiddlewareExtensibilitySample.Middleware
{
#region snippet1
// <snippet1>
public class ConventionalMiddleware
{
private readonly RequestDelegate _next;
@ -35,5 +35,5 @@ namespace MiddlewareExtensibilitySample.Middleware
await _next(context);
}
}
#endregion
// </snippet1>
}

View File

@ -6,7 +6,7 @@ using MiddlewareExtensibilitySample.Models;
namespace MiddlewareExtensibilitySample.Middleware
{
#region snippet1
// <snippet1>
public class FactoryActivatedMiddleware : IMiddleware
{
private readonly AppDbContext _db;
@ -35,5 +35,5 @@ namespace MiddlewareExtensibilitySample.Middleware
await next(context);
}
}
#endregion
// </snippet1>
}

View File

@ -2,7 +2,7 @@ using Microsoft.AspNetCore.Builder;
namespace MiddlewareExtensibilitySample.Middleware
{
#region snippet1
// <snippet1>
public static class MiddlewareExtensions
{
public static IApplicationBuilder UseConventionalMiddleware(
@ -17,5 +17,5 @@ namespace MiddlewareExtensibilitySample.Middleware
return builder.UseMiddleware<FactoryActivatedMiddleware>();
}
}
#endregion
// </snippet1>
}

View File

@ -10,7 +10,7 @@ namespace MiddlewareExtensibilitySample
{
public class Startup
{
#region snippet1
// <snippet1>
public void ConfigureServices(IServiceCollection services)
{
services.AddDbContext<AppDbContext>(options =>
@ -20,9 +20,9 @@ namespace MiddlewareExtensibilitySample
services.AddRazorPages();
}
#endregion
// </snippet1>
#region snippet2
// <snippet2>
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
@ -45,6 +45,6 @@ namespace MiddlewareExtensibilitySample
endpoints.MapRazorPages();
});
}
#endregion
// </snippet2>
}
}