Menulis middleware ASP.NET Core kustom
Catatan
Ini bukan versi terbaru dari artikel ini. Untuk rilis saat ini, lihat versi .NET 8 dari artikel ini.
Peringatan
Versi ASP.NET Core ini tidak lagi didukung. Untuk informasi selengkapnya, lihat Kebijakan Dukungan .NET dan .NET Core. Untuk rilis saat ini, lihat versi .NET 8 dari artikel ini.
Penting
Informasi ini berkaitan dengan produk pra-rilis yang mungkin dimodifikasi secara substansial sebelum dirilis secara komersial. Microsoft tidak memberikan jaminan, tersirat maupun tersurat, sehubungan dengan informasi yang diberikan di sini.
Untuk rilis saat ini, lihat versi .NET 8 dari artikel ini.
Oleh Fiyaz Hasan, Rick Anderson, dan Steve Smith
Middleware adalah perangkat lunak yang dirakit menjadi alur aplikasi untuk menangani permintaan dan respons. ASP.NET Core menyediakan serangkaian komponen middleware bawaan yang kaya, tetapi dalam beberapa skenario Anda mungkin ingin menulis middleware kustom.
Topik ini menjelaskan cara menulis middleware berbasis konvensi. Untuk pendekatan yang menggunakan pengetikan yang kuat dan aktivasi per permintaan, lihat Aktivasi middleware berbasis pabrik di ASP.NET Core.
Kelas middleware
Middleware umumnya dienkapsulasi di kelas dan diekspos dengan metode ekstensi. Pertimbangkan middleware sebaris berikut, yang mengatur budaya untuk permintaan saat ini dari string kueri:
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();
Middleware sebaris yang disorot sebelumnya digunakan untuk menunjukkan pembuatan komponen middleware dengan memanggil Microsoft.AspNetCore.Builder.UseExtensions.Use. Metode ekstensi sebelumnya Use
menambahkan delegasi middleware yang ditentukan sebaris ke alur permintaan aplikasi.
Ada dua kelebihan beban yang tersedia untuk Use
ekstensi:
- Satu mengambil HttpContext dan
Func<Task>
. PanggilFunc<Task>
tanpa parameter apa pun. - Yang lain mengambil
HttpContext
dan RequestDelegate.RequestDelegate
Panggil dengan melewatiHttpContext
.
Lebih suka menggunakan kelebihan beban yang lebih baru karena menyimpan dua alokasi internal per permintaan yang diperlukan saat menggunakan kelebihan beban lainnya.
Uji middleware dengan melewati budaya. Misalnya, minta https://localhost:5001/?culture=es-es
.
Untuk dukungan pelokalan bawaan ASP.NET Core, lihat Globalisasi dan pelokalan di ASP.NET Core.
Kode berikut memindahkan delegasi middleware ke kelas:
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);
}
}
Kelas middleware harus mencakup:
- Konstruktor publik dengan parameter jenis RequestDelegate.
- Metode publik bernama
Invoke
atauInvokeAsync
. Metode ini harus:Task
Mengembalikan .- Terima parameter pertama jenis HttpContext.
Parameter tambahan untuk konstruktor dan Invoke
/InvokeAsync
diisi oleh injeksi dependensi (DI).
Biasanya, metode ekstensi dibuat untuk mengekspos middleware melalui 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>();
}
}
Kode berikut memanggil middleware dari 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();
Dependensi middleware
Middleware harus mengikuti Prinsip Dependensi Eksplisit dengan mengekspos dependensinya dalam konstruktornya. Middleware dibangun sekali per masa pakai aplikasi.
Komponen middleware dapat menyelesaikan dependensinya dari injeksi dependensi (DI) melalui parameter konstruktor. UseMiddleware juga dapat menerima parameter tambahan secara langsung.
Dependensi middleware per permintaan
Middleware dibangun pada startup aplikasi dan karenanya memiliki masa pakai aplikasi. Layanan masa pakai terlingkup yang digunakan oleh konstruktor middleware tidak dibagikan dengan jenis lain yang disuntikkan dependensi selama setiap permintaan. Untuk berbagi layanan terlingkup antara middleware dan jenis lainnya, tambahkan layanan ini ke InvokeAsync
tanda tangan metode. Metode ini InvokeAsync
dapat menerima parameter tambahan yang diisi oleh 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>();
}
}
Opsi seumur hidup dan pendaftaran berisi sampel lengkap middleware dengan layanan seumur hidup terlingkup .
Kode berikut digunakan untuk menguji middleware sebelumnya:
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();
Antarmuka IMessageWriter
dan implementasi:
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);
}
Sumber Daya Tambahan:
- Kode sampel yang digunakan dalam artikel ini
- Sumber UseExtensions di GitHub
- Opsi seumur hidup dan pendaftaran berisi sampel lengkap dari middleware dengan layanan seumur hidup scoped, transient, dan singleton.
- MENDALAMI: BAGAIMANA ALUR MIDDLEWARE INTI ASP.NET DIBANGUN
- ASP.NET Core Middleware
- Menguji middleware ASP.NET Core
- Memigrasikan pengatur dan modul HTTP ke middleware ASP.NET Core
- Startup aplikasi di ASP.NET Core
- Fitur Permintaan di ASP.NET Core
- Aktivasi middleware berbasis pabrik di ASP.NET Core
- Aktivasi middleware dengan kontainer pihak ketiga di ASP.NET Core
Oleh Rick Anderson dan Steve Smith
Middleware adalah perangkat lunak yang dirakit menjadi alur aplikasi untuk menangani permintaan dan respons. ASP.NET Core menyediakan serangkaian komponen middleware bawaan yang kaya, tetapi dalam beberapa skenario Anda mungkin ingin menulis middleware kustom.
Catatan
Topik ini menjelaskan cara menulis middleware berbasis konvensi. Untuk pendekatan yang menggunakan pengetikan yang kuat dan aktivasi per permintaan, lihat Aktivasi middleware berbasis pabrik di ASP.NET Core.
Kelas middleware
Middleware umumnya dienkapsulasi di kelas dan diekspos dengan metode ekstensi. Pertimbangkan middleware berikut, yang mengatur budaya untuk permintaan saat ini dari string kueri:
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}");
});
}
}
Kode sampel sebelumnya digunakan untuk menunjukkan pembuatan komponen middleware. Untuk dukungan pelokalan bawaan ASP.NET Core, lihat Globalisasi dan pelokalan di ASP.NET Core.
Uji middleware dengan melewati budaya. Misalnya, minta https://localhost:5001/?culture=no
.
Kode berikut memindahkan delegasi middleware ke kelas:
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);
}
}
}
Kelas middleware harus mencakup:
- Konstruktor publik dengan parameter jenis RequestDelegate.
- Metode publik bernama
Invoke
atauInvokeAsync
. Metode ini harus:Task
Mengembalikan .- Terima parameter pertama jenis HttpContext.
Parameter tambahan untuk konstruktor dan Invoke
/InvokeAsync
diisi oleh injeksi dependensi (DI).
Dependensi middleware
Middleware harus mengikuti Prinsip Dependensi Eksplisit dengan mengekspos dependensinya dalam konstruktornya. Middleware dibangun sekali per masa pakai aplikasi. Lihat bagian Dependensi middleware per permintaan jika Anda perlu berbagi layanan dengan middleware dalam permintaan.
Komponen middleware dapat menyelesaikan dependensinya dari injeksi dependensi (DI) melalui parameter konstruktor. UseMiddleware juga dapat menerima parameter tambahan secara langsung.
Dependensi middleware per permintaan
Karena middleware dibangun pada startup aplikasi, bukan per permintaan, layanan masa pakai terlingkup yang digunakan oleh konstruktor middleware tidak dibagikan dengan jenis lain yang disuntikkan dependensi selama setiap permintaan. Jika Anda harus berbagi layanan terlingkup antara middleware Anda dan jenis lainnya, tambahkan layanan ini ke InvokeAsync
tanda tangan metode . Metode ini InvokeAsync
dapat menerima parameter tambahan yang diisi oleh 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);
}
}
Opsi seumur hidup dan pendaftaran berisi sampel lengkap middleware dengan layanan seumur hidup terlingkup .
Metode ekstensi middleware
Metode ekstensi berikut mengekspos middleware melalui IApplicationBuilder:
using Microsoft.AspNetCore.Builder;
namespace Culture
{
public static class RequestCultureMiddlewareExtensions
{
public static IApplicationBuilder UseRequestCulture(
this IApplicationBuilder builder)
{
return builder.UseMiddleware<RequestCultureMiddleware>();
}
}
}
Kode berikut memanggil middleware dari Startup.Configure
:
public class Startup
{
public void Configure(IApplicationBuilder app)
{
app.UseRequestCulture();
app.Run(async (context) =>
{
await context.Response.WriteAsync(
$"Hello {CultureInfo.CurrentCulture.DisplayName}");
});
}
}
Sumber Daya Tambahan:
- Opsi seumur hidup dan pendaftaran berisi sampel lengkap dari middleware dengan layanan seumur hidup scoped, transient, dan singleton.
- ASP.NET Core Middleware
- Menguji middleware ASP.NET Core
- Memigrasikan pengatur dan modul HTTP ke middleware ASP.NET Core
- Startup aplikasi di ASP.NET Core
- Fitur Permintaan di ASP.NET Core
- Aktivasi middleware berbasis pabrik di ASP.NET Core
- Aktivasi middleware dengan kontainer pihak ketiga di ASP.NET Core
ASP.NET Core