中間件是一種裝配到應用管道以處理請求和響應的軟件。 ASP.NET Core 提供了一組豐富的內置中間件組件,但在某些情況下,你可能需要寫入自定義中間件。
備注
本主題介紹如何編寫基于約定的中間件。 有關使用強類型和按請求激活的方法,請參閱 ASP.NET Core 中基于工廠的中間件激活。
中間件類
通常,中間件封裝在類中,并且通過擴展的方法公開。 請考慮以下中間件,該中間件通過查詢字符串設置當前請求的區域性:
public class Startup
{
public void Configure(IApplicationBuilder app)
{
app.Use(async (context, next) =>
{
var cultureQuery = context.Request.Query["culture"];
if (!string.IsNullOrWhiteSpace(cultureQuery))
{
var culture = new CultureInfo(cultureQuery);
CultureInfo.CurrentCulture = culture;
CultureInfo.CurrentUICulture = culture;
}
// Call the next delegate/middleware in the pipeline
await next();
});
app.Run(async (context) =>
{
await context.Response.WriteAsync(
$"Hello {CultureInfo.CurrentCulture.DisplayName}");
});
}
}
以上示例代碼用于演示創建中間件組件。 有關 ASP.NET Core 內置本地化支持,請參閱 ASP.NET Core 全球化和本地化。
通過傳入區域性測試中間件。 例如,請求 https://localhost:5001/?culture=no。
以下代碼將中間件委托移動到類似:
using Microsoft.AspNetCore.Http;
using System.Globalization;
using System.Threading.Tasks;
namespace Culture
{
public class RequestCultureMiddleware
{
private readonly RequestDelegate _next;
public RequestCultureMiddleware(RequestDelegate next)
{
_next = next;
}
public async Task InvokeAsync(HttpContext context)
{
var cultureQuery = context.Request.Query["culture"];
if (!string.IsNullOrWhiteSpace(cultureQuery))
{
var culture = new CultureInfo(cultureQuery);
CultureInfo.CurrentCulture = culture;
CultureInfo.CurrentUICulture = culture;
}
// Call the next delegate/middleware in the pipeline
await _next(context);
}
}
}
必須包括中間件類:
- 具有類型為 RequestDelegate 的參數的公共構造函數。
- 名為 Invoke 或 InvokeAsync 的公共方法。 此方法必須:返回 Task。接受類型 HttpContext 的第一個參數。
構造函數和 Invoke/InvokeAsync 其他參數由依賴關系注入 (DI) 填充。
中間件依賴項
中間件應通過在其構造函數中公開其依賴項來遵循顯式依賴項的原則。 在每個應用程序生存期構造一次中間件。 如果需要與請求中的中間件共享服務,請參閱按請求中間件依賴項部分。
中間件組件可通過構造函數參數從依賴關系注入 (DI) 解析其依賴項。 UseMiddleware<T> 也可直接接受其他參數。
按請求中間件依賴項
由于中間件是在應用啟動時構造的,而不是按請求構造的,因此在每個請求過程中,中間件構造函數使用的范圍內生存期服務不與其他依賴關系注入類型共享。 如果必須在中間件和其他類型之間共享范圍內服務,請將這些服務添加到 Invoke 方法的簽名。 Invoke 方法可接受由 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);
}
}
生存期和注冊選項包含范圍內生存期服務的中間件的完整示例。
中間件擴展方法
以下擴展方法通過 IApplicationBuilder 公開中間件:
using Microsoft.AspNetCore.Builder;
namespace Culture
{
public static class RequestCultureMiddlewareExtensions
{
public static IApplicationBuilder UseRequestCulture(
this IApplicationBuilder builder)
{
return builder.UseMiddleware<RequestCultureMiddleware>();
}
}
}
以下代碼通過 Startup.Configure 調用中間件:
public class Startup
{
public void Configure(IApplicationBuilder app)
{
app.UseRequestCulture();
app.Run(async (context) =>
{
await context.Response.WriteAsync(
$"Hello {CultureInfo.CurrentCulture.DisplayName}");
});
}
}