ASP.NET Core Jiné
Od Rick Anderson a Steve Smith
Middleware je software, který se sestaví do kanálu aplikace za účelem zpracování požadavků a odpovědí. Jednotlivé komponenty:
- Zvolí, jestli se má žádost předat další komponentě v kanálu.
- Může provádět práci před a za další komponentou v kanálu.
Delegáti žádostí se používají k sestavení kanálu požadavků. Delegát žádosti zpracuje jednotlivé požadavky HTTP.
Delegáti žádostí jsou nakonfigurováni pomocí Run Map Use metod rozšíření, a. Jednotlivé delegáty žádostí je možné zadat jako anonymní metodu (označovanou v rámci middlewarového middlewaru) nebo ji lze definovat v opakovaně použitelné třídě. Tyto opakovaně použitelné třídy a vložené anonymní metody jsou middleware, označované také jako komponenty middlewaru. Každá součást middlewaru v kanálu požadavků zodpovídá za vyvolání další komponenty v kanálu nebo při krátkém okruhu kanálu. Když jsou krátkodobé okruhy middleware, nazývá se middleware terminálu , protože zabrání dalšímu middlewaru ve zpracování žádosti.
migrace obslužných rutin a modulů HTTP do ASP.NET Core middlewaruvysvětluje rozdíl mezi kanály požadavků v ASP.NET Core a ASP.NET 4. x a poskytuje další ukázky middlewaru.
Vytvoření kanálu middlewaru pomocí WebApplication
kanál žádostí o ASP.NET Core se skládá z posloupnosti delegátů požadavků, který se nazývá jedna po druhé. Následující diagram znázorňuje koncept. Vlákno provádění následuje za černými šipkami.

Každý delegát může provádět operace před a po dalším delegátu. Delegáty zpracování výjimek by se měly volat v rámci kanálu na začátku, takže můžou zachytit výjimky, ke kterým dochází v pozdějších fázích kanálu.
nejjednodušší možná ASP.NET Core aplikace nastaví jediného delegáta žádosti, který zpracovává všechny požadavky. Tento případ nezahrnuje skutečný kanál žádostí. Místo toho je volána jedna anonymní funkce v reakci na každý požadavek HTTP.
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.Run(async context =>
{
await context.Response.WriteAsync("Hello world!");
});
app.Run();
Řetězení více požadavků delegátů společně s Use . nextParametr představuje dalšího delegáta v kanálu. Kanál můžete pro krátké okruhy vymezit tím , že nevoláte next parametr. Obvykle můžete provádět akce před i po next delegátu, jak ukazuje následující příklad:
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.Use(async (context, next) =>
{
// Do work that doesn't write to the Response.
await next.Invoke();
// Do logging or other work that doesn't write to the Response.
});
app.Run(async context =>
{
await context.Response.WriteAsync("Hello from 2nd delegate.");
});
app.Run();
Když delegát neprojde požadavek na dalšího delegáta, nazývá se to krátkodobý kanál žádosti. Krátkodobé okruhy jsou často žádoucí, protože brání zbytečné práci. Například middleware statických souborů může fungovat jako middleware terminálu tím, že zpracovává požadavek na statický soubor a krátký okruh zbývajících částí kanálu. Middleware přidané do kanálu předtím, než middleware, který ukončí další zpracování, stále zpracovává kód po svých next.Invoke příkazech. Přečtěte si ale následující upozornění týkající se pokusu o zápis do odpovědi, která již byla odeslána.
Upozornění
Nevolejte next.Invoke po odeslání odpovědi klientovi. Změny HttpResponse poté, co odpověď začala, vyvolávají výjimku. Například nastavení záhlaví a stavový kód vyvolávají výjimku. Zápis do těla odpovědi po volání next :
- Může způsobit narušení protokolu. Například zápis více než uvedené
Content-Length. - Může poškodit formát textu. Například zápis zápatí HTML do souboru CSS.
HasStarted je užitečnou nápovědou, která označuje, zda byla odeslána hlavička nebo zda byl text napsán do.
Run Delegáti neobdrží next parametr. První Run delegát je vždycky terminál a ukončí kanál. Run je konvence. Některé komponenty middlewaru můžou vystavovat Run[Middleware] metody, které se spouštějí na konci kanálu:
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.Use(async (context, next) =>
{
// Do work that doesn't write to the Response.
await next.Invoke();
// Do logging or other work that doesn't write to the Response.
});
app.Run(async context =>
{
await context.Response.WriteAsync("Hello from 2nd delegate.");
});
app.Run();
Pokud chcete zobrazit komentáře ke kódu přeložené do jiných jazyků než angličtiny, dejte nám vědět v tomto problému diskuze na GitHubu.
V předchozím příkladu Run delegát zapisuje "Hello from 2nd delegate." do odpovědi a pak kanál ukončí. Pokud Use Run je po delegátu přidán jiný nebo delegát Run , není volán.
Preferovat aplikaci Použijte přetížení, které vyžaduje předání kontextu dalšímu.
Aplikace, která přiděluje . Použít metodu rozšíření:
- Vyžaduje předání kontextu do
next. - Ukládá dvě interní přidělení podle požadavků, které jsou požadovány při použití jiné přetížení.
další informace najdete v tomto GitHub problému.
Pořadí middlewaru
následující diagram znázorňuje kompletní kanál zpracování požadavků pro ASP.NET Core aplikace MVC a Razor stránky. Můžete vidět, jak, v typické aplikaci jsou seřazené existující middleware a kdy se přidávají vlastní middleware. Máte plnou kontrolu nad tím, jak změnit pořadí stávajících middlewarů, nebo vložit nové vlastní middleware podle potřeby pro vaše scénáře.
Middleware koncového bodu v předchozím diagramu spouští kanál filtru pro odpovídající typ aplikace — MVC nebo Razor stránky.
Middleware Směrování v předchozím diagramu se zobrazí v následujících statických souborech. Toto je pořadí, ve kterém šablony projektu implementují explicitně voláním aplikace. UseRouting. Pokud nevoláte app.UseRouting , middleware Směrování ve výchozím nastavení spustí na začátku kanálu. Další informace najdete v tématu Směrování.
Pořadí, v jakém jsou přidány komponenty middlewaru do souboru program. cs definuje pořadí, ve kterém jsou komponenty middleware vyvolány na žádostech, a obrácené pořadí pro odpověď. Pořadí je důležité pro zabezpečení, výkon a funkčnost.
Následující zvýrazněný kód v programu program. cs přidá součásti middlewaru související se zabezpečením v typickém doporučeném pořadí:
using IndividualAccountsExample.Data;
using Microsoft.AspNetCore.Identity;
using Microsoft.EntityFrameworkCore;
var builder = WebApplication.CreateBuilder(args);
// Add services to the container.
var connectionString = builder.Configuration.GetConnectionString("DefaultConnection");
builder.Services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlServer(connectionString));
builder.Services.AddDatabaseDeveloperPageExceptionFilter();
builder.Services.AddDefaultIdentity<IdentityUser>(options => options.SignIn.RequireConfirmedAccount = true)
.AddEntityFrameworkStores<ApplicationDbContext>();
builder.Services.AddRazorPages();
var app = builder.Build();
// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
app.UseMigrationsEndPoint();
}
else
{
app.UseExceptionHandler("/Error");
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
// app.UseCookiePolicy();
app.UseRouting();
// app.UseRequestLocalization();
// app.UseCors();
app.UseAuthentication();
app.UseAuthorization();
// app.UseSession();
// app.UseResponseCompression();
// app.UseResponseCaching();
app.MapRazorPages();
app.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
app.Run();
V předchozím kódu:
- Middleware, které se nepřidaly při vytváření nové webové aplikace s jednotlivými účty uživatele , jsou zakomentovány.
- Ne každý middleware se zobrazí v tomto přesném pořadí, ale mnoho do něj. Například:
UseCors,UseAuthentication, a seUseAuthorizationmusí objevit v uvedeném pořadí.UseCorsv současné době musí být uvedena předUseResponseCaching. tento požadavek je vysvětlen v GitHub problém dotnet/aspnetcore #23218.UseRequestLocalizationmusí se nacházet před jakýmkoli middlewarem, který by mohl kontrolovat jazykovou verzi žádosti (napříkladapp.UseMvcWithDefaultRoute()).
V některých scénářích má middleware jiné řazení. Například ukládání do mezipaměti a v pořadí komprese je specifické pro konkrétní scénář a existuje více platných pořadí. Například:
app.UseResponseCaching();
app.UseResponseCompression();
V předchozím kódu je možné snížit využití procesoru ukládáním komprimované odpovědi do mezipaměti, ale můžete také ukončit ukládání více reprezentace prostředku do mezipaměti pomocí různých algoritmů komprese, jako je gzip nebo Brotli.
Následující řazení kombinuje statické soubory a povoluje ukládání komprimovaných statických souborů do mezipaměti:
app.UseResponseCaching();
app.UseResponseCompression();
app.UseStaticFiles();
Následující program. cs kód přidává komponenty middlewaru pro běžné scénáře aplikací:
- Zpracování výjimek a chyb
- Když aplikace běží ve vývojovém prostředí:
- Aplikace middleware stránky s výjimkou vývojářů ( UseDeveloperExceptionPage ) hlásí chyby běhového modulu.
- Zpráva middleware pro chybovou stránku databáze ( UseDatabaseErrorPage ) oznamuje chyby běhového modulu databáze.
- Když aplikace běží v produkčním prostředí:
- Middleware obslužné rutiny výjimek ( UseExceptionHandler ) zachytává výjimky vyvolané v následujících middlewarech.
- Middleware HSTS (HTTP Strict Transport Security Protocol) ( UseHsts ) přidá
Strict-Transport-Securityhlavičku.
- Když aplikace běží ve vývojovém prostředí:
- Middleware () přesměrování protokolu HTTPS ( UseHttpsRedirection ) přesměruje požadavky HTTP na https.
- Soubor middleware () statických souborů ( UseStaticFiles ) vrací statické soubory a další zpracování žádostí o krátkodobé okruhy.
- Cookie Middleware zásad ( UseCookiePolicy ) aplikace v souladu s pravidly pro EU obecné nařízení o ochraně osobních údajů (GDPR).
- Směrování middleware ( UseRouting ) pro směrování požadavků.
- Middleware ověřování ( UseAuthentication ) se pokusí ověřit uživatele předtím, než budou mít přístup k zabezpečeným prostředkům.
- Middleware autorizace ( UseAuthorization ) opravňuje uživatele k přístupu k zabezpečeným prostředkům.
- Middleware relace ( UseSession ) vytváří a udržuje stav relace. Pokud aplikace používá stav relace, volejte middleware relace po Cookie middlewaru zásad a před middlewarem MVC.
- Middleware směrování koncového bodu ( UseEndpoints s MapRazorPages ) pro přidání Razor koncových bodů stránek do kanálu požadavků.
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
app.UseDatabaseErrorPage();
}
else
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseCookiePolicy();
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.UseSession();
app.MapRazorPages();
V předchozím příkladu kódu je každá metoda rozšíření middleware vystavena WebApplicationBuilder prostřednictvím Microsoft.AspNetCore.Builder oboru názvů.
UseExceptionHandler je první součást middleware přidaná do kanálu. Proto middleware obslužné rutiny výjimek zachycuje všechny výjimky, ke kterým dojde v pozdějších voláních.
Middleware statických souborů se zavolá v průběhu kanálu, aby mohl zpracovávat požadavky a krátké okruhy bez toho, aby procházely zbývajícími součástmi. Middleware statických souborů neposkytuje žádné autorizační kontroly. Všechny soubory, které poskytuje middleware pro statický soubor, včetně těch v rámci wwwroot, jsou veřejně dostupné. Přístup k zabezpečení statických souborů naleznete v tématu Statické soubory v ASP.NET Core .
Pokud požadavek nezpracovává middleware pro statický soubor, je předán do middleware ověřování ( UseAuthentication ), který provádí ověřování. Ověřování neověřuje neověřené požadavky v krátkém okruhu. I když middleware ověřování ověřuje požadavky, autorizaci (a odmítnutí) proběhne pouze poté, co MVC vybere konkrétní Razor stránku nebo kontroler MVC a akci.
Následující příklad ukazuje pořadí middlewaru, kde požadavky na statické soubory jsou zpracovávány pomocí middlewaru statického souboru před použitím middlewaru pro komprimaci odezvy. Statické soubory nejsou s tímto pořadím middlewaru komprimovány. RazorOdpovědi na stránky lze komprimovat.
// Static files aren't compressed by Static File Middleware.
app.UseStaticFiles();
app.UseRouting();
app.UseResponseCompression();
app.MapRazorPages();
informace o aplikacích s jednou stránkou naleznete v příručkách k šablonám projektů React a Angular .
Pořadí middlewaru u předávaných hlaviček
Middleware předaných hlaviček by se měla spustit před jiným middlewarem. Toto řazení zajišťuje, aby middleware spoléhající se na předané informace hlaviček mohl spotřebovat hodnoty hlaviček pro zpracování. Pro spuštění předávaných middlewarových hlaviček po diagnostice a middlewaru zpracování chyb si přečtěte téma pořadí middlewaru u předaných hlaviček.
Větvení kanálu middlewaru
Map rozšíření se používají jako konvence pro větvení kanálu. Map rozvětvení kanálu požadavků na základě shody dané cesty požadavku. Pokud cesta k požadavku začíná danou cestou, je větev spuštěná.
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.Map("/map1", HandleMapTest1);
app.Map("/map2", HandleMapTest2);
app.Run(async context =>
{
await context.Response.WriteAsync("Hello from non-Map delegate. <p>");
});
app.Run();
static void HandleMapTest1(IApplicationBuilder app)
{
app.Run(async context =>
{
await context.Response.WriteAsync("Map Test 1");
});
}
static void HandleMapTest2(IApplicationBuilder app)
{
app.Run(async context =>
{
await context.Response.WriteAsync("Map Test 2");
});
}
V následující tabulce jsou uvedeny žádosti a odpovědi z http://localhost:1234 použití předchozího kódu.
| Žádost | Odpověď |
|---|---|
| localhost: 1234 | Hello z delegáta bez mapy. |
| localhost: 1234/Map1 | Mapování testu 1 |
| localhost: 1234/MAP2 – | Mapovat test 2 |
| localhost: 1234/map3 – | Hello z delegáta bez mapy. |
Při Map použití se odpovídající segmenty cesty odeberou z HttpRequest.Path a připojí se k HttpRequest.PathBase pro každý požadavek.
Map podporuje vnořování, například:
app.Map("/level1", level1App => {
level1App.Map("/level2a", level2AApp => {
// "/level1/level2a" processing
});
level1App.Map("/level2b", level2BApp => {
// "/level1/level2b" processing
});
});
Map může také odpovídat více segmentům najednou:
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.Map("/map1/seg1", HandleMultiSeg);
app.Run(async context =>
{
await context.Response.WriteAsync("Hello from non-Map delegate. <p>");
});
app.Run();
static void HandleMultiSeg(IApplicationBuilder app)
{
app.Run(async context =>
{
await context.Response.WriteAsync("Map Test 1");
});
}
MapWhen rozvětvení kanálu požadavků na základě výsledku daného predikátu. Func<HttpContext, bool>K mapování požadavků na novou větev kanálu lze použít jakýkoli predikát typu. V následujícím příkladu se k detekci přítomnosti proměnné řetězce dotazu používá predikát branch :
public class Startup
{
private static void HandleBranch(IApplicationBuilder app)
{
app.Run(async context =>
{
var branchVer = context.Request.Query["branch"];
await context.Response.WriteAsync($"Branch used = {branchVer}");
});
}
public void Configure(IApplicationBuilder app)
{
app.MapWhen(context => context.Request.Query.ContainsKey("branch"),
HandleBranch);
app.Run(async context =>
{
await context.Response.WriteAsync("Hello from non-Map delegate. <p>");
});
}
}
V následující tabulce jsou uvedeny žádosti a odpovědi z http://localhost:1234 použití předchozího kódu:
| Žádost | Odpověď |
|---|---|
| localhost: 1234 | Hello z delegáta bez mapy. |
| localhost: 1234/? větev = Main | Použitá větev = Main |
UseWhen také větví kanál požadavků na základě výsledku daného predikátu. Na rozdíl od MapWhen , tato větev se znovu připojí k hlavnímu kanálu, pokud nemá krátký okruh nebo obsahuje middleware terminálu:
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.UseWhen(context => context.Request.Query.ContainsKey("branch"),
appBuilder => HandleBranchAndRejoin(appBuilder));
app.Run(async context =>
{
await context.Response.WriteAsync("Hello from non-Map delegate. <p>");
});
app.Run();
void HandleBranchAndRejoin(IApplicationBuilder app)
{
var logger = app.ApplicationServices.GetRequiredService<ILogger<Program>>();
app.Use(async (context, next) =>
{
var branchVer = context.Request.Query["branch"];
logger.LogInformation("Branch used = {branchVer}", branchVer);
// Do work that doesn't write to the Response.
await next();
// Do other work that doesn't write to the Response.
});
}
V předchozím příkladu odpověď "Hello z hlavního kanálu". je napsán pro všechny požadavky. Pokud požadavek obsahuje proměnnou řetězce dotazu branch , je jeho hodnota protokolována před opětovným připojením k hlavnímu kanálu.
Vestavěný middleware
ASP.NET Core se dodává s následujícími součástmi middlewaru. Sloupec Order poskytuje poznámky k umístění middlewaru v kanálu zpracování požadavků a za jakých podmínek může middleware ukončit zpracování požadavků. Když middleware middleware vytvoří kanál zpracování požadavků a zabrání dalšímu podřízenému middlewaru ve zpracování žádosti, nazývá se middleware terminálu. Další informace o krátkodobém okruhu najdete v části vytvoření kanálu middlewaru pomocí IApplicationBuilder .
| Middleware | Description | Objednávka |
|---|---|---|
| Authentication | Poskytuje podporu ověřování. | Předtím HttpContext.User , než je potřeba. Terminál pro zpětná volání OAuth. |
| Autorizace | Poskytuje podporu autorizace. | Hned po ověřovacím middlewaru. |
| Cookie Politických | Sleduje souhlas uživatelů při ukládání osobních údajů a vynutila minimální standardy pro cookie pole, například secure a SameSite . |
Před middlewarem, který vydává problémy cookie s. Příklady: ověřování, relace, MVC (TempData). |
| CORS | Konfiguruje sdílení prostředků mezi zdroji. | Před komponenty, které používají CORS. UseCors v současné době UseResponseCaching se musí před touto chyboupřecházet. |
| DeveloperExceptionPage | Vygeneruje stránku s informacemi o chybě, která je určena pouze pro použití ve vývojovém prostředí. | Před komponenty, které generují chyby. Šablony projektu automaticky registrují tento middleware jako první middleware v kanálu při vývoji prostředí. |
| Diagnostika | Několik samostatných middlewarů, které poskytují stránku s výjimkou vývojářů, zpracování výjimek, stránky stavového kódu a výchozí webovou stránku pro nové aplikace. | Před komponenty, které generují chyby. Terminál pro výjimky nebo pro výchozí webovou stránku pro nové aplikace |
| Předávaná záhlaví | Přepošle hlavičky proxy na aktuální požadavek. | Před komponenty, které používají aktualizované pole. Příklady: schéma, hostitel, IP adresa klienta, metoda. |
| Kontroly stavu | kontroluje stav aplikace ASP.NET Core a jejích závislostí, jako je například kontrola dostupnosti databáze. | Terminál, je-li požadavek shodný s koncovým bodem kontroly stavu. |
| Šíření hlaviček | Šíří hlavičky protokolu HTTP z příchozího požadavku do odchozích požadavků klienta HTTP. | |
| Protokolování HTTP | Protokoluje požadavky a odpovědi HTTP. | Na začátku kanálu middlewaru. |
| Přepsání metody HTTP | Umožňuje příchozí žádosti POST přepsat metodu. | Před komponenty, které používají aktualizovanou metodu. |
| Přesměrování HTTPS | Přesměrovat všechny požadavky HTTP na HTTPS. | Před komponenty, které používají adresu URL. |
| HTTP Strict Transport Security (HSTS) | Vylepšení zabezpečení – middleware, který přidává speciální hlavičku odpovědi. | Před odesláním odpovědí a po součástech, které upravují požadavky. Příklady: předávané hlavičky, přepis adresy URL. |
| MVC | Zpracovává požadavky pomocí MVC nebo Razor stránek. | Terminál, pokud požadavek odpovídá trase. |
| OWIN | Interoperabilita s aplikacemi, servery a middlewarem založeným na OWIN | Terminál, pokud middleware OWIN plně zpracovává požadavek. |
| Ukládání do mezipaměti odpovědi | Poskytuje podporu pro ukládání odpovědí do mezipaměti. | Před součástmi, které vyžadují ukládání do mezipaměti. UseCORS musí předcházet UseResponseCaching . |
| Komprese odezvy | Poskytuje podporu pro komprimaci odpovědí. | Před součástmi, které vyžadují kompresi. |
| Lokalizace žádosti | Poskytuje podporu lokalizace. | Před lokalizací citlivých komponent. Po použití se musí objevit po Middlewari směrování RouteDataRequestCultureProvider . |
| Směrování koncových bodů | Definuje a omezuje trasy požadavků. | Terminál pro vyhovující trasy. |
| OVĚŘOVÁNÍ | Zpracovává všechny požadavky od tohoto bodu v řetězci middleware vrácením výchozí stránky pro aplikaci s jednou stránkou (SPA). | V řetězci pozdě, aby měl přednost další middleware pro obsluhu statických souborů, akcí MVC atd. |
| Relace | Poskytuje podporu pro správu uživatelských relací. | Před komponenty, které vyžadují relaci. |
| Statické soubory | Poskytuje podporu pro poskytování statických souborů a procházení adresářů. | Terminál, pokud požadavek odpovídá souboru |
| Přepsání adresy URL | Poskytuje podporu pro přepisování adres URL a přesměrování požadavků. | Před komponenty, které používají adresu URL. |
| W3CLogging | Vygeneruje protokoly přístupu serveru v rozšířeném formátu souboru protokolu W3C. | Na začátku kanálu middlewaru. |
| WebSockets | Povolí protokol WebSockets. | Před komponenty, které jsou vyžadovány pro příjem požadavků protokolu WebSocket. |
Další zdroje informací
- Možnosti životního cyklu a registrace obsahují kompletní ukázku middlewaru s rozsahem, přechodnými a neplatnými službami typu singleton .
- Psaní vlastních ASP.NET Core middlewaru
- Testovací ASP.NET Core middleware
- migrace obslužných rutin a modulů HTTP do ASP.NET Core middlewaru
- Spuštění aplikace v ASP.NET Core
- Žádosti o funkce v ASP.NET Core
- Aktivace middlewaru založená na továrně v ASP.NET Core
- Aktivace middlewaru pomocí kontejneru třetí strany v ASP.NET Core
Od Rick Anderson a Steve Smith
Middleware je software, který se sestaví do kanálu aplikace za účelem zpracování požadavků a odpovědí. Jednotlivé komponenty:
- Zvolí, jestli se má žádost předat další komponentě v kanálu.
- Může provádět práci před a za další komponentou v kanálu.
Delegáti žádostí se používají k sestavení kanálu požadavků. Delegát žádosti zpracuje jednotlivé požadavky HTTP.
Delegáti žádostí jsou nakonfigurováni pomocí Run Map Use metod rozšíření, a. Jednotlivé delegáty žádostí je možné zadat jako anonymní metodu (označovanou v rámci middlewarového middlewaru) nebo ji lze definovat v opakovaně použitelné třídě. Tyto opakovaně použitelné třídy a vložené anonymní metody jsou middleware, označované také jako komponenty middlewaru. Každá součást middlewaru v kanálu požadavků zodpovídá za vyvolání další komponenty v kanálu nebo při krátkém okruhu kanálu. Když jsou krátkodobé okruhy middleware, nazývá se middleware terminálu , protože zabrání dalšímu middlewaru ve zpracování žádosti.
migrace obslužných rutin a modulů HTTP do ASP.NET Core middlewaruvysvětluje rozdíl mezi kanály požadavků v ASP.NET Core a ASP.NET 4. x a poskytuje další ukázky middlewaru.
Vytvoření kanálu middlewaru pomocí IApplicationBuilder
kanál žádostí o ASP.NET Core se skládá z posloupnosti delegátů požadavků, který se nazývá jedna po druhé. Následující diagram znázorňuje koncept. Vlákno provádění následuje za černými šipkami.

Každý delegát může provádět operace před a po dalším delegátu. Delegáty zpracování výjimek by se měly volat v rámci kanálu na začátku, takže můžou zachytit výjimky, ke kterým dochází v pozdějších fázích kanálu.
nejjednodušší možná ASP.NET Core aplikace nastaví jediného delegáta žádosti, který zpracovává všechny požadavky. Tento případ nezahrnuje skutečný kanál žádostí. Místo toho je volána jedna anonymní funkce v reakci na každý požadavek HTTP.
public class Startup
{
public void Configure(IApplicationBuilder app)
{
app.Run(async context =>
{
await context.Response.WriteAsync("Hello, World!");
});
}
}
Řetězení více požadavků delegátů společně s Use . nextParametr představuje dalšího delegáta v kanálu. Kanál můžete pro krátké okruhy vymezit tím , že nevoláte Další parametr. Obvykle můžete provádět akce před i po dalším delegátu, jak ukazuje následující příklad:
public class Startup
{
public void Configure(IApplicationBuilder app)
{
app.Use(async (context, next) =>
{
// Do work that doesn't write to the Response.
await next.Invoke();
// Do logging or other work that doesn't write to the Response.
});
app.Run(async context =>
{
await context.Response.WriteAsync("Hello from 2nd delegate.");
});
}
}
Když delegát neprojde požadavek na dalšího delegáta, nazývá se to krátkodobý kanál žádosti. Krátkodobé okruhy jsou často žádoucí, protože brání zbytečné práci. Například middleware statických souborů může fungovat jako middleware terminálu tím, že zpracovává požadavek na statický soubor a krátký okruh zbývajících částí kanálu. Middleware přidané do kanálu předtím, než middleware, který ukončí další zpracování, stále zpracovává kód po svých next.Invoke příkazech. Přečtěte si ale následující upozornění týkající se pokusu o zápis do odpovědi, která již byla odeslána.
Upozornění
Nevolejte next.Invoke po odeslání odpovědi klientovi. Změny HttpResponse poté, co odpověď začala, vyvolávají výjimku. Například nastavení záhlaví a stavový kód vyvolávají výjimku. Zápis do těla odpovědi po volání next :
- Může způsobit narušení protokolu. Například zápis více než uvedené
Content-Length. - Může poškodit formát textu. Například zápis zápatí HTML do souboru CSS.
HasStarted je užitečnou nápovědou, která označuje, zda byla odeslána hlavička nebo zda byl text napsán do.
Run Delegáti neobdrží next parametr. První Run delegát je vždycky terminál a ukončí kanál. Run je konvence. Některé komponenty middlewaru můžou vystavovat Run[Middleware] metody, které se spouštějí na konci kanálu:
public class Startup
{
public void Configure(IApplicationBuilder app)
{
app.Use(async (context, next) =>
{
// Do work that doesn't write to the Response.
await next.Invoke();
// Do logging or other work that doesn't write to the Response.
});
app.Run(async context =>
{
await context.Response.WriteAsync("Hello from 2nd delegate.");
});
}
}
Pokud chcete zobrazit komentáře ke kódu přeložené do jiných jazyků než angličtiny, dejte nám vědět v tomto problému diskuze na GitHubu.
V předchozím příkladu Run delegát zapisuje "Hello from 2nd delegate." do odpovědi a pak kanál ukončí. Pokud Use Run je po delegátu přidán jiný nebo delegát Run , není volán.
Pořadí middlewaru
následující diagram znázorňuje kompletní kanál zpracování požadavků pro ASP.NET Core aplikace MVC a Razor stránky. Můžete vidět, jak, v typické aplikaci jsou seřazené existující middleware a kdy se přidávají vlastní middleware. Máte plnou kontrolu nad tím, jak změnit pořadí stávajících middlewarů, nebo vložit nové vlastní middleware podle potřeby pro vaše scénáře.
Middleware koncového bodu v předchozím diagramu spouští kanál filtru pro odpovídající typ aplikace — MVC nebo Razor stránky.
Pořadí, v jakém jsou komponenty middleware přidány v Startup.Configure metodě, definuje pořadí, ve kterém jsou komponenty middleware vyvolány na žádostech a obráceném pořadí pro odpověď. Pořadí je důležité pro zabezpečení, výkon a funkčnost.
Následující metoda Startup.Configure přidá komponenty middlewaru související se zabezpečením v typickém doporučeném pořadí:
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
app.UseDatabaseErrorPage();
}
else
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
// app.UseCookiePolicy();
app.UseRouting();
// app.UseRequestLocalization();
// app.UseCors();
app.UseAuthentication();
app.UseAuthorization();
// app.UseSession();
// app.UseResponseCompression();
// app.UseResponseCaching();
app.UseEndpoints(endpoints =>
{
endpoints.MapRazorPages();
endpoints.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
});
}
V předchozím kódu:
- Middleware, který se nepřidá při vytváření nové webové aplikace s účty jednotlivých uživatelů, je zakomentovaný.
- Ne každý middleware se zobrazí v tomto přesném pořadí, ale mnoho jich ano. Například:
UseCors,UseAuthenticationa se musí zobrazovat vUseAuthorizationzobrazeném pořadí.UseCorsv současné době se musíUseResponseCachingzobrazit před touto chybou.UseRequestLocalizationmusí být před libovolným middlewarem, který by mohl zkontrolovat jazykovou verzi požadavku (napříkladapp.UseMvcWithDefaultRoute()).
V některých scénářích má middleware jiné řazení. Například ukládání do mezipaměti a řazení komprese je specifické pro konkrétní scénář a existuje několik platných objednávek. Například:
app.UseResponseCaching();
app.UseResponseCompression();
Pomocí předchozího kódu lze procesor uložit do mezipaměti pomocí komprimované odpovědi, ale můžete nakonec uložit do mezipaměti několik reprezentací prostředku pomocí různých kompresních algoritmů, jako je Gzip nebo Brotli.
Následující řazení kombinuje statické soubory, aby bylo možné ukládat komprimované statické soubory do mezipaměti:
app.UseResponseCaching();
app.UseResponseCompression();
app.UseStaticFiles();
Následující metoda Startup.Configure přidá middlewarové komponenty pro běžné scénáře aplikací:
- Zpracování výjimek nebo chyb
- Když se aplikace spustí ve vývojovém prostředí:
- Middleware stránky výjimky pro vývojáře ( UseDeveloperExceptionPage ) hlásí chyby modulu runtime aplikace.
- Middleware databázové chybové stránky hlásí chyby modulu runtime databáze.
- Když se aplikace spustí v produkčním prostředí:
- Middleware obslužné rutiny výjimky ( UseExceptionHandler ) zachycuje výjimky vyvolané v následujících middlewarech.
- Middleware HTTP Strict Transport Security Protocol (HSTS) ( UseHsts ) přidá
Strict-Transport-Securityhlavičku .
- Když se aplikace spustí ve vývojovém prostředí:
- Middleware pro přesměrování HTTPS ( UseHttpsRedirection ) přesměruje požadavky HTTP na HTTPS.
- Middleware statického souboru ( ) vrací statické soubory a UseStaticFiles krátké okruhy další zpracování požadavků.
- Cookie Middleware zásad ( ) odpovídá aplikaci předpisům UseCookiePolicy EU Obecné nařízení o ochraně osobních údajů (GDPR).
- Middleware směrování ( UseRouting ) pro směrování požadavků.
- Ověřovací middleware ( ) se pokusí uživatele ověřit, než mu bude povolen UseAuthentication přístup k zabezpečeným prostředkům.
- Autorizační middleware ( UseAuthorization ) autorizuje uživatele pro přístup k zabezpečeným prostředkům.
- Middleware relace ( UseSession ) vytváří a udržuje stav relace. Pokud aplikace používá stav relace, volejte middleware relace po middlewaru zásad a Cookie před middlewarem MVC.
- Middleware pro směrování koncových bodů ( s ) pro přidání koncových bodů UseEndpoints Pages MapRazorPages do Razor kanálu požadavku.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
app.UseDatabaseErrorPage();
}
else
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseCookiePolicy();
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.UseSession();
app.UseEndpoints(endpoints =>
{
endpoints.MapRazorPages();
});
}
V předchozím příkladu kódu je každá metoda rozšíření middlewaru zpřístupněna prostřednictvím IApplicationBuilder oboru Microsoft.AspNetCore.Builder názvů .
UseExceptionHandler je první komponenta middlewaru přidaná do kanálu. Middleware obslužné rutiny výjimky proto zachycuje všechny výjimky, ke kterým dojde v pozdějších voláních.
Middleware static file se volá v rané fázi kanálu, aby mohl zpracovávat požadavky a krátký okruh, aniž by prošel zbývajícími komponentami. Middleware statického souboru nemá žádné autorizační kontroly. Všechny soubory, které poskytuje middleware Static File, včetně souborů v rámci wwwroot, jsou veřejně dostupné. Přístup k zabezpečení statických souborů najdete v tématu Statické soubory v ASP.NET Core .
Pokud požadavek nezvládá middleware statického souboru, předá se ověřovacímu middlewaru ( ), který UseAuthentication provádí ověřování. Ověřování nezkrátí neověřené požadavky. I když ověřovací middleware ověřuje požadavky, autorizace (a zamítnutí) nastane až poté, co MVC vybere konkrétní kontroler stránky nebo MVC a Razor akci.
Následující příklad ukazuje pořadí middlewaru, ve kterém middleware před kompresí odpovědí zpracovává požadavky na statické soubory middlewarem statického souboru. Statické soubory nejsou v tomto pořadí middlewaru komprimované. Odpovědi Razor pages je možné komprimovat.
public void Configure(IApplicationBuilder app)
{
// Static files aren't compressed by Static File Middleware.
app.UseStaticFiles();
app.UseRouting();
app.UseResponseCompression();
app.UseEndpoints(endpoints =>
{
endpoints.MapRazorPages();
});
}
U jedno stránkových aplikací (SPA) je middleware SPA obvykle poslední v UseSpaStaticFiles middlewaru. Middleware SPA je poslední:
- Aby všechny ostatní middleware mohly jako první reagovat na odpovídající požadavky.
- Aby bylo možné spustit SSP se směrováním na straně klienta pro všechny trasy, které serverová aplikace nerozpozná.
Další podrobnosti o SSP najdete v příručkách pro šablony React a Angular projektů.
Pořadí middlewaru předáných hlaviček
Middleware předaných hlaviček by se měla spustit před jiným middlewarem. Toto řazení zajišťuje, aby middleware spoléhající se na předané informace hlaviček mohl spotřebovat hodnoty hlaviček pro zpracování. Pro spuštění předávaných middlewarových hlaviček po diagnostice a middlewaru zpracování chyb si přečtěte téma pořadí middlewaru u předaných hlaviček.
Větvení middlewarového kanálu
Map Rozšíření se používají jako konvence pro větvení kanálu. Map větví kanálu požadavku na základě shod dané cesty požadavku. Pokud cesta požadavku začíná danou cestou, větev se spustí.
public class Startup
{
private static void HandleMapTest1(IApplicationBuilder app)
{
app.Run(async context =>
{
await context.Response.WriteAsync("Map Test 1");
});
}
private static void HandleMapTest2(IApplicationBuilder app)
{
app.Run(async context =>
{
await context.Response.WriteAsync("Map Test 2");
});
}
public void Configure(IApplicationBuilder app)
{
app.Map("/map1", HandleMapTest1);
app.Map("/map2", HandleMapTest2);
app.Run(async context =>
{
await context.Response.WriteAsync("Hello from non-Map delegate. <p>");
});
}
}
V následující tabulce jsou uvedeny požadavky a odpovědi http://localhost:1234 z předchozího kódu.
| Žádost | Odpověď |
|---|---|
| localhost:1234 | Hello z delegáta bez mapy |
| localhost:1234/map1 | Test mapy 1 |
| localhost:1234/map2 | Test mapy 2 |
| localhost:1234/map3 | Hello z delegáta bez mapy |
Při použití se odpovídající segmenty cesty pro každý požadavek odebraly a Map HttpRequest.Path HttpRequest.PathBase připojují k .
Map podporuje vnoření, například:
app.Map("/level1", level1App => {
level1App.Map("/level2a", level2AApp => {
// "/level1/level2a" processing
});
level1App.Map("/level2b", level2BApp => {
// "/level1/level2b" processing
});
});
Map může také odpovídat více segmentům najednou:
public class Startup
{
private static void HandleMultiSeg(IApplicationBuilder app)
{
app.Run(async context =>
{
await context.Response.WriteAsync("Map multiple segments.");
});
}
public void Configure(IApplicationBuilder app)
{
app.Map("/map1/seg1", HandleMultiSeg);
app.Run(async context =>
{
await context.Response.WriteAsync("Hello from non-Map delegate.");
});
}
}
MapWhen větví kanálu požadavku na základě výsledku daného predikátu. K mapování požadavků na novou větev kanálu je možné použít jakýkoli Func<HttpContext, bool> predikát typu. V následujícím příkladu se k detekci přítomnosti proměnné řetězce dotazu používá predikát branch :
public class Startup
{
private static void HandleBranch(IApplicationBuilder app)
{
app.Run(async context =>
{
var branchVer = context.Request.Query["branch"];
await context.Response.WriteAsync($"Branch used = {branchVer}");
});
}
public void Configure(IApplicationBuilder app)
{
app.MapWhen(context => context.Request.Query.ContainsKey("branch"),
HandleBranch);
app.Run(async context =>
{
await context.Response.WriteAsync("Hello from non-Map delegate. <p>");
});
}
}
V následující tabulce jsou uvedeny požadavky a odpovědi http://localhost:1234 z předchozího kódu:
| Žádost | Odpověď |
|---|---|
| localhost:1234 | Hello z delegáta bez mapy |
| localhost:1234/?branch=main | Použitá větev = main |
UseWhen také větví kanálu požadavku na základě výsledku daného predikátu. Na rozdíl od systému se tato větev znovu připojí k hlavnímu kanálu, pokud nemá krátký okruh nebo neobsahuje MapWhen terminálový middleware:
public class Startup
{
private void HandleBranchAndRejoin(IApplicationBuilder app, ILogger<Startup> logger)
{
app.Use(async (context, next) =>
{
var branchVer = context.Request.Query["branch"];
logger.LogInformation("Branch used = {branchVer}", branchVer);
// Do work that doesn't write to the Response.
await next();
// Do other work that doesn't write to the Response.
});
}
public void Configure(IApplicationBuilder app, ILogger<Startup> logger)
{
app.UseWhen(context => context.Request.Query.ContainsKey("branch"),
appBuilder => HandleBranchAndRejoin(appBuilder, logger));
app.Run(async context =>
{
await context.Response.WriteAsync("Hello from main pipeline.");
});
}
}
V předchozím příkladu se zobrazí odpověď "Hello from main pipeline" (Dobrý den z hlavního kanálu). se zapisuje pro všechny požadavky. Pokud požadavek obsahuje proměnnou řetězce dotazu , její hodnota se zaprotokoluje před tím, než se hlavní branch kanál znovu připojí.
Integrovaný middleware
ASP.NET Core se dodává s následujícími komponentami middlewaru. Sloupec Order (Objednávka) obsahuje poznámky k umístění middlewaru v kanálu zpracování požadavků a za jakých podmínek může middleware zpracování požadavků ukončit. Když middleware zkrátí kanál zpracování požadavků a zabrání dalšímu zpracování požadavku podřízenému middlewaru, nazývá se to terminální middleware. Další informace o zkrácení najdete v části Vytvoření middlewarového kanálu pomocí IApplicationBuilder.
| Middleware | Description | Objednávka |
|---|---|---|
| Authentication | Poskytuje podporu ověřování. | Než HttpContext.User bude potřeba. Terminál pro zpětná volání OAuth. |
| Autorizace | Poskytuje podporu autorizace. | Ihned po ověřovacím middlewaru. |
| Cookie Zásad | Sleduje souhlas uživatelů s ukládáním osobních údajů a vynucuje minimální standardy pro cookie pole, jako je a secure SameSite . |
Před middlewarem, u které cookie k problémům došl. Příklady: Ověřování, relace, MVC (TempData). |
| CORS | Nakonfiguruje sdílení prostředků mezi zdroji. | Před komponentami, které používají CORS. UseCorsv současné době je nutné UseResponseCaching kvůli této chybě přejít před . |
| Diagnostika | Několik samostatných middlewarů, které poskytují stránku výjimek pro vývojáře, zpracování výjimek, stránky stavového kódu a výchozí webovou stránku pro nové aplikace. | Před komponentami, které generují chyby. Terminál pro výjimky nebo obsluhující výchozí webovou stránku pro nové aplikace |
| Předáná záhlaví | Předá hlavičky proxied aktuálnímu požadavku. | Před komponentami, které využívají aktualizovaná pole. Příklady: schéma, hostitel, IP adresa klienta, metoda. |
| Kontrola stavu | Kontroluje stav aplikace ASP.NET Core její závislosti, například kontroluje dostupnost databáze. | Terminál, pokud požadavek odpovídá koncovému bodu kontroly stavu |
| Šíření hlaviček | Rozšíří hlavičky HTTP z příchozího požadavku na odchozí požadavky klienta HTTP. | |
| Přepsání metody HTTP | Umožňuje příchozímu požadavku POST přepsat metodu . | Před komponentami, které využívají aktualizovanou metodu. |
| Přesměrování HTTPS | Přesměrovat všechny požadavky HTTP na HTTPS. | Před komponentami, které adresu URL využívají. |
| Http Strict Transport Security (HSTS) | Middleware pro vylepšení zabezpečení, který přidává speciální hlavičku odpovědi. | Před odesláním odpovědí a po komponentách, které upravuje požadavky. Příklady: Předánaná záhlaví, Přepis adres URL. |
| MVC | Zpracovává požadavky pomocí MVC/ Razor stránek. | Terminál, pokud požadavek odpovídá trase |
| OWIN | Spolupráce s aplikacemi, servery a middlewarem založenými na OWIN | Terminál, pokud middleware OWIN plně zpracuje požadavek. |
| Odpověď Ukládání do mezipaměti | Poskytuje podporu pro ukládání odpovědí do mezipaměti. | Před komponentami, které vyžadují ukládání do mezipaměti. UseCORS musí předchádovat UseResponseCaching před . |
| Komprese odpovědí | Poskytuje podporu pro komprimaci odpovědí. | Před komponentami, které vyžadují kompresi. |
| Lokalizace požadavku | Poskytuje podporu lokalizace. | Před lokalizací citlivých komponent. Při použití se musí zobrazit po middlewaru RouteDataRequestCultureProvider směrování. |
| Směrování koncového bodu | Definuje a omezuje trasy požadavků. | Terminál pro odpovídající trasy. |
| SPA | Zpracovává všechny požadavky od tohoto bodu v řetězci middlewaru vrácením výchozí stránky jedno stránkovací aplikace (SPA). | V pozdější části řetězu má přednost jiný middleware pro obsluhu statických souborů, akcí MVC atd. |
| Relace | Poskytuje podporu pro správu uživatelských relací. | Před součástmi, které vyžadují relaci. |
| Statické soubory | Poskytuje podporu pro obsluhu statických souborů a procházení adresářů. | Terminál, pokud požadavek odpovídá souboru |
| Přepsání adresy URL | Poskytuje podporu pro přepis adres URL a žádosti o přesměrování. | Před komponentami, které adresu URL využívají. |
| WebSockets | Povolí protokol WebSocket. | Před komponentami, které jsou potřeba k přijetí požadavků WebSocket. |
Další zdroje informací
- Možnosti doby života a registrace obsahují kompletní ukázku middlewaru se službami s vymezeným oborem, přechodnou a jednotnou životností.
- Psaní vlastních ASP.NET Core middlewaru
- Testovací ASP.NET Core middleware
- migrace obslužných rutin a modulů HTTP do ASP.NET Core middlewaru
- Spuštění aplikace v ASP.NET Core
- Žádosti o funkce v ASP.NET Core
- Aktivace middlewaru založená na továrně v ASP.NET Core
- Aktivace middlewaru pomocí kontejneru třetí strany v ASP.NET Core