Registration flag for all middleware
- Dominant language
- C#
- Stars
- 38.4k
- Forks
- 10.9k
- Avg merge
- 2d 5h
- Merged PRs (30d)
- 276
Description
## Summary
Add a registration flag for all middleware to indicate whether it has already been added to the pipeline, similar to `UseAuthentication` and `UseAuthorization`. Currently, `UseSession` and some other middleware do not expose such a flag, making it hard to prevent duplicate registrations.
## Motivation and goals
- Prevent accidental multiple registrations of the same middleware, which can lead to subtle bugs, duplicated processing, or session inconsistencies.
- Provide developers a consistent way to check if a middleware has already been added, improving safety and maintainability.
- `UseAuthentication` and `UseAuthorization` already implement this pattern with internal flags, but `UseSession` does not. Adding this would unify middleware behavior across the framework.
**Goals:**
- Introduce a standard mechanism for middleware to track registration.
- Ensure existing middleware like `UseSession`, `UseCors`, `UseResponseCaching` can optionally adopt this.
- Maintain backward compatibility with existing applications.
## In scope
- Adding an internal registration flag to `SessionMiddleware` and other extension methods. (`UseCors`, `UseResponseCaching`...)
## Out of scope
- Changing the public API signature of middleware extension methods.
## Risks / unknowns
- Developers may expect `UseSession()` to be idempotent already; adding the flag could change subtle behaviors if a middleware was previously registered twice intentionally.
- Backward compatibility must be preserved: applications that currently register `UseSession` multiple times should not break.
- Security/performance: minimal, but double registration previously could have caused slight overhead or unintended side effects.
## Examples
```csharp
using Microsoft.AspNetCore.Session;
using Microsoft.Extensions.Options;
namespace Microsoft.AspNetCore.Builder;
public static class SessionMiddlewareExtensions
{
internal const string SessionMiddlewareSetKey = "__SessionMiddlewareSet";
public static IApplicationBuilder UseSession(this IApplicationBuilder app)
{
ArgumentNullException.ThrowIfNull(app);
app.Properties[SessionMiddlewareSetKey] = true;
return app.UseMiddleware();
}
public static IApplicationBuilder UseSession(this IApplicationBuilder app, SessionOptions options)
{
ArgumentNullException.ThrowIfNull(app);
ArgumentNullException.ThrowIfNull(options);
app.Properties[SessionMiddlewareSetKey] = true;
return app.UseMiddleware(Options.Create(options));
}
}
```
```csharp
// Program.cs
app.UseSession();
// Inside a NuGet package or shared library
if (!app.Properties.ContainsKey("__SessionMiddlewareSet"))
{
app.UseSession();
}
// Developers can rely on similar pattern to UseAuthorization/UseAuthentication
```
Contributor guide
Assessment
This issue has not been assessed yet.