撰寫自訂的 ASP.NET Core 中介軟體

作者 :Fiyaz HasanRick AndersonSteve Smith

中介軟體為組成應用程式管線的軟體,用以處理要求與回應。 ASP.NET Core 提供一組豐富的內建中介軟體元件,但在某些情況下,您可能想要撰寫自訂的中介軟體。

本主題描述如何撰寫 慣例型 中介軟體。 如需使用強型別和每個要求啟用的方法,請參閱ASP.NET Core 中的 Factory 中介軟體啟用

中介軟體類別

中介軟體通常封裝在類別中,並以擴充方法公開。 請考慮下列內嵌中介軟體,這會從查詢字串設定目前要求的文化特性:

using System.Globalization;

var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();

app.UseHttpsRedirection();

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(context);
});

app.Run(async (context) =>
{
    await context.Response.WriteAsync(
        $"CurrentCulture.DisplayName: {CultureInfo.CurrentCulture.DisplayName}");
});

app.Run();

上述醒目提示的內嵌中介軟體是用來示範藉由呼叫 Microsoft.AspNetCore.Builder.UseExtensions.Use 來建立中介軟體元件。 上述 Use 擴充方法會將內嵌定義的中介軟體 委派 新增至應用程式的要求管線。

擴充功能有兩個可用的 Use 多載:

  • 一個接受 HttpContextFunc<Task> 。 不使用任何參數叫用 Func<Task>
  • 另一個 RequestDelegate 則採用 HttpContext 和 。 RequestDelegate傳遞 來叫用 HttpContext

偏好使用稍後的多載,因為它會儲存使用其他多載時所需的兩個內部個別要求配置。

藉由傳入文化特性來測試中介軟體。 例如,要求 https://localhost:5001/?culture=es-es

如需 ASP.NET Core的內建當地語系化支援,請參閱ASP.NET Core中的全球化和當地語系化

下列程式碼會將中介軟體委派移至類別:

using System.Globalization;

namespace Middleware.Example;

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 類型參數的公用建構函式。
  • 名為 InvokeInvokeAsync 的公用方法。 此方法必須:
    • 傳回 Task
    • 接受 HttpContext 類型的第一個參數。

建構函式和 Invoke/InvokeAsync 的其他參數會由相依性插入 (DI) 所填入。

一般而言,會建立擴充方法,以透過 IApplicationBuilder 公開中介軟體:

using System.Globalization;

namespace Middleware.Example;

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);
    }
}

public static class RequestCultureMiddlewareExtensions
{
    public static IApplicationBuilder UseRequestCulture(
        this IApplicationBuilder builder)
    {
        return builder.UseMiddleware<RequestCultureMiddleware>();
    }
}

下列程式碼會從 Program.cs 呼叫中介軟體:

using Middleware.Example;
using System.Globalization;

var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();

app.UseHttpsRedirection();

app.UseRequestCulture();

app.Run(async (context) =>
{
    await context.Response.WriteAsync(
        $"CurrentCulture.DisplayName: {CultureInfo.CurrentCulture.DisplayName}");
});

app.Run();

中介軟體相依性

中介軟體應於其建構函式中公開其相依性,以遵循明確的相依性原則。 中介軟體會在每次「應用程式存留期」就建構一次。

中介軟體元件可透過建構函式參數,解析其來自相依性插入 (DI) 的相依性。 UseMiddleware 也可直接接受其它參數。

依要求的中介軟體相依性

中介軟體會在應用程式啟動時建構,因此具有應用程式生命週期。 中介軟體建構函式所使用的範圍存留期服務不會在每個要求期間與其他相依性插入類型共用。 若要在中介軟體與其他類型之間共用 範圍 服務,請將這些服務新增至 InvokeAsync 方法的簽章。 InvokeAsync 方法可以接受 DI 所填入的其他參數:

namespace Middleware.Example;

public class MyCustomMiddleware
{
    private readonly RequestDelegate _next;

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

    // IMessageWriter is injected into InvokeAsync
    public async Task InvokeAsync(HttpContext httpContext, IMessageWriter svc)
    {
        svc.Write(DateTime.Now.Ticks.ToString());
        await _next(httpContext);
    }
}

public static class MyCustomMiddlewareExtensions
{
    public static IApplicationBuilder UseMyCustomMiddleware(
        this IApplicationBuilder builder)
    {
        return builder.UseMiddleware<MyCustomMiddleware>();
    }
}

存留期和註冊選項 包含具有 範圍 存留期服務之中介軟體的完整範例。

下列程式碼是用來測試上述中介軟體:

using Middleware.Example;
var builder = WebApplication.CreateBuilder(args);

builder.Services.AddScoped<IMessageWriter, LoggingMessageWriter>();

var app = builder.Build();

app.UseHttpsRedirection();

app.UseMyCustomMiddleware();

app.MapGet("/", () => "Hello World!");

app.Run();

介面和實作 IMessageWriter

namespace Middleware.Example;

public interface IMessageWriter
{
    void Write(string message);
}

public class LoggingMessageWriter : IMessageWriter
{

    private readonly ILogger<LoggingMessageWriter> _logger;

    public LoggingMessageWriter(ILogger<LoggingMessageWriter> logger) =>
        _logger = logger;

    public void Write(string message) =>
        _logger.LogInformation(message);
}

其他資源

Rick AndersonSteve Smith 撰寫

中介軟體為組成應用程式管線的軟體,用以處理要求與回應。 ASP.NET Core 提供一組豐富的內建中介軟體元件,但在某些情況下,您可能想要撰寫自訂的中介軟體。

注意

本主題描述如何撰寫 慣例型 中介軟體。 如需使用強型別和每個要求啟用的方法,請參閱ASP.NET Core 中的 Factory 中介軟體啟用

中介軟體類別

中介軟體通常封裝在類別中,並以擴充方法公開。 請考慮下列中介軟體,其會為來自查詢字串的目前要求設定文化特性:

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 類型參數的公用建構函式。
  • 名為 InvokeInvokeAsync 的公用方法。 此方法必須:
    • 傳回 Task
    • 接受 HttpContext 類型的第一個參數。

建構函式和 Invoke/InvokeAsync 的其他參數會由相依性插入 (DI) 所填入。

中介軟體相依性

中介軟體應於其建構函式中公開其相依性,以遵循明確的相依性原則。 中介軟體會在每次「應用程式存留期」就建構一次。 若您需要在要求內與中介軟體共用服務,請參閱依要求的中介軟體相依性一節。

中介軟體元件可透過建構函式參數,解析其來自相依性插入 (DI) 的相依性。 UseMiddleware 也可直接接受其它參數。

依要求的中介軟體相依性

因為中介軟體建構於應用程式啟動時,而非依要求建構,所以在每個要求期間,中介軟體建構函式使用的「已限定範圍」存留期服務不會與其它插入相依性的類型共用。 如果您必須在中介軟體和其他類型間共用「已限定範圍」的服務,請將這些服務新增至 InvokeAsync 方法的簽章。 InvokeAsync 方法可以接受 DI 所填入的其他參數:

public class CustomMiddleware
{
    private readonly RequestDelegate _next;

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

    // IMyScopedService is injected into InvokeAsync
    public async Task InvokeAsync(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}");
        });
    }
}

其他資源