Psaní vlastního middlewaru ASP.NET Core

Poznámka:

Toto není nejnovější verze tohoto článku. Aktuální verzi najdete ve verzi .NET 8 tohoto článku.

Upozorňující

Tato verze ASP.NET Core se už nepodporuje. Další informace najdete v tématu .NET a .NET Core Zásady podpory. Aktuální verzi najdete ve verzi .NET 8 tohoto článku.

Důležité

Tyto informace se týkají předběžného vydání produktu, který může být podstatně změněn před komerčním vydáním. Microsoft neposkytuje žádné záruky, výslovné ani předpokládané, týkající se zde uváděných informací.

Aktuální verzi najdete ve verzi .NET 8 tohoto článku.

Fiyaz Hasan, Rick Anderson a Steve Smith

Middleware je software sestavený do kanálu aplikace pro zpracování požadavků a odpovědí. ASP.NET Core poskytuje bohatou sadu integrovaných komponent middlewaru, ale v některých scénářích můžete chtít napsat vlastní middleware.

Toto téma popisuje, jak psát middleware založený na konvencích. Přístup, který používá silné psaní a aktivaci na vyžádání, najdete v tématu Aktivace middlewaru založeného na továrně v ASP.NET Core.

Middleware – třída

Middleware je obecně zapouzdřen ve třídě a vystaven pomocí rozšiřující metody. Zvažte následující vložený middleware, který nastaví jazykovou verzi aktuálního požadavku z řetězce dotazu:

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

Předchozí zvýrazněný vložený middleware se používá k předvedení vytvoření middlewarové komponenty voláním Microsoft.AspNetCore.Builder.UseExtensions.Use. Předchozí Use metoda rozšíření přidá do kanálu požadavku aplikace delegovaný middleware definovaný v řádku.

Pro rozšíření jsou k dispozici Use dvě přetížení:

  • Jeden vezme HttpContext a Func<Task>. Func<Task> Vyvolání bez jakýchkoli parametrů
  • Druhý si vezme HttpContext a RequestDelegate. RequestDelegate Vyvoláním voláním metody HttpContext.

Preferujte použití pozdějšího přetížení, protože ukládá dvě interní přidělení požadavků, které jsou vyžadovány při použití jiného přetížení.

Otestujte middleware předáním jazykové verze. Například požadavek https://localhost:5001/?culture=es-es.

Informace o integrované podpoře lokalizací ASP.NET Core najdete v tématu Globalizace a lokalizace v ASP.NET Core.

Následující kód přesune delegáta middlewaru do třídy:

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

Middleware třída musí obsahovat:

  • Veřejný konstruktor s parametrem typu RequestDelegate.
  • Veřejná metoda s názvem Invoke nebo InvokeAsync. Tato metoda musí:
    • Vrácení znaku Task.
    • Přijmout první parametr typu HttpContext.

Další parametry konstruktoru a Invoke/InvokeAsync jsou naplněny injektáží závislostí (DI).

Obvykle se vytvoří rozšiřující metoda pro zveřejnění middlewaru prostřednictvím 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>();
    }
}

Následující kód volá middleware z 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();

Závislosti middlewaru

Middleware by měl postupovat podle explicitního principu závislostí tím, že v jeho konstruktoru zpřístupňuje jeho závislosti. Middleware se konstruuje jednou za dobu životnosti aplikace.

Komponenty middlewaru mohou vyřešit své závislosti z injektáže závislostí (DI) prostřednictvím parametrů konstruktoru. UseMiddleware může také přijímat další parametry přímo.

Závislosti middlewaru pro jednotlivé požadavky

Middleware se konstruuje při spuštění aplikace, a proto má životnost aplikace. Služby s vymezenou životností používané konstruktory middlewaru se během každého požadavku nesdílí s jinými typy vloženými do závislostí. Pokud chcete sdílet vymezenou službu mezi middlewarem a jinými typy, přidejte tyto služby do InvokeAsync podpisu metody. Metoda InvokeAsync může přijmout další parametry, které jsou naplněny 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>();
    }
}

Možnosti životnosti a registrace obsahují kompletní ukázku middlewaru s vymezenými službami životnosti.

Následující kód slouží k otestování předchozího middlewaru:

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

Rozhraní IMessageWriter a implementace:

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

Další materiály

Autor: Rick Anderson a Steve Smith

Middleware je software sestavený do kanálu aplikace pro zpracování požadavků a odpovědí. ASP.NET Core poskytuje bohatou sadu integrovaných komponent middlewaru, ale v některých scénářích můžete chtít napsat vlastní middleware.

Poznámka:

Toto téma popisuje, jak psát middleware založený na konvencích. Přístup, který používá silné psaní a aktivaci na vyžádání, najdete v tématu Aktivace middlewaru založeného na továrně v ASP.NET Core.

Middleware – třída

Middleware je obecně zapouzdřen ve třídě a vystaven pomocí rozšiřující metody. Představte si následující middleware, který nastaví jazykovou verzi aktuálního požadavku z řetězce dotazu:

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

    }
}

Předchozí vzorový kód slouží k předvedení vytvoření komponenty middlewaru. Informace o integrované podpoře lokalizací ASP.NET Core najdete v tématu Globalizace a lokalizace v ASP.NET Core.

Otestujte middleware předáním jazykové verze. Například požadavek https://localhost:5001/?culture=no.

Následující kód přesune delegáta middlewaru do třídy:

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

Middleware třída musí obsahovat:

  • Veřejný konstruktor s parametrem typu RequestDelegate.
  • Veřejná metoda s názvem Invoke nebo InvokeAsync. Tato metoda musí:
    • Vrácení znaku Task.
    • Přijmout první parametr typu HttpContext.

Další parametry konstruktoru a Invoke/InvokeAsync jsou naplněny injektáží závislostí (DI).

Závislosti middlewaru

Middleware by měl postupovat podle explicitního principu závislostí tím, že v jeho konstruktoru zpřístupňuje jeho závislosti. Middleware se konstruuje jednou za dobu životnosti aplikace. Pokud potřebujete sdílet služby s middlewarem v rámci požadavku, přečtěte si část Závislostí middlewaru podle požadavku.

Komponenty middlewaru mohou vyřešit své závislosti z injektáže závislostí (DI) prostřednictvím parametrů konstruktoru. UseMiddleware může také přijímat další parametry přímo.

Závislosti middlewaru pro jednotlivé požadavky

Vzhledem k tomu, že middleware se vytváří při spuštění aplikace, nikoli při každém požadavku, nejsou během každého požadavku sdíleny s jinými typy vloženými do závislostí. Pokud musíte sdílet vymezenou službu mezi middlewarem a dalšími typy, přidejte tyto služby do InvokeAsync podpisu metody. Metoda InvokeAsync může přijmout další parametry, které jsou naplněny 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);
    }
}

Možnosti životnosti a registrace obsahují kompletní ukázku middlewaru s vymezenými službami životnosti.

Metoda rozšíření middlewaru

Následující metoda rozšíření zpřístupňuje middleware prostřednictvím IApplicationBuilder:

using Microsoft.AspNetCore.Builder;

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

Následující kód volá middleware z Startup.Configure:

public class Startup
{
    public void Configure(IApplicationBuilder app)
    {
        app.UseRequestCulture();

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

Další materiály