Megjegyzés
Az oldalhoz való hozzáféréshez engedély szükséges. Megpróbálhat bejelentkezni vagy módosítani a címtárat.
Az oldalhoz való hozzáféréshez engedély szükséges. Megpróbálhatja módosítani a címtárat.
Ryan Nowak, Kirk Larkin és Rick Anderson
Note
Ez nem a cikk legújabb verziója. Az aktuális kiadásról a cikk .NET 10-es verziójában olvashat.
Warning
A ASP.NET Core ezen verziója már nem támogatott. További információt a .NET és a .NET Core támogatási szabályzatában talál. A jelen cikk .NET 9-es verzióját lásd az aktuális kiadásért .
Az útválasztás feladata a bejövő HTTP-kérések egyeztetése és a kérések elküldése az alkalmazás végrehajtható végpontjaira. A végpontok az alkalmazás végrehajtható kéréskezelési kódjának egységei. A végpontok az alkalmazásban vannak definiálva, és az alkalmazás indításakor vannak konfigurálva. A végpontegyeztetési folyamat kinyerheti az értékeket a kérelem URL-címéből, és megadhatja ezeket az értékeket a kérelmek feldolgozásához. Az alkalmazás végpontadatainak használatával az útválasztás a végpontokra leképező URL-címeket is képes létrehozni.
Az alkalmazások a következő eszközökkel konfigurálhatják az útválasztást:
- Controllers
- Razor lapok
- SignalR
- gRPC-szolgáltatások
- Végpont-kompatibilis köztes szoftver, mint például a Health Checks.
- Útválasztással regisztrált delegátumok és lambdák.
Ez a cikk a ASP.NET Core útválasztásának alacsony szintű részleteit ismerteti. Az útválasztás konfigurálásával kapcsolatos információk:
- A vezérlőkről lásd: Útválasztás a vezérlőműveletekhez a ASP.NET Core-ban.
- Az Razor Pages konvenciókról lásd az ASP.NET Core oldal útvonal- és alkalmazási konvencióit Razor.
- Az Blazor ebben a cikkben szereplő útmutatást kiegészítő vagy felülíró útválasztási útmutatásért lásd ASP.NET Alapvető Blazor útválasztás és navigáció című témakört.
Az útválasztás alapjai
Az alábbi kód egy egyszerű útválasztási példát mutat be:
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.MapGet("/", () => "Hello World!");
app.Run();
Az előző példa egyetlen végpontot tartalmaz a MapGet metódus használatával:
- HA HTTP-kérést
GETküld a rendszer a gyökér URL-címre/:- A kérelem delegáltja végrehajtja.
-
Hello World!az HTTP-válaszként íródik.
- Ha a kérelem metódusa nem
GET, vagy a gyökér URL-címe nem/, a rendszer nem ad vissza útvonal-egyezést, és a rendszer egy HTTP 404-et ad vissza.
Az útválasztás egy köztes szoftverpárt használ, amelyet a UseRouting és a UseEndpoints regisztrál.
-
UseRoutingA köztesszoftver-folyamatnak megfelelő útvonalat ad hozzá. Ez a köztes szoftver megvizsgálja az alkalmazásban definiált végpontokat, és a kérés alapján kiválasztja a legjobb egyezést . -
UseEndpointsvégpontvégrehajtást ad a köztes szoftverfolyamathoz. A kijelölt végponthoz társított delegáltat a program futtatja.
Az alkalmazásoknak általában nem kell, hogy meghívják UseRouting vagy UseEndpoints.
WebApplicationBuilder olyan köztes szoftverfolyamatot állít be, amely az Program.cs-ben hozzáadott köztes szoftvereket a UseRouting és UseEndpoints segítségével burkolja. Az alkalmazások azonban módosíthatják a metódusok sorrendjét UseRouting és UseEndpoints futtatását, ha kifejezetten meghívják ezeket a metódusokat. A következő kód például explicit hívást indít a következőre UseRouting:
app.Use(async (context, next) =>
{
// ...
await next(context);
});
app.UseRouting();
app.MapGet("/", () => "Hello World!");
Az előző kódban:
- A
app.Usehívás regisztrál egy egyedi middleware-t, amely a csővezeték elején fut. - A
UseRoutinghívás úgy konfigurálja az útvonal-illesztési köztes réteget, hogy az az egyéni köztes réteg után fusson. - A
MapGet-vel regisztrált végpont a folyamat végén fut.
Ha az előző példa nem tartalmazott volna hívást a UseRouting-ra, akkor az egyéni köztes szoftver az útvonal illesztési köztes szoftver után futott volna.
Megjegyzés: közvetlenül a WebApplication végrehajtott útvonalakat a folyamat végén.
Endpoints
A MapGet metódus egy végpont definiálására szolgál. A végpont a következő lehet:
- Az URL-cím és a HTTP-metódus egyeztetésével kijelölve.
- A delegált futtatásával hajtva végre.
Az alkalmazás által egyeztethető és végrehajtható végpontok a UseEndpoints-ben vannak konfigurálva. Például MapGet, MapPost és hasonló metódusok csatlakoztatják a kérelem delegáltjait az útválasztási rendszerhez. További módszerekkel csatlakoztathatók ASP.NET Core-keretrendszer funkciói az útválasztási rendszerhez:
- MapRazorPages a Razor oldalak számára
- MapControllers vezérlőkhöz
- MapHub<THub> for SignalR
- MapGrpcService<TService> for gRPC
Az alábbi példa egy kifinomultabb útvonalsablont tartalmazó útválasztást mutat be:
app.MapGet("/hello/{name:alpha}", (string name) => $"Hello {name}!");
A karakterlánc /hello/{name:alpha} egy útvonalsablon. Egy útvonalsablon használatával konfigurálható a végpont egyeztetése. Ebben az esetben a sablon megfelel a következőnek:
- URL-cím, például
/hello/Docs - Minden olyan URL-elérési út, amely betűrendes karakterek sorozatával
/hello/kezdődik.:alphaolyan útvonalkorlátozást alkalmaz, amely csak betűrendes karaktereknek felel meg. Az útvonalkorlátozásokat a cikk későbbi részében ismertetjük.
Az URL-elérési út második szegmense: {name:alpha}
- A paraméterhez
namevan kötve. - A rendszer rögzíti és tárolja a(z) HttpRequest.RouteValues fájlban.
Az alábbi példa az állapot-ellenőrzéssel és engedélyezéssel rendelkező útválasztást mutatja be:
app.UseAuthentication();
app.UseAuthorization();
app.MapHealthChecks("/healthz").RequireAuthorization();
app.MapGet("/", () => "Hello World!");
Az előző példa bemutatja, hogyan:
- Az engedélyezési köztes szoftver használható útválasztással.
- A végpontok az engedélyezési viselkedés konfigurálására használhatók.
A MapHealthChecks hívás egy állapot-ellenőrzési végpontot ad hozzá. A RequireAuthorization láncolása ehhez a híváshoz egy engedélyezési szabályzatot csatol a végponthoz.
A UseAuthentication és UseAuthorization meghívása hozzáadja a hitelesítési és engedélyezési middleware-t. Ezek a köztes szoftverek UseRouting és UseEndpoints közé vannak helyezve, hogy:
- Nézze meg, melyik végpontot választotta
UseRouting. - Engedélyezési szabályzat alkalmazása a végpontra történő küldés előtt UseEndpoints .
Végpont metaadatai
Az előző példában két végpont található, de csak az állapot-ellenőrzési végpont rendelkezik engedélyezési szabályzattal. Ha a kérelem megfelel az állapot-ellenőrzési végpontnak, /healthza rendszer engedélyezési ellenőrzést végez. Ez azt mutatja be, hogy a végpontokhoz további adatok is csatolhatók. Ezt a további adatot végponti metaadatoknak nevezzük:
- A metaadatok feldolgozhatók útválasztást ismerő köztes szoftver használatával.
- A metaadatok bármilyen .NET típusúak lehetnek.
Útválasztási fogalmak
Az útválasztási rendszer a közbenső szoftver folyamatára épül a hatékony végpontkoncepció hozzáadásával. A végpontok az alkalmazás funkcióinak azon egységeit jelölik, amelyek útválasztás, engedélyezés és ASP.NET Core-rendszerek tetszőleges száma tekintetében különböznek egymástól.
ASP.NET alapvető végpontdefiníció
Az ASP.NET Core-végpont a következő:
- Végrehajtható: rendelkezik egy RequestDelegate.
- Bővíthető: Metaadat-gyűjteménysel rendelkezik.
- Kiválasztható: Opcionálisan útválasztási információkkal rendelkezik.
- Enumerable: A végpontok gyűjteménye a EndpointDataSource való lekéréssel listázható.
Az alábbi kód bemutatja, hogyan kérheti le és vizsgálhatja meg az aktuális kérésnek megfelelő végpontot:
app.Use(async (context, next) =>
{
var currentEndpoint = context.GetEndpoint();
if (currentEndpoint is null)
{
await next(context);
return;
}
Console.WriteLine($"Endpoint: {currentEndpoint.DisplayName}");
if (currentEndpoint is RouteEndpoint routeEndpoint)
{
Console.WriteLine($" - Route Pattern: {routeEndpoint.RoutePattern}");
}
foreach (var endpointMetadata in currentEndpoint.Metadata)
{
Console.WriteLine($" - Metadata: {endpointMetadata}");
}
await next(context);
});
app.MapGet("/", () => "Inspect Endpoint.");
Ha a végpont ki van választva, lekérhető a HttpContext. Tulajdonságai megvizsgálhatók. A végpontobjektumok nem módosíthatók, és a létrehozás után nem módosíthatók. A végpont leggyakoribb típusa a RouteEndpoint.
RouteEndpoint információkat tartalmaz, amelyek lehetővé teszik az útválasztási rendszer számára, hogy kiválaszthassa azt.
Az előző kódban a app.Use egy beágyazott middleware-t konfigurál.
Az alábbi kód azt mutatja, hogy attól függően, hogy a folyamatban hol app.Use van meghívva, előfordulhat, hogy nincs végpont:
// Location 1: before routing runs, endpoint is always null here.
app.Use(async (context, next) =>
{
Console.WriteLine($"1. Endpoint: {context.GetEndpoint()?.DisplayName ?? "(null)"}");
await next(context);
});
app.UseRouting();
// Location 2: after routing runs, endpoint will be non-null if routing found a match.
app.Use(async (context, next) =>
{
Console.WriteLine($"2. Endpoint: {context.GetEndpoint()?.DisplayName ?? "(null)"}");
await next(context);
});
// Location 3: runs when this endpoint matches
app.MapGet("/", (HttpContext context) =>
{
Console.WriteLine($"3. Endpoint: {context.GetEndpoint()?.DisplayName ?? "(null)"}");
return "Hello World!";
}).WithDisplayName("Hello");
app.UseEndpoints(_ => { });
// Location 4: runs after UseEndpoints - will only run if there was no match.
app.Use(async (context, next) =>
{
Console.WriteLine($"4. Endpoint: {context.GetEndpoint()?.DisplayName ?? "(null)"}");
await next(context);
});
Az előző mintában olyan utasítások szerepelnek, amelyek megjelenítik, hogy ki van-e jelölve egy végpont. Az egyértelműség kedvéért a minta megjelenítendő nevet rendel a megadott / végponthoz.
Az előző minta a köztes szoftver folyamaton belüli futtatásának pontos ellenőrzésére UseRoutingUseEndpoints irányuló hívásokat is tartalmaz.
Ennek a kódnak a futtatása egy / URL-címmel megjeleníti:
1. Endpoint: (null)
2. Endpoint: Hello
3. Endpoint: Hello
A kód futtatása bármely más URL-címmel:
1. Endpoint: (null)
2. Endpoint: (null)
4. Endpoint: (null)
Ez a kimenet a következőt mutatja be:
- A végpont mindig null értékű, mielőtt
UseRoutingmeghívják. - Ha talál egyezést, a végpont nem null, és a
UseRoutingés UseEndpoints között van. - A
UseEndpointsköztes szoftver terminál , ha talál egyezést. A terminál köztes szoftverét a cikk későbbi részében definiáljuk. - A köztesréteg csak akkor fut, ha a
UseEndpointsvégrehajtása után nem található egyezés.
A UseRouting köztes szoftver a SetEndpoint metódus használatával csatolja a végpontot az aktuális környezethez. A köztes szoftvereket lecserélheti egyéni UseRouting logikára, és továbbra is élvezheti a végpontok használatának előnyeit. A végpontok alacsony szintű primitívek, például köztes szoftverek, és nem kapcsolódnak az útválasztási megvalósításhoz. A legtöbb alkalmazásnak nem kell egyéni logikára cserélnie UseRouting .
A UseEndpoints köztes szoftvert úgy alakították ki, hogy a UseRouting köztes szoftverrel tandem használatra legyen. A végpontok végrehajtásának alapvető logikája nem bonyolult. A végpont lekérésére GetEndpoint használata, majd annak RequestDelegate tulajdonságának meghívása.
Az alábbi kód bemutatja, hogy a köztes szoftver hogyan befolyásolhatja vagy reagálhat az útválasztásra:
app.UseHttpMethodOverride();
app.UseRouting();
app.Use(async (context, next) =>
{
if (context.GetEndpoint()?.Metadata.GetMetadata<RequiresAuditAttribute>() is not null)
{
Console.WriteLine($"ACCESS TO SENSITIVE DATA AT: {DateTime.UtcNow}");
}
await next(context);
});
app.MapGet("/", () => "Audit isn't required.");
app.MapGet("/sensitive", () => "Audit required for sensitive data.")
.WithMetadata(new RequiresAuditAttribute());
public class RequiresAuditAttribute : Attribute { }
Az előző példa két fontos fogalmat mutat be:
- A köztes szoftver előzetesen futtatható a
UseRoutingelőtt, hogy módosítsa azokat az adatokat, amelyeken az útválasztás működik.- Az útválasztás előtt megjelenő köztes szoftver általában módosítja a kérés bizonyos tulajdonságát, például UseRewriter: , UseHttpMethodOverridevagy UsePathBase.
- A middleware a
UseRoutingés UseEndpoints között futtatható annak érdekében, hogy az útválasztás eredményeit feldolgozza, mielőtt a végpont végrehajtásra kerül.- Köztes szoftver, amely a
UseRoutingésUseEndpointsközött fut:- A végpontok megértéséhez általában a metaadatokat vizsgálja meg.
- Gyakran hoz biztonsági döntéseket, mint a
UseAuthorizationésUseCors.
- A köztes szoftver és a metaadatok kombinációja lehetővé teszi a szabályzatok végpontonkénti konfigurálását.
- Köztes szoftver, amely a
Az előző kód egy végpontonkénti szabályzatokat támogató egyéni köztes szoftver példáját mutatja be. A köztes szoftver naplót ír a konzol bizalmas adataihoz való hozzáférésről. A köztes szoftver konfigurálható egy végpont metaadatokkal történő naplózásáraRequiresAuditAttribute. Ez a minta egy feliratkozásos mintát mutat be, amelyben csak a bizalmasként megjelölt végpontokat naplózzák. Ezt a logikát meg lehet határozni fordítottan, például naplózva mindent, ami nincs biztonságosként megjelölve. A végpont metaadat-rendszere rugalmas. Ez a logika bármilyen módon megtervezhető a használati esetnek megfelelően.
Az előző mintakód a végpontok alapfogalmait mutatja be. A minta nem éles használatra készült. A naplózási napló köztes szoftverének teljesebb verziója a következő lenne:
- Jelentkezzen be egy fájlba vagy adatbázisba.
- Adjon meg olyan részleteket, mint a felhasználó, az IP-cím, a bizalmas végpont neve stb.
A naplózási szabályzat metaadatai RequiresAuditAttribute egy Attribute-ként vannak definiálva a könnyebb használat érdekében olyan osztályalapú keretrendszerekkel, mint például a vezérlők és SignalR. A kódhoz vezető útvonal használata esetén:
- A metaadatok egy builder API-val vannak csatolva.
- Az osztályalapú keretrendszerek a végpontok létrehozásakor tartalmazzák a megfelelő metódus és osztály összes attribútumát.
A metaadat-típusok ajánlott eljárása, hogy interfészként vagy attribútumként definiálja őket. Az interfészek és attribútumok lehetővé teszik a kód újrafelhasználását. A metaadat-rendszer rugalmas, és nem ír elő korlátozásokat.
Terminál köztes szoftver összehasonlítása az útválasztással
Az alábbi példa a terminál köztes szoftverét és az útválasztást mutatja be:
// Approach 1: Terminal Middleware.
app.Use(async (context, next) =>
{
if (context.Request.Path == "/")
{
await context.Response.WriteAsync("Terminal Middleware.");
return;
}
await next(context);
});
app.UseRouting();
// Approach 2: Routing.
app.MapGet("/Routing", () => "Routing.");
A Approach 1:-vel látható köztes szoftver stílusa a terminál köztes szoftver. Terminál köztes szoftvernek nevezzük, mert egyező műveletet hajt végre:
- Az előző mintában az illesztési művelet a
Path == "/"a köztes szoftverhez ésPath == "/Routing"az útválasztáshoz tartozik. - Ha egy egyezés sikeres, végrehajt néhány funkciót, és visszatér anélkül, hogy meghívná a
nextköztes szoftvert.
Terminál köztes szoftvernek nevezik, mert leállítja a keresést, végrehajt néhány funkciót, majd visszaadja.
Az alábbi lista összehasonlítja a terminál köztes szoftverét az útválasztással:
- Mindkét módszer lehetővé teszi a feldolgozási folyamat leállítását:
- A köztes szoftver a
nextmeghívása helyett visszatéréssel leállítja a futószalagot. - A végpontok mindig terminálok.
- A köztes szoftver a
- A terminálközvetítő lehetővé teszi a köztes szoftver tetszőleges helyen való elhelyezését a folyamatban:
- A végpontok a UseEndpoints pozíción futnak.
- A terminál köztes réteg lehetővé teszi, hogy tetszőleges kód határozza meg, mikor egyezik a köztes szoftver.
- Az egyéni útvonalegyeztető kód részletes lehet, és nehezen írható helyesen.
- Az útválasztás egyszerű megoldásokat kínál a tipikus alkalmazásokhoz. A legtöbb alkalmazás nem igényel egyéni útvonalegyeztető kódot.
- A végpontok interfészei köztes szoftverekkel, mint például
UseAuthorizationésUseCors, kommunikálnak.- A
UseAuthorizationvagyUseCorsterminálközvetítő használata manuális beavatkozást igényel az engedélyezési rendszerbe való interfészépítés során.
- A
Egy végpont mindkettőt definiálja:
- A kérések feldolgozására jogosult meghatalmazott.
- Tetszőleges metaadatok gyűjteménye. A metaadatok az egyes végpontokhoz csatolt szabályzatokon és konfigurációkon alapuló, átfogó problémák megvalósítására szolgálnak.
A terminál köztes szoftver hatékony eszköz lehet, de a következőt igényelheti:
- Jelentős mennyiségű kódolás és tesztelés.
- Manuális integráció más rendszerekkel a kívánt rugalmasság elérése érdekében.
A terminál middleware megírása előtt fontolja meg az útvonalvezérléssel való integrálást.
A meglévő terminálközvetítmények, amelyek integrálódnak a Map-pal vagy a MapWhen, általában útválasztást támogató végponttá alakíthatók. MapHealthChecks a routerelem mintáját mutatja be:
- Bővítménymetódus írása a fájlra IEndpointRouteBuilder.
- Beágyazott köztes szoftverfolyamat létrehozása a következővel CreateApplicationBuilder: .
- Csatolja a köztes szoftvert az új folyamathoz. Ebben az esetben: UseHealthChecks.
- Build a köztes szoftverfolyamatot egy RequestDelegate.
- Hívja meg
Mapés adja meg az új köztes szoftverfolyamatot. - Adja vissza az
Mapáltal biztosított építőobjektumot a bővítménymetódusból.
Az alábbi kód a MapHealthChecks használatát mutatja be:
app.UseAuthentication();
app.UseAuthorization();
app.MapHealthChecks("/healthz").RequireAuthorization();
Az előző minta bemutatja, miért fontos az építő objektum visszaadása. A szerkesztőobjektum visszaadásával az alkalmazás fejlesztője olyan szabályzatokat konfigurálhat, mint a végpont engedélyezése. Ebben a példában az állapot-ellenőrző köztes szoftver nem rendelkezik közvetlen integrációval az engedélyezési rendszerrel.
A metaadat-rendszer a terminál köztes szoftvereket használó bővíthetőségi szerzők által tapasztalt problémákra válaszul jött létre. Minden köztes szoftver esetében problémás a saját integráció megvalósítása az engedélyezési rendszerrel.
URL-cím egyeztetése
- Az a folyamat, amellyel az útválasztás megfelel a végpontnak küldött bejövő kérésnek.
- Az URL-elérési út és a fejlécek adatain alapul.
- A kérelemben szereplő bármely adatra kiterjeszthető.
Az útvonalkezelő köztes szoftver végrehajtásakor beállít Endpoint és útvonali értékeket egy kérés tulajdonságához az HttpContext aktuális kérés alapján.
- A HttpContext.GetEndpoint hívása megkapja a végpontot.
-
HttpRequest.RouteValueslekéri az útvonalértékek gyűjteményét.
Az útválasztási köztes szoftver után futó köztes szoftver megvizsgálhatja a végpontot, és végrehajthatja a műveletet. Egy engedélyezési köztes szoftver például kikérdezheti a végpont metaadatgyűjteményét egy engedélyezési szabályzathoz. A kérelemfeldolgozási folyamat összes köztes szoftverének végrehajtása után a rendszer meghívja a kijelölt végpont delegáltját.
A végponti útválasztás útválasztási rendszere felelős az összes irányítási döntésért. Mivel a köztes szoftver a kiválasztott végponton alapuló szabályzatokat alkalmaz, fontos, hogy:
- Minden olyan döntés, amely befolyásolhatja a küldést vagy a biztonsági szabályzatok alkalmazását, az útválasztási rendszeren belül történik.
Warning
A visszamenőleges kompatibilitás érdekében a vezérlő vagy Razor a Pages végpont delegáltjának végrehajtásakor a rendszer az eddig végrehajtott kérésfeldolgozás alapján a megfelelő értékekre állítja RouteContext.RouteData be a tulajdonságokat.
A RouteContext típus elavultként lesz megjelölve egy későbbi kiadásban:
- Migrálás
RouteData.ValuesHttpRequest.RouteValues-re. - Migrálja
RouteData.DataTokensaz IDataTokensMetadata lekéréséhez a végpont metaadataiból.
Az URL-egyeztetés konfigurálható fázisokban működik. Minden fázisban a kimenet egyezések halmaza. Az egyezések halmaza a következő szakaszban tovább szűkíthető. Az útválasztási implementáció nem garantálja az egyező végpontok feldolgozási sorrendjét. Az összes lehetséges találat feldolgozása egyszerre történik. Az URL-egyeztetési fázisok a következő sorrendben történnek. ASP.NET Core:
- Feldolgozza az URL-útvonalat a végpontok és útvonalsablonjaik alapján, és összegyűjti az összes egyezést.
- A megelőző listát veszi alapul, és eltávolítja azokat az egyezéseket, amelyek nem felelnek meg az útvonal-korlátozásoknak.
- Felveszi az előző listát, és eltávolítja azokat az egyezéseket, amelyek nem felelnek meg a MatcherPolicy példányok kritériumainak.
- Az EndpointSelector elemet használja az előző lista végső döntésének meghozatalához.
A végpontok listája a következő szempontok szerint van rangsorolva:
A rendszer minden fázisban feldolgoz minden egyező végpontot, amíg el nem éri azokat EndpointSelector . A EndpointSelector az utolsó fázis. A találatok közül a legmagasabb prioritású végpontot választja ki a legjobb egyezésként. Ha vannak olyan találatok, amelyek prioritása megegyezik a legjobb egyezésével, a rendszer nem egyértelmű egyezés-kivételt ad ki.
Az útvonal elsőbbsége egy pontosabb útvonalsablon alapján van kiszámítva, amely magasabb prioritást kap. Vegyük például a sablonokat /hello és /{message}:
- Mindkettő megfelel az URL-cím elérési útjának
/hello. -
/hellopontosabb, ezért magasabb prioritású.
Általánosságban elmondható, hogy az útvonalak prioritása hatékonyan kiválasztja a gyakorlatban használt URL-sémákhoz leginkább illő találatokat. A kétértelműség elkerülése érdekében csak akkor használja Order , ha szükséges.
Az útválasztás által biztosított bővíthetőség miatt nem lehetséges, hogy az útválasztási rendszer előre kiszámítsa a nem egyértelmű útvonalakat. Vegyük például az útvonalsablonokat /{message:alpha} és /{message:int}:
- A
alphakényszer csak alfabetikus karaktereket egyezik meg. - A
intkényszer csak a számoknak felel meg. - Ezek a sablonok ugyanazt az útvonal elsőbbséget élvezik, de nincs egyetlen URL-cím, amely mindkettőnek megfelel.
- Ha az útválasztási rendszer kétértelmű hibát jelentett az indításkor, az blokkolná ezt az érvényes használati esetet.
Warning
A belső UseEndpoints műveletek sorrendje egyetlen kivétellel nem befolyásolja az útválasztás viselkedését. MapControllerRoute és MapAreaRoute automatikusan rendelési értéket rendelnek a végpontokhoz a meghívásuk sorrendje alapján. Ez a vezérlők hosszú távú viselkedését szimulálja anélkül, hogy az útválasztási rendszer ugyanazokat a garanciákat nyújtja, mint a régebbi útválasztási implementációk.
Végpont-útválasztás a ASP.NET Core-ban:
- Nem rendelkezik az útvonalak fogalmával.
- Nem biztosít rendelési garanciát. A rendszer az összes végpontot egyszerre dolgozza fel.
Útvonalsablon elsőbbsége és végpontválasztási sorrend
Az útvonalsablonok elsőbbsége egy olyan rendszer, amely minden útvonalsablonhoz hozzárendel egy értéket az adottság alapján. Útvonalsablon elsőbbsége:
- Gyakori esetekben nem szükséges módosítani a végpontok sorrendjét.
- Kísérletek az útválasztási viselkedés józan észbeli elvárásainak való megfelelésre.
Fontolja meg például a sablonokat /Products/List és a /Products/{id}. Ésszerű lenne feltételezni, hogy /Products/List jobb választás, mint /Products/{id} az URL útvonal /Products/List számára. Ez azért működik, mert a konstans szegmensnek /List jobb elsőbbsége van a paraméterszegmensnél /{id}.
A sorrend működésének részletei az útvonalsablonok definiálásának módjával vannak összekapcsolva:
- A több szegmenst tartalmazó sablonok pontosabbnak tekinthetők.
- A literális szöveggel rendelkező szegmensek pontosabbak, mint a paraméterszegmensek.
- A korlátozással rendelkező paraméterszegmensek egynél specifikusabbnak tekinthetők anélkül.
- Az összetett szegmenseket kényszerrel rendelkező paraméterszegmensnek tekintjük.
- A catch-all paraméterek a legkevésbé specifikusak. Az Útvonalsablonok szakaszban a catch-all útvonalokkal kapcsolatos fontos információkért tekintse meg a catch-all című témakört.
AZ URL-létrehozás fogalmai
URL-cím létrehozása:
- Az a folyamat, amellyel az útválasztás létrehozhat egy URL-útvonalat az útvonalértékek készlete alapján.
- Lehetővé teszi a végpontok és a hozzájuk hozzáférő URL-címek logikai elkülönítését.
A végpont útválasztása tartalmazza az API-t LinkGenerator .
LinkGenerator egy egyszeri szolgáltatás, amely a DI-től érhető el. Az LinkGenerator API a végrehajtási kérelem környezetén kívül is használható.
Az Mvc.IUrlHelper és az olyan forgatókönyvek, mint IUrlHelpera Címkesegítők, a HTML-segítők és a műveleti eredmények, az API belső használatával biztosítják a LinkGenerator hivatkozásgeneráló képességeket.
A kapcsolatgenerátort a cím - és címsémák fogalma is alátámasztja. A címséma a hivatkozásgenerálás szempontjából megfontolandó végpontok meghatározásának módja. Az útvonalnév és az útvonalértékek forgatókönyvei például sok felhasználó számára ismerősek a vezérlőkből, a Razor Pages pedig címsémaként van implementálva.
A hivatkozásgenerátor a következő bővítménymódszerekkel hivatkozhat vezérlőkre és Razor lapokra:
Ezen metódusok túlterhelései olyan argumentumokat fogadnak el, amelyek tartalmazzák a HttpContext. Ezek a módszerek funkcionálisan egyenértékűek az Url.Action és a Url.Page, de további rugalmasságot és lehetőségeket kínálnak.
A GetPath* metódusok leginkább a Url.Action és Url.Page metódusokhoz hasonlítanak, mivel abszolút elérési utat tartalmazó URI-t hoznak létre. A GetUri* metódusok mindig egy sémát és kiszolgálót tartalmazó abszolút URI-t hoznak létre. Azok a metódusok, amelyek elfogadnak egy HttpContext-t, URI-t generálnak a végrehajtás alatt álló kérés kontextusában. A környezeti útvonalértékek, az URL alapelérési út, a séma és a gazdagép a végrehajtott kérelemből kerülnek felhasználásra, kivéve, ha felülbírálják őket.
LinkGenerator egy címmel kerül meghívásra. Az URI létrehozása két lépésben történik:
- Egy cím a címnek megfelelő végpontok listájához van kötve.
- Az egyes végpontok RoutePattern kiértékelése addig történik, amíg a megadott értékeknek megfelelő útvonalminta nem található. Az eredményül kapott kimenetet a hivatkozásgenerátorhoz megadott többi URI-résszel kombinálják, és visszaadják.
A LinkGenerator által biztosított metódusok támogatják a szabványos hivatkozáslétrehozási képességeket bármilyen címtípus esetén. A hivatkozásgenerátor használatának legkényelmesebb módja egy adott címtípus műveleteit végrehajtó bővítménymetelyek:
| Bővítménymetódus | Description |
|---|---|
| GetPathByAddress | A megadott értékek alapján abszolút elérési úttal rendelkező URI-t hoz létre. |
| GetUriByAddress | Abszolút URI-t hoz létre a megadott értékek alapján. |
Warning
Ügyeljen a hívási LinkGenerator módszerek alábbi következményeire:
Olyan alkalmazáskonfigurációkban körültekintően használjon
GetUri*bővítménymetelyeket, amelyek nem ellenőrzik aHostbejövő kérések fejlécét. Ha aHostbejövő kérések fejléce nincs érvényesítve, a nem megbízható kérések bemenete visszaküldhető az ügyfélnek egy nézetben vagy lapon lévő URI-kban. Javasoljuk, hogy minden éles alkalmazás konfigurálja a kiszolgálót aHostfejléc ismert érvényes értékekkel való ellenőrzésére.Óvatosan használja a LinkGenerator-t köztes rétegekben, különösen a
Map-el vagyMapWhen-el együtt.Map*módosítja a végrehajtási kérelem alap elérési útját, ami hatással van a hivatkozásgenerálás kimenetére. Az összes API lehetővé teszi egy LinkGenerator alap elérési út megadását. Adjon meg egy üres alap elérési utat a kapcsolatgenerálás hatásánakMap*visszavonásához.
Middleware-példa
A következő példában egy köztes szoftver az LinkGenerator API használatával hoz létre egy hivatkozást egy olyan műveletmetódusra, amely felsorolja a termékeket. A hivatkozásgenerátor használata az osztályba való injektálással és hívással GenerateLink az alkalmazás bármely osztálya számára elérhető:
public class ProductsMiddleware
{
private readonly LinkGenerator _linkGenerator;
public ProductsMiddleware(RequestDelegate next, LinkGenerator linkGenerator) =>
_linkGenerator = linkGenerator;
public async Task InvokeAsync(HttpContext httpContext)
{
httpContext.Response.ContentType = MediaTypeNames.Text.Plain;
var productsPath = _linkGenerator.GetPathByAction("Products", "Store");
await httpContext.Response.WriteAsync(
$"Go to {productsPath} to see our products.");
}
}
Útvonalsablonok
A tokenek {} definiálják az útvonalparamétereket, amelyek akkor vannak megkötve, ha az útvonal megfelel. Egy útvonalszakaszban több útvonalparaméter is definiálható, de az útvonalparamétereket literális értékkel kell elválasztani. Például:
{controller=Home}{action=Index}
nem érvényes útvonal, mert nincs szó szerinti érték {controller} és {action} között. Az útvonalparamétereknek névvel kell rendelkezniük, és további attribútumokkal is rendelkezniük kell.
Az útvonalparamétereken (például {id}) és az elérési útelválasztón / kívüli literális szövegnek meg kell egyeznie az URL-címben szereplő szövegekkel. A szövegegyeztetés kis- és nagybetűkre nem érzékeny, és az URL-cím elérési útjának dekódolt ábrázolása alapján történik. Ha egy literális útvonalparaméter elválasztójelével { szeretne megegyezni, vagy }a karakter ismétlésével lépjen ki a határolóból. Például {{ vagy }}.
Csillag * vagy dupla csillag **:
- Az útvonalparaméter előtagjaként használható az URI többi részéhez való kötéshez.
- Az úgynevezett catch-all paraméterek. Például
blog/{**slug}:- Megfelel minden olyan URI-nak, amely a kezdőértékkel
blog/kezdődik, és bármilyen értéket követ. - Az alábbi
blog/érték hozzá van rendelve a slug route értékhez.
- Megfelel minden olyan URI-nak, amely a kezdőértékkel
Warning
A catch-all paraméter helytelenül felelhet meg az útvonalaknak egy útválasztási hiba miatt. A hiba által érintett alkalmazások jellemzői a következők:
- Egy mindent megragadó útvonal, például:
{**slug}" - A catch-all útvonal nem egyezik meg azokkal a kérésekkel, amelyeket meg kellene egyeznie.
- Ha eltávolít más útvonalakat, az összeset megfogó útvonal elkezd működni.
Tekintse meg a GitHub 18677 és 16579 hibáit a példaesetekért, amelyekben ez a hiba felmerül.
A hiba jóváhagyási javítása a .NET Core 3.1.301-ben vagy újabb SDK-ban található. A következő kód beállít egy belső kapcsolót, amely megoldja ezt a hibát:
public static void Main(string[] args)
{
AppContext.SetSwitch("Microsoft.AspNetCore.Routing.UseCorrectCatchAllBehavior",
true);
CreateHostBuilder(args).Build().Run();
}
// Remaining code removed for brevity.
Az általános paraméterek az üres sztringgel is egyezhetnek.
A catch-all paraméter kikerüli a megfelelő karaktereket, amikor az útvonal egy URL-cím létrehozásához van használva, beleértve az elérésiút-elválasztó / karaktereket is. Például a(z) foo/{*path} útvonalértékekkel rendelkező { path = "my/path" } útvonal generál foo/my%2Fpath. Figyelje meg a szökött perjelet. Az útvonal elválasztó karakterek körjáratbeli kezeléséhez használja az ** útvonalparaméter előtagot. Az foo/{**path} útvonal { path = "my/path" }foo/my/path generál.
További szempontokat is figyelembe kell vennie azoknak az URL-mintáknak, amelyek megkísérlik rögzíteni a fájlnevet egy opcionális fájlkiterjesztéssel. Vegyük például a sablont files/{filename}.{ext?}. Ha van érték mindkettő filename és ext számára, mindkettő ki lesz töltve. Ha az URL-címben csak egy érték filename szerepel, az útvonal megfelel, mert a végén a . opcionális. Az alábbi URL-címek egyeznek az útvonalon:
/files/myFile.txt/files/myFile
Előfordulhat, hogy az útvonalparaméterek alapértelmezett értékei úgy vannak meghatározva, hogy a paraméter neve után egy egyenlőségjel (=) választja el az alapértelmezett értéket. Például {controller=Home} úgy határozza meg Home-et, mint az alapértelmezett értéket controller számára. Az alapértelmezett érték akkor használatos, ha a paraméter URL-címében nincs érték. Az útvonalparaméterek megadása nem kötelező, ha hozzáfűz egy kérdőjelet (?) a paraméternév végéhez. Például: id?. A választható értékek és az alapértelmezett útvonalparaméterek közötti különbség a következő:
- Az alapértelmezett értékkel rendelkező útvonalparaméterek mindig létrehoznak egy értéket.
- Az opcionális paraméterek csak akkor tartalmazhatnak értéket, ha a kérelem URL-címe megad egy értéket.
Az útvonalparaméterek olyan korlátozásokkal rendelkezhetnek, amelyeknek meg kell felelniük az URL-címhez kötött útvonalértéknek. Az útvonalparaméter neve után a : és a feltétel neve hozzáadása egy útvonalparaméter beágyazott feltételét határozza meg. Ha a kényszer argumentumokat igényel, zárójelek (...) közé kerülnek a kényszer neve után. Egy másik és egy kényszernév hozzáfűzésével több : is megadható.
A kényszer nevét és argumentumait a rendszer átadja a IInlineConstraintResolver szolgáltatásnak, hogy létrehozhasson egy, az URL-feldolgozásban használandó példányt IRouteConstraint . Az útvonalsablon blog/{article:minlength(10)} például egy korlátozást minlength határoz meg az argumentummal 10. Az útvonalkorlátozásokról és a keretrendszer által biztosított korlátozásokról további információt az Útvonalkorlátozások szakaszban talál.
Az útvonalparaméterek paraméterátalakítókkal is rendelkezhetnek. A paraméterátalakítók átalakítják egy paraméter értékét, amikor hivatkozásokat és egyező műveleteket és oldalakat hoznak létre URL-címekhez. A kényszerekhez hasonlóan a paraméterátalakítók is hozzáadhatók az útvonalparaméteren belül azáltal, hogy a paraméternév után hozzáadnak egy '/' jelet és a transzformátornevet. Az útvonalsablon blog/{article:slugify} például egy transzformátort slugify határoz meg. A paraméterátalakítókkal kapcsolatos további információkért tekintse meg a Paraméterátalakítók szakaszt.
Az alábbi táblázat a példaútvonalak sablonjait és viselkedését mutatja be:
| Útvonalsablon | Példa egyező URI-ra | A kérelem URI-ja... |
|---|---|---|
hello |
/hello |
Csak az egyetlen elérési út /hellofelel meg. |
{Page=Home} |
/ |
Egyezések és halmazok Page a következőre Home: . |
{Page=Home} |
/Contact |
Egyezések és halmazok Page a következőre Contact: . |
{controller}/{action}/{id?} |
/Products/List |
Megfelelteti a Products vezérlőt és a List műveletet. |
{controller}/{action}/{id?} |
/Products/Details/123 |
A Products vezérlőnek és a Details műveletnek felel meg, amelynél id 123-ra van állítva. |
{controller=Home}/{action=Index}/{id?} |
/ |
Leképezi a Home vezérlőt és a Index metódust. A id figyelmen kívül van hagyva. |
{controller=Home}/{action=Index}/{id?} |
/Products |
Leképezi a Products vezérlőt és a Index metódust. A id figyelmen kívül van hagyva. |
Általában a sablon használata a legegyszerűbb útválasztási módszer. Az útvonalsablonon kívül is megadhat kényszereket és alapértelmezett értékeket.
Összetett szegmensek
Az összetett szegmensek feldolgozása a literális elválasztójelek jobbról balra történő egyeztetésével történik , nem mohó módon. Például [Route("/a{b}c{d}")] egy összetett szegmens.
Az összetett szegmensek olyan módon működnek, amelyet meg kell érteni a sikeres használatukhoz. Az ebben a szakaszban található példa bemutatja, hogy az összetett szegmensek miért működnek igazán jól, ha az elválasztó szöveg nem jelenik meg a paraméterértékeken belül. Összetettebb esetekben regexet kell használni, majd manuálisan kinyerni az értékeket.
Warning
Amikor a System.Text.RegularExpressions-t használja nem megbízható bemenetek feldolgozására, meg kell adnia egy időtúllépési értéket. Egy rosszindulatú felhasználó adhat RegularExpressions bemenetet, ami szolgáltatásmegtagadásos támadást okozhat. ASP.NET Core keretrendszer API-k, amelyek RegularExpressions időtúllépést használnak.
Ez egy összefoglaló az /a{b}c{d} sablon és a /abcd URL-útvonal esetén végzett útválasztási lépésekről. Ez | segít az algoritmus működésének vizualizációjában:
- Az első literál, jobbról balra, az
c. Így/abcdkeres jobbról balra, és megtalálja/ab|c|d. - A jobb oldalon (
d) lévő összes elem megfelel az útvonalparaméternek{d}. - A következő karakter, jobbról balra, az
a. Így/ab|c|dkeresésével ott folytatjuk, ahol abbahagytuk, majdamegtalálható/|a|b|c|d. - A jobb oldali (
b) érték most már megfelel az útvonalparaméternek{b}. - Nincs fennmaradó szöveg és nincs fennmaradó útvonalsablon, így ez megfelelésnek számít.
Íme egy példa egy negatív esetre, amely ugyanazt a sablont /a{b}c{d} és az URL-címet /aabcdhasználja. Ez | segít az algoritmus működésének vizualizációjában. Ez az eset nem egyezik, amit ugyanaz az algoritmus magyaráz meg.
- Az első literál, jobbról balra, az
c. Így/aabcdkeres jobbról balra, és megtalálja/aab|c|d. - A jobb oldalon (
d) lévő összes elem megfelel az útvonalparaméternek{d}. - A következő karakter, jobbról balra, az
a. Így/aab|c|dkeresésével ott folytatjuk, ahol abbahagytuk, majdamegtalálható/a|a|b|c|d. - A jobb oldali (
b) érték most már megfelel az útvonalparaméternek{b}. - Ezen a ponton még van szöveg
a, de az algoritmus elfogyott az elemzésre használt útvonalsablonból, így ez nem egyezik.
Mivel a megfelelő algoritmus nem kapzsi:
- Ez megfelel az egyes lépésekben lehetséges legkisebb szövegmennyiségnek.
- Ha az elválasztó érték a paraméterértékek között jelenik meg, az eredmény nem egyezik.
A reguláris kifejezések sokkal jobban szabályozhatják az egyező viselkedésüket.
Mohó illesztés, más néven maximális illesztés, megpróbálja megtalálni a bemeneti szövegben a regex mintát kielégítő lehető leghosszabb egyezést. A nem mohó egyeztetés, más néven lusta egyeztetés a regex mintát kielégítő bemeneti szövegben a lehető legrövidebb egyezést keresi.
Útválasztás speciális karakterekkel
A speciális karaktereket tartalmazó útválasztás váratlan eredményekhez vezethet. Vegyük például az alábbi műveletmetódusú vezérlőt:
[HttpGet("{id?}/name")]
public async Task<ActionResult<string>> GetName(string id)
{
var todoItem = await _context.TodoItems.FindAsync(id);
if (todoItem == null || todoItem.Name == null)
{
return NotFound();
}
return todoItem.Name;
}
Ha string id a következő kódolt értékeket tartalmazza, váratlan eredmények léphetnek fel:
| ASCII | Encoded |
|---|---|
/ |
%2F |
|
+ |
Az útvonalparaméterek nem mindig vannak dekódolva az URL-ből. Ez a probléma a jövőben megoldható. További információkért tekintse meg ezt a GitHub-problémát;
Útvonalkorlátozások
Az útvonalkorlátozások akkor lépnek érvénybe, amikor egyezés történt a bejövő URL-címhez, és az URL-elérési út tokenizálva van útvonalértékekké. Az útvonalkorlátozások általában ellenőrzik az útvonalsablonon keresztül társított útvonalértéket, és valós vagy hamis döntést hoznak arról, hogy az érték elfogadható-e. Egyes útvonalkorlátozások az útvonalértéken kívüli adatokat használnak annak megfontolására, hogy a kérés irányítható-e. A http-ige alapján például HttpMethodRouteConstraint elfogadhat vagy elutasíthat egy kérést. A korlátozások az útválasztási kérelmekben és a csatolások generálásában használatosak.
Warning
Ne használjon korlátozásokat a bemeneti ellenőrzéshez. Ha bemeneti érvényesítéshez kényszereket használnak, érvénytelen bemenet esetén "Nem található" választ kapunk 404. Az érvénytelen bemenetnek egy Bad Request 400 kell létrehoznia a megfelelő hibaüzenettel. Az útvonalkorlátozások a hasonló útvonalak egyértelműsítésére szolgálnak, nem pedig egy adott útvonal bemeneteinek ellenőrzésére.
Az alábbi táblázat az alapértelmezett útvonalkorlátozásokat és azok várható viselkedését mutatja be:
| korlátozás | Example | Példa egyezések | Notes |
|---|---|---|---|
int |
{id:int} |
123456789, -123456789 |
Bármely egész számnak megfelel |
bool |
{active:bool} |
true, FALSE |
Egyezések true vagy false. Case-insensitive |
datetime |
{dob:datetime} |
2016-12-31, 2016-12-31 7:32pm |
Megfelel az invariáns kultúra érvényes DateTime értékének. Lásd az előző figyelmeztetést |
decimal |
{price:decimal} |
49.99, -1,000.01 |
Megfelel az invariáns kultúra érvényes decimal értékének. Lásd az előző figyelmeztetést |
double |
{weight:double} |
1.234, -1,001.01e8 |
Megfelel az invariáns kultúra érvényes double értékének. Lásd az előző figyelmeztetést |
float |
{weight:float} |
1.234, -1,001.01e8 |
Megfelel az invariáns kultúra érvényes float értékének. Lásd az előző figyelmeztetést |
guid |
{id:guid} |
CD2C1638-1638-72D5-1638-DEADBEEF1638 |
Érvényes Guid érték egyező |
long |
{ticks:long} |
123456789, -123456789 |
Érvényes long érték egyező |
minlength(value) |
{username:minlength(4)} |
Rick |
A karakterláncnak legalább 4 karakter hosszúnak kell lennie. |
maxlength(value) |
{filename:maxlength(8)} |
MyFile |
A sztring legfeljebb 8 karakter hosszúságú lehet |
length(length) |
{filename:length(12)} |
somefile.txt |
A sztringnek pontosan 12 karakter hosszúnak kell lennie |
length(min,max) |
{filename:length(8,16)} |
somefile.txt |
A sztringnek legalább 8 és legfeljebb 16 karakter hosszúnak kell lennie |
min(value) |
{age:min(18)} |
19 |
Az egész szám értékének legalább 18-nak kell lennie |
max(value) |
{age:max(120)} |
91 |
Az egész szám értéke legfeljebb 120 lehet |
range(min,max) |
{age:range(18,120)} |
91 |
Az egész szám értéke legalább 18, de legfeljebb 120 lehet |
alpha |
{name:alpha} |
Rick |
A sztringnek egy vagy több betűből a-z kell állnia, és nem tesz különbséget a kis- és nagybetűk között. |
regex(expression) |
{ssn:regex(^\\d{{3}}-\\d{{2}}-\\d{{4}}$)} |
123-45-6789 |
A karakterláncnak meg kell egyeznie a reguláris kifejezéssel. Tippek a reguláris kifejezések definiálásáról |
required |
{name:required} |
Rick |
Arra szolgál, hogy kényszerítse, hogy egy nem paraméteres érték jelen legyen az URL-cím létrehozása során |
file |
{filename:file} |
myfile.txt |
A sztring tartalmazhat elérési utakat, de az utolsó szegmensnek ponttal (.) kell rendelkeznie, és egy vagy több nem pont karakternek kell követnie |
nonfile |
{page:nonfile} |
PageName |
A string utolsó elérési útszakaszában nem lehet pont, amelyet egy vagy több nem pont (.) karakter követ. |
Warning
Amikor a System.Text.RegularExpressions-t használja nem megbízható bemenetek feldolgozására, meg kell adnia egy időtúllépési értéket. Egy rosszindulatú felhasználó adhat RegularExpressions bemenetet, ami szolgáltatásmegtagadásos támadást okozhat. ASP.NET Core keretrendszer API-k, amelyek RegularExpressions időtúllépést használnak.
Egy paraméterre több, kettőspontra tagolt korlátozás alkalmazható. A következő korlátozás például egy paramétert 1 vagy annál nagyobb egész számra korlátozza:
[Route("users/{id:int:min(1)}")]
public User GetUserById(int id) { }
Warning
Az URL-címet ellenőrző és CLR-típussá konvertált útvonalkorlátozások mindig az invariáns kultúrát használják. Például a CLR típus int vagy DateTime. Ezek a korlátozások feltételezik, hogy az URL-cím nem honosítható. A keretrendszer által biztosított útvonalkorlátozások nem módosítják az útvonalértékekben tárolt értékeket. Az URL-címből elemezett útvonalértékek sztringekként vannak tárolva. A kényszer például float megkísérli lebegőpontossá alakítani az útvonal értékét, de a konvertált érték csak annak ellenőrzésére szolgál, hogy az lebegőpontossá alakítható-e.
Reguláris kifejezések alkalmazása kényszerekben
Warning
Amikor a System.Text.RegularExpressions-t használja nem megbízható bemenetek feldolgozására, meg kell adnia egy időtúllépési értéket. Egy rosszindulatú felhasználó adhat RegularExpressions bemenetet, ami szolgáltatásmegtagadásos támadást okozhat. ASP.NET Core keretrendszer API-k, amelyek RegularExpressions időtúllépést használnak.
A reguláris kifejezések az útvonal-korlátozással regex(...) beágyazott kényszerként is megadhatóak. A MapControllerRoute család metódusai egy korlátozások objektumkonstansát is elfogadják. Ha ezt az űrlapot használja, a sztringértékeket a rendszer normál kifejezésként értelmezi.
A következő kód beágyazott regex kényszert használ:
app.MapGet("{message:regex(^\\d{{3}}-\\d{{2}}-\\d{{4}}$)}",
() => "Inline Regex Constraint Matched");
Az alábbi kód egy objektumkonstanst használ a regex kényszer megadásához:
app.MapControllerRoute(
name: "people",
pattern: "people/{ssn}",
constraints: new { ssn = "^\\d{3}-\\d{2}-\\d{4}$", },
defaults: new { controller = "People", action = "List" });
A ASP.NET Core-keretrendszer hozzáadja RegexOptions.IgnoreCase | RegexOptions.Compiled | RegexOptions.CultureInvariant a reguláris kifejezéskonstruktort. A tagok leírását itt tekinti meg RegexOptions .
A reguláris kifejezések az útválasztás és a C# nyelv által használthoz hasonló határolókat és mintákat használnak. A reguláris kifejezés elemeit escape-elve kell használni. Ha a reguláris kifejezést ^\d{3}-\d{2}-\d{4}$ beágyazott kényszerben szeretné használni, használja az alábbiak egyikét:
- Cserélje le
\a sztringben megadott karaktereket a C#-forrásfájlban szereplő karakterekre\\, hogy elkerülje a sztring-feloldó\karaktert. - Szó szerinti karakterlánckonstansok.
Az útvonal-paraméterek elválasztó karaktereinek, mint például a {, }, [, ], kifejezésben történő megduplázásával megszabadulhatunk, például {{, }}, [[, ]]. Az alábbi táblázat egy reguláris kifejezést és annak szökött verzióját mutatja be:
| Reguláris kifejezés | Megmenekült reguláris kifejezés |
|---|---|
^\d{3}-\d{2}-\d{4}$ |
^\\d{{3}}-\\d{{2}}-\\d{{4}}$ |
^[a-z]{2}$ |
^[[a-z]]{{2}}$ |
Az útválasztás során használt reguláris kifejezések gyakran a ^ karakterrel kezdődnek, és megfelelnek a sztring kezdőpozíciójának. A kifejezések gyakran a $ karakterrel végződnek, és illeszkednek a karaktersor végéhez. A ^ karakterek és $ a karakterek biztosítják, hogy a reguláris kifejezés megegyezik a teljes útvonalparaméter értékével. A ^ és $ karakterek nélkül a reguláris kifejezés bármelyik részsztringgel egyezik meg a sztringen belül, ami gyakran nem kívánatos. Az alábbi táblázat példákat tartalmaz, és elmagyarázza, hogy miért egyeznek vagy miért nem egyeznek:
| Expression | String | Match | Comment |
|---|---|---|---|
[a-z]{2} |
hello | Yes | Részszűrési egyezések |
[a-z]{2} |
123abc456 | Yes | Részszűrési egyezések |
[a-z]{2} |
mz | Yes | Kifejezés egyezése |
[a-z]{2} |
MZ | Yes | Nem érzékeny a kis- és nagybetűkre |
^[a-z]{2}$ |
hello | No | Lásd ^ és $ fent |
^[a-z]{2}$ |
123abc456 | No | Lásd ^ és $ fent |
A reguláris kifejezésszintaxissal kapcsolatos további információkért lásd a .NET-keretrendszer reguláris kifejezéseit.
Ha egy paramétert egy ismert lehetséges értékkészletre szeretne korlátozni, használjon egy reguláris kifejezést. Például {action:regex(^(list|get|create)$)} csak a action következő útvonalértéknek felel meglist: , vagy .getcreate Ha a kényszerszótárba kerül, a sztring ^(list|get|create)$ egyenértékű. A kényszerek szótárában megadott, az ismert kényszerek egyikével nem egyező kényszereket a rendszer normál kifejezésként is kezeli. A sablonon belül átadott, az ismert megkötések egyikével nem egyező kényszereket a rendszer nem kezeli normál kifejezésként.
Egyéni útvonalkorlátozások
Az interfész implementálásával IRouteConstraint egyéni útvonalkorlátozások hozhatók létre. Az IRouteConstraint interfész tartalmaz Match, amely akkor ad vissza true , ha a korlátozás teljesül, és false egyébként.
Ritkán van szükség egyéni útvonalkorlátozásokra. Egyéni útvonalkorlátozás implementálása előtt fontolja meg az alternatív megoldásokat, például a modellkötést.
A ASP.NET Alapvető korlátozások mappa jó példákat kínál a korlátozások létrehozására. Például GuidRouteConstraint.
Egyéni IRouteConstraintbeállítás használatához az útvonalkorlátozás típusát regisztrálni kell az alkalmazás szolgáltatástárolójában ConstraintMap . Egy ConstraintMap egy szótár, amely az útvonalkényszer kulcsokat olyan IRouteConstraint implementációkhoz rendeli, amelyek érvényesítik ezeket a kényszereket. Alkalmazás ConstraintMap-t frissíthetünk Program.cs, akár egy AddRouting hívás részeként, akár közvetlenül RouteOptions konfigurálásával builder.Services.Configure<RouteOptions>. Például:
builder.Services.AddRouting(options =>
options.ConstraintMap.Add("noZeroes", typeof(NoZeroesRouteConstraint)));
Az előző korlátozás a következő kódban van alkalmazva:
[ApiController]
[Route("api/[controller]")]
public class NoZeroesController : ControllerBase
{
[HttpGet("{id:noZeroes}")]
public IActionResult Get(string id) =>
Content(id);
}
Az NoZeroesRouteConstraint megvalósítása megakadályozza, hogy a 0 egy útvonalparaméterben legyen használva.
public class NoZeroesRouteConstraint : IRouteConstraint
{
private static readonly Regex _regex = new(
@"^[1-9]*$",
RegexOptions.CultureInvariant | RegexOptions.IgnoreCase,
TimeSpan.FromMilliseconds(100));
public bool Match(
HttpContext? httpContext, IRouter? route, string routeKey,
RouteValueDictionary values, RouteDirection routeDirection)
{
if (!values.TryGetValue(routeKey, out var routeValue))
{
return false;
}
var routeValueString = Convert.ToString(routeValue, CultureInfo.InvariantCulture);
if (routeValueString is null)
{
return false;
}
return _regex.IsMatch(routeValueString);
}
}
Warning
Amikor a System.Text.RegularExpressions-t használja nem megbízható bemenetek feldolgozására, meg kell adnia egy időtúllépési értéket. Egy rosszindulatú felhasználó adhat RegularExpressions bemenetet, ami szolgáltatásmegtagadásos támadást okozhat. ASP.NET Core keretrendszer API-k, amelyek RegularExpressions időtúllépést használnak.
Az előző kód:
- Megakadályozza
0az{id}útvonal szegmensét. - Látható, hogy egy egyszerű példát mutat be egy egyéni korlátozás implementálására. Éles alkalmazásban nem használható.
Az alábbi kód jobb módszer arra, hogy megakadályozza a id-t tartalmazó 0 feldolgozását.
[HttpGet("{id}")]
public IActionResult Get(string id)
{
if (id.Contains('0'))
{
return StatusCode(StatusCodes.Status406NotAcceptable);
}
return Content(id);
}
Az előző kód a következő előnyökkel rendelkezik a NoZeroesRouteConstraint megközelítéssel szemben:
- Nem igényel egyéni korlátozást.
- Leíróbb hibát ad vissza, ha az útvonalparaméter tartalmazza
0.
Paraméter-átalakítók
Paramétertranszformátorok:
- Hajtson végre egy műveletet a hivatkozás létrehozásához a LinkGenerator használatával.
- Implementálás Microsoft.AspNetCore.Routing.IOutboundParameterTransformer.
- A(z) ConstraintMap használatával konfigurálható.
- Vegye át a paraméter útvonalértékét, és alakítsa át egy új sztringértékké.
- Ennek eredménye az átalakított érték használata a létrehozott hivatkozásban.
Például egy egyéni slugify paraméter-transzformátor az útvonalmintában blog\{article:slugify} a generált adatokkal Url.Action(new { article = "MyTestArticle" })blog\my-test-article.
Fontolja meg a következő IOutboundParameterTransformer megvalósítást:
public class SlugifyParameterTransformer : IOutboundParameterTransformer
{
public string? TransformOutbound(object? value)
{
if (value is null)
{
return null;
}
return Regex.Replace(
value.ToString()!,
"([a-z])([A-Z])",
"$1-$2",
RegexOptions.CultureInvariant,
TimeSpan.FromMilliseconds(100))
.ToLowerInvariant();
}
}
Ha paraméterátalakítót szeretne használni egy útvonalmintában, konfigurálja a következővel ConstraintMapProgram.cs:
builder.Services.AddRouting(options =>
options.ConstraintMap["slugify"] = typeof(SlugifyParameterTransformer));
Az ASP.NET Core keretrendszer paraméterátalakítókat használ, hogy átalakítsa az URI-t a végpont feloldása során. A paraméterátalakítók például átalakítják az útvonal értékeit, amelyeket a area, controller, action és page összepárosítására használnak.
app.MapControllerRoute(
name: "default",
pattern: "{controller:slugify=Home}/{action:slugify=Index}/{id?}");
Az előző útvonalsablon esetén a művelet SubscriptionManagementController.GetAll megfelel az URI-nak /subscription-management/get-all. A paraméter-átalakító nem módosítja a hivatkozás létrehozásához használt útvonalértékeket. Például a Url.Action("GetAll", "SubscriptionManagement") kimenetet ad /subscription-management/get-all.
ASP.NET Core API-konvenciókat biztosít a paraméterátalakítók generált útvonalakkal való használatához:
- Az Microsoft.AspNetCore.Mvc.ApplicationModels.RouteTokenTransformerConvention MVC-konvenció egy megadott paraméterátalakítót alkalmaz az alkalmazás összes attribútumútvonalára. A paraméter-transzformátor átalakítja az attribútumat útvonalának jogkivonatait, amikor lecserélésre kerülnek. További információért lásd: Paraméterátalakító használata a tokencserék testreszabására.
- Razor A Pages az API-konvenciót PageRouteTransformerConvention használja. Ez az egyezmény egy megadott paraméterátalakítót alkalmaz az összes automatikusan felderített Razor lapra. A paraméter-átalakító átalakítja a Pages-útvonalak mappa- és fájlnév-szegmenseit Razor . További információ: Oldalútvonalak testreszabása paraméterátalakítóval.
URL-létrehozási referencia
Ez a szakasz az URL-generálás által implementált algoritmusra mutató hivatkozást tartalmaz. A gyakorlatban az URL-létrehozás legösszetettebb példái vezérlőket vagy Razor oldalakat használnak. További információkért tekintse meg az útválasztást a vezérlőkben .
Az URL-létrehozási folyamat egy hívással LinkGenerator.GetPathByAddress vagy egy hasonló módszerrel kezdődik. A metódus címmel, útvonalértékekkel és opcionálisan az aktuális kéréssel HttpContextkapcsolatos információkkal rendelkezik.
Az első lépés az, hogy a cím segítségével, a cím típusának megfelelő IEndpointAddressScheme<TAddress> alkalmazásával megold egy jelölt végpontkészletet.
Miután a címséma megtalálta a jelölteket, a végpontok iteratív módon lesznek rendezve és feldolgozva, amíg egy URL-létrehozási művelet sikeres nem lesz. Az URL-generálás nem ellenőrzi a kétértelműségeket, az első eredmény a végeredmény.
URL-létrehozás hibaelhárítása naplózással
Az URL-létrehozás hibaelhárításának első lépése a naplózási szint Microsoft.AspNetCore.RoutingTRACE beállítása.
LinkGenerator a feldolgozással kapcsolatos számos részletet naplóz, amelyek hasznosak lehetnek a problémák elhárításához.
Az URL-címgenerálással kapcsolatos részletekért tekintse meg az URL-létrehozási referenciát .
Addresses
A címek az URL-generálás azon koncepciója, amellyel a hívásokat a hivatkozásgenerátorhoz kötik a jelölt végpontok halmazához.
A címek egy bővíthető fogalom, amely alapértelmezés szerint két implementációval rendelkezik:
-
Végpontnév (
string) használata címként:- Hasonló funkciókat biztosít az MVC útvonalnevéhez.
- IEndpointNameMetadata A metaadatok típusát használja.
- Feloldja a megadott sztringet az összes regisztrált végpont metaadataival.
- Kivételt jelez az indításkor, ha több végpont ugyanazt a nevet használja.
- Az általános célú használat a vezérlőkön és Razor lapokon kívül ajánlott.
-
Útvonalértékek (RouteValuesAddress) használata címként:
- Hasonló funkciókat biztosít a vezérlőkhöz és az örökölt Pages URL-címek generálásához.
- Nagyon összetett a bővítéshez és a hibakereséshez.
- Biztosítja az implementációt, amelyet a
IUrlHelperTag Helper-ek, a HTML-segítők, a műveleti eredmények stb. használják.
A címséma szerepe, hogy a cím és az egyező végpontok közötti társítás tetszőleges feltételek szerint történik:
- A végpontnévséma alapszintű szótárkeresést hajt végre.
- Az útvonalértékek sémája a beállítási algoritmus összetett legjobb részhalmazával rendelkezik.
Környezeti értékek és explicit értékek
Az aktuális kérésből az útválasztás az aktuális kérés HttpContext.Request.RouteValuesútvonalértékeit éri el. Az aktuális kéréshez társított értékeket környezeti értékeknek nevezzük. Az egyértelműség kedvéért a dokumentáció a metódusoknak átadott útvonalértékekre hivatkozik explicit értékekként.
Az alábbi példa környezeti értékeket és explicit értékeket mutat be. Környezeti értékeket biztosít az aktuális kérésből és explicit értékekből:
public class WidgetController : ControllerBase
{
private readonly LinkGenerator _linkGenerator;
public WidgetController(LinkGenerator linkGenerator) =>
_linkGenerator = linkGenerator;
public IActionResult Index()
{
var indexPath = _linkGenerator.GetPathByAction(
HttpContext, values: new { id = 17 })!;
return Content(indexPath);
}
// ...
Az előző kód:
- Visszatér
/Widget/Index/17 - Meghajtást kap LinkGenerator által.
A következő kód csak explicit értékeket és nem tartalmaz környezeti értékeket:
var subscribePath = _linkGenerator.GetPathByAction(
"Subscribe", "Home", new { id = 17 })!;
Az előző metódus visszaadja /Home/Subscribe/17
A WidgetController a következőt adja vissza: /Widget/Subscribe/17
var subscribePath = _linkGenerator.GetPathByAction(
HttpContext, "Subscribe", null, new { id = 17 });
A következő kód az aktuális kérelem környezeti értékeiből és explicit értékekből biztosítja a vezérlőt:
public class GadgetController : ControllerBase
{
public IActionResult Index() =>
Content(Url.Action("Edit", new { id = 17 })!);
}
Az előző kódban:
-
/Gadget/Edit/17vissza lesz adva. - Url lekéri a IUrlHelper.
-
Action Egy műveletmetódus abszolút elérési útját tartalmazó URL-címet hoz létre. Az URL-cím a megadott
actionnevet ésrouteértékeket tartalmazza.
Az alábbi kód az aktuális kérelem környezeti értékeit és explicit értékeit tartalmazza:
public class IndexModel : PageModel
{
public void OnGet()
{
var editUrl = Url.Page("./Edit", new { id = 17 });
// ...
}
}
Az előző kód beállítja a url értékét /Edit/17-re, ha a Lap szerkesztése Razor oldal az alábbi oldalirányelvet tartalmazza:
@page "{id:int}"
Ha a Szerkesztés lap nem tartalmazza az "{id:int}" útvonalsablont, akkor url a következő: /Edit?id=17.
Az MVC viselkedése IUrlHelper összetettségi réteget ad hozzá az itt leírt szabályok mellett:
-
IUrlHelpermindig környezeti értékként adja meg az aktuális kérés útvonalértékeit. -
Az IUrlHelper.Action mindig explicit értékként másolja át az aktuális
actionéscontrollerútvonalértékeket, kivéve, ha a fejlesztő felülírja. -
IUrlHelper.Page az aktuális
pageútvonalértéket mindig explicit értékként másolja, kivéve, ha felül van bírálva. -
IUrlHelper.Pagemindig explicit értékként felülbírálja az aktuálishandlerútvonal értékétnullhacsak nincs felülírva.
A felhasználókat gyakran meglepik a környezeti értékek viselkedési részletei, mert úgy tűnik, hogy az MVC nem követi a saját szabályait. Előzmény- és kompatibilitási okokból bizonyos útvonalértékek, például action, controller, pageés handler saját speciális eseti viselkedésük van.
A LinkGenerator.GetPathByAction és LinkGenerator.GetPathByPage által biztosított egyenértékű funkcionalitás a IUrlHelper ezen anomáliáit duplikálja a kompatibilitás érdekében.
URL-létrehozási folyamat
A jelölt végpontok készletének megtalálása után az URL-generáló algoritmus:
- Iteratív módon dolgozza fel a végpontokat.
- Az első sikeres eredményt adja vissza.
A folyamat első lépése az útvonalérték érvénytelenítése. Az útvonalérték érvénytelenítése az a folyamat, amellyel az útválasztás dönti el, hogy a környezeti értékekből melyik útvonalértékeket kell használni, és melyeket figyelmen kívül kell hagyni. A rendszer minden környezeti értéket figyelembe vesz, és kombinálja az explicit értékekkel, vagy figyelmen kívül hagyja.
A környezeti értékek szerepét úgy lehet a legjobban értelmezni, hogy azok célja az alkalmazásfejlesztők gépelési munkájának csökkentése néhány gyakori esetben. Hagyományosan az MVC-hez kapcsolódó forgatókönyvek, amelyekben a környezeti értékek hasznosak:
- Ha ugyanabban a vezérlőben egy másik művelethez kapcsolódik, a vezérlő nevét nem kell megadni.
- Ha ugyanazon a területen egy másik vezérlőhöz kapcsolódik, a terület nevét nem kell megadni.
- Ha ugyanahhoz a műveletmetódushoz kapcsolódik, az útvonalértékeket nem kell megadni.
- Amikor az alkalmazás egy másik részéhez kapcsolódik, nem szeretne olyan útvonalértékeket átvinni, amelyeknek nincs jelentésük az alkalmazás ezen részében.
A LinkGenerator vagy IUrlHelper hívások, amelyek null-t adnak vissza, általában az útvonalértékek érvénytelenítésének nem megfelelő megértése miatt fordulnak elő. Az útvonalértékek érvénytelenítésének hibaelhárításához explicit módon adjon meg több útvonalértéket, és ellenőrizze, hogy ez megoldja-e a problémát.
Az útvonalérték érvénytelenítése azzal a feltételezéssel működik, hogy az alkalmazás URL-sémája hierarchikus, a hierarchia balról jobbra épül fel. Fontolja meg az alapszintű vezérlőútvonal-sablont {controller}/{action}/{id?} , hogy intuitív módon értelmezhesse ennek működését a gyakorlatban. Az érték módosításaérvényteleníti a jobb oldalon megjelenő összes útvonalértéket. Ez tükrözi a hierarchia feltételezését. Ha az alkalmazásnak van egy környezeti értéke id, és a művelet egy másik értéket ad meg a controller számára:
-
idnem lesz újra felhasználva, mert{controller}a bal oldalon{id?}található.
Néhány példa az alapelv bemutatására:
- Ha az explicit értékek egy értéket
idtartalmaznak, a környezeti értékidfigyelmen kívül lesz hagyva. A(z)controllerésactionértékeit használhatjuk. - Ha az explicit értékek egy értéket
actiontartalmaznak, a rendszer figyelmen kívül hagyja a környezeti értékeketaction. Azcontrolleresetében a környezeti értékek felhasználhatók. Ha a explicit értékactioneltér a környezeti értéktőlaction, akkor azidérték nem lesz felhasználva. Ha az explicit értékactionmegegyezik a környezeti értékkelaction, akkor azidérték használható. - Ha az explicit értékek egy értéket
controllertartalmaznak, a rendszer figyelmen kívül hagyja a környezeti értékeketcontroller. Ha az explicit értékcontrollereltér a környezeti értéktőlcontroller, akkor nem használják azactionésidértékeket. Ha az explicit értékcontrollermegegyezik a környezeti értékkelcontroller, akkor azactionésidértékek használhatók.
Ezt a folyamatot tovább bonyolítja az attribútumútvonalak és a dedikált hagyományos útvonalak megléte. A vezérlő hagyományos útvonalai, mint például a {controller}/{action}/{id?}, egy hierarchiát határoznak meg útvonalparaméterekkel.
A vezérlőkhöz és lapokhoz tartozó dedikált hagyományos útvonalak és Razor esetén:
- Az útvonalértékek hierarchiája létezik.
- Nem jelennek meg a sablonban.
Ezekben az esetekben az URL-generálás határozza meg a szükséges értékek fogalmát. A vezérlők és Razor lapok által létrehozott végpontok olyan kötelező értékekkel rendelkeznek, amelyek lehetővé teszik az útvonalértékek érvénytelenítését.
Az útvonalérték érvénytelenítési algoritmusa részletesen:
- A szükséges értékneveket a rendszer kombinálja az útvonalparaméterekkel, majd balról jobbra dolgozza fel őket.
- Minden paraméter esetében a környezeti érték és az explicit érték összehasonlítása:
- Ha a környezeti érték és az explicit érték megegyezik, a folyamat folytatódik.
- Ha a környezeti érték jelen van, és az explicit érték nem, akkor a környezeti érték lesz használva az URL-cím létrehozásakor.
- Ha a környezeti érték nem jelenik meg, és az explicit érték az, utasítsa el a környezeti értéket és az összes további környezeti értéket.
- Ha a környezeti érték és az explicit érték jelen van, és a két érték eltérő, utasítsa el a környezeti értéket és az összes további környezeti értéket.
Ezen a ponton az URL-létrehozási művelet készen áll az útvonalkorlátozások kiértékelésére. Az elfogadott értékek halmaza az alapértelmezett paraméterértékekkel van kombinálva, amelyek a korlátozások számára biztosítottak. Ha a korlátozások mindegyike megfelel, a művelet folytatódik.
Ezután az elfogadott értékek használhatók az útvonalsablon kibontásához. Az útvonalsablon feldolgozása:
- Balról jobbra.
- Minden paraméterhez az elfogadott érték van behelyettesítve.
- A következő különleges esetek esetén:
- Ha az elfogadott értékekből hiányzik egy érték, és a paraméter alapértelmezett értékkel rendelkezik, a rendszer az alapértelmezett értéket használja.
- Ha az elfogadott értékekből hiányzik egy érték, és a paraméter nem kötelező, a feldolgozás folytatódik.
- Ha egy hiányzó opcionális paraméter jobb oldalán található útvonalparaméter rendelkezik értékkel, a művelet meghiúsul.
- Ha lehetséges, összecsukja az egybefüggő alapértelmezett értékű paramétereket és az opcionális paramétereket.
A lekérdezési sztringhez explicit módon megadott értékek, amelyek nem egyeznek az útvonal egy szegmensével, hozzáadódnak a lekérdezési sztringhez. Az alábbi táblázat az útvonalsablon {controller}/{action}/{id?}használatakor mutatja be az eredményt.
| Környezeti értékek | Explicit értékek | Result |
|---|---|---|
| vezérlő = "Home" | action = "Névjegy" | /Home/About |
| vezérlő = "Home" | controller = "Order", action = "About" | /Order/About |
| controller = "Home", szín = "Vörös" | action = "Névjegy" | /Home/About |
| vezérlő = "Home" | action = "About", color = "Red" | /Home/About?color=Red |
Választható útvonalparaméter sorrendje
Az opcionális útvonalparamétereknek az összes szükséges útvonalparaméter és literál után kell érkezniük. A következő kódban a id és name paramétereknek a color paraméter után kell szerepelniük.
using Microsoft.AspNetCore.Mvc;
namespace WebApplication1.Controllers;
[Route("api/[controller]")]
public class MyController : ControllerBase
{
// GET /api/my/red/2/joe
// GET /api/my/red/2
// GET /api/my
[HttpGet("{color}/{id:int?}/{name?}")]
public IActionResult GetByIdAndOptionalName(string color, int id = 1, string? name = null)
{
return Ok($"{color} {id} {name ?? ""}");
}
}
Az útvonalérték érvénytelenítésével kapcsolatos problémák
Az alábbi kód egy olyan URL-létrehozási sémát mutat be, amelyet az útválasztás nem támogat:
app.MapControllerRoute(
"default",
"{culture}/{controller=Home}/{action=Index}/{id?}");
app.MapControllerRoute(
"blog",
"{culture}/{**slug}",
new { controller = "Blog", action = "ReadPost" });
Az előző kódban a rendszer az culture útvonalparamétert használja a honosításhoz. A cél az, hogy a culture paraméter mindig környezeti értékként legyen elfogadva. A culture paraméter azonban nem fogadható el környezeti értékként a szükséges értékek működése miatt:
- Az
"default"útvonalparaméter acultureútvonalsablonbancontrollerbal oldalán található, így acontrollermódosításai nem érvénytelenítikculture. - Az
"blog"útvonalsablonban azcultureútvonalparaméter azcontroller-tól jobbra található, ahogy az a szükséges értékekben megjelenik.
URL-útvonalak elemzése a LinkParser
Az LinkParser osztály támogatja egy URL-elérési út útvonalkészletbe való elemzését. A ParsePathByEndpointName metódus egy végpontnevet és egy URL-elérési utat használ, és visszaadja az URL-útvonalból kinyert útvonalértékeket.
A következő példavezérlőben az GetProduct művelet egy api/Products/{id} útvonalsablont használ, és rendelkezik Name típusú GetProduct-val:
[ApiController]
[Route("api/[controller]")]
public class ProductsController : ControllerBase
{
[HttpGet("{id}", Name = nameof(GetProduct))]
public IActionResult GetProduct(string id)
{
// ...
Ugyanabban a vezérlőosztályban a AddRelatedProduct művelet egy URL-elérési utat vár, pathToRelatedProductamely lekérdezési sztring paraméterként adható meg:
[HttpPost("{id}/Related")]
public IActionResult AddRelatedProduct(
string id, string pathToRelatedProduct, [FromServices] LinkParser linkParser)
{
var routeValues = linkParser.ParsePathByEndpointName(
nameof(GetProduct), pathToRelatedProduct);
var relatedProductId = routeValues?["id"];
// ...
Az előző példában a AddRelatedProduct művelet kinyeri az id útvonal értékét az URL-elérési útból. Ha például a(z) /api/Products/1 URL-elérési út van beállítva, az relatedProductId érték 1-re van állítva. Ez a megközelítés lehetővé teszi az API-ügyfelek számára, hogy URL-útvonalakat használjanak az erőforrásokra való hivatkozáskor anélkül, hogy ismerni kellene az ilyen URL-címek felépítését.
Végpont metaadatainak konfigurálása
Az alábbi hivatkozások a végpont metaadatainak konfigurálásáról nyújtanak információt:
- Cors engedélyezése végponti útválasztással
-
IAuthorizationPolicyProvider-minta egyéni
[MinimumAgeAuthorize]attribútum használatával - Hitelesítés tesztelése az [Engedélyezés] attribútummal
- RequireAuthorization
- A séma kiválasztása az [Engedélyezés] attribútummal
- Szabályzatok alkalmazása az [Engedélyezés] attribútummal
- Szerepköralapú hitelesítés az ASP.NET Core-ban
Hosztok egyezése útvonalakban a RequireHost használatával
RequireHost korlátozást alkalmaz az útvonalra, amely megköveteli a megadott gazdagépet. A RequireHost paraméter vagy a [Gazdagép] lehet:
- Hoszt:
www.domain.com,www.domain.combármely porttal illik. - Gazdagép helyettesítő karakterrel:
*.domain.com, egyezéswww.domain.com,subdomain.domain.comvagywww.subdomain.domain.combármely porton. - Port:
*:5000, megegyezik az 5000-es porttal bármely gazdagépen. - Hoszt és port:
www.domain.com:5000vagy*.domain.com:5000, amely egyezik a hoszttal és a porttal.
Több paraméter is megadható RequireHost vagy [Host] használatával. A kényszer egyezik a paraméterek bármelyikére érvényes gazdagépekkel. Például [Host("domain.com", "*.domain.com")] megegyezik domain.com, www.domain.com és subdomain.domain.com.
Az alábbi kód RequireHost használja a megadott gazdagép megkövetelésére az útvonalon.
app.MapGet("/", () => "Contoso").RequireHost("contoso.com");
app.MapGet("/", () => "AdventureWorks").RequireHost("adventure-works.com");
app.MapHealthChecks("/healthz").RequireHost("*:8080");
A következő kód a [Host] vezérlő attribútumával követeli meg a megadott gazdagépek bármelyikét:
[Host("contoso.com", "adventure-works.com")]
public class HostsController : Controller
{
public IActionResult Index() =>
View();
[Host("example.com")]
public IActionResult Example() =>
View();
}
Ha az attribútumot a [Host] vezérlőre és a műveleti módszerre is alkalmazza a rendszer:
- A műveleten szereplő attribútumot használja a rendszer.
- A vezérlőattribútum figyelmen kívül lesz hagyva.
Warning
A gazdagép fejléc-re támaszkodó API-k, mint például HttpRequest.Host és RequireHost, potenciális hamisításnak vannak kitéve az ügyfelek által.
A gazda- és porthamisítás megakadályozása érdekében használja az alábbi módszerek egyikét:
- Használja HttpContext.Connection (ConnectionInfo.LocalPort) ott, ahol a portok ellenőrzésre kerülnek.
- Hosztszűrés alkalmazása.
Útvonalcsoportok
A MapGroup bővítménymetódus segít a végpontcsoportok közös előtaggal való rendszerezésében. Csökkenti az ismétlődő kódot, és lehetővé teszi a végpontok teljes csoportjainak testreszabását egyetlen hívással olyan metódusokhoz, mint a RequireAuthorization és WithMetadata, amelyek végpont metaadatait adják hozzá.
A következő kód például két hasonló végpontcsoportot hoz létre:
app.MapGroup("/public/todos")
.MapTodosApi()
.WithTags("Public");
app.MapGroup("/private/todos")
.MapTodosApi()
.WithTags("Private")
.AddEndpointFilterFactory(QueryPrivateTodos)
.RequireAuthorization();
EndpointFilterDelegate QueryPrivateTodos(EndpointFilterFactoryContext factoryContext, EndpointFilterDelegate next)
{
var dbContextIndex = -1;
foreach (var argument in factoryContext.MethodInfo.GetParameters())
{
if (argument.ParameterType == typeof(TodoDb))
{
dbContextIndex = argument.Position;
break;
}
}
// Skip filter if the method doesn't have a TodoDb parameter.
if (dbContextIndex < 0)
{
return next;
}
return async invocationContext =>
{
var dbContext = invocationContext.GetArgument<TodoDb>(dbContextIndex);
dbContext.IsPrivate = true;
try
{
return await next(invocationContext);
}
finally
{
// This should only be relevant if you're pooling or otherwise reusing the DbContext instance.
dbContext.IsPrivate = false;
}
};
}
public static RouteGroupBuilder MapTodosApi(this RouteGroupBuilder group)
{
group.MapGet("/", GetAllTodos);
group.MapGet("/{id}", GetTodo);
group.MapPost("/", CreateTodo);
group.MapPut("/{id}", UpdateTodo);
group.MapDelete("/{id}", DeleteTodo);
return group;
}
Ebben a forgatókönyvben a Location fejléc relatív címét használhatja a 201 Created eredményben:
public static async Task<Created<Todo>> CreateTodo(Todo todo, TodoDb database)
{
await database.AddAsync(todo);
await database.SaveChangesAsync();
return TypedResults.Created($"{todo.Id}", todo);
}
A végpontok első csoportja csak a /public/todos előtagú kéréseknek felel meg, és hitelesítés nélkül is elérhetők. A végpontok második csoportja csak a /private/todos előtagú kéréseknek felel meg, és hitelesítést igényel.
A QueryPrivateTodosvégpontszűrő-előállító egy helyi függvény, amely módosítja az útvonalkezelő TodoDb paramétereit annak érdekében, hogy lehetővé tegye a privát teendőadatok elérését és tárolását.
Az útvonalcsoportok a beágyazott csoportokat és az összetett előtagmintákat is támogatják útvonalparaméterekkel és korlátozásokkal. Az alábbi példában a user csoporthoz hozzárendelt útvonalkezelő rögzítheti a külső csoport előtagjaiban definiált {org} és {group} útvonalparamétereket.
Az előtag üres is lehet. Ez akkor lehet hasznos, ha végponti metaadatokat vagy szűrőket ad hozzá a végpontok egy csoportjához az útvonalminta módosítása nélkül.
var all = app.MapGroup("").WithOpenApi();
var org = all.MapGroup("{org}");
var user = org.MapGroup("{user}");
user.MapGet("", (string org, string user) => $"{org}/{user}");
A szűrők vagy metaadatok csoporthoz való hozzáadása ugyanúgy viselkedik, mint az egyes végpontokhoz való egyenkénti hozzáadásuk, mielőtt további szűrőket vagy metaadatokat ad hozzá egy belső csoporthoz vagy adott végponthoz.
var outer = app.MapGroup("/outer");
var inner = outer.MapGroup("/inner");
inner.AddEndpointFilter((context, next) =>
{
app.Logger.LogInformation("/inner group filter");
return next(context);
});
outer.AddEndpointFilter((context, next) =>
{
app.Logger.LogInformation("/outer group filter");
return next(context);
});
inner.MapGet("/", () => "Hi!").AddEndpointFilter((context, next) =>
{
app.Logger.LogInformation("MapGet filter");
return next(context);
});
A fenti példában a külső szűrő naplózza a bejövő kérést a belső szűrő előtt annak ellenére, hogy másodikként lett hozzáadva. Mivel a szűrők különböző csoportokra lettek alkalmazva, a egymáshoz viszonyított sorrend nem számít. A rendelésszűrők hozzáadásának sorrendje számít, ha ugyanarra a csoportra vagy egy adott végpontra alkalmazzák.
A /outer/inner/ kérés a következőket naplózza:
/outer group filter
/inner group filter
MapGet filter
Teljesítmény-útmutató útválasztáshoz
Ha egy alkalmazás teljesítményproblémával rendelkezik, az útválasztást gyakran gyanúsítják a problémaként. Azért feltételezik az útválasztás problémáját, mert a keretrendszerek, mint például a vezérlők és a Pages, a naplózási üzenetekben jelzik, mennyi időt töltenek a keretrendszeren belül. Ha jelentős különbség van a vezérlők által jelentett idő és a kérelem teljes időtartama között:
- A fejlesztők megszüntetik az alkalmazáskódjukat a probléma forrásaként.
- Gyakran feltételezzük, hogy az útválasztás az oka.
Az útválasztást több ezer végponton tesztelik. Nem valószínű, hogy egy tipikus alkalmazás teljesítményproblémába ütközik csak túl nagy mérete miatt. A lassú útválasztási teljesítmény leggyakoribb kiváltó oka általában egy rosszul viselkedő egyéni köztes szoftver.
Az alábbi kódminta a késés forrásának szűkítéséhez használható alapszintű technikát mutatja be:
var logger = app.Services.GetRequiredService<ILogger<Program>>();
app.Use(async (context, next) =>
{
var stopwatch = Stopwatch.StartNew();
await next(context);
stopwatch.Stop();
logger.LogInformation("Time 1: {ElapsedMilliseconds}ms", stopwatch.ElapsedMilliseconds);
});
app.UseRouting();
app.Use(async (context, next) =>
{
var stopwatch = Stopwatch.StartNew();
await next(context);
stopwatch.Stop();
logger.LogInformation("Time 2: {ElapsedMilliseconds}ms", stopwatch.ElapsedMilliseconds);
});
app.UseAuthorization();
app.Use(async (context, next) =>
{
var stopwatch = Stopwatch.StartNew();
await next(context);
stopwatch.Stop();
logger.LogInformation("Time 3: {ElapsedMilliseconds}ms", stopwatch.ElapsedMilliseconds);
});
app.MapGet("/", () => "Timing Test.");
Útvonalak időzítése
- Az egyes köztes szoftvereket az előző kódban látható időzítő köztes szoftver egy-egy példányával kell beágyazni.
- Adjon hozzá egy egyedi azonosítót, amely korrelálja az időzítési adatokat a kóddal.
Ez egy alapvető módja annak, hogy szűkítse a késést, ha jelentős, például több mint 10ms. A Time 2 kivonása a Time 1 jelentésből a UseRouting köztes szoftverben töltött időt jelzi.
Az alábbi kód az előző időzítési kód tömörebb megközelítését használja:
public sealed class AutoStopwatch : IDisposable
{
private readonly ILogger _logger;
private readonly string _message;
private readonly Stopwatch _stopwatch;
private bool _disposed;
public AutoStopwatch(ILogger logger, string message) =>
(_logger, _message, _stopwatch) = (logger, message, Stopwatch.StartNew());
public void Dispose()
{
if (_disposed)
{
return;
}
_logger.LogInformation("{Message}: {ElapsedMilliseconds}ms",
_message, _stopwatch.ElapsedMilliseconds);
_disposed = true;
}
}
var logger = app.Services.GetRequiredService<ILogger<Program>>();
var timerCount = 0;
app.Use(async (context, next) =>
{
using (new AutoStopwatch(logger, $"Time {++timerCount}"))
{
await next(context);
}
});
app.UseRouting();
app.Use(async (context, next) =>
{
using (new AutoStopwatch(logger, $"Time {++timerCount}"))
{
await next(context);
}
});
app.UseAuthorization();
app.Use(async (context, next) =>
{
using (new AutoStopwatch(logger, $"Time {++timerCount}"))
{
await next(context);
}
});
app.MapGet("/", () => "Timing Test.");
Potenciálisan költséges útválasztási funkciók
Az alábbi lista betekintést nyújt az alapszintű útvonalsablonokhoz képest viszonylag költséges útválasztási funkciókba:
- Reguláris kifejezések: Olyan reguláris kifejezések írhatók, amelyek összetettek, vagy hosszú ideig futnak kis mennyiségű bemenettel.
- Összetett szegmensek (
{x}-{y}-{z}):- Lényegesen drágábbak, mint egy normál URL-elérési út szegmensének elemzése.
- Ez azt eredményezi, hogy a rendszer sokkal több alsztringet foglal le.
- Szinkron adathozzáférés: Számos összetett alkalmazás rendelkezik adatbázis-hozzáféréssel az útválasztás részeként. Használjon olyan bővíthetőségi pontokat, mint az MatcherPolicy és EndpointSelectorContext, amelyek aszinkronok.
Útmutatás nagy útvonaltáblákhoz
Alapértelmezés szerint az ASP.NET Core egy olyan útválasztási algoritmust használ, amely memória felhasználást cserél fel processzoridőre. Ez jó hatással van arra, hogy az útvonal-egyeztetési idő csak az egyező útvonal hosszától függ, és nem az útvonalak számától. Ez a megközelítés azonban bizonyos esetekben potenciálisan problémás lehet, ha az alkalmazás nagy számú útvonalon (ezres nagyságrendben) rendelkezik, és nagy mennyiségű változó előtag található az útvonalakban. Ha például az útvonalaknak vannak paraméterei az útvonal korai szakaszaiban, például {parameter}/some/literal.
Nem valószínű, hogy egy alkalmazás olyan helyzetbe kerül, ahol ez probléma, kivéve, ha:
- Az alkalmazásban sok útvonal használja ezt a mintát.
- Az alkalmazásban számos útvonal található.
Hogyan állapítható meg, hogy egy alkalmazás szembesül-e a nagy útválasztási táblázat problémájával?
- Két tünetet kell keresni:
- Az alkalmazás lassan indul el az első kéréskor.
- Vegye figyelembe, hogy ez kötelező, de nem elegendő. Számos más nem útvonalbeli probléma is fennáll, mint ami lassú alkalmazásindítást okozhat. Ellenőrizze az alábbi feltételt, hogy pontosan megállapíthassa, hogy az alkalmazás fut-e ebben a helyzetben.
- Az alkalmazás sok memóriát használ fel az indítás során, és egy memóriadump sok
Microsoft.AspNetCore.Routing.Matching.DfaNodepéldányokat mutat.
- Az alkalmazás lassan indul el az első kéréskor.
A probléma megoldása
A forgatókönyvet nagyrészt javító útvonalakra számos technika és optimalizálás alkalmazható:
- Ha lehetséges, alkalmazzon útvonalkorlátozásokat a paraméterekre, például
{parameter:int},{parameter:guid}stb{parameter:regex(\\d+)}.- Ez lehetővé teszi, hogy az útválasztási algoritmus belsőleg optimalizálja az egyezéshez használt struktúrákat, és drasztikusan csökkentse a felhasznált memóriát.
- Az esetek túlnyomó többségében ez elegendő lesz ahhoz, hogy visszatérjen egy elfogadható viselkedéshez.
- Módosítsa az útvonalakat úgy, hogy a paramétereket a sablon későbbi szegmenseibe helyezze át.
- Ez csökkenti a lehetséges "elérési utak" számát, hogy megfeleljen egy adott elérési úthoz megadott végpontnak.
- Használjon dinamikus útvonalat, és végezze el dinamikusan a vezérlőre/lapra való leképezést.
- Ez elérhető
MapDynamicControllerRouteésMapDynamicPageRoutehasználatával.
- Ez elérhető
Rövidzárlatú köztes szoftver útválasztás után
Amikor az útválasztás megfelel egy végpontnak, általában lehetővé teszi a köztes szoftver folyamatának futtatását a végpontlogika meghívása előtt. A szolgáltatások csökkenthetik az erőforrás-használatot, ha kiszűrik az ismert kéréseket a folyamat korai szakaszában. A ShortCircuit kiterjesztési metódus használatával az útválasztás azonnal meghívja a végpont logikáját, és ezt követően befejezi a kérést. Előfordulhat például, hogy egy adott útvonalnak nem kell hitelesítésen vagy CORS köztes szoftveren keresztül haladnia. Az alábbi rövidzárlat-kérések az /short-circuit útvonalnak megfelelőek:
app.MapGet("/short-circuit", () => "Short circuiting!").ShortCircuit();
A ShortCircuit(IEndpointConventionBuilder, Nullable<Int32>) metódus opcionálisan állapotkódot is tartalmazhat.
A MapShortCircuit metódussal egyszerre több útvonalhoz is beállíthat rövidzárlatot úgy, hogy egy URL-előtagokat tartalmazó params tömböt ad át neki. A böngészők és a robotok például gyakran mintavételezik a kiszolgálókat olyan jól ismert útvonalakon, mint a robots.txt és a favicon.ico. Ha az alkalmazás nem rendelkezik ezekkel a fájlokkal, egy kódsor mindkét útvonalat konfigurálhatja:
app.MapShortCircuit(404, "robots.txt", "favicon.ico");
MapShortCircuit visszaadja IEndpointConventionBuilder , hogy további útvonalkorlátozások, például a gazdagépszűrés hozzáadhatók legyenek hozzá.
A ShortCircuit metódusok és MapShortCircuit a metódusok nem befolyásolják a korábban UseRoutingelhelyezett köztes szoftvereket. Ha ezeket a metódusokat olyan végpontokkal próbálja használni, amelyek [Authorize] vagy [RequireCors] metaadatokkal is rendelkeznek, a kérések sikertelenek lesznek.InvalidOperationException Ez a metaadat a [Authorize] vagy [EnableCors] attribútumok, illetve a RequireCors vagy RequireAuthorization metódusok alkalmazásával van felruházva.
A rövidzárlatozó köztes szoftver hatásának megtekintéséhez állítsa a "Microsoft" naplózási kategóriát "Információ" értékre a appsettings.Development.json mezőben.
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft": "Information",
"Microsoft.Hosting.Lifetime": "Information"
}
}
}
Futtassa az alábbi kódot:
var app = WebApplication.Create();
app.UseHttpLogging();
app.MapGet("/", () => "No short-circuiting!");
app.MapGet("/short-circuit", () => "Short circuiting!").ShortCircuit();
app.MapShortCircuit(404, "robots.txt", "favicon.ico");
app.Run();
A következő példa a konzolnaplók közül való, amelyek a / végpont futtatásával lettek létrehozva. A naplózási köztes szoftver kimenetét tartalmazza:
info: Microsoft.AspNetCore.Routing.EndpointMiddleware[0]
Executing endpoint 'HTTP: GET /'
info: Microsoft.AspNetCore.Routing.EndpointMiddleware[1]
Executed endpoint 'HTTP: GET /'
info: Microsoft.AspNetCore.HttpLogging.HttpLoggingMiddleware[2]
Response:
StatusCode: 200
Content-Type: text/plain; charset=utf-8
Date: Wed, 03 May 2023 21:05:59 GMT
Server: Kestrel
Alt-Svc: h3=":5182"; ma=86400
Transfer-Encoding: chunked
Az alábbi példa a /short-circuit végpont futtatásából származik. Nem rendelkezik semmivel a naplózási köztes szoftverből, mert a köztes szoftver rövidzárlatú volt:
info: Microsoft.AspNetCore.Routing.EndpointRoutingMiddleware[4]
The endpoint 'HTTP: GET /short-circuit' is being executed without running additional middleware.
info: Microsoft.AspNetCore.Routing.EndpointRoutingMiddleware[5]
The endpoint 'HTTP: GET /short-circuit' has been executed without running additional middleware.
Útmutató könyvtárszerzőknek
Ez a szakasz útmutatást tartalmaz az útválasztásra alapuló könyvtárak szerzői számára. Ezek a részletek biztosítják, hogy az alkalmazásfejlesztők jól használják az útválasztást kiterjesztő kódtárakat és keretrendszereket.
Végpontok definiálása
Az útválasztást használó keretrendszer létrehozásához, amely az URL-ek egyeztetésére szolgál, kezdje azzal, hogy definiál egy felhasználói élményt, amely a UseEndpoints alapján épül fel.
ÉPÍTS a IEndpointRouteBuilder tetejére. Ez lehetővé teszi, hogy a felhasználók összekeverés nélkül más ASP.NET Core-funkciókkal is megírják a keretrendszert. Minden ASP.NET Core-sablon tartalmazza az útválasztást. Tegyük fel, hogy az útválasztás jelen van és ismerős a felhasználók számára.
// Your framework
app.MapMyFramework(...);
app.MapHealthChecks("/healthz");
A DO egy lezárt betontípust ad vissza az adott implementálásra MapMyFramework(...)IEndpointConventionBuilderirányuló hívásból. A legtöbb keretrendszer-metódus Map... ezt a mintát követi. A IEndpointConventionBuilder felület:
- Lehetővé teszi a metaadatok összeállítását.
- Különféle bővítési módszerek célozzák meg.
A saját típus deklarálása lehetővé teszi saját keretrendszerspecifikus funkciók hozzáadását a szerkesztőhöz. Nem baj, ha egy keretrendszer által deklarált szerkesztőt burkolunk, és hívásokat továbbítunk neki.
// Your framework
app.MapMyFramework(...)
.RequireAuthorization()
.WithMyFrameworkFeature(awesome: true);
app.MapHealthChecks("/healthz");
GONDOLKODJ azon, hogy megírod a saját EndpointDataSource.
EndpointDataSource a végpontok gyűjteményének deklarálására és frissítésére szolgáló alacsony szintű primitív.
EndpointDataSource egy hatékony API, amelyet a vezérlők és Razor a Pages használnak. További információ: Dinamikus végpont útválasztása.
Az útválasztási tesztek egy alapvető példával rendelkeznek egy nem frissített adatforrásra.
FONTOLJA MEG a megvalósítást GetGroupedEndpoints. Ez teljes körű vezérlést biztosít a csoportkonvenciók és a csoportosított végpontok végső metaadatai felett. Ez lehetővé teszi például, hogy az egyéni EndpointDataSource implementációk a csoportokhoz hozzáadott végpontszűrőket futtassanak.
NE próbáljon meg alapértelmezés szerint egy objektumot regisztrálni.EndpointDataSource Követelje meg a felhasználóktól, hogy regisztrálják a keretrendszert UseEndpoints. Az útválasztás filozófiája, hogy alapértelmezés szerint semmi nem szerepel benne, és ez UseEndpoints a végpontok regisztrálásának helye.
Útvonalválasztással integrált köztes szoftver létrehozása
FONTOLJA meg a metaadat-típusok interfészként való meghatározását.
A DO lehetővé teszi a metaadat-típusok attribútumként való használatát osztályokon és metódusokon.
public interface ICoolMetadata
{
bool IsCool { get; }
}
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
public class CoolMetadataAttribute : Attribute, ICoolMetadata
{
public bool IsCool => true;
}
Az olyan keretrendszerek, mint a vezérlők és Razor a Lapok, támogatják a metaadat-attribútumok típusokra és metódusokra való alkalmazását. Metaadattípusok deklarálása esetén:
- Elérhetővé teheti őket attribútumként.
- A felhasználók többsége ismeri az attribútumok alkalmazását.
A metaadat-típus felületként való deklarálása további rugalmassági réteget ad:
- A felületek összeállíthatók.
- A fejlesztők deklarálhatják a saját típusaikat, amelyek több szabályzatot kombinálnak.
A DO lehetővé teszi a metaadatok felülbírálását az alábbi példában látható módon:
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
public class SuppressCoolMetadataAttribute : Attribute, ICoolMetadata
{
public bool IsCool => false;
}
[CoolMetadata]
public class MyController : Controller
{
public void MyCool() { }
[SuppressCoolMetadata]
public void Uncool() { }
}
Az alábbi irányelvek követésének legjobb módja, ha elkerüli a jelölő metaadatainak meghatározását:
- Ne csak a metaadat-típus jelenlétét keresse.
- Definiáljon egy tulajdonságot a metaadatokon, és ellenőrizze a tulajdonságot.
A metaadat-gyűjtemény rendezett, és támogatja a prioritás szerinti felülrendelést. Vezérlők esetében a műveletmetódus metaadatai a legspecifikusak.
Tegye a köztes szoftvert hasznossá útválasztással és útválasztás nélkül:
app.UseAuthorization(new AuthorizationPolicy() { ... });
// Your framework
app.MapMyFramework(...).RequireAuthorization();
Ennek az útmutatónak a példájaként vegye figyelembe a köztes UseAuthorization szoftvereket. Az engedélyezési köztes szoftver lehetővé teszi, hogy tartalék szabályzatot adjon át.
A tartalék szabályzat, ha meg van adva, mindkettőre vonatkozik:
- Meghatározott szabályzat nélküli végpontok.
- A végpontnak nem megfelelő kérések.
Ez hasznossá teszi az engedélyezési köztes szoftvereket az útválasztás környezetén kívül. Az engedélyezési köztes szoftver használható a hagyományos köztes szoftver programozásához.
Hibakeresési diagnosztika
A részletes útválasztási diagnosztikai kimenethez állítsa be a Logging:LogLevel:Microsoft értékét Debug-re. A fejlesztési környezetben állítsa be a naplószintet: appsettings.Development.json
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft": "Debug",
"Microsoft.Hosting.Lifetime": "Information"
}
}
}
További erőforrások
- Mintakód megtekintése vagy letöltése (hogyan töltsd le)
Az útválasztás feladata a bejövő HTTP-kérések egyeztetése és a kérések elküldése az alkalmazás végrehajtható végpontjaira. A végpontok az alkalmazás végrehajtható kéréskezelési kódjának egységei. A végpontok az alkalmazásban vannak definiálva, és az alkalmazás indításakor vannak konfigurálva. A végpontegyeztetési folyamat kinyerheti az értékeket a kérelem URL-címéből, és megadhatja ezeket az értékeket a kérelmek feldolgozásához. Az alkalmazás végpontadatainak használatával az útválasztás a végpontokra leképező URL-címeket is képes létrehozni.
Az alkalmazások a következő eszközökkel konfigurálhatják az útválasztást:
- Controllers
- Razor lapok
- SignalR
- gRPC-szolgáltatások
- Végpont-kompatibilis köztes szoftver, mint például a Health Checks.
- Útválasztással regisztrált delegátumok és lambdák.
Ez a cikk a ASP.NET Core útválasztásának alacsony szintű részleteit ismerteti. Az útválasztás konfigurálásával kapcsolatos információk:
- A vezérlőkről lásd: Útválasztás a vezérlőműveletekhez a ASP.NET Core-ban.
- Az Razor Pages konvenciókról lásd az ASP.NET Core oldal útvonal- és alkalmazási konvencióit Razor.
Az útválasztás alapjai
Az alábbi kód egy egyszerű útválasztási példát mutat be:
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.MapGet("/", () => "Hello World!");
app.Run();
Az előző példa egyetlen végpontot tartalmaz a MapGet metódus használatával:
- HA HTTP-kérést
GETküld a rendszer a gyökér URL-címre/:- A kérelem delegáltja végrehajtja.
-
Hello World!az HTTP-válaszként íródik.
- Ha a kérelem metódusa nem
GET, vagy a gyökér URL-címe nem/, a rendszer nem ad vissza útvonal-egyezést, és a rendszer egy HTTP 404-et ad vissza.
Az útválasztás egy köztes szoftverpárt használ, amelyet a UseRouting és a UseEndpoints regisztrál.
-
UseRoutingA köztesszoftver-folyamatnak megfelelő útvonalat ad hozzá. Ez a köztes szoftver megvizsgálja az alkalmazásban definiált végpontokat, és a kérés alapján kiválasztja a legjobb egyezést . -
UseEndpointsvégpontvégrehajtást ad a köztes szoftverfolyamathoz. A kijelölt végponthoz társított delegáltat a program futtatja.
Az alkalmazásoknak általában nem kell, hogy meghívják UseRouting vagy UseEndpoints.
WebApplicationBuilder olyan köztes szoftverfolyamatot állít be, amely az Program.cs-ben hozzáadott köztes szoftvereket a UseRouting és UseEndpoints segítségével burkolja. Az alkalmazások azonban módosíthatják a metódusok sorrendjét UseRouting és UseEndpoints futtatását, ha kifejezetten meghívják ezeket a metódusokat. A következő kód például explicit hívást indít a következőre UseRouting:
app.Use(async (context, next) =>
{
// ...
await next(context);
});
app.UseRouting();
app.MapGet("/", () => "Hello World!");
Az előző kódban:
- A
app.Usehívás regisztrál egy egyedi middleware-t, amely a csővezeték elején fut. - A
UseRoutinghívás úgy konfigurálja az útvonal-illesztési köztes réteget, hogy az az egyéni köztes réteg után fusson. - A
MapGet-vel regisztrált végpont a folyamat végén fut.
Ha az előző példa nem tartalmazott volna hívást a UseRouting-ra, akkor az egyéni köztes szoftver az útvonal illesztési köztes szoftver után futott volna.
Endpoints
A MapGet metódus egy végpont definiálására szolgál. A végpont a következő lehet:
- Az URL-cím és a HTTP-metódus egyeztetésével kijelölve.
- A delegált futtatásával hajtva végre.
Az alkalmazás által egyeztethető és végrehajtható végpontok a UseEndpoints-ben vannak konfigurálva. Például MapGet, MapPost és hasonló metódusok csatlakoztatják a kérelem delegáltjait az útválasztási rendszerhez. További módszerekkel csatlakoztathatók ASP.NET Core-keretrendszer funkciói az útválasztási rendszerhez:
- MapRazorPages a Razor oldalak számára
- MapControllers vezérlőkhöz
- MapHub<THub> for SignalR
- MapGrpcService<TService> for gRPC
Az alábbi példa egy kifinomultabb útvonalsablont tartalmazó útválasztást mutat be:
app.MapGet("/hello/{name:alpha}", (string name) => $"Hello {name}!");
A karakterlánc /hello/{name:alpha} egy útvonalsablon. Egy útvonalsablon használatával konfigurálható a végpont egyeztetése. Ebben az esetben a sablon megfelel a következőnek:
- URL-cím, például
/hello/Docs - Minden olyan URL-elérési út, amely betűrendes karakterek sorozatával
/hello/kezdődik.:alphaolyan útvonalkorlátozást alkalmaz, amely csak betűrendes karaktereknek felel meg. Az útvonalkorlátozásokat a cikk későbbi részében ismertetjük.
Az URL-elérési út második szegmense: {name:alpha}
- A paraméterhez
namevan kötve. - A rendszer rögzíti és tárolja a(z) HttpRequest.RouteValues fájlban.
Az alábbi példa az állapot-ellenőrzéssel és engedélyezéssel rendelkező útválasztást mutatja be:
app.UseAuthentication();
app.UseAuthorization();
app.MapHealthChecks("/healthz").RequireAuthorization();
app.MapGet("/", () => "Hello World!");
Az előző példa bemutatja, hogyan:
- Az engedélyezési köztes szoftver használható útválasztással.
- A végpontok az engedélyezési viselkedés konfigurálására használhatók.
A MapHealthChecks hívás egy állapot-ellenőrzési végpontot ad hozzá. A RequireAuthorization láncolása ehhez a híváshoz egy engedélyezési szabályzatot csatol a végponthoz.
A UseAuthentication és UseAuthorization meghívása hozzáadja a hitelesítési és engedélyezési middleware-t. Ezek a köztes szoftverek UseRouting és UseEndpoints közé vannak helyezve, hogy:
- Nézze meg, melyik végpontot választotta
UseRouting. - Engedélyezési szabályzat alkalmazása a végpontra történő küldés előtt UseEndpoints .
Végpont metaadatai
Az előző példában két végpont található, de csak az állapot-ellenőrzési végpont rendelkezik engedélyezési szabályzattal. Ha a kérelem megfelel az állapot-ellenőrzési végpontnak, /healthza rendszer engedélyezési ellenőrzést végez. Ez azt mutatja be, hogy a végpontokhoz további adatok is csatolhatók. Ezt a további adatot végponti metaadatoknak nevezzük:
- A metaadatok feldolgozhatók útválasztást ismerő köztes szoftver használatával.
- A metaadatok bármilyen .NET típusúak lehetnek.
Útválasztási fogalmak
Az útválasztási rendszer a közbenső szoftver folyamatára épül a hatékony végpontkoncepció hozzáadásával. A végpontok az alkalmazás funkcióinak azon egységeit jelölik, amelyek útválasztás, engedélyezés és ASP.NET Core-rendszerek tetszőleges száma tekintetében különböznek egymástól.
ASP.NET alapvető végpontdefiníció
Az ASP.NET Core-végpont a következő:
- Végrehajtható: rendelkezik egy RequestDelegate.
- Bővíthető: Metaadat-gyűjteménysel rendelkezik.
- Kiválasztható: Opcionálisan útválasztási információkkal rendelkezik.
- Enumerable: A végpontok gyűjteménye a EndpointDataSource való lekéréssel listázható.
Az alábbi kód bemutatja, hogyan kérheti le és vizsgálhatja meg az aktuális kérésnek megfelelő végpontot:
app.Use(async (context, next) =>
{
var currentEndpoint = context.GetEndpoint();
if (currentEndpoint is null)
{
await next(context);
return;
}
Console.WriteLine($"Endpoint: {currentEndpoint.DisplayName}");
if (currentEndpoint is RouteEndpoint routeEndpoint)
{
Console.WriteLine($" - Route Pattern: {routeEndpoint.RoutePattern}");
}
foreach (var endpointMetadata in currentEndpoint.Metadata)
{
Console.WriteLine($" - Metadata: {endpointMetadata}");
}
await next(context);
});
app.MapGet("/", () => "Inspect Endpoint.");
Ha a végpont ki van választva, lekérhető a HttpContext. Tulajdonságai megvizsgálhatók. A végpontobjektumok nem módosíthatók, és a létrehozás után nem módosíthatók. A végpont leggyakoribb típusa a RouteEndpoint.
RouteEndpoint információkat tartalmaz, amelyek lehetővé teszik az útválasztási rendszer számára, hogy kiválaszthassa azt.
Az előző kódban a app.Use egy beágyazott middleware-t konfigurál.
Az alábbi kód azt mutatja, hogy attól függően, hogy a folyamatban hol app.Use van meghívva, előfordulhat, hogy nincs végpont:
// Location 1: before routing runs, endpoint is always null here.
app.Use(async (context, next) =>
{
Console.WriteLine($"1. Endpoint: {context.GetEndpoint()?.DisplayName ?? "(null)"}");
await next(context);
});
app.UseRouting();
// Location 2: after routing runs, endpoint will be non-null if routing found a match.
app.Use(async (context, next) =>
{
Console.WriteLine($"2. Endpoint: {context.GetEndpoint()?.DisplayName ?? "(null)"}");
await next(context);
});
// Location 3: runs when this endpoint matches
app.MapGet("/", (HttpContext context) =>
{
Console.WriteLine($"3. Endpoint: {context.GetEndpoint()?.DisplayName ?? "(null)"}");
return "Hello World!";
}).WithDisplayName("Hello");
app.UseEndpoints(_ => { });
// Location 4: runs after UseEndpoints - will only run if there was no match.
app.Use(async (context, next) =>
{
Console.WriteLine($"4. Endpoint: {context.GetEndpoint()?.DisplayName ?? "(null)"}");
await next(context);
});
Az előző mintában olyan utasítások szerepelnek, amelyek megjelenítik, hogy ki van-e jelölve egy végpont. Az egyértelműség kedvéért a minta megjelenítendő nevet rendel a megadott / végponthoz.
Az előző minta a köztes szoftver folyamaton belüli futtatásának pontos ellenőrzésére UseRoutingUseEndpoints irányuló hívásokat is tartalmaz.
Ennek a kódnak a futtatása egy / URL-címmel megjeleníti:
1. Endpoint: (null)
2. Endpoint: Hello
3. Endpoint: Hello
A kód futtatása bármely más URL-címmel:
1. Endpoint: (null)
2. Endpoint: (null)
4. Endpoint: (null)
Ez a kimenet a következőt mutatja be:
- A végpont mindig null értékű, mielőtt
UseRoutingmeghívják. - Ha talál egyezést, a végpont nem null, és a
UseRoutingés UseEndpoints között van. - A
UseEndpointsköztes szoftver terminál , ha talál egyezést. A terminál köztes szoftverét a cikk későbbi részében definiáljuk. - A köztesréteg csak akkor fut, ha a
UseEndpointsvégrehajtása után nem található egyezés.
A UseRouting köztes szoftver a SetEndpoint metódus használatával csatolja a végpontot az aktuális környezethez. A köztes szoftvereket lecserélheti egyéni UseRouting logikára, és továbbra is élvezheti a végpontok használatának előnyeit. A végpontok alacsony szintű primitívek, például köztes szoftverek, és nem kapcsolódnak az útválasztási megvalósításhoz. A legtöbb alkalmazásnak nem kell egyéni logikára cserélnie UseRouting .
A UseEndpoints köztes szoftvert úgy alakították ki, hogy a UseRouting köztes szoftverrel tandem használatra legyen. A végpontok végrehajtásának alapvető logikája nem bonyolult. A végpont lekérésére GetEndpoint használata, majd annak RequestDelegate tulajdonságának meghívása.
Az alábbi kód bemutatja, hogy a köztes szoftver hogyan befolyásolhatja vagy reagálhat az útválasztásra:
app.UseHttpMethodOverride();
app.UseRouting();
app.Use(async (context, next) =>
{
if (context.GetEndpoint()?.Metadata.GetMetadata<RequiresAuditAttribute>() is not null)
{
Console.WriteLine($"ACCESS TO SENSITIVE DATA AT: {DateTime.UtcNow}");
}
await next(context);
});
app.MapGet("/", () => "Audit isn't required.");
app.MapGet("/sensitive", () => "Audit required for sensitive data.")
.WithMetadata(new RequiresAuditAttribute());
public class RequiresAuditAttribute : Attribute { }
Az előző példa két fontos fogalmat mutat be:
- A köztes szoftver előzetesen futtatható a
UseRoutingelőtt, hogy módosítsa azokat az adatokat, amelyeken az útválasztás működik.- Az útválasztás előtt megjelenő köztes szoftver általában módosítja a kérés bizonyos tulajdonságát, például UseRewriter: , UseHttpMethodOverridevagy UsePathBase.
- A middleware a
UseRoutingés UseEndpoints között futtatható annak érdekében, hogy az útválasztás eredményeit feldolgozza, mielőtt a végpont végrehajtásra kerül.- Köztes szoftver, amely a
UseRoutingésUseEndpointsközött fut:- A végpontok megértéséhez általában a metaadatokat vizsgálja meg.
- Gyakran hoz biztonsági döntéseket, mint a
UseAuthorizationésUseCors.
- A köztes szoftver és a metaadatok kombinációja lehetővé teszi a szabályzatok végpontonkénti konfigurálását.
- Köztes szoftver, amely a
Az előző kód egy végpontonkénti szabályzatokat támogató egyéni köztes szoftver példáját mutatja be. A köztes szoftver naplót ír a konzol bizalmas adataihoz való hozzáférésről. A köztes szoftver konfigurálható egy végpont metaadatokkal történő naplózásáraRequiresAuditAttribute. Ez a minta egy feliratkozásos mintát mutat be, amelyben csak a bizalmasként megjelölt végpontokat naplózzák. Ezt a logikát meg lehet határozni fordítottan, például naplózva mindent, ami nincs biztonságosként megjelölve. A végpont metaadat-rendszere rugalmas. Ez a logika bármilyen módon megtervezhető a használati esetnek megfelelően.
Az előző mintakód a végpontok alapfogalmait mutatja be. A minta nem éles használatra készült. A naplózási napló köztes szoftverének teljesebb verziója a következő lenne:
- Jelentkezzen be egy fájlba vagy adatbázisba.
- Adjon meg olyan részleteket, mint a felhasználó, az IP-cím, a bizalmas végpont neve stb.
A naplózási szabályzat metaadatai RequiresAuditAttribute egy Attribute-ként vannak definiálva a könnyebb használat érdekében olyan osztályalapú keretrendszerekkel, mint például a vezérlők és SignalR. A kódhoz vezető útvonal használata esetén:
- A metaadatok egy builder API-val vannak csatolva.
- Az osztályalapú keretrendszerek a végpontok létrehozásakor tartalmazzák a megfelelő metódus és osztály összes attribútumát.
A metaadat-típusok ajánlott eljárása, hogy interfészként vagy attribútumként definiálja őket. Az interfészek és attribútumok lehetővé teszik a kód újrafelhasználását. A metaadat-rendszer rugalmas, és nem ír elő korlátozásokat.
Terminál köztes szoftver összehasonlítása az útválasztással
Az alábbi példa a terminál köztes szoftverét és az útválasztást mutatja be:
// Approach 1: Terminal Middleware.
app.Use(async (context, next) =>
{
if (context.Request.Path == "/")
{
await context.Response.WriteAsync("Terminal Middleware.");
return;
}
await next(context);
});
app.UseRouting();
// Approach 2: Routing.
app.MapGet("/Routing", () => "Routing.");
A Approach 1:-vel látható köztes szoftver stílusa a terminál köztes szoftver. Terminál köztes szoftvernek nevezzük, mert egyező műveletet hajt végre:
- Az előző mintában az illesztési művelet a
Path == "/"a köztes szoftverhez ésPath == "/Routing"az útválasztáshoz tartozik. - Ha egy egyezés sikeres, végrehajt néhány funkciót, és visszatér anélkül, hogy meghívná a
nextköztes szoftvert.
Terminál köztes szoftvernek nevezik, mert leállítja a keresést, végrehajt néhány funkciót, majd visszaadja.
Az alábbi lista összehasonlítja a terminál köztes szoftverét az útválasztással:
- Mindkét módszer lehetővé teszi a feldolgozási folyamat leállítását:
- A köztes szoftver a
nextmeghívása helyett visszatéréssel leállítja a futószalagot. - A végpontok mindig terminálok.
- A köztes szoftver a
- A terminálközvetítő lehetővé teszi a köztes szoftver tetszőleges helyen való elhelyezését a folyamatban:
- A végpontok a UseEndpoints pozíción futnak.
- A terminál köztes réteg lehetővé teszi, hogy tetszőleges kód határozza meg, mikor egyezik a köztes szoftver.
- Az egyéni útvonalegyeztető kód részletes lehet, és nehezen írható helyesen.
- Az útválasztás egyszerű megoldásokat kínál a tipikus alkalmazásokhoz. A legtöbb alkalmazás nem igényel egyéni útvonalegyeztető kódot.
- A végpontok interfészei köztes szoftverekkel, mint például
UseAuthorizationésUseCors, kommunikálnak.- A
UseAuthorizationvagyUseCorsterminálközvetítő használata manuális beavatkozást igényel az engedélyezési rendszerbe való interfészépítés során.
- A
Egy végpont mindkettőt definiálja:
- A kérések feldolgozására jogosult meghatalmazott.
- Tetszőleges metaadatok gyűjteménye. A metaadatok az egyes végpontokhoz csatolt szabályzatokon és konfigurációkon alapuló, átfogó problémák megvalósítására szolgálnak.
A terminál köztes szoftver hatékony eszköz lehet, de a következőt igényelheti:
- Jelentős mennyiségű kódolás és tesztelés.
- Manuális integráció más rendszerekkel a kívánt rugalmasság elérése érdekében.
A terminál middleware megírása előtt fontolja meg az útvonalvezérléssel való integrálást.
A meglévő terminálközvetítmények, amelyek integrálódnak a Map-pal vagy a MapWhen, általában útválasztást támogató végponttá alakíthatók. MapHealthChecks a routerelem mintáját mutatja be:
- Bővítménymetódus írása a fájlra IEndpointRouteBuilder.
- Beágyazott köztes szoftverfolyamat létrehozása a következővel CreateApplicationBuilder: .
- Csatolja a köztes szoftvert az új folyamathoz. Ebben az esetben: UseHealthChecks.
- Build a köztes szoftverfolyamatot egy RequestDelegate.
- Hívja meg
Mapés adja meg az új köztes szoftverfolyamatot. - Adja vissza az
Mapáltal biztosított építőobjektumot a bővítménymetódusból.
Az alábbi kód a MapHealthChecks használatát mutatja be:
app.UseAuthentication();
app.UseAuthorization();
app.MapHealthChecks("/healthz").RequireAuthorization();
Az előző minta bemutatja, miért fontos az építő objektum visszaadása. A szerkesztőobjektum visszaadásával az alkalmazás fejlesztője olyan szabályzatokat konfigurálhat, mint a végpont engedélyezése. Ebben a példában az állapot-ellenőrző köztes szoftver nem rendelkezik közvetlen integrációval az engedélyezési rendszerrel.
A metaadat-rendszer a terminál köztes szoftvereket használó bővíthetőségi szerzők által tapasztalt problémákra válaszul jött létre. Minden köztes szoftver esetében problémás a saját integráció megvalósítása az engedélyezési rendszerrel.
URL-cím egyeztetése
- Az a folyamat, amellyel az útválasztás megfelel a végpontnak küldött bejövő kérésnek.
- Az URL-elérési út és a fejlécek adatain alapul.
- A kérelemben szereplő bármely adatra kiterjeszthető.
Az útvonalkezelő köztes szoftver végrehajtásakor beállít Endpoint és útvonali értékeket egy kérés tulajdonságához az HttpContext aktuális kérés alapján.
- A HttpContext.GetEndpoint hívása megkapja a végpontot.
-
HttpRequest.RouteValueslekéri az útvonalértékek gyűjteményét.
A köztes szoftver azután fut, hogy az útválasztási köztes szoftver megvizsgálhatja a végpontot, és végrehajthatja a műveletet. Egy engedélyezési köztes szoftver például kikérdezheti a végpont metaadatgyűjteményét egy engedélyezési szabályzathoz. A kérelemfeldolgozási folyamat összes köztes szoftverének végrehajtása után a rendszer meghívja a kijelölt végpont delegáltját.
A végponti útválasztás útválasztási rendszere felelős az összes irányítási döntésért. Mivel a köztes szoftver a kiválasztott végponton alapuló szabályzatokat alkalmaz, fontos, hogy:
- Minden olyan döntés, amely befolyásolhatja a küldést vagy a biztonsági szabályzatok alkalmazását, az útválasztási rendszeren belül történik.
Warning
A visszamenőleges kompatibilitás érdekében a vezérlő vagy Razor a Pages végpont delegáltjának végrehajtásakor a rendszer az eddig végrehajtott kérésfeldolgozás alapján a megfelelő értékekre állítja RouteContext.RouteData be a tulajdonságokat.
A RouteContext típus elavultként lesz megjelölve egy későbbi kiadásban:
- Migrálás
RouteData.ValuesHttpRequest.RouteValues-re. - Migrálja
RouteData.DataTokensaz IDataTokensMetadata lekéréséhez a végpont metaadataiból.
Az URL-egyeztetés konfigurálható fázisokban működik. Minden fázisban a kimenet egyezések halmaza. Az egyezések halmaza a következő szakaszban tovább szűkíthető. Az útválasztási implementáció nem garantálja az egyező végpontok feldolgozási sorrendjét. Az összes lehetséges találat feldolgozása egyszerre történik. Az URL-egyeztetési fázisok a következő sorrendben történnek. ASP.NET Core:
- Feldolgozza az URL-útvonalat a végpontok és útvonalsablonjaik alapján, és összegyűjti az összes egyezést.
- A megelőző listát veszi alapul, és eltávolítja azokat az egyezéseket, amelyek nem felelnek meg az útvonal-korlátozásoknak.
- Felveszi az előző listát, és eltávolítja azokat az egyezéseket, amelyek nem felelnek meg a MatcherPolicy példányok kritériumainak.
- Az EndpointSelector elemet használja az előző lista végső döntésének meghozatalához.
A végpontok listája a következő szempontok szerint van rangsorolva:
A rendszer minden fázisban feldolgoz minden egyező végpontot, amíg el nem éri azokat EndpointSelector . A EndpointSelector az utolsó fázis. A találatok közül a legmagasabb prioritású végpontot választja ki a legjobb egyezésként. Ha vannak olyan találatok, amelyek prioritása megegyezik a legjobb egyezésével, a rendszer nem egyértelmű egyezés-kivételt ad ki.
Az útvonal elsőbbsége egy pontosabb útvonalsablon alapján van kiszámítva, amely magasabb prioritást kap. Vegyük például a sablonokat /hello és /{message}:
- Mindkettő megfelel az URL-cím elérési útjának
/hello. -
/hellopontosabb, ezért magasabb prioritású.
Általánosságban elmondható, hogy az útvonalak prioritása hatékonyan kiválasztja a gyakorlatban használt URL-sémákhoz leginkább illő találatokat. A kétértelműség elkerülése érdekében csak akkor használja Order , ha szükséges.
Az útválasztás által biztosított bővíthetőség miatt nem lehetséges, hogy az útválasztási rendszer előre kiszámítsa a nem egyértelmű útvonalakat. Vegyük például az útvonalsablonokat /{message:alpha} és /{message:int}:
- A
alphakényszer csak alfabetikus karaktereket egyezik meg. - A
intkényszer csak a számoknak felel meg. - Ezek a sablonok ugyanazt az útvonal elsőbbséget élvezik, de nincs egyetlen URL-cím, amely mindkettőnek megfelel.
- Ha az útválasztási rendszer kétértelmű hibát jelentett az indításkor, az blokkolná ezt az érvényes használati esetet.
Warning
A belső UseEndpoints műveletek sorrendje egyetlen kivétellel nem befolyásolja az útválasztás viselkedését. MapControllerRoute és MapAreaRoute automatikusan rendelési értéket rendelnek a végpontokhoz a meghívásuk sorrendje alapján. Ez a vezérlők hosszú távú viselkedését szimulálja anélkül, hogy az útválasztási rendszer ugyanazokat a garanciákat nyújtja, mint a régebbi útválasztási implementációk.
Végpont-útválasztás a ASP.NET Core-ban:
- Nem rendelkezik az útvonalak fogalmával.
- Nem biztosít rendelési garanciát. A rendszer az összes végpontot egyszerre dolgozza fel.
Útvonalsablon elsőbbsége és végpontválasztási sorrend
Az útvonalsablonok elsőbbsége egy olyan rendszer, amely minden útvonalsablonhoz hozzárendel egy értéket az adottság alapján. Útvonalsablon elsőbbsége:
- Gyakori esetekben nem szükséges módosítani a végpontok sorrendjét.
- Kísérletek az útválasztási viselkedés józan észbeli elvárásainak való megfelelésre.
Fontolja meg például a sablonokat /Products/List és a /Products/{id}. Ésszerű lenne feltételezni, hogy /Products/List jobb választás, mint /Products/{id} az URL útvonal /Products/List számára. Ez azért működik, mert a konstans szegmensnek /List jobb elsőbbsége van a paraméterszegmensnél /{id}.
A sorrend működésének részletei az útvonalsablonok definiálásának módjával vannak összekapcsolva:
- A több szegmenst tartalmazó sablonok pontosabbnak tekinthetők.
- A literális szöveggel rendelkező szegmensek pontosabbak, mint a paraméterszegmensek.
- A korlátozással rendelkező paraméterszegmensek egynél specifikusabbnak tekinthetők anélkül.
- Az összetett szegmenseket kényszerrel rendelkező paraméterszegmensnek tekintjük.
- A catch-all paraméterek a legkevésbé specifikusak. Az Útvonalsablonok szakaszban a catch-all útvonalokkal kapcsolatos fontos információkért tekintse meg a catch-all című témakört.
AZ URL-létrehozás fogalmai
URL-cím létrehozása:
- Az a folyamat, amellyel az útválasztás létrehozhat egy URL-útvonalat az útvonalértékek készlete alapján.
- Lehetővé teszi a végpontok és a hozzájuk hozzáférő URL-címek logikai elkülönítését.
A végpont útválasztása tartalmazza az API-t LinkGenerator .
LinkGenerator egy egyszeri szolgáltatás, amely a DI-től érhető el. Az LinkGenerator API a végrehajtási kérelem környezetén kívül is használható.
Az Mvc.IUrlHelper és az olyan forgatókönyvek, mint IUrlHelpera Címkesegítők, a HTML-segítők és a műveleti eredmények, az API belső használatával biztosítják a LinkGenerator hivatkozásgeneráló képességeket.
A kapcsolatgenerátort a cím - és címsémák fogalma is alátámasztja. A címséma a hivatkozásgenerálás szempontjából megfontolandó végpontok meghatározásának módja. Az útvonalnév és az útvonalértékek forgatókönyvei például sok felhasználó számára ismerősek a vezérlőkből, a Razor Pages pedig címsémaként van implementálva.
A hivatkozásgenerátor a következő bővítménymódszerekkel hivatkozhat vezérlőkre és Razor lapokra:
Ezen metódusok túlterhelései olyan argumentumokat fogadnak el, amelyek tartalmazzák a HttpContext. Ezek a módszerek funkcionálisan egyenértékűek az Url.Action és a Url.Page, de további rugalmasságot és lehetőségeket kínálnak.
A GetPath* metódusok leginkább a Url.Action és Url.Page metódusokhoz hasonlítanak, mivel abszolút elérési utat tartalmazó URI-t hoznak létre. A GetUri* metódusok mindig egy sémát és kiszolgálót tartalmazó abszolút URI-t hoznak létre. Azok a metódusok, amelyek elfogadnak egy HttpContext-t, URI-t generálnak a végrehajtás alatt álló kérés kontextusában. A környezeti útvonalértékek, az URL alapelérési út, a séma és a gazdagép a végrehajtott kérelemből kerülnek felhasználásra, kivéve, ha felülbírálják őket.
LinkGenerator egy címmel kerül meghívásra. Az URI létrehozása két lépésben történik:
- Egy cím a címnek megfelelő végpontok listájához van kötve.
- Az egyes végpontok RoutePattern kiértékelése addig történik, amíg a megadott értékeknek megfelelő útvonalminta nem található. Az eredményül kapott kimenetet a hivatkozásgenerátorhoz megadott többi URI-résszel kombinálják, és visszaadják.
A LinkGenerator által biztosított metódusok támogatják a szabványos hivatkozáslétrehozási képességeket bármilyen címtípus esetén. A hivatkozásgenerátor használatának legkényelmesebb módja egy adott címtípus műveleteit végrehajtó bővítménymetelyek:
| Bővítménymetódus | Description |
|---|---|
| GetPathByAddress | A megadott értékek alapján abszolút elérési úttal rendelkező URI-t hoz létre. |
| GetUriByAddress | Abszolút URI-t hoz létre a megadott értékek alapján. |
Warning
Ügyeljen a hívási LinkGenerator módszerek alábbi következményeire:
Olyan alkalmazáskonfigurációkban körültekintően használjon
GetUri*bővítménymetelyeket, amelyek nem ellenőrzik aHostbejövő kérések fejlécét. Ha aHostbejövő kérések fejléce nincs érvényesítve, a nem megbízható kérések bemenete visszaküldhető az ügyfélnek egy nézetben vagy lapon lévő URI-kban. Javasoljuk, hogy minden éles alkalmazás konfigurálja a kiszolgálót aHostfejléc ismert érvényes értékekkel való ellenőrzésére.Óvatosan használja a LinkGenerator-t köztes rétegekben, különösen a
Map-el vagyMapWhen-el együtt.Map*módosítja a végrehajtási kérelem alap elérési útját, ami hatással van a hivatkozásgenerálás kimenetére. Az összes API lehetővé teszi egy LinkGenerator alap elérési út megadását. Adjon meg egy üres alap elérési utat a kapcsolatgenerálás hatásánakMap*visszavonásához.
Middleware-példa
A következő példában egy köztes szoftver az LinkGenerator API használatával hoz létre egy hivatkozást egy olyan műveletmetódusra, amely felsorolja a termékeket. A hivatkozásgenerátor használata az osztályba való injektálással és hívással GenerateLink az alkalmazás bármely osztálya számára elérhető:
public class ProductsMiddleware
{
private readonly LinkGenerator _linkGenerator;
public ProductsMiddleware(RequestDelegate next, LinkGenerator linkGenerator) =>
_linkGenerator = linkGenerator;
public async Task InvokeAsync(HttpContext httpContext)
{
httpContext.Response.ContentType = MediaTypeNames.Text.Plain;
var productsPath = _linkGenerator.GetPathByAction("Products", "Store");
await httpContext.Response.WriteAsync(
$"Go to {productsPath} to see our products.");
}
}
Útvonalsablonok
A tokenek {} definiálják az útvonalparamétereket, amelyek akkor vannak megkötve, ha az útvonal megfelel. Egy útvonalszakaszban több útvonalparaméter is definiálható, de az útvonalparamétereket literális értékkel kell elválasztani. Például:
{controller=Home}{action=Index}
nem érvényes útvonal, mert nincs szó szerinti érték {controller} és {action} között. Az útvonalparamétereknek névvel kell rendelkezniük, és további attribútumokkal is rendelkezniük kell.
Az útvonalparamétereken (például {id}) és az elérési útelválasztón / kívüli literális szövegnek meg kell egyeznie az URL-címben szereplő szövegekkel. A szövegegyeztetés kis- és nagybetűkre nem érzékeny, és az URL-cím elérési útjának dekódolt ábrázolása alapján történik. Ha egy literális útvonalparaméter elválasztójelével { szeretne megegyezni, vagy }a karakter ismétlésével lépjen ki a határolóból. Például {{ vagy }}.
Csillag * vagy dupla csillag **:
- Az útvonalparaméter előtagjaként használható az URI többi részéhez való kötéshez.
- Az úgynevezett catch-all paraméterek. Például
blog/{**slug}:- Megfelel minden olyan URI-nak, amely a kezdőértékkel
blog/kezdődik, és bármilyen értéket követ. - Az alábbi
blog/érték hozzá van rendelve a slug route értékhez.
- Megfelel minden olyan URI-nak, amely a kezdőértékkel
Warning
A catch-all paraméter helytelenül felelhet meg az útvonalaknak egy útválasztási hiba miatt. A hiba által érintett alkalmazások jellemzői a következők:
- Egy mindent megragadó útvonal, például:
{**slug}" - A catch-all útvonal nem egyezik meg azokkal a kérésekkel, amelyeket meg kellene egyeznie.
- Ha eltávolít más útvonalakat, az összeset megfogó útvonal elkezd működni.
Tekintse meg a GitHub 18677 és 16579 hibáit a példaesetekért, amelyekben ez a hiba felmerül.
A hiba jóváhagyási javítása a .NET Core 3.1.301-ben vagy újabb SDK-ban található. A következő kód beállít egy belső kapcsolót, amely megoldja ezt a hibát:
public static void Main(string[] args)
{
AppContext.SetSwitch("Microsoft.AspNetCore.Routing.UseCorrectCatchAllBehavior",
true);
CreateHostBuilder(args).Build().Run();
}
// Remaining code removed for brevity.
Az általános paraméterek az üres sztringgel is egyezhetnek.
A catch-all paraméter kikerüli a megfelelő karaktereket, amikor az útvonal egy URL-cím létrehozásához van használva, beleértve az elérésiút-elválasztó / karaktereket is. Például a(z) foo/{*path} útvonalértékekkel rendelkező { path = "my/path" } útvonal generál foo/my%2Fpath. Figyelje meg a szökött perjelet. Az útvonal elválasztó karakterek körjáratbeli kezeléséhez használja az ** útvonalparaméter előtagot. Az foo/{**path} útvonal { path = "my/path" }foo/my/path generál.
További szempontokat is figyelembe kell vennie azoknak az URL-mintáknak, amelyek megkísérlik rögzíteni a fájlnevet egy opcionális fájlkiterjesztéssel. Vegyük például a sablont files/{filename}.{ext?}. Ha van érték mindkettő filename és ext számára, mindkettő ki lesz töltve. Ha az URL-címben csak egy érték filename szerepel, az útvonal megfelel, mert a végén a . opcionális. Az alábbi URL-címek egyeznek az útvonalon:
/files/myFile.txt/files/myFile
Előfordulhat, hogy az útvonalparaméterek alapértelmezett értékei úgy vannak meghatározva, hogy a paraméter neve után egy egyenlőségjel (=) választja el az alapértelmezett értéket. Például {controller=Home} úgy határozza meg Home-et, mint az alapértelmezett értéket controller számára. Az alapértelmezett érték akkor használatos, ha a paraméter URL-címében nincs érték. Az útvonalparaméterek megadása nem kötelező, ha hozzáfűz egy kérdőjelet (?) a paraméternév végéhez. Például: id?. A választható értékek és az alapértelmezett útvonalparaméterek közötti különbség a következő:
- Az alapértelmezett értékkel rendelkező útvonalparaméterek mindig létrehoznak egy értéket.
- Az opcionális paraméterek csak akkor tartalmazhatnak értéket, ha a kérelem URL-címe megad egy értéket.
Az útvonalparaméterek olyan korlátozásokkal rendelkezhetnek, amelyeknek meg kell felelniük az URL-címhez kötött útvonalértéknek. Az útvonalparaméter neve után a : és a feltétel neve hozzáadása egy útvonalparaméter beágyazott feltételét határozza meg. Ha a kényszer argumentumokat igényel, zárójelek (...) közé kerülnek a kényszer neve után. Egy másik és egy kényszernév hozzáfűzésével több : is megadható.
A kényszer nevét és argumentumait a rendszer átadja a IInlineConstraintResolver szolgáltatásnak, hogy létrehozhasson egy, az URL-feldolgozásban használandó példányt IRouteConstraint . Az útvonalsablon blog/{article:minlength(10)} például egy korlátozást minlength határoz meg az argumentummal 10. Az útvonalkorlátozásokról és a keretrendszer által biztosított korlátozásokról további információt az Útvonalkorlátozások szakaszban talál.
Az útvonalparaméterek paraméterátalakítókkal is rendelkezhetnek. A paraméterátalakítók átalakítják egy paraméter értékét, amikor hivatkozásokat és egyező műveleteket és oldalakat hoznak létre URL-címekhez. A kényszerekhez hasonlóan a paraméterátalakítók is hozzáadhatók az útvonalparaméteren belül azáltal, hogy a paraméternév után hozzáadnak egy '/' jelet és a transzformátornevet. Az útvonalsablon blog/{article:slugify} például egy transzformátort slugify határoz meg. A paraméterátalakítókkal kapcsolatos további információkért tekintse meg a Paraméterátalakítók szakaszt.
Az alábbi táblázat a példaútvonalak sablonjait és viselkedését mutatja be:
| Útvonalsablon | Példa egyező URI-ra | A kérelem URI-ja... |
|---|---|---|
hello |
/hello |
Csak az egyetlen elérési út /hellofelel meg. |
{Page=Home} |
/ |
Egyezések és halmazok Page a következőre Home: . |
{Page=Home} |
/Contact |
Egyezések és halmazok Page a következőre Contact: . |
{controller}/{action}/{id?} |
/Products/List |
Megfelelteti a Products vezérlőt és a List műveletet. |
{controller}/{action}/{id?} |
/Products/Details/123 |
A Products vezérlőnek és a Details műveletnek felel meg, amelynél id 123-ra van állítva. |
{controller=Home}/{action=Index}/{id?} |
/ |
Leképezi a Home vezérlőt és a Index metódust. A id figyelmen kívül van hagyva. |
{controller=Home}/{action=Index}/{id?} |
/Products |
Leképezi a Products vezérlőt és a Index metódust. A id figyelmen kívül van hagyva. |
Általában a sablon használata a legegyszerűbb útválasztási módszer. Az útvonalsablonon kívül is megadhat kényszereket és alapértelmezett értékeket.
Összetett szegmensek
Az összetett szegmensek feldolgozása a literális elválasztójelek jobbról balra történő egyeztetésével történik , nem mohó módon. Például [Route("/a{b}c{d}")] egy összetett szegmens.
Az összetett szegmensek olyan módon működnek, amelyet meg kell érteni a sikeres használatukhoz. Az ebben a szakaszban található példa bemutatja, hogy az összetett szegmensek miért működnek igazán jól, ha az elválasztó szöveg nem jelenik meg a paraméterértékeken belül. Összetettebb esetekben regexet kell használni, majd manuálisan kinyerni az értékeket.
Warning
Amikor a System.Text.RegularExpressions-t használja nem megbízható bemenetek feldolgozására, meg kell adnia egy időtúllépési értéket. Egy rosszindulatú felhasználó adhat RegularExpressions bemenetet, ami szolgáltatásmegtagadásos támadást okozhat. ASP.NET Core keretrendszer API-k, amelyek RegularExpressions időtúllépést használnak.
Ez egy összefoglaló az /a{b}c{d} sablon és a /abcd URL-útvonal esetén végzett útválasztási lépésekről. Ez | segít az algoritmus működésének vizualizációjában:
- Az első literál, jobbról balra, az
c. Így/abcdkeres jobbról balra, és megtalálja/ab|c|d. - A jobb oldalon (
d) lévő összes elem megfelel az útvonalparaméternek{d}. - A következő karakter, jobbról balra, az
a. Így/ab|c|dkeresésével ott folytatjuk, ahol abbahagytuk, majdamegtalálható/|a|b|c|d. - A jobb oldali (
b) érték most már megfelel az útvonalparaméternek{b}. - Nincs fennmaradó szöveg és nincs fennmaradó útvonalsablon, így ez megfelelésnek számít.
Íme egy példa egy negatív esetre, amely ugyanazt a sablont /a{b}c{d} és az URL-címet /aabcdhasználja. Ez | segít az algoritmus működésének vizualizációjában. Ez az eset nem egyezik, amit ugyanaz az algoritmus magyaráz meg.
- Az első literál, jobbról balra, az
c. Így/aabcdkeres jobbról balra, és megtalálja/aab|c|d. - A jobb oldalon (
d) lévő összes elem megfelel az útvonalparaméternek{d}. - A következő karakter, jobbról balra, az
a. Így/aab|c|dkeresésével ott folytatjuk, ahol abbahagytuk, majdamegtalálható/a|a|b|c|d. - A jobb oldali (
b) érték most már megfelel az útvonalparaméternek{b}. - Ezen a ponton még van szöveg
a, de az algoritmus elfogyott az elemzésre használt útvonalsablonból, így ez nem egyezik.
Mivel a megfelelő algoritmus nem kapzsi:
- Ez megfelel az egyes lépésekben lehetséges legkisebb szövegmennyiségnek.
- Ha az elválasztó érték a paraméterértékek között jelenik meg, az eredmény nem egyezik.
A reguláris kifejezések sokkal jobban szabályozhatják az egyező viselkedésüket.
A mohó egyezés, más néven lusta egyezés, a lehető legnagyobb sztringhez illeszkedik. A nem mohó egyezik a lehető legkisebb sztringgel.
Útválasztás speciális karakterekkel
A speciális karaktereket tartalmazó útválasztás váratlan eredményekhez vezethet. Vegyük például az alábbi műveletmetódusú vezérlőt:
[HttpGet("{id?}/name")]
public async Task<ActionResult<string>> GetName(string id)
{
var todoItem = await _context.TodoItems.FindAsync(id);
if (todoItem == null || todoItem.Name == null)
{
return NotFound();
}
return todoItem.Name;
}
Ha string id a következő kódolt értékeket tartalmazza, váratlan eredmények léphetnek fel:
| ASCII | Encoded |
|---|---|
/ |
%2F |
|
+ |
Az útvonalparaméterek nem mindig vannak dekódolva az URL-ből. Ez a probléma a jövőben megoldható. További információkért tekintse meg ezt a GitHub-problémát;
Útvonalkorlátozások
Az útvonalkorlátozások akkor lépnek érvénybe, amikor egyezés történt a bejövő URL-címhez, és az URL-elérési út tokenizálva van útvonalértékekké. Az útvonalkorlátozások általában ellenőrzik az útvonalsablonon keresztül társított útvonalértéket, és valós vagy hamis döntést hoznak arról, hogy az érték elfogadható-e. Egyes útvonalkorlátozások az útvonalértéken kívüli adatokat használnak annak megfontolására, hogy a kérés irányítható-e. A http-ige alapján például HttpMethodRouteConstraint elfogadhat vagy elutasíthat egy kérést. A korlátozások az útválasztási kérelmekben és a csatolások generálásában használatosak.
Warning
Ne használjon korlátozásokat a bemeneti ellenőrzéshez. Ha bemeneti érvényesítéshez kényszereket használnak, érvénytelen bemenet esetén "Nem található" választ kapunk 404. Az érvénytelen bemenetnek egy Bad Request 400 kell létrehoznia a megfelelő hibaüzenettel. Az útvonalkorlátozások a hasonló útvonalak egyértelműsítésére szolgálnak, nem pedig egy adott útvonal bemeneteinek ellenőrzésére.
Az alábbi táblázat a példaút-korlátozásokat és azok várható viselkedését mutatja be:
| korlátozás | Example | Példa egyezések | Notes |
|---|---|---|---|
int |
{id:int} |
123456789, -123456789 |
Bármely egész számnak megfelel |
bool |
{active:bool} |
true, FALSE |
Egyezések true vagy false. Case-insensitive |
datetime |
{dob:datetime} |
2016-12-31, 2016-12-31 7:32pm |
Megfelel az invariáns kultúra érvényes DateTime értékének. Lásd az előző figyelmeztetést. |
decimal |
{price:decimal} |
49.99, -1,000.01 |
Megfelel az invariáns kultúra érvényes decimal értékének. Lásd az előző figyelmeztetést. |
double |
{weight:double} |
1.234, -1,001.01e8 |
Megfelel az invariáns kultúra érvényes double értékének. Lásd az előző figyelmeztetést. |
float |
{weight:float} |
1.234, -1,001.01e8 |
Megfelel az invariáns kultúra érvényes float értékének. Lásd az előző figyelmeztetést. |
guid |
{id:guid} |
CD2C1638-1638-72D5-1638-DEADBEEF1638 |
Érvényes Guid érték egyező |
long |
{ticks:long} |
123456789, -123456789 |
Érvényes long érték egyező |
minlength(value) |
{username:minlength(4)} |
Rick |
A karakterláncnak legalább 4 karakter hosszúnak kell lennie. |
maxlength(value) |
{filename:maxlength(8)} |
MyFile |
A sztring legfeljebb 8 karakter hosszúságú lehet |
length(length) |
{filename:length(12)} |
somefile.txt |
A sztringnek pontosan 12 karakter hosszúnak kell lennie |
length(min,max) |
{filename:length(8,16)} |
somefile.txt |
A sztringnek legalább 8 és legfeljebb 16 karakter hosszúnak kell lennie |
min(value) |
{age:min(18)} |
19 |
Az egész szám értékének legalább 18-nak kell lennie |
max(value) |
{age:max(120)} |
91 |
Az egész szám értéke legfeljebb 120 lehet |
range(min,max) |
{age:range(18,120)} |
91 |
Az egész szám értéke legalább 18, de legfeljebb 120 lehet |
alpha |
{name:alpha} |
Rick |
A sztringnek egy vagy több betűből a-z kell állnia, függetlenül a kis- és nagybetűktől. |
regex(expression) |
{ssn:regex(^\\d{{3}}-\\d{{2}}-\\d{{4}}$)} |
123-45-6789 |
A karakterláncnak meg kell egyeznie a reguláris kifejezéssel. Tippek a reguláris kifejezés definiálásáról. |
required |
{name:required} |
Rick |
Arra szolgál, hogy kényszerítse, hogy egy nem paraméteres érték jelen legyen az URL-cím létrehozása során |
Warning
Amikor a System.Text.RegularExpressions-t használja nem megbízható bemenetek feldolgozására, meg kell adnia egy időtúllépési értéket. Egy rosszindulatú felhasználó adhat RegularExpressions bemenetet, ami szolgáltatásmegtagadásos támadást okozhat. ASP.NET Core keretrendszer API-k, amelyek RegularExpressions időtúllépést használnak.
Egy paraméterre több, kettőspontra tagolt korlátozás alkalmazható. A következő korlátozás például egy paramétert 1 vagy annál nagyobb egész számra korlátozza:
[Route("users/{id:int:min(1)}")]
public User GetUserById(int id) { }
Warning
Az URL-címet ellenőrző és CLR-típussá konvertált útvonalkorlátozások mindig az invariáns kultúrát használják. Például a CLR típus int vagy DateTime. Ezek a korlátozások feltételezik, hogy az URL-cím nem honosítható. A keretrendszer által biztosított útvonalkorlátozások nem módosítják az útvonalértékekben tárolt értékeket. Az URL-címből elemezett útvonalértékek sztringekként vannak tárolva. A kényszer például float megkísérli lebegőpontossá alakítani az útvonal értékét, de a konvertált érték csak annak ellenőrzésére szolgál, hogy az lebegőpontossá alakítható-e.
Reguláris kifejezések alkalmazása kényszerekben
Warning
Amikor a System.Text.RegularExpressions-t használja nem megbízható bemenetek feldolgozására, meg kell adnia egy időtúllépési értéket. Egy rosszindulatú felhasználó adhat RegularExpressions bemenetet, ami szolgáltatásmegtagadásos támadást okozhat. ASP.NET Core keretrendszer API-k, amelyek RegularExpressions időtúllépést használnak.
A reguláris kifejezések az útvonal-korlátozással regex(...) beágyazott kényszerként is megadhatóak. A MapControllerRoute család metódusai egy korlátozások objektumkonstansát is elfogadják. Ha ezt az űrlapot használja, a sztringértékeket a rendszer normál kifejezésként értelmezi.
A következő kód beágyazott regex kényszert használ:
app.MapGet("{message:regex(^\\d{{3}}-\\d{{2}}-\\d{{4}}$)}",
() => "Inline Regex Constraint Matched");
Az alábbi kód egy objektumkonstanst használ a regex kényszer megadásához:
app.MapControllerRoute(
name: "people",
pattern: "people/{ssn}",
constraints: new { ssn = "^\\d{3}-\\d{2}-\\d{4}$", },
defaults: new { controller = "People", action = "List" });
A ASP.NET Core-keretrendszer hozzáadja RegexOptions.IgnoreCase | RegexOptions.Compiled | RegexOptions.CultureInvariant a reguláris kifejezéskonstruktort. A tagok leírását itt tekinti meg RegexOptions .
A reguláris kifejezések az útválasztás és a C# nyelv által használthoz hasonló határolókat és mintákat használnak. A reguláris kifejezés elemeit escape-elve kell használni. Ha a reguláris kifejezést ^\d{3}-\d{2}-\d{4}$ beágyazott kényszerben szeretné használni, használja az alábbiak egyikét:
- Cserélje le
\a sztringben megadott karaktereket a C#-forrásfájlban szereplő karakterekre\\, hogy elkerülje a sztring-feloldó\karaktert. - Szó szerinti karakterlánckonstansok.
Az útvonal-paraméterek elválasztó karaktereinek, mint például a {, }, [, ], kifejezésben történő megduplázásával megszabadulhatunk, például {{, }}, [[, ]]. Az alábbi táblázat egy reguláris kifejezést és annak szökött verzióját mutatja be:
| Reguláris kifejezés | Megmenekült reguláris kifejezés |
|---|---|
^\d{3}-\d{2}-\d{4}$ |
^\\d{{3}}-\\d{{2}}-\\d{{4}}$ |
^[a-z]{2}$ |
^[[a-z]]{{2}}$ |
Az útválasztás során használt reguláris kifejezések gyakran a ^ karakterrel kezdődnek, és megfelelnek a sztring kezdőpozíciójának. A kifejezések gyakran a $ karakterrel végződnek, és illeszkednek a karaktersor végéhez. A ^ karakterek és $ a karakterek biztosítják, hogy a reguláris kifejezés megegyezik a teljes útvonalparaméter értékével. A ^ és $ karakterek nélkül a reguláris kifejezés bármelyik részsztringgel egyezik meg a sztringen belül, ami gyakran nem kívánatos. Az alábbi táblázat példákat tartalmaz, és elmagyarázza, hogy miért egyeznek vagy miért nem egyeznek:
| Expression | String | Match | Comment |
|---|---|---|---|
[a-z]{2} |
hello | Yes | Részszűrési egyezések |
[a-z]{2} |
123abc456 | Yes | Részszűrési egyezések |
[a-z]{2} |
mz | Yes | Kifejezés egyezése |
[a-z]{2} |
MZ | Yes | Nem érzékeny a kis- és nagybetűkre |
^[a-z]{2}$ |
hello | No | Lásd ^ és $ fent |
^[a-z]{2}$ |
123abc456 | No | Lásd ^ és $ fent |
A reguláris kifejezésszintaxissal kapcsolatos további információkért lásd a .NET-keretrendszer reguláris kifejezéseit.
Ha egy paramétert egy ismert lehetséges értékkészletre szeretne korlátozni, használjon egy reguláris kifejezést. Például {action:regex(^(list|get|create)$)} csak a action következő útvonalértéknek felel meglist: , vagy .getcreate Ha a kényszerszótárba kerül, a sztring ^(list|get|create)$ egyenértékű. A kényszerek szótárában megadott, az ismert kényszerek egyikével nem egyező kényszereket a rendszer normál kifejezésként is kezeli. A sablonon belül átadott, az ismert megkötések egyikével nem egyező kényszereket a rendszer nem kezeli normál kifejezésként.
Egyéni útvonalkorlátozások
Az interfész implementálásával IRouteConstraint egyéni útvonalkorlátozások hozhatók létre. Az IRouteConstraint interfész tartalmaz Match, amely akkor ad vissza true , ha a korlátozás teljesül, és false egyébként.
Ritkán van szükség egyéni útvonalkorlátozásokra. Egyéni útvonalkorlátozás implementálása előtt fontolja meg az alternatív megoldásokat, például a modellkötést.
A ASP.NET Alapvető korlátozások mappa jó példákat kínál a korlátozások létrehozására. Például GuidRouteConstraint.
Egyéni IRouteConstraintbeállítás használatához az útvonalkorlátozás típusát regisztrálni kell az alkalmazás szolgáltatástárolójában ConstraintMap . Egy ConstraintMap egy szótár, amely az útvonalkényszer kulcsokat olyan IRouteConstraint implementációkhoz rendeli, amelyek érvényesítik ezeket a kényszereket. Alkalmazás ConstraintMap-t frissíthetünk Program.cs, akár egy AddRouting hívás részeként, akár közvetlenül RouteOptions konfigurálásával builder.Services.Configure<RouteOptions>. Például:
builder.Services.AddRouting(options =>
options.ConstraintMap.Add("noZeroes", typeof(NoZeroesRouteConstraint)));
Az előző korlátozás a következő kódban van alkalmazva:
[ApiController]
[Route("api/[controller]")]
public class NoZeroesController : ControllerBase
{
[HttpGet("{id:noZeroes}")]
public IActionResult Get(string id) =>
Content(id);
}
Az NoZeroesRouteConstraint megvalósítása megakadályozza, hogy a 0 egy útvonalparaméterben legyen használva.
public class NoZeroesRouteConstraint : IRouteConstraint
{
private static readonly Regex _regex = new(
@"^[1-9]*$",
RegexOptions.CultureInvariant | RegexOptions.IgnoreCase,
TimeSpan.FromMilliseconds(100));
public bool Match(
HttpContext? httpContext, IRouter? route, string routeKey,
RouteValueDictionary values, RouteDirection routeDirection)
{
if (!values.TryGetValue(routeKey, out var routeValue))
{
return false;
}
var routeValueString = Convert.ToString(routeValue, CultureInfo.InvariantCulture);
if (routeValueString is null)
{
return false;
}
return _regex.IsMatch(routeValueString);
}
}
Warning
Amikor a System.Text.RegularExpressions-t használja nem megbízható bemenetek feldolgozására, meg kell adnia egy időtúllépési értéket. Egy rosszindulatú felhasználó adhat RegularExpressions bemenetet, ami szolgáltatásmegtagadásos támadást okozhat. ASP.NET Core keretrendszer API-k, amelyek RegularExpressions időtúllépést használnak.
Az előző kód:
- Megakadályozza
0az{id}útvonal szegmensét. - Látható, hogy egy egyszerű példát mutat be egy egyéni korlátozás implementálására. Éles alkalmazásban nem használható.
Az alábbi kód jobb módszer arra, hogy megakadályozza a id-t tartalmazó 0 feldolgozását.
[HttpGet("{id}")]
public IActionResult Get(string id)
{
if (id.Contains('0'))
{
return StatusCode(StatusCodes.Status406NotAcceptable);
}
return Content(id);
}
Az előző kód a következő előnyökkel rendelkezik a NoZeroesRouteConstraint megközelítéssel szemben:
- Nem igényel egyéni korlátozást.
- Leíróbb hibát ad vissza, ha az útvonalparaméter tartalmazza
0.
Paraméter-átalakítók
Paramétertranszformátorok:
- Hajtson végre egy műveletet a hivatkozás létrehozásához a LinkGenerator használatával.
- Implementálás Microsoft.AspNetCore.Routing.IOutboundParameterTransformer.
- A(z) ConstraintMap használatával konfigurálható.
- Vegye át a paraméter útvonalértékét, és alakítsa át egy új sztringértékké.
- Ennek eredménye az átalakított érték használata a létrehozott hivatkozásban.
Például egy egyéni slugify paraméter-transzformátor az útvonalmintában blog\{article:slugify} a generált adatokkal Url.Action(new { article = "MyTestArticle" })blog\my-test-article.
Fontolja meg a következő IOutboundParameterTransformer megvalósítást:
public class SlugifyParameterTransformer : IOutboundParameterTransformer
{
public string? TransformOutbound(object? value)
{
if (value is null)
{
return null;
}
return Regex.Replace(
value.ToString()!,
"([a-z])([A-Z])",
"$1-$2",
RegexOptions.CultureInvariant,
TimeSpan.FromMilliseconds(100))
.ToLowerInvariant();
}
}
Ha paraméterátalakítót szeretne használni egy útvonalmintában, konfigurálja a következővel ConstraintMapProgram.cs:
builder.Services.AddRouting(options =>
options.ConstraintMap["slugify"] = typeof(SlugifyParameterTransformer));
Az ASP.NET Core keretrendszer paraméterátalakítókat használ, hogy átalakítsa az URI-t a végpont feloldása során. A paraméterátalakítók például átalakítják az útvonal értékeit, amelyeket a area, controller, action és page összepárosítására használnak.
app.MapControllerRoute(
name: "default",
pattern: "{controller:slugify=Home}/{action:slugify=Index}/{id?}");
Az előző útvonalsablon esetén a művelet SubscriptionManagementController.GetAll megfelel az URI-nak /subscription-management/get-all. A paraméter-átalakító nem módosítja a hivatkozás létrehozásához használt útvonalértékeket. Például a Url.Action("GetAll", "SubscriptionManagement") kimenetet ad /subscription-management/get-all.
ASP.NET Core API-konvenciókat biztosít a paraméterátalakítók generált útvonalakkal való használatához:
- Az Microsoft.AspNetCore.Mvc.ApplicationModels.RouteTokenTransformerConvention MVC-konvenció egy megadott paraméterátalakítót alkalmaz az alkalmazás összes attribútumútvonalára. A paraméter-transzformátor átalakítja az attribútumat útvonalának jogkivonatait, amikor lecserélésre kerülnek. További információért lásd: Paraméterátalakító használata a tokencserék testreszabására.
- Razor A Pages az API-konvenciót PageRouteTransformerConvention használja. Ez az egyezmény egy megadott paraméterátalakítót alkalmaz az összes automatikusan felderített Razor lapra. A paraméter-átalakító átalakítja a Pages-útvonalak mappa- és fájlnév-szegmenseit Razor . További információ: Oldalútvonalak testreszabása paraméterátalakítóval.
URL-létrehozási referencia
Ez a szakasz az URL-generálás által implementált algoritmusra mutató hivatkozást tartalmaz. A gyakorlatban az URL-létrehozás legösszetettebb példái vezérlőket vagy Razor oldalakat használnak. További információkért tekintse meg az útválasztást a vezérlőkben .
Az URL-létrehozási folyamat egy hívással LinkGenerator.GetPathByAddress vagy egy hasonló módszerrel kezdődik. A metódus címmel, útvonalértékekkel és opcionálisan az aktuális kéréssel HttpContextkapcsolatos információkkal rendelkezik.
Az első lépés az, hogy a cím segítségével, a cím típusának megfelelő IEndpointAddressScheme<TAddress> alkalmazásával megold egy jelölt végpontkészletet.
Miután a címséma megtalálta a jelölteket, a végpontok iteratív módon lesznek rendezve és feldolgozva, amíg egy URL-létrehozási művelet sikeres nem lesz. Az URL-generálás nem ellenőrzi a kétértelműségeket, az első eredmény a végeredmény.
URL-létrehozás hibaelhárítása naplózással
Az URL-létrehozás hibaelhárításának első lépése a naplózási szint Microsoft.AspNetCore.RoutingTRACE beállítása.
LinkGenerator a feldolgozással kapcsolatos számos részletet naplóz, amelyek hasznosak lehetnek a problémák elhárításához.
Az URL-címgenerálással kapcsolatos részletekért tekintse meg az URL-létrehozási referenciát .
Addresses
A címek az URL-generálás azon koncepciója, amellyel a hívásokat a hivatkozásgenerátorhoz kötik a jelölt végpontok halmazához.
A címek egy bővíthető fogalom, amely alapértelmezés szerint két implementációval rendelkezik:
-
Végpontnév (
string) használata címként:- Hasonló funkciókat biztosít az MVC útvonalnevéhez.
- IEndpointNameMetadata A metaadatok típusát használja.
- Feloldja a megadott sztringet az összes regisztrált végpont metaadataival.
- Kivételt jelez az indításkor, ha több végpont ugyanazt a nevet használja.
- Az általános célú használat a vezérlőkön és Razor lapokon kívül ajánlott.
-
Útvonalértékek (RouteValuesAddress) használata címként:
- Hasonló funkciókat biztosít a vezérlőkhöz és az örökölt Pages URL-címek generálásához.
- Nagyon összetett a bővítéshez és a hibakereséshez.
- Biztosítja az implementációt, amelyet a
IUrlHelperTag Helper-ek, a HTML-segítők, a műveleti eredmények stb. használják.
A címséma szerepe, hogy a cím és az egyező végpontok közötti társítás tetszőleges feltételek szerint történik:
- A végpontnévséma alapszintű szótárkeresést hajt végre.
- Az útvonalértékek sémája a beállítási algoritmus összetett legjobb részhalmazával rendelkezik.
Környezeti értékek és explicit értékek
Az aktuális kérésből az útválasztás az aktuális kérés HttpContext.Request.RouteValuesútvonalértékeit éri el. Az aktuális kéréshez társított értékeket környezeti értékeknek nevezzük. Az egyértelműség kedvéért a dokumentáció a metódusoknak átadott útvonalértékekre hivatkozik explicit értékekként.
Az alábbi példa környezeti értékeket és explicit értékeket mutat be. Környezeti értékeket biztosít az aktuális kérésből és explicit értékekből:
public class WidgetController : ControllerBase
{
private readonly LinkGenerator _linkGenerator;
public WidgetController(LinkGenerator linkGenerator) =>
_linkGenerator = linkGenerator;
public IActionResult Index()
{
var indexPath = _linkGenerator.GetPathByAction(
HttpContext, values: new { id = 17 })!;
return Content(indexPath);
}
// ...
Az előző kód:
- Visszatér
/Widget/Index/17 - Meghajtást kap LinkGenerator által.
A következő kód csak explicit értékeket és nem tartalmaz környezeti értékeket:
var subscribePath = _linkGenerator.GetPathByAction(
"Subscribe", "Home", new { id = 17 })!;
Az előző metódus visszaadja /Home/Subscribe/17
A WidgetController a következőt adja vissza: /Widget/Subscribe/17
var subscribePath = _linkGenerator.GetPathByAction(
HttpContext, "Subscribe", null, new { id = 17 });
A következő kód az aktuális kérelem környezeti értékeiből és explicit értékekből biztosítja a vezérlőt:
public class GadgetController : ControllerBase
{
public IActionResult Index() =>
Content(Url.Action("Edit", new { id = 17 })!);
}
Az előző kódban:
-
/Gadget/Edit/17vissza lesz adva. - Url lekéri a IUrlHelper.
-
Action Egy műveletmetódus abszolút elérési útját tartalmazó URL-címet hoz létre. Az URL-cím a megadott
actionnevet ésrouteértékeket tartalmazza.
Az alábbi kód az aktuális kérelem környezeti értékeit és explicit értékeit tartalmazza:
public class IndexModel : PageModel
{
public void OnGet()
{
var editUrl = Url.Page("./Edit", new { id = 17 });
// ...
}
}
Az előző kód beállítja a url értékét /Edit/17-re, ha a Lap szerkesztése Razor oldal az alábbi oldalirányelvet tartalmazza:
@page "{id:int}"
Ha a Szerkesztés lap nem tartalmazza az "{id:int}" útvonalsablont, akkor url a következő: /Edit?id=17.
Az MVC viselkedése IUrlHelper összetettségi réteget ad hozzá az itt leírt szabályok mellett:
-
IUrlHelpermindig környezeti értékként adja meg az aktuális kérés útvonalértékeit. -
Az IUrlHelper.Action mindig explicit értékként másolja át az aktuális
actionéscontrollerútvonalértékeket, kivéve, ha a fejlesztő felülírja. -
IUrlHelper.Page az aktuális
pageútvonalértéket mindig explicit értékként másolja, kivéve, ha felül van bírálva. -
IUrlHelper.Pagemindig explicit értékként felülbírálja az aktuálishandlerútvonal értékétnullhacsak nincs felülírva.
A felhasználókat gyakran meglepik a környezeti értékek viselkedési részletei, mert úgy tűnik, hogy az MVC nem követi a saját szabályait. Előzmény- és kompatibilitási okokból bizonyos útvonalértékek, például action, controller, pageés handler saját speciális eseti viselkedésük van.
A LinkGenerator.GetPathByAction és LinkGenerator.GetPathByPage által biztosított egyenértékű funkcionalitás a IUrlHelper ezen anomáliáit duplikálja a kompatibilitás érdekében.
URL-létrehozási folyamat
A jelölt végpontok készletének megtalálása után az URL-generáló algoritmus:
- Iteratív módon dolgozza fel a végpontokat.
- Az első sikeres eredményt adja vissza.
A folyamat első lépése az útvonalérték érvénytelenítése. Az útvonalérték érvénytelenítése az a folyamat, amellyel az útválasztás dönti el, hogy a környezeti értékekből melyik útvonalértékeket kell használni, és melyeket figyelmen kívül kell hagyni. A rendszer minden környezeti értéket figyelembe vesz, és kombinálja az explicit értékekkel, vagy figyelmen kívül hagyja.
A környezeti értékek szerepét úgy lehet a legjobban értelmezni, hogy azok célja az alkalmazásfejlesztők gépelési munkájának csökkentése néhány gyakori esetben. Hagyományosan az MVC-hez kapcsolódó forgatókönyvek, amelyekben a környezeti értékek hasznosak:
- Ha ugyanabban a vezérlőben egy másik művelethez kapcsolódik, a vezérlő nevét nem kell megadni.
- Ha ugyanazon a területen egy másik vezérlőhöz kapcsolódik, a terület nevét nem kell megadni.
- Ha ugyanahhoz a műveletmetódushoz kapcsolódik, az útvonalértékeket nem kell megadni.
- Amikor az alkalmazás egy másik részéhez kapcsolódik, nem szeretne olyan útvonalértékeket átvinni, amelyeknek nincs jelentésük az alkalmazás ezen részében.
A LinkGenerator vagy IUrlHelper hívások, amelyek null-t adnak vissza, általában az útvonalértékek érvénytelenítésének nem megfelelő megértése miatt fordulnak elő. Az útvonalértékek érvénytelenítésének hibaelhárításához explicit módon adjon meg több útvonalértéket, és ellenőrizze, hogy ez megoldja-e a problémát.
Az útvonalérték érvénytelenítése azzal a feltételezéssel működik, hogy az alkalmazás URL-sémája hierarchikus, a hierarchia balról jobbra épül fel. Fontolja meg az alapszintű vezérlőútvonal-sablont {controller}/{action}/{id?} , hogy intuitív módon értelmezhesse ennek működését a gyakorlatban. Az érték módosításaérvényteleníti a jobb oldalon megjelenő összes útvonalértéket. Ez tükrözi a hierarchia feltételezését. Ha az alkalmazásnak van egy környezeti értéke id, és a művelet egy másik értéket ad meg a controller számára:
-
idnem lesz újra felhasználva, mert{controller}a bal oldalon{id?}található.
Néhány példa az alapelv bemutatására:
- Ha az explicit értékek egy értéket
idtartalmaznak, a környezeti értékidfigyelmen kívül lesz hagyva. A(z)controllerésactionértékeit használhatjuk. - Ha az explicit értékek egy értéket
actiontartalmaznak, a rendszer figyelmen kívül hagyja a környezeti értékeketaction. Azcontrolleresetében a környezeti értékek felhasználhatók. Ha a explicit értékactioneltér a környezeti értéktőlaction, akkor azidérték nem lesz felhasználva. Ha az explicit értékactionmegegyezik a környezeti értékkelaction, akkor azidérték használható. - Ha az explicit értékek egy értéket
controllertartalmaznak, a rendszer figyelmen kívül hagyja a környezeti értékeketcontroller. Ha az explicit értékcontrollereltér a környezeti értéktőlcontroller, akkor nem használják azactionésidértékeket. Ha az explicit értékcontrollermegegyezik a környezeti értékkelcontroller, akkor azactionésidértékek használhatók.
Ezt a folyamatot tovább bonyolítja az attribútumútvonalak és a dedikált hagyományos útvonalak megléte. A vezérlő hagyományos útvonalai, mint például a {controller}/{action}/{id?}, egy hierarchiát határoznak meg útvonalparaméterekkel.
A vezérlőkhöz és lapokhoz tartozó dedikált hagyományos útvonalak és Razor esetén:
- Az útvonalértékek hierarchiája létezik.
- Nem jelennek meg a sablonban.
Ezekben az esetekben az URL-generálás határozza meg a szükséges értékek fogalmát. A vezérlők és Razor lapok által létrehozott végpontok olyan kötelező értékekkel rendelkeznek, amelyek lehetővé teszik az útvonalértékek érvénytelenítését.
Az útvonalérték érvénytelenítési algoritmusa részletesen:
- A szükséges értékneveket a rendszer kombinálja az útvonalparaméterekkel, majd balról jobbra dolgozza fel őket.
- Minden paraméter esetében a környezeti érték és az explicit érték összehasonlítása:
- Ha a környezeti érték és az explicit érték megegyezik, a folyamat folytatódik.
- Ha a környezeti érték jelen van, és az explicit érték nem, akkor a környezeti érték lesz használva az URL-cím létrehozásakor.
- Ha a környezeti érték nem jelenik meg, és az explicit érték az, utasítsa el a környezeti értéket és az összes további környezeti értéket.
- Ha a környezeti érték és az explicit érték jelen van, és a két érték eltérő, utasítsa el a környezeti értéket és az összes további környezeti értéket.
Ezen a ponton az URL-létrehozási művelet készen áll az útvonalkorlátozások kiértékelésére. Az elfogadott értékek halmaza az alapértelmezett paraméterértékekkel van kombinálva, amelyek a korlátozások számára biztosítottak. Ha a korlátozások mindegyike megfelel, a művelet folytatódik.
Ezután az elfogadott értékek használhatók az útvonalsablon kibontásához. Az útvonalsablon feldolgozása:
- Balról jobbra.
- Minden paraméterhez az elfogadott érték van behelyettesítve.
- A következő különleges esetek esetén:
- Ha az elfogadott értékekből hiányzik egy érték, és a paraméter alapértelmezett értékkel rendelkezik, a rendszer az alapértelmezett értéket használja.
- Ha az elfogadott értékekből hiányzik egy érték, és a paraméter nem kötelező, a feldolgozás folytatódik.
- Ha egy hiányzó opcionális paraméter jobb oldalán található útvonalparaméter rendelkezik értékkel, a művelet meghiúsul.
- Ha lehetséges, összecsukja az egybefüggő alapértelmezett értékű paramétereket és az opcionális paramétereket.
A lekérdezési sztringhez explicit módon megadott értékek, amelyek nem egyeznek az útvonal egy szegmensével, hozzáadódnak a lekérdezési sztringhez. Az alábbi táblázat az útvonalsablon {controller}/{action}/{id?}használatakor mutatja be az eredményt.
| Környezeti értékek | Explicit értékek | Result |
|---|---|---|
| vezérlő = "Home" | action = "Névjegy" | /Home/About |
| vezérlő = "Home" | controller = "Order", action = "About" | /Order/About |
| controller = "Home", szín = "Vörös" | action = "Névjegy" | /Home/About |
| vezérlő = "Home" | action = "About", color = "Red" | /Home/About?color=Red |
Választható útvonalparaméter sorrendje
Az opcionális útvonalparamétereknek az összes szükséges útvonalparaméter után kell érkezniük. A következő kódban a id és name paramétereknek a color paraméter után kell szerepelniük.
using Microsoft.AspNetCore.Mvc;
namespace WebApplication1.Controllers;
[Route("api/[controller]")]
public class MyController : ControllerBase
{
// GET /api/my/red/2/joe
// GET /api/my/red/2
// GET /api/my
[HttpGet("{color}/{id:int?}/{name?}")]
public IActionResult GetByIdAndOptionalName(string color, int id = 1, string? name = null)
{
return Ok($"{color} {id} {name ?? ""}");
}
}
Az útvonalérték érvénytelenítésével kapcsolatos problémák
Az alábbi kód egy olyan URL-létrehozási sémát mutat be, amelyet az útválasztás nem támogat:
app.MapControllerRoute(
"default",
"{culture}/{controller=Home}/{action=Index}/{id?}");
app.MapControllerRoute(
"blog",
"{culture}/{**slug}",
new { controller = "Blog", action = "ReadPost" });
Az előző kódban a rendszer az culture útvonalparamétert használja a honosításhoz. A cél az, hogy a culture paraméter mindig környezeti értékként legyen elfogadva. A culture paraméter azonban nem fogadható el környezeti értékként a szükséges értékek működése miatt:
- Az
"default"útvonalparaméter acultureútvonalsablonbancontrollerbal oldalán található, így acontrollermódosításai nem érvénytelenítikculture. - Az
"blog"útvonalsablonban azcultureútvonalparaméter azcontroller-tól jobbra található, ahogy az a szükséges értékekben megjelenik.
URL-útvonalak elemzése a LinkParser
Az LinkParser osztály támogatja egy URL-elérési út útvonalkészletbe való elemzését. A ParsePathByEndpointName metódus egy végpontnevet és egy URL-elérési utat használ, és visszaadja az URL-útvonalból kinyert útvonalértékeket.
A következő példavezérlőben az GetProduct művelet egy api/Products/{id} útvonalsablont használ, és rendelkezik Name típusú GetProduct-val:
[ApiController]
[Route("api/[controller]")]
public class ProductsController : ControllerBase
{
[HttpGet("{id}", Name = nameof(GetProduct))]
public IActionResult GetProduct(string id)
{
// ...
Ugyanabban a vezérlőosztályban a AddRelatedProduct művelet egy URL-elérési utat vár, pathToRelatedProductamely lekérdezési sztring paraméterként adható meg:
[HttpPost("{id}/Related")]
public IActionResult AddRelatedProduct(
string id, string pathToRelatedProduct, [FromServices] LinkParser linkParser)
{
var routeValues = linkParser.ParsePathByEndpointName(
nameof(GetProduct), pathToRelatedProduct);
var relatedProductId = routeValues?["id"];
// ...
Az előző példában a AddRelatedProduct művelet kinyeri az id útvonal értékét az URL-elérési útból. Ha például a(z) /api/Products/1 URL-elérési út van beállítva, az relatedProductId érték 1-re van állítva. Ez a megközelítés lehetővé teszi az API-ügyfelek számára, hogy URL-útvonalakat használjanak az erőforrásokra való hivatkozáskor anélkül, hogy ismerni kellene az ilyen URL-címek felépítését.
Végpont metaadatainak konfigurálása
Az alábbi hivatkozások a végpont metaadatainak konfigurálásáról nyújtanak információt:
- Cors engedélyezése végponti útválasztással
-
IAuthorizationPolicyProvider-minta egyéni
[MinimumAgeAuthorize]attribútum használatával - Hitelesítés tesztelése az [Engedélyezés] attribútummal
- RequireAuthorization
- A séma kiválasztása az [Engedélyezés] attribútummal
- Szabályzatok alkalmazása az [Engedélyezés] attribútummal
- Szerepköralapú hitelesítés az ASP.NET Core-ban
Hosztok egyezése útvonalakban a RequireHost használatával
RequireHost korlátozást alkalmaz az útvonalra, amely megköveteli a megadott gazdagépet. A RequireHost paraméter vagy a [Gazdagép] lehet:
- Hoszt:
www.domain.com,www.domain.combármely porttal illik. - Gazdagép helyettesítő karakterrel:
*.domain.com, egyezéswww.domain.com,subdomain.domain.comvagywww.subdomain.domain.combármely porton. - Port:
*:5000, megegyezik az 5000-es porttal bármely gazdagépen. - Hoszt és port:
www.domain.com:5000vagy*.domain.com:5000, amely egyezik a hoszttal és a porttal.
Több paraméter is megadható RequireHost vagy [Host] használatával. A kényszer egyezik a paraméterek bármelyikére érvényes gazdagépekkel. Például [Host("domain.com", "*.domain.com")] megegyezik domain.com, www.domain.com és subdomain.domain.com.
Az alábbi kód RequireHost használja a megadott gazdagép megkövetelésére az útvonalon.
app.MapGet("/", () => "Contoso").RequireHost("contoso.com");
app.MapGet("/", () => "AdventureWorks").RequireHost("adventure-works.com");
app.MapHealthChecks("/healthz").RequireHost("*:8080");
A következő kód a [Host] vezérlő attribútumával követeli meg a megadott gazdagépek bármelyikét:
[Host("contoso.com", "adventure-works.com")]
public class HostsController : Controller
{
public IActionResult Index() =>
View();
[Host("example.com")]
public IActionResult Example() =>
View();
}
Ha az attribútumot a [Host] vezérlőre és a műveleti módszerre is alkalmazza a rendszer:
- A műveleten szereplő attribútumot használja a rendszer.
- A vezérlőattribútum figyelmen kívül lesz hagyva.
Útvonalcsoportok
A MapGroup bővítménymetódus segít a végpontcsoportok közös előtaggal való rendszerezésében. Csökkenti az ismétlődő kódot, és lehetővé teszi a végpontok teljes csoportjainak testreszabását egyetlen hívással olyan metódusokhoz, mint a RequireAuthorization és WithMetadata, amelyek végpont metaadatait adják hozzá.
A következő kód például két hasonló végpontcsoportot hoz létre:
app.MapGroup("/public/todos")
.MapTodosApi()
.WithTags("Public");
app.MapGroup("/private/todos")
.MapTodosApi()
.WithTags("Private")
.AddEndpointFilterFactory(QueryPrivateTodos)
.RequireAuthorization();
EndpointFilterDelegate QueryPrivateTodos(EndpointFilterFactoryContext factoryContext, EndpointFilterDelegate next)
{
var dbContextIndex = -1;
foreach (var argument in factoryContext.MethodInfo.GetParameters())
{
if (argument.ParameterType == typeof(TodoDb))
{
dbContextIndex = argument.Position;
break;
}
}
// Skip filter if the method doesn't have a TodoDb parameter.
if (dbContextIndex < 0)
{
return next;
}
return async invocationContext =>
{
var dbContext = invocationContext.GetArgument<TodoDb>(dbContextIndex);
dbContext.IsPrivate = true;
try
{
return await next(invocationContext);
}
finally
{
// This should only be relevant if you're pooling or otherwise reusing the DbContext instance.
dbContext.IsPrivate = false;
}
};
}
public static RouteGroupBuilder MapTodosApi(this RouteGroupBuilder group)
{
group.MapGet("/", GetAllTodos);
group.MapGet("/{id}", GetTodo);
group.MapPost("/", CreateTodo);
group.MapPut("/{id}", UpdateTodo);
group.MapDelete("/{id}", DeleteTodo);
return group;
}
Ebben a forgatókönyvben a Location fejléc relatív címét használhatja a 201 Created eredményben:
public static async Task<Created<Todo>> CreateTodo(Todo todo, TodoDb database)
{
await database.AddAsync(todo);
await database.SaveChangesAsync();
return TypedResults.Created($"{todo.Id}", todo);
}
A végpontok első csoportja csak a /public/todos előtagú kéréseknek felel meg, és hitelesítés nélkül is elérhetők. A végpontok második csoportja csak a /private/todos előtagú kéréseknek felel meg, és hitelesítést igényel.
A QueryPrivateTodosvégpontszűrő-előállító egy helyi függvény, amely módosítja az útvonalkezelő TodoDb paramétereit annak érdekében, hogy lehetővé tegye a privát teendőadatok elérését és tárolását.
Az útvonalcsoportok a beágyazott csoportokat és az összetett előtagmintákat is támogatják útvonalparaméterekkel és korlátozásokkal. Az alábbi példában a user csoporthoz hozzárendelt útvonalkezelő rögzítheti a külső csoport előtagjaiban definiált {org} és {group} útvonalparamétereket.
Az előtag üres is lehet. Ez akkor lehet hasznos, ha végponti metaadatokat vagy szűrőket ad hozzá a végpontok egy csoportjához az útvonalminta módosítása nélkül.
var all = app.MapGroup("").WithOpenApi();
var org = all.MapGroup("{org}");
var user = org.MapGroup("{user}");
user.MapGet("", (string org, string user) => $"{org}/{user}");
A szűrők vagy metaadatok csoporthoz való hozzáadása ugyanúgy viselkedik, mint az egyes végpontokhoz való egyenkénti hozzáadásuk, mielőtt további szűrőket vagy metaadatokat ad hozzá egy belső csoporthoz vagy adott végponthoz.
var outer = app.MapGroup("/outer");
var inner = outer.MapGroup("/inner");
inner.AddEndpointFilter((context, next) =>
{
app.Logger.LogInformation("/inner group filter");
return next(context);
});
outer.AddEndpointFilter((context, next) =>
{
app.Logger.LogInformation("/outer group filter");
return next(context);
});
inner.MapGet("/", () => "Hi!").AddEndpointFilter((context, next) =>
{
app.Logger.LogInformation("MapGet filter");
return next(context);
});
A fenti példában a külső szűrő naplózza a bejövő kérést a belső szűrő előtt annak ellenére, hogy másodikként lett hozzáadva. Mivel a szűrők különböző csoportokra lettek alkalmazva, a egymáshoz viszonyított sorrend nem számít. A rendelésszűrők hozzáadásának sorrendje számít, ha ugyanarra a csoportra vagy egy adott végpontra alkalmazzák.
A /outer/inner/ kérés a következőket naplózza:
/outer group filter
/inner group filter
MapGet filter
Teljesítmény-útmutató útválasztáshoz
Ha egy alkalmazás teljesítményproblémával rendelkezik, az útválasztást gyakran gyanúsítják a problémaként. Azért feltételezik az útválasztás problémáját, mert a keretrendszerek, mint például a vezérlők és a Pages, a naplózási üzenetekben jelzik, mennyi időt töltenek a keretrendszeren belül. Ha jelentős különbség van a vezérlők által jelentett idő és a kérelem teljes időtartama között:
- A fejlesztők megszüntetik az alkalmazáskódjukat a probléma forrásaként.
- Gyakran feltételezzük, hogy az útválasztás az oka.
Az útválasztást több ezer végponton tesztelik. Nem valószínű, hogy egy tipikus alkalmazás teljesítményproblémába ütközik csak túl nagy mérete miatt. A lassú útválasztási teljesítmény leggyakoribb kiváltó oka általában egy rosszul viselkedő egyéni köztes szoftver.
Az alábbi kódminta a késés forrásának szűkítéséhez használható alapszintű technikát mutatja be:
var logger = app.Services.GetRequiredService<ILogger<Program>>();
app.Use(async (context, next) =>
{
var stopwatch = Stopwatch.StartNew();
await next(context);
stopwatch.Stop();
logger.LogInformation("Time 1: {ElapsedMilliseconds}ms", stopwatch.ElapsedMilliseconds);
});
app.UseRouting();
app.Use(async (context, next) =>
{
var stopwatch = Stopwatch.StartNew();
await next(context);
stopwatch.Stop();
logger.LogInformation("Time 2: {ElapsedMilliseconds}ms", stopwatch.ElapsedMilliseconds);
});
app.UseAuthorization();
app.Use(async (context, next) =>
{
var stopwatch = Stopwatch.StartNew();
await next(context);
stopwatch.Stop();
logger.LogInformation("Time 3: {ElapsedMilliseconds}ms", stopwatch.ElapsedMilliseconds);
});
app.MapGet("/", () => "Timing Test.");
Útvonalak időzítése
- Az egyes köztes szoftvereket az előző kódban látható időzítő köztes szoftver egy-egy példányával kell beágyazni.
- Adjon hozzá egy egyedi azonosítót, amely korrelálja az időzítési adatokat a kóddal.
Ez egy alapvető módja annak, hogy szűkítse a késést, ha jelentős, például több mint 10ms. A Time 2 kivonása a Time 1 jelentésből a UseRouting köztes szoftverben töltött időt jelzi.
Az alábbi kód az előző időzítési kód tömörebb megközelítését használja:
public sealed class AutoStopwatch : IDisposable
{
private readonly ILogger _logger;
private readonly string _message;
private readonly Stopwatch _stopwatch;
private bool _disposed;
public AutoStopwatch(ILogger logger, string message) =>
(_logger, _message, _stopwatch) = (logger, message, Stopwatch.StartNew());
public void Dispose()
{
if (_disposed)
{
return;
}
_logger.LogInformation("{Message}: {ElapsedMilliseconds}ms",
_message, _stopwatch.ElapsedMilliseconds);
_disposed = true;
}
}
var logger = app.Services.GetRequiredService<ILogger<Program>>();
var timerCount = 0;
app.Use(async (context, next) =>
{
using (new AutoStopwatch(logger, $"Time {++timerCount}"))
{
await next(context);
}
});
app.UseRouting();
app.Use(async (context, next) =>
{
using (new AutoStopwatch(logger, $"Time {++timerCount}"))
{
await next(context);
}
});
app.UseAuthorization();
app.Use(async (context, next) =>
{
using (new AutoStopwatch(logger, $"Time {++timerCount}"))
{
await next(context);
}
});
app.MapGet("/", () => "Timing Test.");
Potenciálisan költséges útválasztási funkciók
Az alábbi lista betekintést nyújt az alapszintű útvonalsablonokhoz képest viszonylag költséges útválasztási funkciókba:
- Reguláris kifejezések: Olyan reguláris kifejezések írhatók, amelyek összetettek, vagy hosszú ideig futnak kis mennyiségű bemenettel.
- Összetett szegmensek (
{x}-{y}-{z}):- Lényegesen drágábbak, mint egy normál URL-elérési út szegmensének elemzése.
- Ez azt eredményezi, hogy a rendszer sokkal több alsztringet foglal le.
- Szinkron adathozzáférés: Számos összetett alkalmazás rendelkezik adatbázis-hozzáféréssel az útválasztás részeként. Használjon olyan bővíthetőségi pontokat, mint az MatcherPolicy és EndpointSelectorContext, amelyek aszinkronok.
Útmutatás nagy útvonaltáblákhoz
Alapértelmezés szerint az ASP.NET Core egy olyan útválasztási algoritmust használ, amely memória felhasználást cserél fel processzoridőre. Ez jó hatással van arra, hogy az útvonal-egyeztetési idő csak az egyező útvonal hosszától függ, és nem az útvonalak számától. Ez a megközelítés azonban bizonyos esetekben potenciálisan problémás lehet, ha az alkalmazás nagy számú útvonalon (ezres nagyságrendben) rendelkezik, és nagy mennyiségű változó előtag található az útvonalakban. Ha például az útvonalaknak vannak paraméterei az útvonal korai szakaszaiban, például {parameter}/some/literal.
Nem valószínű, hogy egy alkalmazás olyan helyzetbe kerül, ahol ez probléma, kivéve, ha:
- Az alkalmazásban sok útvonal használja ezt a mintát.
- Az alkalmazásban számos útvonal található.
Hogyan állapítható meg, hogy egy alkalmazás szembesül-e a nagy útválasztási táblázat problémájával?
- Két tünetet kell keresni:
- Az alkalmazás lassan indul el az első kéréskor.
- Vegye figyelembe, hogy ez kötelező, de nem elegendő. Számos más nem útvonalbeli probléma is fennáll, mint ami lassú alkalmazásindítást okozhat. Ellenőrizze az alábbi feltételt, hogy pontosan megállapíthassa, hogy az alkalmazás fut-e ebben a helyzetben.
- Az alkalmazás sok memóriát használ fel az indítás során, és egy memóriadump sok
Microsoft.AspNetCore.Routing.Matching.DfaNodepéldányokat mutat.
- Az alkalmazás lassan indul el az első kéréskor.
A probléma megoldása
Számos technika és optimalizálás alkalmazható az útvonalakra, amelyek nagyban javítják ezt a forgatókönyvet:
- Ha lehetséges, alkalmazzon útvonalkorlátozásokat a paraméterekre, például
{parameter:int},{parameter:guid}stb{parameter:regex(\\d+)}.- Ez lehetővé teszi, hogy az útválasztási algoritmus belsőleg optimalizálja az egyezéshez használt struktúrákat, és drasztikusan csökkentse a felhasznált memóriát.
- Az esetek túlnyomó többségében ez elegendő lesz ahhoz, hogy visszatérjen egy elfogadható viselkedéshez.
- Módosítsa az útvonalakat úgy, hogy a paramétereket a sablon későbbi szegmenseibe helyezze át.
- Ez csökkenti a lehetséges "elérési utak" számát, hogy megfeleljen egy adott elérési úthoz megadott végpontnak.
- Használjon dinamikus útvonalat, és végezze el dinamikusan a vezérlőre/lapra való leképezést.
- Ez elérhető
MapDynamicControllerRouteésMapDynamicPageRoutehasználatával.
- Ez elérhető
Útmutató könyvtárszerzőknek
Ez a szakasz útmutatást tartalmaz az útválasztásra alapuló könyvtárak szerzői számára. Ezek a részletek biztosítják, hogy az alkalmazásfejlesztők jól használják az útválasztást kiterjesztő kódtárakat és keretrendszereket.
Végpontok definiálása
Az útválasztást használó keretrendszer létrehozásához, amely az URL-ek egyeztetésére szolgál, kezdje azzal, hogy definiál egy felhasználói élményt, amely a UseEndpoints alapján épül fel.
ÉPÍTS a IEndpointRouteBuilder tetejére. Ez lehetővé teszi, hogy a felhasználók összekeverés nélkül más ASP.NET Core-funkciókkal is megírják a keretrendszert. Minden ASP.NET Core-sablon tartalmazza az útválasztást. Tegyük fel, hogy az útválasztás jelen van és ismerős a felhasználók számára.
// Your framework
app.MapMyFramework(...);
app.MapHealthChecks("/healthz");
A DO egy lezárt betontípust ad vissza az adott implementálásra MapMyFramework(...)IEndpointConventionBuilderirányuló hívásból. A legtöbb keretrendszer-metódus Map... ezt a mintát követi. A IEndpointConventionBuilder felület:
- Lehetővé teszi a metaadatok összeállítását.
- Különféle bővítési módszerek célozzák meg.
A saját típus deklarálása lehetővé teszi saját keretrendszerspecifikus funkciók hozzáadását a szerkesztőhöz. Nem baj, ha egy keretrendszer által deklarált szerkesztőt burkolunk, és hívásokat továbbítunk neki.
// Your framework
app.MapMyFramework(...)
.RequireAuthorization()
.WithMyFrameworkFeature(awesome: true);
app.MapHealthChecks("/healthz");
GONDOLKODJ azon, hogy megírod a saját EndpointDataSource.
EndpointDataSource a végpontok gyűjteményének deklarálására és frissítésére szolgáló alacsony szintű primitív.
EndpointDataSource egy hatékony API, amelyet a vezérlők és Razor a Pages használnak.
Az útválasztási tesztek egy alapvető példával rendelkeznek egy nem frissített adatforrásra.
FONTOLJA MEG a megvalósítást GetGroupedEndpoints. Ez teljes körű vezérlést biztosít a csoportkonvenciók és a csoportosított végpontok végső metaadatai felett. Ez lehetővé teszi például, hogy az egyéni EndpointDataSource implementációk a csoportokhoz hozzáadott végpontszűrőket futtassanak.
NE próbáljon meg alapértelmezés szerint egy objektumot regisztrálni.EndpointDataSource Követelje meg a felhasználóktól, hogy regisztrálják a keretrendszert UseEndpoints. Az útválasztás filozófiája, hogy alapértelmezés szerint semmi nem szerepel benne, és ez UseEndpoints a végpontok regisztrálásának helye.
Útvonalválasztással integrált köztes szoftver létrehozása
FONTOLJA meg a metaadat-típusok interfészként való meghatározását.
A DO lehetővé teszi a metaadat-típusok attribútumként való használatát osztályokon és metódusokon.
public interface ICoolMetadata
{
bool IsCool { get; }
}
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
public class CoolMetadataAttribute : Attribute, ICoolMetadata
{
public bool IsCool => true;
}
Az olyan keretrendszerek, mint a vezérlők és Razor a Lapok, támogatják a metaadat-attribútumok típusokra és metódusokra való alkalmazását. Metaadattípusok deklarálása esetén:
- Elérhetővé teheti őket attribútumként.
- A felhasználók többsége ismeri az attribútumok alkalmazását.
A metaadat-típus felületként való deklarálása további rugalmassági réteget ad:
- A felületek összeállíthatók.
- A fejlesztők deklarálhatják a saját típusaikat, amelyek több szabályzatot kombinálnak.
A DO lehetővé teszi a metaadatok felülbírálását az alábbi példában látható módon:
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
public class SuppressCoolMetadataAttribute : Attribute, ICoolMetadata
{
public bool IsCool => false;
}
[CoolMetadata]
public class MyController : Controller
{
public void MyCool() { }
[SuppressCoolMetadata]
public void Uncool() { }
}
Az alábbi irányelvek követésének legjobb módja, ha elkerüli a jelölő metaadatainak meghatározását:
- Ne csak a metaadat-típus jelenlétét keresse.
- Definiáljon egy tulajdonságot a metaadatokon, és ellenőrizze a tulajdonságot.
A metaadat-gyűjtemény rendezett, és támogatja a prioritás szerinti felülrendelést. Vezérlők esetében a műveletmetódus metaadatai a legspecifikusak.
Tegye a köztes szoftvert hasznossá útválasztással és útválasztás nélkül:
app.UseAuthorization(new AuthorizationPolicy() { ... });
// Your framework
app.MapMyFramework(...).RequireAuthorization();
Ennek az útmutatónak a példájaként vegye figyelembe a köztes UseAuthorization szoftvereket. Az engedélyezési köztes szoftver lehetővé teszi, hogy tartalék szabályzatot adjon át.
A tartalék szabályzat, ha meg van adva, mindkettőre vonatkozik:
- Meghatározott szabályzat nélküli végpontok.
- A végpontnak nem megfelelő kérések.
Ez hasznossá teszi az engedélyezési köztes szoftvereket az útválasztás környezetén kívül. Az engedélyezési köztes szoftver használható a hagyományos köztes szoftver programozásához.
Hibakeresési diagnosztika
A részletes útválasztási diagnosztikai kimenethez állítsa be a Logging:LogLevel:Microsoft értékét Debug-re. A fejlesztési környezetben állítsa be a naplószintet: appsettings.Development.json
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft": "Debug",
"Microsoft.Hosting.Lifetime": "Information"
}
}
}
További erőforrások
- Mintakód megtekintése vagy letöltése (hogyan töltsd le)
Az útválasztás feladata a bejövő HTTP-kérések egyeztetése és a kérések elküldése az alkalmazás végrehajtható végpontjaira. A végpontok az alkalmazás végrehajtható kéréskezelési kódjának egységei. A végpontok az alkalmazásban vannak definiálva, és az alkalmazás indításakor vannak konfigurálva. A végpontegyeztetési folyamat kinyerheti az értékeket a kérelem URL-címéből, és megadhatja ezeket az értékeket a kérelmek feldolgozásához. Az alkalmazás végpontadatainak használatával az útválasztás a végpontokra leképező URL-címeket is képes létrehozni.
Az alkalmazások a következő eszközökkel konfigurálhatják az útválasztást:
- Controllers
- Razor lapok
- SignalR
- gRPC-szolgáltatások
- Végpont-kompatibilis köztes szoftver, mint például a Health Checks.
- Útválasztással regisztrált delegátumok és lambdák.
Ez a cikk a ASP.NET Core útválasztásának alacsony szintű részleteit ismerteti. Az útválasztás konfigurálásával kapcsolatos információk:
- A vezérlőkről lásd: Útválasztás a vezérlőműveletekhez a ASP.NET Core-ban.
- Az Razor Pages konvenciókról lásd az ASP.NET Core oldal útvonal- és alkalmazási konvencióit Razor.
Az útválasztás alapjai
Az alábbi kód egy egyszerű útválasztási példát mutat be:
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.MapGet("/", () => "Hello World!");
app.Run();
Az előző példa egyetlen végpontot tartalmaz a MapGet metódus használatával:
- HA HTTP-kérést
GETküld a rendszer a gyökér URL-címre/:- A kérelem delegáltja végrehajtja.
-
Hello World!az HTTP-válaszként íródik.
- Ha a kérelem metódusa nem
GET, vagy a gyökér URL-címe nem/, a rendszer nem ad vissza útvonal-egyezést, és a rendszer egy HTTP 404-et ad vissza.
Az útválasztás egy köztes szoftverpárt használ, amelyet a UseRouting és a UseEndpoints regisztrál.
-
UseRoutingA köztesszoftver-folyamatnak megfelelő útvonalat ad hozzá. Ez a köztes szoftver megvizsgálja az alkalmazásban definiált végpontokat, és a kérés alapján kiválasztja a legjobb egyezést . -
UseEndpointsvégpontvégrehajtást ad a köztes szoftverfolyamathoz. A kijelölt végponthoz társított delegáltat a program futtatja.
Az alkalmazásoknak általában nem kell, hogy meghívják UseRouting vagy UseEndpoints.
WebApplicationBuilder olyan köztes szoftverfolyamatot állít be, amely az Program.cs-ben hozzáadott köztes szoftvereket a UseRouting és UseEndpoints segítségével burkolja. Az alkalmazások azonban módosíthatják a metódusok sorrendjét UseRouting és UseEndpoints futtatását, ha kifejezetten meghívják ezeket a metódusokat. A következő kód például explicit hívást indít a következőre UseRouting:
app.Use(async (context, next) =>
{
// ...
await next(context);
});
app.UseRouting();
app.MapGet("/", () => "Hello World!");
Az előző kódban:
- A
app.Usehívás regisztrál egy egyedi middleware-t, amely a csővezeték elején fut. - A
UseRoutinghívás úgy konfigurálja az útvonal-illesztési köztes réteget, hogy az az egyéni köztes réteg után fusson. - A
MapGet-vel regisztrált végpont a folyamat végén fut.
Ha az előző példa nem tartalmazott volna hívást a UseRouting-ra, akkor az egyéni köztes szoftver az útvonal illesztési köztes szoftver után futott volna.
Endpoints
A MapGet metódus egy végpont definiálására szolgál. A végpont a következő lehet:
- Az URL-cím és a HTTP-metódus egyeztetésével kijelölve.
- A delegált futtatásával hajtva végre.
Az alkalmazás által egyeztethető és végrehajtható végpontok a UseEndpoints-ben vannak konfigurálva. Például MapGet, MapPost és hasonló metódusok csatlakoztatják a kérelem delegáltjait az útválasztási rendszerhez. További módszerekkel csatlakoztathatók ASP.NET Core-keretrendszer funkciói az útválasztási rendszerhez:
- MapRazorPages a Razor oldalak számára
- MapControllers vezérlőkhöz
- MapHub<THub> for SignalR
- MapGrpcService<TService> for gRPC
Az alábbi példa egy kifinomultabb útvonalsablont tartalmazó útválasztást mutat be:
app.MapGet("/hello/{name:alpha}", (string name) => $"Hello {name}!");
A karakterlánc /hello/{name:alpha} egy útvonalsablon. Egy útvonalsablon használatával konfigurálható a végpont egyeztetése. Ebben az esetben a sablon megfelel a következőnek:
- URL-cím, például
/hello/Docs - Minden olyan URL-elérési út, amely betűrendes karakterek sorozatával
/hello/kezdődik.:alphaolyan útvonalkorlátozást alkalmaz, amely csak betűrendes karaktereknek felel meg. Az útvonalkorlátozásokat a cikk későbbi részében ismertetjük.
Az URL-elérési út második szegmense: {name:alpha}
- A paraméterhez
namevan kötve. - A rendszer rögzíti és tárolja a(z) HttpRequest.RouteValues fájlban.
Az alábbi példa az állapot-ellenőrzéssel és engedélyezéssel rendelkező útválasztást mutatja be:
app.UseAuthentication();
app.UseAuthorization();
app.MapHealthChecks("/healthz").RequireAuthorization();
app.MapGet("/", () => "Hello World!");
Az előző példa bemutatja, hogyan:
- Az engedélyezési köztes szoftver használható útválasztással.
- A végpontok az engedélyezési viselkedés konfigurálására használhatók.
A MapHealthChecks hívás egy állapot-ellenőrzési végpontot ad hozzá. A RequireAuthorization láncolása ehhez a híváshoz egy engedélyezési szabályzatot csatol a végponthoz.
A UseAuthentication és UseAuthorization meghívása hozzáadja a hitelesítési és engedélyezési middleware-t. Ezek a köztes szoftverek UseRouting és UseEndpoints közé vannak helyezve, hogy:
- Nézze meg, melyik végpontot választotta
UseRouting. - Engedélyezési szabályzat alkalmazása a végpontra történő küldés előtt UseEndpoints .
Végpont metaadatai
Az előző példában két végpont található, de csak az állapot-ellenőrzési végpont rendelkezik engedélyezési szabályzattal. Ha a kérelem megfelel az állapot-ellenőrzési végpontnak, /healthza rendszer engedélyezési ellenőrzést végez. Ez azt mutatja be, hogy a végpontokhoz további adatok is csatolhatók. Ezt a további adatot végponti metaadatoknak nevezzük:
- A metaadatok feldolgozhatók útválasztást ismerő köztes szoftver használatával.
- A metaadatok bármilyen .NET típusúak lehetnek.
Útválasztási fogalmak
Az útválasztási rendszer a közbenső szoftver folyamatára épül a hatékony végpontkoncepció hozzáadásával. A végpontok az alkalmazás funkcióinak azon egységeit jelölik, amelyek útválasztás, engedélyezés és ASP.NET Core-rendszerek tetszőleges száma tekintetében különböznek egymástól.
ASP.NET alapvető végpontdefiníció
Az ASP.NET Core-végpont a következő:
- Végrehajtható: rendelkezik egy RequestDelegate.
- Bővíthető: Metaadat-gyűjteménysel rendelkezik.
- Kiválasztható: Opcionálisan útválasztási információkkal rendelkezik.
- Enumerable: A végpontok gyűjteménye a EndpointDataSource való lekéréssel listázható.
Az alábbi kód bemutatja, hogyan kérheti le és vizsgálhatja meg az aktuális kérésnek megfelelő végpontot:
app.Use(async (context, next) =>
{
var currentEndpoint = context.GetEndpoint();
if (currentEndpoint is null)
{
await next(context);
return;
}
Console.WriteLine($"Endpoint: {currentEndpoint.DisplayName}");
if (currentEndpoint is RouteEndpoint routeEndpoint)
{
Console.WriteLine($" - Route Pattern: {routeEndpoint.RoutePattern}");
}
foreach (var endpointMetadata in currentEndpoint.Metadata)
{
Console.WriteLine($" - Metadata: {endpointMetadata}");
}
await next(context);
});
app.MapGet("/", () => "Inspect Endpoint.");
Ha a végpont ki van választva, lekérhető a HttpContext. Tulajdonságai megvizsgálhatók. A végpontobjektumok nem módosíthatók, és a létrehozás után nem módosíthatók. A végpont leggyakoribb típusa a RouteEndpoint.
RouteEndpoint információkat tartalmaz, amelyek lehetővé teszik az útválasztási rendszer számára, hogy kiválaszthassa azt.
Az előző kódban a app.Use egy beágyazott middleware-t konfigurál.
Az alábbi kód azt mutatja, hogy attól függően, hogy a folyamatban hol app.Use van meghívva, előfordulhat, hogy nincs végpont:
// Location 1: before routing runs, endpoint is always null here.
app.Use(async (context, next) =>
{
Console.WriteLine($"1. Endpoint: {context.GetEndpoint()?.DisplayName ?? "(null)"}");
await next(context);
});
app.UseRouting();
// Location 2: after routing runs, endpoint will be non-null if routing found a match.
app.Use(async (context, next) =>
{
Console.WriteLine($"2. Endpoint: {context.GetEndpoint()?.DisplayName ?? "(null)"}");
await next(context);
});
// Location 3: runs when this endpoint matches
app.MapGet("/", (HttpContext context) =>
{
Console.WriteLine($"3. Endpoint: {context.GetEndpoint()?.DisplayName ?? "(null)"}");
return "Hello World!";
}).WithDisplayName("Hello");
app.UseEndpoints(_ => { });
// Location 4: runs after UseEndpoints - will only run if there was no match.
app.Use(async (context, next) =>
{
Console.WriteLine($"4. Endpoint: {context.GetEndpoint()?.DisplayName ?? "(null)"}");
await next(context);
});
Az előző mintában olyan utasítások szerepelnek, amelyek megjelenítik, hogy ki van-e jelölve egy végpont. Az egyértelműség kedvéért a minta megjelenítendő nevet rendel a megadott / végponthoz.
Az előző minta a köztes szoftver folyamaton belüli futtatásának pontos ellenőrzésére UseRoutingUseEndpoints irányuló hívásokat is tartalmaz.
Ennek a kódnak a futtatása egy / URL-címmel megjeleníti:
1. Endpoint: (null)
2. Endpoint: Hello
3. Endpoint: Hello
A kód futtatása bármely más URL-címmel:
1. Endpoint: (null)
2. Endpoint: (null)
4. Endpoint: (null)
Ez a kimenet a következőt mutatja be:
- A végpont mindig null értékű, mielőtt
UseRoutingmeghívják. - Ha talál egyezést, a végpont nem null, és a
UseRoutingés UseEndpoints között van. - A
UseEndpointsköztes szoftver terminál , ha talál egyezést. A terminál köztes szoftverét a cikk későbbi részében definiáljuk. - A köztesréteg csak akkor fut, ha a
UseEndpointsvégrehajtása után nem található egyezés.
A UseRouting köztes szoftver a SetEndpoint metódus használatával csatolja a végpontot az aktuális környezethez. A köztes szoftvereket lecserélheti egyéni UseRouting logikára, és továbbra is élvezheti a végpontok használatának előnyeit. A végpontok alacsony szintű primitívek, például köztes szoftverek, és nem kapcsolódnak az útválasztási megvalósításhoz. A legtöbb alkalmazásnak nem kell egyéni logikára cserélnie UseRouting .
A UseEndpoints köztes szoftvert úgy alakították ki, hogy a UseRouting köztes szoftverrel tandem használatra legyen. A végpontok végrehajtásának alapvető logikája nem bonyolult. A végpont lekérésére GetEndpoint használata, majd annak RequestDelegate tulajdonságának meghívása.
Az alábbi kód bemutatja, hogy a köztes szoftver hogyan befolyásolhatja vagy reagálhat az útválasztásra:
app.UseHttpMethodOverride();
app.UseRouting();
app.Use(async (context, next) =>
{
if (context.GetEndpoint()?.Metadata.GetMetadata<RequiresAuditAttribute>() is not null)
{
Console.WriteLine($"ACCESS TO SENSITIVE DATA AT: {DateTime.UtcNow}");
}
await next(context);
});
app.MapGet("/", () => "Audit isn't required.");
app.MapGet("/sensitive", () => "Audit required for sensitive data.")
.WithMetadata(new RequiresAuditAttribute());
public class RequiresAuditAttribute : Attribute { }
Az előző példa két fontos fogalmat mutat be:
- A köztes szoftver előzetesen futtatható a
UseRoutingelőtt, hogy módosítsa azokat az adatokat, amelyeken az útválasztás működik.- Az útválasztás előtt megjelenő köztes szoftver általában módosítja a kérés bizonyos tulajdonságát, például UseRewriter: , UseHttpMethodOverridevagy UsePathBase.
- A middleware a
UseRoutingés UseEndpoints között futtatható annak érdekében, hogy az útválasztás eredményeit feldolgozza, mielőtt a végpont végrehajtásra kerül.- Köztes szoftver, amely a
UseRoutingésUseEndpointsközött fut:- A végpontok megértéséhez általában a metaadatokat vizsgálja meg.
- Gyakran hoz biztonsági döntéseket, mint a
UseAuthorizationésUseCors.
- A köztes szoftver és a metaadatok kombinációja lehetővé teszi a szabályzatok végpontonkénti konfigurálását.
- Köztes szoftver, amely a
Az előző kód egy végpontonkénti szabályzatokat támogató egyéni köztes szoftver példáját mutatja be. A köztes szoftver naplót ír a konzol bizalmas adataihoz való hozzáférésről. A köztes szoftver konfigurálható egy végpont metaadatokkal történő naplózásáraRequiresAuditAttribute. Ez a minta egy feliratkozásos mintát mutat be, amelyben csak a bizalmasként megjelölt végpontokat naplózzák. Ezt a logikát meg lehet határozni fordítottan, például naplózva mindent, ami nincs biztonságosként megjelölve. A végpont metaadat-rendszere rugalmas. Ez a logika bármilyen módon megtervezhető a használati esetnek megfelelően.
Az előző mintakód a végpontok alapfogalmait mutatja be. A minta nem éles használatra készült. A naplózási napló köztes szoftverének teljesebb verziója a következő lenne:
- Jelentkezzen be egy fájlba vagy adatbázisba.
- Adjon meg olyan részleteket, mint a felhasználó, az IP-cím, a bizalmas végpont neve stb.
A naplózási szabályzat metaadatai RequiresAuditAttribute egy Attribute-ként vannak definiálva a könnyebb használat érdekében olyan osztályalapú keretrendszerekkel, mint például a vezérlők és SignalR. A kódhoz vezető útvonal használata esetén:
- A metaadatok egy builder API-val vannak csatolva.
- Az osztályalapú keretrendszerek a végpontok létrehozásakor tartalmazzák a megfelelő metódus és osztály összes attribútumát.
A metaadat-típusok ajánlott eljárása, hogy interfészként vagy attribútumként definiálja őket. Az interfészek és attribútumok lehetővé teszik a kód újrafelhasználását. A metaadat-rendszer rugalmas, és nem ír elő korlátozásokat.
Terminál köztes szoftver összehasonlítása az útválasztással
Az alábbi példa a terminál köztes szoftverét és az útválasztást mutatja be:
// Approach 1: Terminal Middleware.
app.Use(async (context, next) =>
{
if (context.Request.Path == "/")
{
await context.Response.WriteAsync("Terminal Middleware.");
return;
}
await next(context);
});
app.UseRouting();
// Approach 2: Routing.
app.MapGet("/Routing", () => "Routing.");
A Approach 1:-vel látható köztes szoftver stílusa a terminál köztes szoftver. Terminál köztes szoftvernek nevezzük, mert egyező műveletet hajt végre:
- Az előző mintában az illesztési művelet a
Path == "/"a köztes szoftverhez ésPath == "/Routing"az útválasztáshoz tartozik. - Ha egy egyezés sikeres, végrehajt néhány funkciót, és visszatér anélkül, hogy meghívná a
nextköztes szoftvert.
Terminál köztes szoftvernek nevezik, mert leállítja a keresést, végrehajt néhány funkciót, majd visszaadja.
Az alábbi lista összehasonlítja a terminál köztes szoftverét az útválasztással:
- Mindkét módszer lehetővé teszi a feldolgozási folyamat leállítását:
- A köztes szoftver a
nextmeghívása helyett visszatéréssel leállítja a futószalagot. - A végpontok mindig terminálok.
- A köztes szoftver a
- A terminálközvetítő lehetővé teszi a köztes szoftver tetszőleges helyen való elhelyezését a folyamatban:
- A végpontok a UseEndpoints pozíción futnak.
- A terminál köztes réteg lehetővé teszi, hogy tetszőleges kód határozza meg, mikor egyezik a köztes szoftver.
- Az egyéni útvonalegyeztető kód részletes lehet, és nehezen írható helyesen.
- Az útválasztás egyszerű megoldásokat kínál a tipikus alkalmazásokhoz. A legtöbb alkalmazás nem igényel egyéni útvonalegyeztető kódot.
- A végpontok interfészei köztes szoftverekkel, mint például
UseAuthorizationésUseCors, kommunikálnak.- A
UseAuthorizationvagyUseCorsterminálközvetítő használata manuális beavatkozást igényel az engedélyezési rendszerbe való interfészépítés során.
- A
Egy végpont mindkettőt definiálja:
- A kérések feldolgozására jogosult meghatalmazott.
- Tetszőleges metaadatok gyűjteménye. A metaadatok az egyes végpontokhoz csatolt szabályzatokon és konfigurációkon alapuló, átfogó problémák megvalósítására szolgálnak.
A terminál köztes szoftver hatékony eszköz lehet, de a következőt igényelheti:
- Jelentős mennyiségű kódolás és tesztelés.
- Manuális integráció más rendszerekkel a kívánt rugalmasság elérése érdekében.
A terminál middleware megírása előtt fontolja meg az útvonalvezérléssel való integrálást.
A meglévő terminálközvetítmények, amelyek integrálódnak a Map-pal vagy a MapWhen, általában útválasztást támogató végponttá alakíthatók. MapHealthChecks a routerelem mintáját mutatja be:
- Bővítménymetódus írása a fájlra IEndpointRouteBuilder.
- Beágyazott köztes szoftverfolyamat létrehozása a következővel CreateApplicationBuilder: .
- Csatolja a köztes szoftvert az új folyamathoz. Ebben az esetben: UseHealthChecks.
- Build a köztes szoftverfolyamatot egy RequestDelegate.
- Hívja meg
Mapés adja meg az új köztes szoftverfolyamatot. - Adja vissza az
Mapáltal biztosított építőobjektumot a bővítménymetódusból.
Az alábbi kód a MapHealthChecks használatát mutatja be:
app.UseAuthentication();
app.UseAuthorization();
app.MapHealthChecks("/healthz").RequireAuthorization();
Az előző minta bemutatja, miért fontos az építő objektum visszaadása. A szerkesztőobjektum visszaadásával az alkalmazás fejlesztője olyan szabályzatokat konfigurálhat, mint a végpont engedélyezése. Ebben a példában az állapot-ellenőrző köztes szoftver nem rendelkezik közvetlen integrációval az engedélyezési rendszerrel.
A metaadat-rendszer a terminál köztes szoftvereket használó bővíthetőségi szerzők által tapasztalt problémákra válaszul jött létre. Minden köztes szoftver esetében problémás a saját integráció megvalósítása az engedélyezési rendszerrel.
URL-cím egyeztetése
- Az a folyamat, amellyel az útválasztás megfelel a végpontnak küldött bejövő kérésnek.
- Az URL-elérési út és a fejlécek adatain alapul.
- A kérelemben szereplő bármely adatra kiterjeszthető.
Az útvonalkezelő köztes szoftver végrehajtásakor beállít Endpoint és útvonali értékeket egy kérés tulajdonságához az HttpContext aktuális kérés alapján.
- A HttpContext.GetEndpoint hívása megkapja a végpontot.
-
HttpRequest.RouteValueslekéri az útvonalértékek gyűjteményét.
A köztes szoftver azután fut, hogy az útválasztási köztes szoftver megvizsgálhatja a végpontot, és végrehajthatja a műveletet. Egy engedélyezési köztes szoftver például kikérdezheti a végpont metaadatgyűjteményét egy engedélyezési szabályzathoz. A kérelemfeldolgozási folyamat összes köztes szoftverének végrehajtása után a rendszer meghívja a kijelölt végpont delegáltját.
A végponti útválasztás útválasztási rendszere felelős az összes irányítási döntésért. Mivel a köztes szoftver a kiválasztott végponton alapuló szabályzatokat alkalmaz, fontos, hogy:
- Minden olyan döntés, amely befolyásolhatja a küldést vagy a biztonsági szabályzatok alkalmazását, az útválasztási rendszeren belül történik.
Warning
A visszamenőleges kompatibilitás érdekében a vezérlő vagy Razor a Pages végpont delegáltjának végrehajtásakor a rendszer az eddig végrehajtott kérésfeldolgozás alapján a megfelelő értékekre állítja RouteContext.RouteData be a tulajdonságokat.
A RouteContext típus elavultként lesz megjelölve egy későbbi kiadásban:
- Migrálás
RouteData.ValuesHttpRequest.RouteValues-re. - Migrálja
RouteData.DataTokensaz IDataTokensMetadata lekéréséhez a végpont metaadataiból.
Az URL-egyeztetés konfigurálható fázisokban működik. Minden fázisban a kimenet egyezések halmaza. Az egyezések halmaza a következő szakaszban tovább szűkíthető. Az útválasztási implementáció nem garantálja az egyező végpontok feldolgozási sorrendjét. Az összes lehetséges találat feldolgozása egyszerre történik. Az URL-egyeztetési fázisok a következő sorrendben történnek. ASP.NET Core:
- Feldolgozza az URL-útvonalat a végpontok és útvonalsablonjaik alapján, és összegyűjti az összes egyezést.
- A megelőző listát veszi alapul, és eltávolítja azokat az egyezéseket, amelyek nem felelnek meg az útvonal-korlátozásoknak.
- Felveszi az előző listát, és eltávolítja azokat az egyezéseket, amelyek nem felelnek meg a MatcherPolicy példányok kritériumainak.
- Az EndpointSelector elemet használja az előző lista végső döntésének meghozatalához.
A végpontok listája a következő szempontok szerint van rangsorolva:
A rendszer minden fázisban feldolgoz minden egyező végpontot, amíg el nem éri azokat EndpointSelector . A EndpointSelector az utolsó fázis. A találatok közül a legmagasabb prioritású végpontot választja ki a legjobb egyezésként. Ha vannak olyan találatok, amelyek prioritása megegyezik a legjobb egyezésével, a rendszer nem egyértelmű egyezés-kivételt ad ki.
Az útvonal elsőbbsége egy pontosabb útvonalsablon alapján van kiszámítva, amely magasabb prioritást kap. Vegyük például a sablonokat /hello és /{message}:
- Mindkettő megfelel az URL-cím elérési útjának
/hello. -
/hellopontosabb, ezért magasabb prioritású.
Általánosságban elmondható, hogy az útvonalak prioritása hatékonyan kiválasztja a gyakorlatban használt URL-sémákhoz leginkább illő találatokat. A kétértelműség elkerülése érdekében csak akkor használja Order , ha szükséges.
Az útválasztás által biztosított bővíthetőség miatt nem lehetséges, hogy az útválasztási rendszer előre kiszámítsa a nem egyértelmű útvonalakat. Vegyük például az útvonalsablonokat /{message:alpha} és /{message:int}:
- A
alphakényszer csak alfabetikus karaktereket egyezik meg. - A
intkényszer csak a számoknak felel meg. - Ezek a sablonok ugyanazt az útvonal elsőbbséget élvezik, de nincs egyetlen URL-cím, amely mindkettőnek megfelel.
- Ha az útválasztási rendszer kétértelmű hibát jelentett az indításkor, az blokkolná ezt az érvényes használati esetet.
Warning
A belső UseEndpoints műveletek sorrendje egyetlen kivétellel nem befolyásolja az útválasztás viselkedését. MapControllerRoute és MapAreaRoute automatikusan rendelési értéket rendelnek a végpontokhoz a meghívásuk sorrendje alapján. Ez a vezérlők hosszú távú viselkedését szimulálja anélkül, hogy az útválasztási rendszer ugyanazokat a garanciákat nyújtja, mint a régebbi útválasztási implementációk.
Végpont-útválasztás a ASP.NET Core-ban:
- Nem rendelkezik az útvonalak fogalmával.
- Nem biztosít rendelési garanciát. A rendszer az összes végpontot egyszerre dolgozza fel.
Útvonalsablon elsőbbsége és végpontválasztási sorrend
Az útvonalsablonok elsőbbsége egy olyan rendszer, amely minden útvonalsablonhoz hozzárendel egy értéket az adottság alapján. Útvonalsablon elsőbbsége:
- Gyakori esetekben nem szükséges módosítani a végpontok sorrendjét.
- Kísérletek az útválasztási viselkedés józan észbeli elvárásainak való megfelelésre.
Fontolja meg például a sablonokat /Products/List és a /Products/{id}. Ésszerű lenne feltételezni, hogy /Products/List jobb választás, mint /Products/{id} az URL útvonal /Products/List számára. Ez azért működik, mert a konstans szegmensnek /List jobb elsőbbsége van a paraméterszegmensnél /{id}.
A sorrend működésének részletei az útvonalsablonok definiálásának módjával vannak összekapcsolva:
- A több szegmenst tartalmazó sablonok pontosabbnak tekinthetők.
- A literális szöveggel rendelkező szegmensek pontosabbak, mint a paraméterszegmensek.
- A korlátozással rendelkező paraméterszegmensek egynél specifikusabbnak tekinthetők anélkül.
- Az összetett szegmenseket kényszerrel rendelkező paraméterszegmensnek tekintjük.
- A catch-all paraméterek a legkevésbé specifikusak. Az Útvonalsablonok szakaszban a catch-all útvonalokkal kapcsolatos fontos információkért tekintse meg a catch-all című témakört.
AZ URL-létrehozás fogalmai
URL-cím létrehozása:
- Az a folyamat, amellyel az útválasztás létrehozhat egy URL-útvonalat az útvonalértékek készlete alapján.
- Lehetővé teszi a végpontok és a hozzájuk hozzáférő URL-címek logikai elkülönítését.
A végpont útválasztása tartalmazza az API-t LinkGenerator .
LinkGenerator egy egyszeri szolgáltatás, amely a DI-től érhető el. Az LinkGenerator API a végrehajtási kérelem környezetén kívül is használható.
Az Mvc.IUrlHelper és az olyan forgatókönyvek, mint IUrlHelpera Címkesegítők, a HTML-segítők és a műveleti eredmények, az API belső használatával biztosítják a LinkGenerator hivatkozásgeneráló képességeket.
A kapcsolatgenerátort a cím - és címsémák fogalma is alátámasztja. A címséma a hivatkozásgenerálás szempontjából megfontolandó végpontok meghatározásának módja. Az útvonalnév és az útvonalértékek forgatókönyvei például sok felhasználó számára ismerősek a vezérlőkből, a Razor Pages pedig címsémaként van implementálva.
A hivatkozásgenerátor a következő bővítménymódszerekkel hivatkozhat vezérlőkre és Razor lapokra:
Ezen metódusok túlterhelései olyan argumentumokat fogadnak el, amelyek tartalmazzák a HttpContext. Ezek a módszerek funkcionálisan egyenértékűek az Url.Action és a Url.Page, de további rugalmasságot és lehetőségeket kínálnak.
A GetPath* metódusok leginkább a Url.Action és Url.Page metódusokhoz hasonlítanak, mivel abszolút elérési utat tartalmazó URI-t hoznak létre. A GetUri* metódusok mindig egy sémát és kiszolgálót tartalmazó abszolút URI-t hoznak létre. Azok a metódusok, amelyek elfogadnak egy HttpContext-t, URI-t generálnak a végrehajtás alatt álló kérés kontextusában. A környezeti útvonalértékek, az URL alapelérési út, a séma és a gazdagép a végrehajtott kérelemből kerülnek felhasználásra, kivéve, ha felülbírálják őket.
LinkGenerator egy címmel kerül meghívásra. Az URI létrehozása két lépésben történik:
- Egy cím a címnek megfelelő végpontok listájához van kötve.
- Az egyes végpontok RoutePattern kiértékelése addig történik, amíg a megadott értékeknek megfelelő útvonalminta nem található. Az eredményül kapott kimenetet a hivatkozásgenerátorhoz megadott többi URI-résszel kombinálják, és visszaadják.
A LinkGenerator által biztosított metódusok támogatják a szabványos hivatkozáslétrehozási képességeket bármilyen címtípus esetén. A hivatkozásgenerátor használatának legkényelmesebb módja egy adott címtípus műveleteit végrehajtó bővítménymetelyek:
| Bővítménymetódus | Description |
|---|---|
| GetPathByAddress | A megadott értékek alapján abszolút elérési úttal rendelkező URI-t hoz létre. |
| GetUriByAddress | Abszolút URI-t hoz létre a megadott értékek alapján. |
Warning
Ügyeljen a hívási LinkGenerator módszerek alábbi következményeire:
Olyan alkalmazáskonfigurációkban körültekintően használjon
GetUri*bővítménymetelyeket, amelyek nem ellenőrzik aHostbejövő kérések fejlécét. Ha aHostbejövő kérések fejléce nincs érvényesítve, a nem megbízható kérések bemenete visszaküldhető az ügyfélnek egy nézetben vagy lapon lévő URI-kban. Javasoljuk, hogy minden éles alkalmazás konfigurálja a kiszolgálót aHostfejléc ismert érvényes értékekkel való ellenőrzésére.Óvatosan használja a LinkGenerator-t köztes rétegekben, különösen a
Map-el vagyMapWhen-el együtt.Map*módosítja a végrehajtási kérelem alap elérési útját, ami hatással van a hivatkozásgenerálás kimenetére. Az összes API lehetővé teszi egy LinkGenerator alap elérési út megadását. Adjon meg egy üres alap elérési utat a kapcsolatgenerálás hatásánakMap*visszavonásához.
Middleware-példa
A következő példában egy köztes szoftver az LinkGenerator API használatával hoz létre egy hivatkozást egy olyan műveletmetódusra, amely felsorolja a termékeket. A hivatkozásgenerátor használata az osztályba való injektálással és hívással GenerateLink az alkalmazás bármely osztálya számára elérhető:
public class ProductsMiddleware
{
private readonly LinkGenerator _linkGenerator;
public ProductsMiddleware(RequestDelegate next, LinkGenerator linkGenerator) =>
_linkGenerator = linkGenerator;
public async Task InvokeAsync(HttpContext httpContext)
{
httpContext.Response.ContentType = MediaTypeNames.Text.Plain;
var productsPath = _linkGenerator.GetPathByAction("Products", "Store");
await httpContext.Response.WriteAsync(
$"Go to {productsPath} to see our products.");
}
}
Útvonalsablonok
A tokenek {} definiálják az útvonalparamétereket, amelyek akkor vannak megkötve, ha az útvonal megfelel. Egy útvonalszakaszban több útvonalparaméter is definiálható, de az útvonalparamétereket literális értékkel kell elválasztani. Például:
{controller=Home}{action=Index}
nem érvényes útvonal, mert nincs szó szerinti érték {controller} és {action} között. Az útvonalparamétereknek névvel kell rendelkezniük, és további attribútumokkal is rendelkezniük kell.
Az útvonalparamétereken (például {id}) és az elérési útelválasztón / kívüli literális szövegnek meg kell egyeznie az URL-címben szereplő szövegekkel. A szövegegyeztetés kis- és nagybetűkre nem érzékeny, és az URL-cím elérési útjának dekódolt ábrázolása alapján történik. Ha egy literális útvonalparaméter elválasztójelével { szeretne megegyezni, vagy }a karakter ismétlésével lépjen ki a határolóból. Például {{ vagy }}.
Csillag * vagy dupla csillag **:
- Az útvonalparaméter előtagjaként használható az URI többi részéhez való kötéshez.
- Az úgynevezett catch-all paraméterek. Például
blog/{**slug}:- Megfelel minden olyan URI-nak, amely a kezdőértékkel
blog/kezdődik, és bármilyen értéket követ. - Az alábbi
blog/érték hozzá van rendelve a slug route értékhez.
- Megfelel minden olyan URI-nak, amely a kezdőértékkel
Warning
A catch-all paraméter helytelenül felelhet meg az útvonalaknak egy útválasztási hiba miatt. A hiba által érintett alkalmazások jellemzői a következők:
- Egy mindent megragadó útvonal, például:
{**slug}" - A catch-all útvonal nem egyezik meg azokkal a kérésekkel, amelyeket meg kellene egyeznie.
- Ha eltávolít más útvonalakat, az összeset megfogó útvonal elkezd működni.
Tekintse meg a GitHub 18677 és 16579 hibáit a példaesetekért, amelyekben ez a hiba felmerül.
A hiba jóváhagyási javítása a .NET Core 3.1.301-ben vagy újabb SDK-ban található. A következő kód beállít egy belső kapcsolót, amely megoldja ezt a hibát:
public static void Main(string[] args)
{
AppContext.SetSwitch("Microsoft.AspNetCore.Routing.UseCorrectCatchAllBehavior",
true);
CreateHostBuilder(args).Build().Run();
}
// Remaining code removed for brevity.
Az általános paraméterek az üres sztringgel is egyezhetnek.
A catch-all paraméter kikerüli a megfelelő karaktereket, amikor az útvonal egy URL-cím létrehozásához van használva, beleértve az elérésiút-elválasztó / karaktereket is. Például a(z) foo/{*path} útvonalértékekkel rendelkező { path = "my/path" } útvonal generál foo/my%2Fpath. Figyelje meg a szökött perjelet. Az útvonal elválasztó karakterek körjáratbeli kezeléséhez használja az ** útvonalparaméter előtagot. Az foo/{**path} útvonal { path = "my/path" }foo/my/path generál.
További szempontokat is figyelembe kell vennie azoknak az URL-mintáknak, amelyek megkísérlik rögzíteni a fájlnevet egy opcionális fájlkiterjesztéssel. Vegyük például a sablont files/{filename}.{ext?}. Ha van érték mindkettő filename és ext számára, mindkettő ki lesz töltve. Ha az URL-címben csak egy érték filename szerepel, az útvonal megfelel, mert a végén a . opcionális. Az alábbi URL-címek egyeznek az útvonalon:
/files/myFile.txt/files/myFile
Előfordulhat, hogy az útvonalparaméterek alapértelmezett értékei úgy vannak meghatározva, hogy a paraméter neve után egy egyenlőségjel (=) választja el az alapértelmezett értéket. Például {controller=Home} úgy határozza meg Home-et, mint az alapértelmezett értéket controller számára. Az alapértelmezett érték akkor használatos, ha a paraméter URL-címében nincs érték. Az útvonalparaméterek megadása nem kötelező, ha hozzáfűz egy kérdőjelet (?) a paraméternév végéhez. Például: id?. A választható értékek és az alapértelmezett útvonalparaméterek közötti különbség a következő:
- Az alapértelmezett értékkel rendelkező útvonalparaméterek mindig létrehoznak egy értéket.
- Az opcionális paraméterek csak akkor tartalmazhatnak értéket, ha a kérelem URL-címe megad egy értéket.
Az útvonalparaméterek olyan korlátozásokkal rendelkezhetnek, amelyeknek meg kell felelniük az URL-címhez kötött útvonalértéknek. Az útvonalparaméter neve után a : és a feltétel neve hozzáadása egy útvonalparaméter beágyazott feltételét határozza meg. Ha a kényszer argumentumokat igényel, zárójelek (...) közé kerülnek a kényszer neve után. Egy másik és egy kényszernév hozzáfűzésével több : is megadható.
A kényszer nevét és argumentumait a rendszer átadja a IInlineConstraintResolver szolgáltatásnak, hogy létrehozhasson egy, az URL-feldolgozásban használandó példányt IRouteConstraint . Az útvonalsablon blog/{article:minlength(10)} például egy korlátozást minlength határoz meg az argumentummal 10. Az útvonalkorlátozásokról és a keretrendszer által biztosított korlátozásokról további információt az Útvonalkorlátozások szakaszban talál.
Az útvonalparaméterek paraméterátalakítókkal is rendelkezhetnek. A paraméterátalakítók átalakítják egy paraméter értékét, amikor hivatkozásokat és egyező műveleteket és oldalakat hoznak létre URL-címekhez. A kényszerekhez hasonlóan a paraméterátalakítók is hozzáadhatók az útvonalparaméteren belül azáltal, hogy a paraméternév után hozzáadnak egy '/' jelet és a transzformátornevet. Az útvonalsablon blog/{article:slugify} például egy transzformátort slugify határoz meg. A paraméterátalakítókkal kapcsolatos további információkért tekintse meg a Paraméterátalakítók szakaszt.
Az alábbi táblázat a példaútvonalak sablonjait és viselkedését mutatja be:
| Útvonalsablon | Példa egyező URI-ra | A kérelem URI-ja... |
|---|---|---|
hello |
/hello |
Csak az egyetlen elérési út /hellofelel meg. |
{Page=Home} |
/ |
Egyezések és halmazok Page a következőre Home: . |
{Page=Home} |
/Contact |
Egyezések és halmazok Page a következőre Contact: . |
{controller}/{action}/{id?} |
/Products/List |
Megfelelteti a Products vezérlőt és a List műveletet. |
{controller}/{action}/{id?} |
/Products/Details/123 |
A Products vezérlőnek és a Details műveletnek felel meg, amelynél id 123-ra van állítva. |
{controller=Home}/{action=Index}/{id?} |
/ |
Leképezi a Home vezérlőt és a Index metódust. A id figyelmen kívül van hagyva. |
{controller=Home}/{action=Index}/{id?} |
/Products |
Leképezi a Products vezérlőt és a Index metódust. A id figyelmen kívül van hagyva. |
Általában a sablon használata a legegyszerűbb útválasztási módszer. Az útvonalsablonon kívül is megadhat kényszereket és alapértelmezett értékeket.
Összetett szegmensek
Az összetett szegmensek feldolgozása a literális elválasztójelek jobbról balra történő egyeztetésével történik , nem mohó módon. Például [Route("/a{b}c{d}")] egy összetett szegmens.
Az összetett szegmensek olyan módon működnek, amelyet meg kell érteni a sikeres használatukhoz. Az ebben a szakaszban található példa bemutatja, hogy az összetett szegmensek miért működnek igazán jól, ha az elválasztó szöveg nem jelenik meg a paraméterértékeken belül. Összetettebb esetekben regexet kell használni, majd manuálisan kinyerni az értékeket.
Warning
Amikor a System.Text.RegularExpressions-t használja nem megbízható bemenetek feldolgozására, meg kell adnia egy időtúllépési értéket. Egy rosszindulatú felhasználó adhat RegularExpressions bemenetet, ami szolgáltatásmegtagadásos támadást okozhat. ASP.NET Core keretrendszer API-k, amelyek RegularExpressions időtúllépést használnak.
Ez egy összefoglaló az /a{b}c{d} sablon és a /abcd URL-útvonal esetén végzett útválasztási lépésekről. Ez | segít az algoritmus működésének vizualizációjában:
- Az első literál, jobbról balra, az
c. Így/abcdkeres jobbról balra, és megtalálja/ab|c|d. - A jobb oldalon (
d) lévő összes elem megfelel az útvonalparaméternek{d}. - A következő karakter, jobbról balra, az
a. Így/ab|c|dkeresésével ott folytatjuk, ahol abbahagytuk, majdamegtalálható/|a|b|c|d. - A jobb oldali (
b) érték most már megfelel az útvonalparaméternek{b}. - Nincs fennmaradó szöveg és nincs fennmaradó útvonalsablon, így ez megfelelésnek számít.
Íme egy példa egy negatív esetre, amely ugyanazt a sablont /a{b}c{d} és az URL-címet /aabcdhasználja. Ez | segít az algoritmus működésének vizualizációjában. Ez az eset nem egyezik, amit ugyanaz az algoritmus magyaráz meg.
- Az első literál, jobbról balra, az
c. Így/aabcdkeres jobbról balra, és megtalálja/aab|c|d. - A jobb oldalon (
d) lévő összes elem megfelel az útvonalparaméternek{d}. - A következő karakter, jobbról balra, az
a. Így/aab|c|dkeresésével ott folytatjuk, ahol abbahagytuk, majdamegtalálható/a|a|b|c|d. - A jobb oldali (
b) érték most már megfelel az útvonalparaméternek{b}. - Ezen a ponton még van szöveg
a, de az algoritmus elfogyott az elemzésre használt útvonalsablonból, így ez nem egyezik.
Mivel a megfelelő algoritmus nem kapzsi:
- Ez megfelel az egyes lépésekben lehetséges legkisebb szövegmennyiségnek.
- Ha az elválasztó érték a paraméterértékek között jelenik meg, az eredmény nem egyezik.
A reguláris kifejezések sokkal jobban szabályozhatják az egyező viselkedésüket.
A mohó egyezés, más néven lusta egyezés, a lehető legnagyobb sztringhez illeszkedik. A nem mohó egyezik a lehető legkisebb sztringgel.
Útválasztás speciális karakterekkel
A speciális karaktereket tartalmazó útválasztás váratlan eredményekhez vezethet. Vegyük például az alábbi műveletmetódusú vezérlőt:
[HttpGet("{id?}/name")]
public async Task<ActionResult<string>> GetName(string id)
{
var todoItem = await _context.TodoItems.FindAsync(id);
if (todoItem == null || todoItem.Name == null)
{
return NotFound();
}
return todoItem.Name;
}
Ha string id a következő kódolt értékeket tartalmazza, váratlan eredmények léphetnek fel:
| ASCII | Encoded |
|---|---|
/ |
%2F |
|
+ |
Az útvonalparaméterek nem mindig vannak dekódolva az URL-ből. Ez a probléma a jövőben megoldható. További információkért tekintse meg ezt a GitHub-problémát;
Útvonalkorlátozások
Az útvonalkorlátozások akkor lépnek érvénybe, amikor egyezés történt a bejövő URL-címhez, és az URL-elérési út tokenizálva van útvonalértékekké. Az útvonalkorlátozások általában ellenőrzik az útvonalsablonon keresztül társított útvonalértéket, és valós vagy hamis döntést hoznak arról, hogy az érték elfogadható-e. Egyes útvonalkorlátozások az útvonalértéken kívüli adatokat használnak annak megfontolására, hogy a kérés irányítható-e. A http-ige alapján például HttpMethodRouteConstraint elfogadhat vagy elutasíthat egy kérést. A korlátozások az útválasztási kérelmekben és a csatolások generálásában használatosak.
Warning
Ne használjon korlátozásokat a bemeneti ellenőrzéshez. Ha bemeneti érvényesítéshez kényszereket használnak, érvénytelen bemenet esetén "Nem található" választ kapunk 404. Az érvénytelen bemenetnek egy Bad Request 400 kell létrehoznia a megfelelő hibaüzenettel. Az útvonalkorlátozások a hasonló útvonalak egyértelműsítésére szolgálnak, nem pedig egy adott útvonal bemeneteinek ellenőrzésére.
Az alábbi táblázat a példaút-korlátozásokat és azok várható viselkedését mutatja be:
| korlátozás | Example | Példa egyezések | Notes |
|---|---|---|---|
int |
{id:int} |
123456789, -123456789 |
Bármely egész számnak megfelel |
bool |
{active:bool} |
true, FALSE |
Egyezések true vagy false. Case-insensitive |
datetime |
{dob:datetime} |
2016-12-31, 2016-12-31 7:32pm |
Megfelel az invariáns kultúra érvényes DateTime értékének. Lásd az előző figyelmeztetést. |
decimal |
{price:decimal} |
49.99, -1,000.01 |
Megfelel az invariáns kultúra érvényes decimal értékének. Lásd az előző figyelmeztetést. |
double |
{weight:double} |
1.234, -1,001.01e8 |
Megfelel az invariáns kultúra érvényes double értékének. Lásd az előző figyelmeztetést. |
float |
{weight:float} |
1.234, -1,001.01e8 |
Megfelel az invariáns kultúra érvényes float értékének. Lásd az előző figyelmeztetést. |
guid |
{id:guid} |
CD2C1638-1638-72D5-1638-DEADBEEF1638 |
Érvényes Guid érték egyező |
long |
{ticks:long} |
123456789, -123456789 |
Érvényes long érték egyező |
minlength(value) |
{username:minlength(4)} |
Rick |
A karakterláncnak legalább 4 karakter hosszúnak kell lennie. |
maxlength(value) |
{filename:maxlength(8)} |
MyFile |
A sztring legfeljebb 8 karakter hosszúságú lehet |
length(length) |
{filename:length(12)} |
somefile.txt |
A sztringnek pontosan 12 karakter hosszúnak kell lennie |
length(min,max) |
{filename:length(8,16)} |
somefile.txt |
A sztringnek legalább 8 és legfeljebb 16 karakter hosszúnak kell lennie |
min(value) |
{age:min(18)} |
19 |
Az egész szám értékének legalább 18-nak kell lennie |
max(value) |
{age:max(120)} |
91 |
Az egész szám értéke legfeljebb 120 lehet |
range(min,max) |
{age:range(18,120)} |
91 |
Az egész szám értéke legalább 18, de legfeljebb 120 lehet |
alpha |
{name:alpha} |
Rick |
A sztringnek egy vagy több betűből a-z kell állnia, függetlenül a kis- és nagybetűktől. |
regex(expression) |
{ssn:regex(^\\d{{3}}-\\d{{2}}-\\d{{4}}$)} |
123-45-6789 |
A karakterláncnak meg kell egyeznie a reguláris kifejezéssel. Tippek a reguláris kifejezés definiálásáról. |
required |
{name:required} |
Rick |
Arra szolgál, hogy kényszerítse, hogy egy nem paraméteres érték jelen legyen az URL-cím létrehozása során |
Warning
Amikor a System.Text.RegularExpressions-t használja nem megbízható bemenetek feldolgozására, meg kell adnia egy időtúllépési értéket. Egy rosszindulatú felhasználó adhat RegularExpressions bemenetet, ami szolgáltatásmegtagadásos támadást okozhat. ASP.NET Core keretrendszer API-k, amelyek RegularExpressions időtúllépést használnak.
Egy paraméterre több, kettőspontra tagolt korlátozás alkalmazható. A következő korlátozás például egy paramétert 1 vagy annál nagyobb egész számra korlátozza:
[Route("users/{id:int:min(1)}")]
public User GetUserById(int id) { }
Warning
Az URL-címet ellenőrző és CLR-típussá konvertált útvonalkorlátozások mindig az invariáns kultúrát használják. Például a CLR típus int vagy DateTime. Ezek a korlátozások feltételezik, hogy az URL-cím nem honosítható. A keretrendszer által biztosított útvonalkorlátozások nem módosítják az útvonalértékekben tárolt értékeket. Az URL-címből elemezett útvonalértékek sztringekként vannak tárolva. A kényszer például float megkísérli lebegőpontossá alakítani az útvonal értékét, de a konvertált érték csak annak ellenőrzésére szolgál, hogy az lebegőpontossá alakítható-e.
Reguláris kifejezések alkalmazása kényszerekben
Warning
Amikor a System.Text.RegularExpressions-t használja nem megbízható bemenetek feldolgozására, meg kell adnia egy időtúllépési értéket. Egy rosszindulatú felhasználó adhat RegularExpressions bemenetet, ami szolgáltatásmegtagadásos támadást okozhat. ASP.NET Core keretrendszer API-k, amelyek RegularExpressions időtúllépést használnak.
A reguláris kifejezések az útvonal-korlátozással regex(...) beágyazott kényszerként is megadhatóak. A MapControllerRoute család metódusai egy korlátozások objektumkonstansát is elfogadják. Ha ezt az űrlapot használja, a sztringértékeket a rendszer normál kifejezésként értelmezi.
A következő kód beágyazott regex kényszert használ:
app.MapGet("{message:regex(^\\d{{3}}-\\d{{2}}-\\d{{4}}$)}",
() => "Inline Regex Constraint Matched");
Az alábbi kód egy objektumkonstanst használ a regex kényszer megadásához:
app.MapControllerRoute(
name: "people",
pattern: "people/{ssn}",
constraints: new { ssn = "^\\d{3}-\\d{2}-\\d{4}$", },
defaults: new { controller = "People", action = "List" });
A ASP.NET Core-keretrendszer hozzáadja RegexOptions.IgnoreCase | RegexOptions.Compiled | RegexOptions.CultureInvariant a reguláris kifejezéskonstruktort. A tagok leírását itt tekinti meg RegexOptions .
A reguláris kifejezések az útválasztás és a C# nyelv által használthoz hasonló határolókat és mintákat használnak. A reguláris kifejezés elemeit escape-elve kell használni. Ha a reguláris kifejezést ^\d{3}-\d{2}-\d{4}$ beágyazott kényszerben szeretné használni, használja az alábbiak egyikét:
- Cserélje le
\a sztringben megadott karaktereket a C#-forrásfájlban szereplő karakterekre\\, hogy elkerülje a sztring-feloldó\karaktert. - Szó szerinti karakterlánckonstansok.
Az útvonal-paraméterek elválasztó karaktereinek, mint például a {, }, [, ], kifejezésben történő megduplázásával megszabadulhatunk, például {{, }}, [[, ]]. Az alábbi táblázat egy reguláris kifejezést és annak szökött verzióját mutatja be:
| Reguláris kifejezés | Megmenekült reguláris kifejezés |
|---|---|
^\d{3}-\d{2}-\d{4}$ |
^\\d{{3}}-\\d{{2}}-\\d{{4}}$ |
^[a-z]{2}$ |
^[[a-z]]{{2}}$ |
Az útválasztás során használt reguláris kifejezések gyakran a ^ karakterrel kezdődnek, és megfelelnek a sztring kezdőpozíciójának. A kifejezések gyakran a $ karakterrel végződnek, és illeszkednek a karaktersor végéhez. A ^ karakterek és $ a karakterek biztosítják, hogy a reguláris kifejezés megegyezik a teljes útvonalparaméter értékével. A ^ és $ karakterek nélkül a reguláris kifejezés bármelyik részsztringgel egyezik meg a sztringen belül, ami gyakran nem kívánatos. Az alábbi táblázat példákat tartalmaz, és elmagyarázza, hogy miért egyeznek vagy miért nem egyeznek:
| Expression | String | Match | Comment |
|---|---|---|---|
[a-z]{2} |
hello | Yes | Részszűrési egyezések |
[a-z]{2} |
123abc456 | Yes | Részszűrési egyezések |
[a-z]{2} |
mz | Yes | Kifejezés egyezése |
[a-z]{2} |
MZ | Yes | Nem érzékeny a kis- és nagybetűkre |
^[a-z]{2}$ |
hello | No | Lásd ^ és $ fent |
^[a-z]{2}$ |
123abc456 | No | Lásd ^ és $ fent |
A reguláris kifejezésszintaxissal kapcsolatos további információkért lásd a .NET-keretrendszer reguláris kifejezéseit.
Ha egy paramétert egy ismert lehetséges értékkészletre szeretne korlátozni, használjon egy reguláris kifejezést. Például {action:regex(^(list|get|create)$)} csak a action következő útvonalértéknek felel meglist: , vagy .getcreate Ha a kényszerszótárba kerül, a sztring ^(list|get|create)$ egyenértékű. A kényszerek szótárában megadott, az ismert kényszerek egyikével nem egyező kényszereket a rendszer normál kifejezésként is kezeli. A sablonon belül átadott, az ismert megkötések egyikével nem egyező kényszereket a rendszer nem kezeli normál kifejezésként.
Egyéni útvonalkorlátozások
Az interfész implementálásával IRouteConstraint egyéni útvonalkorlátozások hozhatók létre. Az IRouteConstraint interfész tartalmaz Match, amely akkor ad vissza true , ha a korlátozás teljesül, és false egyébként.
Ritkán van szükség egyéni útvonalkorlátozásokra. Egyéni útvonalkorlátozás implementálása előtt fontolja meg az alternatív megoldásokat, például a modellkötést.
A ASP.NET Alapvető korlátozások mappa jó példákat kínál a korlátozások létrehozására. Például GuidRouteConstraint.
Egyéni IRouteConstraintbeállítás használatához az útvonalkorlátozás típusát regisztrálni kell az alkalmazás szolgáltatástárolójában ConstraintMap . Egy ConstraintMap egy szótár, amely az útvonalkényszer kulcsokat olyan IRouteConstraint implementációkhoz rendeli, amelyek érvényesítik ezeket a kényszereket. Alkalmazás ConstraintMap-t frissíthetünk Program.cs, akár egy AddRouting hívás részeként, akár közvetlenül RouteOptions konfigurálásával builder.Services.Configure<RouteOptions>. Például:
builder.Services.AddRouting(options =>
options.ConstraintMap.Add("noZeroes", typeof(NoZeroesRouteConstraint)));
Az előző korlátozás a következő kódban van alkalmazva:
[ApiController]
[Route("api/[controller]")]
public class NoZeroesController : ControllerBase
{
[HttpGet("{id:noZeroes}")]
public IActionResult Get(string id) =>
Content(id);
}
Az NoZeroesRouteConstraint megvalósítása megakadályozza, hogy a 0 egy útvonalparaméterben legyen használva.
public class NoZeroesRouteConstraint : IRouteConstraint
{
private static readonly Regex _regex = new(
@"^[1-9]*$",
RegexOptions.CultureInvariant | RegexOptions.IgnoreCase,
TimeSpan.FromMilliseconds(100));
public bool Match(
HttpContext? httpContext, IRouter? route, string routeKey,
RouteValueDictionary values, RouteDirection routeDirection)
{
if (!values.TryGetValue(routeKey, out var routeValue))
{
return false;
}
var routeValueString = Convert.ToString(routeValue, CultureInfo.InvariantCulture);
if (routeValueString is null)
{
return false;
}
return _regex.IsMatch(routeValueString);
}
}
Warning
Amikor a System.Text.RegularExpressions-t használja nem megbízható bemenetek feldolgozására, meg kell adnia egy időtúllépési értéket. Egy rosszindulatú felhasználó adhat RegularExpressions bemenetet, ami szolgáltatásmegtagadásos támadást okozhat. ASP.NET Core keretrendszer API-k, amelyek RegularExpressions időtúllépést használnak.
Az előző kód:
- Megakadályozza
0az{id}útvonal szegmensét. - Látható, hogy egy egyszerű példát mutat be egy egyéni korlátozás implementálására. Éles alkalmazásban nem használható.
Az alábbi kód jobb módszer arra, hogy megakadályozza a id-t tartalmazó 0 feldolgozását.
[HttpGet("{id}")]
public IActionResult Get(string id)
{
if (id.Contains('0'))
{
return StatusCode(StatusCodes.Status406NotAcceptable);
}
return Content(id);
}
Az előző kód a következő előnyökkel rendelkezik a NoZeroesRouteConstraint megközelítéssel szemben:
- Nem igényel egyéni korlátozást.
- Leíróbb hibát ad vissza, ha az útvonalparaméter tartalmazza
0.
Paraméter-átalakítók
Paramétertranszformátorok:
- Hajtson végre egy műveletet a hivatkozás létrehozásához a LinkGenerator használatával.
- Implementálás Microsoft.AspNetCore.Routing.IOutboundParameterTransformer.
- A(z) ConstraintMap használatával konfigurálható.
- Vegye át a paraméter útvonalértékét, és alakítsa át egy új sztringértékké.
- Ennek eredménye az átalakított érték használata a létrehozott hivatkozásban.
Például egy egyéni slugify paraméter-transzformátor az útvonalmintában blog\{article:slugify} a generált adatokkal Url.Action(new { article = "MyTestArticle" })blog\my-test-article.
Fontolja meg a következő IOutboundParameterTransformer megvalósítást:
public class SlugifyParameterTransformer : IOutboundParameterTransformer
{
public string? TransformOutbound(object? value)
{
if (value is null)
{
return null;
}
return Regex.Replace(
value.ToString()!,
"([a-z])([A-Z])",
"$1-$2",
RegexOptions.CultureInvariant,
TimeSpan.FromMilliseconds(100))
.ToLowerInvariant();
}
}
Ha paraméterátalakítót szeretne használni egy útvonalmintában, konfigurálja a következővel ConstraintMapProgram.cs:
builder.Services.AddRouting(options =>
options.ConstraintMap["slugify"] = typeof(SlugifyParameterTransformer));
Az ASP.NET Core keretrendszer paraméterátalakítókat használ, hogy átalakítsa az URI-t a végpont feloldása során. A paraméterátalakítók például átalakítják az útvonal értékeit, amelyeket a area, controller, action és page összepárosítására használnak.
app.MapControllerRoute(
name: "default",
pattern: "{controller:slugify=Home}/{action:slugify=Index}/{id?}");
Az előző útvonalsablon esetén a művelet SubscriptionManagementController.GetAll megfelel az URI-nak /subscription-management/get-all. A paraméter-átalakító nem módosítja a hivatkozás létrehozásához használt útvonalértékeket. Például a Url.Action("GetAll", "SubscriptionManagement") kimenetet ad /subscription-management/get-all.
ASP.NET Core API-konvenciókat biztosít a paraméterátalakítók generált útvonalakkal való használatához:
- Az Microsoft.AspNetCore.Mvc.ApplicationModels.RouteTokenTransformerConvention MVC-konvenció egy megadott paraméterátalakítót alkalmaz az alkalmazás összes attribútumútvonalára. A paraméter-transzformátor átalakítja az attribútumat útvonalának jogkivonatait, amikor lecserélésre kerülnek. További információért lásd: Paraméterátalakító használata a tokencserék testreszabására.
- Razor A Pages az API-konvenciót PageRouteTransformerConvention használja. Ez az egyezmény egy megadott paraméterátalakítót alkalmaz az összes automatikusan felderített Razor lapra. A paraméter-átalakító átalakítja a Pages-útvonalak mappa- és fájlnév-szegmenseit Razor . További információ: Oldalútvonalak testreszabása paraméterátalakítóval.
URL-létrehozási referencia
Ez a szakasz az URL-generálás által implementált algoritmusra mutató hivatkozást tartalmaz. A gyakorlatban az URL-létrehozás legösszetettebb példái vezérlőket vagy Razor oldalakat használnak. További információkért tekintse meg az útválasztást a vezérlőkben .
Az URL-létrehozási folyamat egy hívással LinkGenerator.GetPathByAddress vagy egy hasonló módszerrel kezdődik. A metódus címmel, útvonalértékekkel és opcionálisan az aktuális kéréssel HttpContextkapcsolatos információkkal rendelkezik.
Az első lépés az, hogy a cím segítségével, a cím típusának megfelelő IEndpointAddressScheme<TAddress> alkalmazásával megold egy jelölt végpontkészletet.
Miután a címséma megtalálta a jelölteket, a végpontok iteratív módon lesznek rendezve és feldolgozva, amíg egy URL-létrehozási művelet sikeres nem lesz. Az URL-generálás nem ellenőrzi a kétértelműségeket, az első eredmény a végeredmény.
URL-létrehozás hibaelhárítása naplózással
Az URL-létrehozás hibaelhárításának első lépése a naplózási szint Microsoft.AspNetCore.RoutingTRACE beállítása.
LinkGenerator a feldolgozással kapcsolatos számos részletet naplóz, amelyek hasznosak lehetnek a problémák elhárításához.
Az URL-címgenerálással kapcsolatos részletekért tekintse meg az URL-létrehozási referenciát .
Addresses
A címek az URL-generálás azon koncepciója, amellyel a hívásokat a hivatkozásgenerátorhoz kötik a jelölt végpontok halmazához.
A címek egy bővíthető fogalom, amely alapértelmezés szerint két implementációval rendelkezik:
-
Végpontnév (
string) használata címként:- Hasonló funkciókat biztosít az MVC útvonalnevéhez.
- IEndpointNameMetadata A metaadatok típusát használja.
- Feloldja a megadott sztringet az összes regisztrált végpont metaadataival.
- Kivételt jelez az indításkor, ha több végpont ugyanazt a nevet használja.
- Az általános célú használat a vezérlőkön és Razor lapokon kívül ajánlott.
-
Útvonalértékek (RouteValuesAddress) használata címként:
- Hasonló funkciókat biztosít a vezérlőkhöz és az örökölt Pages URL-címek generálásához.
- Nagyon összetett a bővítéshez és a hibakereséshez.
- Biztosítja az implementációt, amelyet a
IUrlHelperTag Helper-ek, a HTML-segítők, a műveleti eredmények stb. használják.
A címséma szerepe, hogy a cím és az egyező végpontok közötti társítás tetszőleges feltételek szerint történik:
- A végpontnévséma alapszintű szótárkeresést hajt végre.
- Az útvonalértékek sémája a beállítási algoritmus összetett legjobb részhalmazával rendelkezik.
Környezeti értékek és explicit értékek
Az aktuális kérésből az útválasztás az aktuális kérés HttpContext.Request.RouteValuesútvonalértékeit éri el. Az aktuális kéréshez társított értékeket környezeti értékeknek nevezzük. Az egyértelműség kedvéért a dokumentáció a metódusoknak átadott útvonalértékekre hivatkozik explicit értékekként.
Az alábbi példa környezeti értékeket és explicit értékeket mutat be. Környezeti értékeket biztosít az aktuális kérésből és explicit értékekből:
public class WidgetController : ControllerBase
{
private readonly LinkGenerator _linkGenerator;
public WidgetController(LinkGenerator linkGenerator) =>
_linkGenerator = linkGenerator;
public IActionResult Index()
{
var indexPath = _linkGenerator.GetPathByAction(
HttpContext, values: new { id = 17 })!;
return Content(indexPath);
}
// ...
Az előző kód:
- Visszatér
/Widget/Index/17 - Meghajtást kap LinkGenerator által.
A következő kód csak explicit értékeket és nem tartalmaz környezeti értékeket:
var subscribePath = _linkGenerator.GetPathByAction(
"Subscribe", "Home", new { id = 17 })!;
Az előző metódus visszaadja /Home/Subscribe/17
A WidgetController a következőt adja vissza: /Widget/Subscribe/17
var subscribePath = _linkGenerator.GetPathByAction(
HttpContext, "Subscribe", null, new { id = 17 });
A következő kód az aktuális kérelem környezeti értékeiből és explicit értékekből biztosítja a vezérlőt:
public class GadgetController : ControllerBase
{
public IActionResult Index() =>
Content(Url.Action("Edit", new { id = 17 })!);
}
Az előző kódban:
-
/Gadget/Edit/17vissza lesz adva. - Url lekéri a IUrlHelper.
-
Action Egy műveletmetódus abszolút elérési útját tartalmazó URL-címet hoz létre. Az URL-cím a megadott
actionnevet ésrouteértékeket tartalmazza.
Az alábbi kód az aktuális kérelem környezeti értékeit és explicit értékeit tartalmazza:
public class IndexModel : PageModel
{
public void OnGet()
{
var editUrl = Url.Page("./Edit", new { id = 17 });
// ...
}
}
Az előző kód beállítja a url értékét /Edit/17-re, ha a Lap szerkesztése Razor oldal az alábbi oldalirányelvet tartalmazza:
@page "{id:int}"
Ha a Szerkesztés lap nem tartalmazza az "{id:int}" útvonalsablont, akkor url a következő: /Edit?id=17.
Az MVC viselkedése IUrlHelper összetettségi réteget ad hozzá az itt leírt szabályok mellett:
-
IUrlHelpermindig környezeti értékként adja meg az aktuális kérés útvonalértékeit. -
Az IUrlHelper.Action mindig explicit értékként másolja át az aktuális
actionéscontrollerútvonalértékeket, kivéve, ha a fejlesztő felülírja. -
IUrlHelper.Page az aktuális
pageútvonalértéket mindig explicit értékként másolja, kivéve, ha felül van bírálva. -
IUrlHelper.Pagemindig explicit értékként felülbírálja az aktuálishandlerútvonal értékétnullhacsak nincs felülírva.
A felhasználókat gyakran meglepik a környezeti értékek viselkedési részletei, mert úgy tűnik, hogy az MVC nem követi a saját szabályait. Előzmény- és kompatibilitási okokból bizonyos útvonalértékek, például action, controller, pageés handler saját speciális eseti viselkedésük van.
A LinkGenerator.GetPathByAction és LinkGenerator.GetPathByPage által biztosított egyenértékű funkcionalitás a IUrlHelper ezen anomáliáit duplikálja a kompatibilitás érdekében.
URL-létrehozási folyamat
A jelölt végpontok készletének megtalálása után az URL-generáló algoritmus:
- Iteratív módon dolgozza fel a végpontokat.
- Az első sikeres eredményt adja vissza.
A folyamat első lépése az útvonalérték érvénytelenítése. Az útvonalérték érvénytelenítése az a folyamat, amellyel az útválasztás dönti el, hogy a környezeti értékekből melyik útvonalértékeket kell használni, és melyeket figyelmen kívül kell hagyni. A rendszer minden környezeti értéket figyelembe vesz, és kombinálja az explicit értékekkel, vagy figyelmen kívül hagyja.
A környezeti értékek szerepét úgy lehet a legjobban értelmezni, hogy azok célja az alkalmazásfejlesztők gépelési munkájának csökkentése néhány gyakori esetben. Hagyományosan az MVC-hez kapcsolódó forgatókönyvek, amelyekben a környezeti értékek hasznosak:
- Ha ugyanabban a vezérlőben egy másik művelethez kapcsolódik, a vezérlő nevét nem kell megadni.
- Ha ugyanazon a területen egy másik vezérlőhöz kapcsolódik, a terület nevét nem kell megadni.
- Ha ugyanahhoz a műveletmetódushoz kapcsolódik, az útvonalértékeket nem kell megadni.
- Amikor az alkalmazás egy másik részéhez kapcsolódik, nem szeretne olyan útvonalértékeket átvinni, amelyeknek nincs jelentésük az alkalmazás ezen részében.
A LinkGenerator vagy IUrlHelper hívások, amelyek null-t adnak vissza, általában az útvonalértékek érvénytelenítésének nem megfelelő megértése miatt fordulnak elő. Az útvonalértékek érvénytelenítésének hibaelhárításához explicit módon adjon meg több útvonalértéket, és ellenőrizze, hogy ez megoldja-e a problémát.
Az útvonalérték érvénytelenítése azzal a feltételezéssel működik, hogy az alkalmazás URL-sémája hierarchikus, a hierarchia balról jobbra épül fel. Fontolja meg az alapszintű vezérlőútvonal-sablont {controller}/{action}/{id?} , hogy intuitív módon értelmezhesse ennek működését a gyakorlatban. Az érték módosításaérvényteleníti a jobb oldalon megjelenő összes útvonalértéket. Ez tükrözi a hierarchia feltételezését. Ha az alkalmazásnak van egy környezeti értéke id, és a művelet egy másik értéket ad meg a controller számára:
-
idnem lesz újra felhasználva, mert{controller}a bal oldalon{id?}található.
Néhány példa az alapelv bemutatására:
- Ha az explicit értékek egy értéket
idtartalmaznak, a környezeti értékidfigyelmen kívül lesz hagyva. A(z)controllerésactionértékeit használhatjuk. - Ha az explicit értékek egy értéket
actiontartalmaznak, a rendszer figyelmen kívül hagyja a környezeti értékeketaction. Azcontrolleresetében a környezeti értékek felhasználhatók. Ha a explicit értékactioneltér a környezeti értéktőlaction, akkor azidérték nem lesz felhasználva. Ha az explicit értékactionmegegyezik a környezeti értékkelaction, akkor azidérték használható. - Ha az explicit értékek egy értéket
controllertartalmaznak, a rendszer figyelmen kívül hagyja a környezeti értékeketcontroller. Ha az explicit értékcontrollereltér a környezeti értéktőlcontroller, akkor nem használják azactionésidértékeket. Ha az explicit értékcontrollermegegyezik a környezeti értékkelcontroller, akkor azactionésidértékek használhatók.
Ezt a folyamatot tovább bonyolítja az attribútumútvonalak és a dedikált hagyományos útvonalak megléte. A vezérlő hagyományos útvonalai, mint például a {controller}/{action}/{id?}, egy hierarchiát határoznak meg útvonalparaméterekkel.
A vezérlőkhöz és lapokhoz tartozó dedikált hagyományos útvonalak és Razor esetén:
- Az útvonalértékek hierarchiája létezik.
- Nem jelennek meg a sablonban.
Ezekben az esetekben az URL-generálás határozza meg a szükséges értékek fogalmát. A vezérlők és Razor lapok által létrehozott végpontok olyan kötelező értékekkel rendelkeznek, amelyek lehetővé teszik az útvonalértékek érvénytelenítését.
Az útvonalérték érvénytelenítési algoritmusa részletesen:
- A szükséges értékneveket a rendszer kombinálja az útvonalparaméterekkel, majd balról jobbra dolgozza fel őket.
- Minden paraméter esetében a környezeti érték és az explicit érték összehasonlítása:
- Ha a környezeti érték és az explicit érték megegyezik, a folyamat folytatódik.
- Ha a környezeti érték jelen van, és az explicit érték nem, akkor a környezeti érték lesz használva az URL-cím létrehozásakor.
- Ha a környezeti érték nem jelenik meg, és az explicit érték az, utasítsa el a környezeti értéket és az összes további környezeti értéket.
- Ha a környezeti érték és az explicit érték jelen van, és a két érték eltérő, utasítsa el a környezeti értéket és az összes további környezeti értéket.
Ezen a ponton az URL-létrehozási művelet készen áll az útvonalkorlátozások kiértékelésére. Az elfogadott értékek halmaza az alapértelmezett paraméterértékekkel van kombinálva, amelyek a korlátozások számára biztosítottak. Ha a korlátozások mindegyike megfelel, a művelet folytatódik.
Ezután az elfogadott értékek használhatók az útvonalsablon kibontásához. Az útvonalsablon feldolgozása:
- Balról jobbra.
- Minden paraméterhez az elfogadott érték van behelyettesítve.
- A következő különleges esetek esetén:
- Ha az elfogadott értékekből hiányzik egy érték, és a paraméter alapértelmezett értékkel rendelkezik, a rendszer az alapértelmezett értéket használja.
- Ha az elfogadott értékekből hiányzik egy érték, és a paraméter nem kötelező, a feldolgozás folytatódik.
- Ha egy hiányzó opcionális paraméter jobb oldalán található útvonalparaméter rendelkezik értékkel, a művelet meghiúsul.
- Ha lehetséges, összecsukja az egybefüggő alapértelmezett értékű paramétereket és az opcionális paramétereket.
A lekérdezési sztringhez explicit módon megadott értékek, amelyek nem egyeznek az útvonal egy szegmensével, hozzáadódnak a lekérdezési sztringhez. Az alábbi táblázat az útvonalsablon {controller}/{action}/{id?}használatakor mutatja be az eredményt.
| Környezeti értékek | Explicit értékek | Result |
|---|---|---|
| vezérlő = "Home" | action = "Névjegy" | /Home/About |
| vezérlő = "Home" | controller = "Order", action = "About" | /Order/About |
| controller = "Home", szín = "Vörös" | action = "Névjegy" | /Home/About |
| vezérlő = "Home" | action = "About", color = "Red" | /Home/About?color=Red |
Az útvonalérték érvénytelenítésével kapcsolatos problémák
Az alábbi kód egy olyan URL-létrehozási sémát mutat be, amelyet az útválasztás nem támogat:
app.MapControllerRoute(
"default",
"{culture}/{controller=Home}/{action=Index}/{id?}");
app.MapControllerRoute(
"blog",
"{culture}/{**slug}",
new { controller = "Blog", action = "ReadPost" });
Az előző kódban a rendszer az culture útvonalparamétert használja a honosításhoz. A cél az, hogy a culture paraméter mindig környezeti értékként legyen elfogadva. A culture paraméter azonban nem fogadható el környezeti értékként a szükséges értékek működése miatt:
- Az
"default"útvonalparaméter acultureútvonalsablonbancontrollerbal oldalán található, így acontrollermódosításai nem érvénytelenítikculture. - Az
"blog"útvonalsablonban azcultureútvonalparaméter azcontroller-tól jobbra található, ahogy az a szükséges értékekben megjelenik.
URL-útvonalak elemzése a LinkParser
Az LinkParser osztály támogatja egy URL-elérési út útvonalkészletbe való elemzését. A ParsePathByEndpointName metódus egy végpontnevet és egy URL-elérési utat használ, és visszaadja az URL-útvonalból kinyert útvonalértékeket.
A következő példavezérlőben az GetProduct művelet egy api/Products/{id} útvonalsablont használ, és rendelkezik Name típusú GetProduct-val:
[ApiController]
[Route("api/[controller]")]
public class ProductsController : ControllerBase
{
[HttpGet("{id}", Name = nameof(GetProduct))]
public IActionResult GetProduct(string id)
{
// ...
Ugyanabban a vezérlőosztályban a AddRelatedProduct művelet egy URL-elérési utat vár, pathToRelatedProductamely lekérdezési sztring paraméterként adható meg:
[HttpPost("{id}/Related")]
public IActionResult AddRelatedProduct(
string id, string pathToRelatedProduct, [FromServices] LinkParser linkParser)
{
var routeValues = linkParser.ParsePathByEndpointName(
nameof(GetProduct), pathToRelatedProduct);
var relatedProductId = routeValues?["id"];
// ...
Az előző példában a AddRelatedProduct művelet kinyeri az id útvonal értékét az URL-elérési útból. Ha például a(z) /api/Products/1 URL-elérési út van beállítva, az relatedProductId érték 1-re van állítva. Ez a megközelítés lehetővé teszi az API-ügyfelek számára, hogy URL-útvonalakat használjanak az erőforrásokra való hivatkozáskor anélkül, hogy ismerni kellene az ilyen URL-címek felépítését.
Végpont metaadatainak konfigurálása
Az alábbi hivatkozások a végpont metaadatainak konfigurálásáról nyújtanak információt:
- Cors engedélyezése végponti útválasztással
-
IAuthorizationPolicyProvider-minta egyéni
[MinimumAgeAuthorize]attribútum használatával - Hitelesítés tesztelése az [Engedélyezés] attribútummal
- RequireAuthorization
- A séma kiválasztása az [Engedélyezés] attribútummal
- Szabályzatok alkalmazása az [Engedélyezés] attribútummal
- Szerepköralapú hitelesítés az ASP.NET Core-ban
Hosztok egyezése útvonalakban a RequireHost használatával
RequireHost korlátozást alkalmaz az útvonalra, amely megköveteli a megadott gazdagépet. A RequireHost paraméter vagy a [Gazdagép] lehet:
- Hoszt:
www.domain.com,www.domain.combármely porttal illik. - Gazdagép helyettesítő karakterrel:
*.domain.com, egyezéswww.domain.com,subdomain.domain.comvagywww.subdomain.domain.combármely porton. - Port:
*:5000, megegyezik az 5000-es porttal bármely gazdagépen. - Hoszt és port:
www.domain.com:5000vagy*.domain.com:5000, amely egyezik a hoszttal és a porttal.
Több paraméter is megadható RequireHost vagy [Host] használatával. A kényszer egyezik a paraméterek bármelyikére érvényes gazdagépekkel. Például [Host("domain.com", "*.domain.com")] megegyezik domain.com, www.domain.com és subdomain.domain.com.
Az alábbi kód RequireHost használja a megadott gazdagép megkövetelésére az útvonalon.
app.MapGet("/", () => "Contoso").RequireHost("contoso.com");
app.MapGet("/", () => "AdventureWorks").RequireHost("adventure-works.com");
app.MapHealthChecks("/healthz").RequireHost("*:8080");
A következő kód a [Host] vezérlő attribútumával követeli meg a megadott gazdagépek bármelyikét:
[Host("contoso.com", "adventure-works.com")]
public class HostsController : Controller
{
public IActionResult Index() =>
View();
[Host("example.com")]
public IActionResult Example() =>
View();
}
Ha az attribútumot a [Host] vezérlőre és a műveleti módszerre is alkalmazza a rendszer:
- A műveleten szereplő attribútumot használja a rendszer.
- A vezérlőattribútum figyelmen kívül lesz hagyva.
Teljesítmény-útmutató útválasztáshoz
Ha egy alkalmazás teljesítményproblémával rendelkezik, az útválasztást gyakran gyanúsítják a problémaként. Azért feltételezik az útválasztás problémáját, mert a keretrendszerek, mint például a vezérlők és a Pages, a naplózási üzenetekben jelzik, mennyi időt töltenek a keretrendszeren belül. Ha jelentős különbség van a vezérlők által jelentett idő és a kérelem teljes időtartama között:
- A fejlesztők megszüntetik az alkalmazáskódjukat a probléma forrásaként.
- Gyakran feltételezzük, hogy az útválasztás az oka.
Az útválasztást több ezer végponton tesztelik. Nem valószínű, hogy egy tipikus alkalmazás teljesítményproblémába ütközik csak túl nagy mérete miatt. A lassú útválasztási teljesítmény leggyakoribb kiváltó oka általában egy rosszul viselkedő egyéni köztes szoftver.
Az alábbi kódminta a késés forrásának szűkítéséhez használható alapszintű technikát mutatja be:
var logger = app.Services.GetRequiredService<ILogger<Program>>();
app.Use(async (context, next) =>
{
var stopwatch = Stopwatch.StartNew();
await next(context);
stopwatch.Stop();
logger.LogInformation("Time 1: {ElapsedMilliseconds}ms", stopwatch.ElapsedMilliseconds);
});
app.UseRouting();
app.Use(async (context, next) =>
{
var stopwatch = Stopwatch.StartNew();
await next(context);
stopwatch.Stop();
logger.LogInformation("Time 2: {ElapsedMilliseconds}ms", stopwatch.ElapsedMilliseconds);
});
app.UseAuthorization();
app.Use(async (context, next) =>
{
var stopwatch = Stopwatch.StartNew();
await next(context);
stopwatch.Stop();
logger.LogInformation("Time 3: {ElapsedMilliseconds}ms", stopwatch.ElapsedMilliseconds);
});
app.MapGet("/", () => "Timing Test.");
Útvonalak időzítése
- Az egyes köztes szoftvereket az előző kódban látható időzítő köztes szoftver egy-egy példányával kell beágyazni.
- Adjon hozzá egy egyedi azonosítót, amely korrelálja az időzítési adatokat a kóddal.
Ez egy alapvető módja annak, hogy szűkítse a késést, ha jelentős, például több mint 10ms. A Time 2 kivonása a Time 1 jelentésből a UseRouting köztes szoftverben töltött időt jelzi.
Az alábbi kód az előző időzítési kód tömörebb megközelítését használja:
public sealed class AutoStopwatch : IDisposable
{
private readonly ILogger _logger;
private readonly string _message;
private readonly Stopwatch _stopwatch;
private bool _disposed;
public AutoStopwatch(ILogger logger, string message) =>
(_logger, _message, _stopwatch) = (logger, message, Stopwatch.StartNew());
public void Dispose()
{
if (_disposed)
{
return;
}
_logger.LogInformation("{Message}: {ElapsedMilliseconds}ms",
_message, _stopwatch.ElapsedMilliseconds);
_disposed = true;
}
}
var logger = app.Services.GetRequiredService<ILogger<Program>>();
var timerCount = 0;
app.Use(async (context, next) =>
{
using (new AutoStopwatch(logger, $"Time {++timerCount}"))
{
await next(context);
}
});
app.UseRouting();
app.Use(async (context, next) =>
{
using (new AutoStopwatch(logger, $"Time {++timerCount}"))
{
await next(context);
}
});
app.UseAuthorization();
app.Use(async (context, next) =>
{
using (new AutoStopwatch(logger, $"Time {++timerCount}"))
{
await next(context);
}
});
app.MapGet("/", () => "Timing Test.");
Potenciálisan költséges útválasztási funkciók
Az alábbi lista betekintést nyújt az alapszintű útvonalsablonokhoz képest viszonylag költséges útválasztási funkciókba:
- Reguláris kifejezések: Olyan reguláris kifejezések írhatók, amelyek összetettek, vagy hosszú ideig futnak kis mennyiségű bemenettel.
- Összetett szegmensek (
{x}-{y}-{z}):- Lényegesen drágábbak, mint egy normál URL-elérési út szegmensének elemzése.
- Ez azt eredményezi, hogy a rendszer sokkal több alsztringet foglal le.
- Szinkron adathozzáférés: Számos összetett alkalmazás rendelkezik adatbázis-hozzáféréssel az útválasztás részeként. Használjon olyan bővíthetőségi pontokat, mint az MatcherPolicy és EndpointSelectorContext, amelyek aszinkronok.
Útmutatás nagy útvonaltáblákhoz
Alapértelmezés szerint az ASP.NET Core egy olyan útválasztási algoritmust használ, amely memória felhasználást cserél fel processzoridőre. Ez jó hatással van arra, hogy az útvonal-egyeztetési idő csak az egyező útvonal hosszától függ, és nem az útvonalak számától. Ez a megközelítés azonban bizonyos esetekben potenciálisan problémás lehet, ha az alkalmazás nagy számú útvonalon (ezres nagyságrendben) rendelkezik, és nagy mennyiségű változó előtag található az útvonalakban. Ha például az útvonalaknak vannak paraméterei az útvonal korai szakaszaiban, például {parameter}/some/literal.
Nem valószínű, hogy egy alkalmazás olyan helyzetbe kerül, ahol ez probléma, kivéve, ha:
- Az alkalmazásban sok útvonal használja ezt a mintát.
- Az alkalmazásban számos útvonal található.
Hogyan állapítható meg, hogy egy alkalmazás szembesül-e a nagy útválasztási táblázat problémájával?
- Két tünetet kell keresni:
- Az alkalmazás lassan indul el az első kéréskor.
- Vegye figyelembe, hogy ez kötelező, de nem elegendő. Számos más nem útvonalbeli probléma is fennáll, mint ami lassú alkalmazásindítást okozhat. Ellenőrizze az alábbi feltételt, hogy pontosan megállapíthassa, hogy az alkalmazás fut-e ebben a helyzetben.
- Az alkalmazás sok memóriát használ fel az indítás során, és egy memóriadump sok
Microsoft.AspNetCore.Routing.Matching.DfaNodepéldányokat mutat.
- Az alkalmazás lassan indul el az első kéréskor.
A probléma megoldása
Számos technika és optimalizálás alkalmazható az útvonalakra, amelyek nagyban javítják ezt a forgatókönyvet:
- Ha lehetséges, alkalmazzon útvonalkorlátozásokat a paraméterekre, például
{parameter:int},{parameter:guid}stb{parameter:regex(\\d+)}.- Ez lehetővé teszi, hogy az útválasztási algoritmus belsőleg optimalizálja az egyezéshez használt struktúrákat, és drasztikusan csökkentse a felhasznált memóriát.
- Az esetek túlnyomó többségében ez elegendő lesz ahhoz, hogy visszatérjen egy elfogadható viselkedéshez.
- Módosítsa az útvonalakat úgy, hogy a paramétereket a sablon későbbi szegmenseibe helyezze át.
- Ez csökkenti a lehetséges "elérési utak" számát, hogy megfeleljen egy adott elérési úthoz megadott végpontnak.
- Használjon dinamikus útvonalat, és végezze el dinamikusan a vezérlőre/lapra való leképezést.
- Ez elérhető
MapDynamicControllerRouteésMapDynamicPageRoutehasználatával.
- Ez elérhető
Útmutató könyvtárszerzőknek
Ez a szakasz útmutatást tartalmaz az útválasztásra alapuló könyvtárak szerzői számára. Ezek a részletek biztosítják, hogy az alkalmazásfejlesztők jól használják az útválasztást kiterjesztő kódtárakat és keretrendszereket.
Végpontok definiálása
Az útválasztást használó keretrendszer létrehozásához, amely az URL-ek egyeztetésére szolgál, kezdje azzal, hogy definiál egy felhasználói élményt, amely a UseEndpoints alapján épül fel.
ÉPÍTS a IEndpointRouteBuilder tetejére. Ez lehetővé teszi, hogy a felhasználók összekeverés nélkül más ASP.NET Core-funkciókkal is megírják a keretrendszert. Minden ASP.NET Core-sablon tartalmazza az útválasztást. Tegyük fel, hogy az útválasztás jelen van és ismerős a felhasználók számára.
// Your framework
app.MapMyFramework(...);
app.MapHealthChecks("/healthz");
A DO egy lezárt betontípust ad vissza az adott implementálásra MapMyFramework(...)IEndpointConventionBuilderirányuló hívásból. A legtöbb keretrendszer-metódus Map... ezt a mintát követi. A IEndpointConventionBuilder felület:
- Lehetővé teszi a metaadatok összeállítását.
- Különféle bővítési módszerek célozzák meg.
A saját típus deklarálása lehetővé teszi saját keretrendszerspecifikus funkciók hozzáadását a szerkesztőhöz. Nem baj, ha egy keretrendszer által deklarált szerkesztőt burkolunk, és hívásokat továbbítunk neki.
// Your framework
app.MapMyFramework(...)
.RequireAuthorization()
.WithMyFrameworkFeature(awesome: true);
app.MapHealthChecks("/healthz");
GONDOLKODJ azon, hogy megírod a saját EndpointDataSource.
EndpointDataSource a végpontok gyűjteményének deklarálására és frissítésére szolgáló alacsony szintű primitív.
EndpointDataSource egy hatékony API, amelyet a vezérlők és Razor a Pages használnak.
Az útválasztási tesztek egy alapvető példával rendelkeznek egy nem frissített adatforrásra.
NE próbáljon meg alapértelmezés szerint egy objektumot regisztrálni.EndpointDataSource Követelje meg a felhasználóktól, hogy regisztrálják a keretrendszert UseEndpoints. Az útválasztás filozófiája, hogy alapértelmezés szerint semmi nem szerepel benne, és ez UseEndpoints a végpontok regisztrálásának helye.
Útvonalválasztással integrált köztes szoftver létrehozása
FONTOLJA meg a metaadat-típusok interfészként való meghatározását.
A DO lehetővé teszi a metaadat-típusok attribútumként való használatát osztályokon és metódusokon.
public interface ICoolMetadata
{
bool IsCool { get; }
}
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
public class CoolMetadataAttribute : Attribute, ICoolMetadata
{
public bool IsCool => true;
}
Az olyan keretrendszerek, mint a vezérlők és Razor a Lapok, támogatják a metaadat-attribútumok típusokra és metódusokra való alkalmazását. Metaadattípusok deklarálása esetén:
- Elérhetővé teheti őket attribútumként.
- A felhasználók többsége ismeri az attribútumok alkalmazását.
A metaadat-típus felületként való deklarálása további rugalmassági réteget ad:
- A felületek összeállíthatók.
- A fejlesztők deklarálhatják a saját típusaikat, amelyek több szabályzatot kombinálnak.
A DO lehetővé teszi a metaadatok felülbírálását az alábbi példában látható módon:
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
public class SuppressCoolMetadataAttribute : Attribute, ICoolMetadata
{
public bool IsCool => false;
}
[CoolMetadata]
public class MyController : Controller
{
public void MyCool() { }
[SuppressCoolMetadata]
public void Uncool() { }
}
Az alábbi irányelvek követésének legjobb módja, ha elkerüli a jelölő metaadatainak meghatározását:
- Ne csak a metaadat-típus jelenlétét keresse.
- Definiáljon egy tulajdonságot a metaadatokon, és ellenőrizze a tulajdonságot.
A metaadat-gyűjtemény rendezett, és támogatja a prioritás szerinti felülrendelést. Vezérlők esetében a műveletmetódus metaadatai a legspecifikusak.
Tegye a köztes szoftvert hasznossá útválasztással és útválasztás nélkül:
app.UseAuthorization(new AuthorizationPolicy() { ... });
// Your framework
app.MapMyFramework(...).RequireAuthorization();
Ennek az útmutatónak a példájaként vegye figyelembe a köztes UseAuthorization szoftvereket. Az engedélyezési köztes szoftver lehetővé teszi, hogy tartalék szabályzatot adjon át.
A tartalék szabályzat, ha meg van adva, mindkettőre vonatkozik:
- Meghatározott szabályzat nélküli végpontok.
- A végpontnak nem megfelelő kérések.
Ez hasznossá teszi az engedélyezési köztes szoftvereket az útválasztás környezetén kívül. Az engedélyezési köztes szoftver használható a hagyományos köztes szoftver programozásához.
Hibakeresési diagnosztika
A részletes útválasztási diagnosztikai kimenethez állítsa be a Logging:LogLevel:Microsoft értékét Debug-re. A fejlesztési környezetben állítsa be a naplószintet: appsettings.Development.json
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft": "Debug",
"Microsoft.Hosting.Lifetime": "Information"
}
}
}
További erőforrások
- Mintakód megtekintése vagy letöltése (hogyan töltsd le)
Az útválasztás feladata a bejövő HTTP-kérések egyeztetése és a kérések elküldése az alkalmazás végrehajtható végpontjaira. A végpontok az alkalmazás végrehajtható kéréskezelési kódjának egységei. A végpontok az alkalmazásban vannak definiálva, és az alkalmazás indításakor vannak konfigurálva. A végpontegyeztetési folyamat kinyerheti az értékeket a kérelem URL-címéből, és megadhatja ezeket az értékeket a kérelmek feldolgozásához. Az alkalmazás végpontadatainak használatával az útválasztás a végpontokra leképező URL-címeket is képes létrehozni.
Az alkalmazások a következő eszközökkel konfigurálhatják az útválasztást:
- Controllers
- Razor lapok
- SignalR
- gRPC-szolgáltatások
- Végpont-kompatibilis köztes szoftver, mint például a Health Checks.
- Útválasztással regisztrált delegátumok és lambdák.
Ez a dokumentum a ASP.NET Core útválasztásának alacsony szintű részleteit ismerteti. Az útválasztás konfigurálásával kapcsolatos információk:
- A vezérlőkről lásd: Útválasztás a vezérlőműveletekhez a ASP.NET Core-ban.
- Az Razor Pages konvenciókról lásd az ASP.NET Core oldal útvonal- és alkalmazási konvencióit Razor.
A dokumentumban ismertetett végpont-útválasztási rendszer ASP.NET Core 3.0-s vagy újabb verziójára vonatkozik. Az előző útválasztási rendszerrel IRouterkapcsolatos információkért válassza ki a ASP.NET Core 2.1-es verzióját az alábbi módszerek egyikével:
- Az előző verzió verzióválasztója.
- Válassza ASP.NET Core 2.1 útválasztást.
Mintakód megtekintése vagy letöltése (hogyan töltsd le)
A dokumentum letöltési mintáit egy adott Startup osztály engedélyezi. Egy adott minta futtatásához módosítsa Program.cs úgy, hogy meghívja a kívánt Startup osztályt.
Az útválasztás alapjai
Minden ASP.NET Core-sablon tartalmazza az útválasztást a létrehozott kódban. Az útválasztást a middleware folyamatába regisztrálják a Startup.Configure.
Az alábbi kód egy egyszerű útválasztási példát mutat be:
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseRouting();
app.UseEndpoints(endpoints =>
{
endpoints.MapGet("/", async context =>
{
await context.Response.WriteAsync("Hello World!");
});
});
}
Az útválasztás egy köztes szoftverpárt használ, amelyet a UseRouting és a UseEndpoints regisztrál.
-
UseRoutingA köztesszoftver-folyamatnak megfelelő útvonalat ad hozzá. Ez a köztes szoftver megvizsgálja az alkalmazásban definiált végpontokat, és a kérés alapján kiválasztja a legjobb egyezést . -
UseEndpointsvégpontvégrehajtást ad a köztes szoftverfolyamathoz. A kijelölt végponthoz társított delegáltat a program futtatja.
Az előző példa egyetlen útvonalat tartalmaz a kódvégponthoz a MapGet metódus használatával:
- HA HTTP-kérést
GETküld a rendszer a gyökér URL-címre/:- A kérelem delegáltja végrehajtja a elemet.
-
Hello World!az HTTP-válaszként íródik. Alapértelmezés szerint a gyökér URL-címe/https://localhost:5001/.
- Ha a kérelem metódusa nem
GET, vagy a gyökér URL-címe nem/, a rendszer nem ad vissza útvonal-egyezést, és a rendszer egy HTTP 404-et ad vissza.
Endpoint
A MapGet metódus egy végpont definiálására szolgál. A végpont a következő lehet:
- Az URL-cím és a HTTP-metódus egyeztetésével kijelölve.
- A delegált futtatásával hajtva végre.
Az alkalmazás által egyeztethető és végrehajtható végpontok a UseEndpoints-ben vannak konfigurálva. Például MapGet, MapPost és hasonló metódusok csatlakoztatják a kérelem delegáltjait az útválasztási rendszerhez. További módszerekkel csatlakoztathatók ASP.NET Core-keretrendszer funkciói az útválasztási rendszerhez:
- MapRazorPages a Razor oldalak számára
- MapControllers vezérlőkhöz
- MapHub<THub> for SignalR
- MapGrpcService<TService> for gRPC
Az alábbi példa egy kifinomultabb útvonalsablont tartalmazó útválasztást mutat be:
app.UseEndpoints(endpoints =>
{
endpoints.MapGet("/hello/{name:alpha}", async context =>
{
var name = context.Request.RouteValues["name"];
await context.Response.WriteAsync($"Hello {name}!");
});
});
A karakterlánc /hello/{name:alpha} egy útvonalsablon. A végpont egyeztetésének konfigurálására szolgál. Ebben az esetben a sablon megfelel a következőnek:
- URL-cím, például
/hello/Ryan - Minden olyan URL-elérési út, amely betűrendes karakterek sorozatával
/hello/kezdődik.:alphaolyan útvonalkorlátozást alkalmaz, amely csak betűrendes karaktereknek felel meg. Az útvonalkorlátozásokat a dokumentum későbbi részében ismertetjük.
Az URL-elérési út második szegmense: {name:alpha}
- A paraméterhez
namevan kötve. - A rendszer a HttpRequest.RouteValues-ban rögzíti és tárolja.
A dokumentumban ismertetett végpont-útválasztási rendszer ASP.NET Core 3.0-s verziójától új. A ASP.NET Core összes verziója azonban ugyanazokat az útvonalsablon-funkciókat és útvonalkorlátozásokat támogatja.
Az alábbi példa az állapot-ellenőrzéssel és engedélyezéssel rendelkező útválasztást mutatja be:
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
// Matches request to an endpoint.
app.UseRouting();
// Endpoint aware middleware.
// Middleware can use metadata from the matched endpoint.
app.UseAuthentication();
app.UseAuthorization();
// Execute the matched endpoint.
app.UseEndpoints(endpoints =>
{
// Configure the Health Check endpoint and require an authorized user.
endpoints.MapHealthChecks("/healthz").RequireAuthorization();
// Configure another endpoint, no authorization requirements.
endpoints.MapGet("/", async context =>
{
await context.Response.WriteAsync("Hello World!");
});
});
}
Ha szeretné, hogy a kódkommentárok angolon kívül más nyelvekre is le legyenek fordítva, jelezze nekünk a GitHub vitafórumkérdésénél.
Az előző példa bemutatja, hogyan:
- Az engedélyezési köztes szoftver használható útválasztással.
- A végpontok az engedélyezési viselkedés konfigurálására használhatók.
A MapHealthChecks hívás egy állapot-ellenőrzési végpontot ad hozzá. A RequireAuthorization láncolása ehhez a híváshoz egy engedélyezési szabályzatot csatol a végponthoz.
A UseAuthentication és UseAuthorization meghívása hozzáadja a hitelesítési és engedélyezési middleware-t. Ezek a köztes szoftverek UseRouting és UseEndpoints közé vannak helyezve, hogy:
- Nézze meg, melyik végpontot választotta
UseRouting. - Engedélyezési szabályzat alkalmazása a végpontra történő küldés előtt UseEndpoints .
Végpont metaadatai
Az előző példában két végpont található, de csak az állapot-ellenőrzési végpont rendelkezik engedélyezési szabályzattal. Ha a kérelem megfelel az állapot-ellenőrzési végpontnak, /healthza rendszer engedélyezési ellenőrzést végez. Ez azt mutatja be, hogy a végpontokhoz további adatok is csatolhatók. Ezt a további adatot végponti metaadatoknak nevezzük:
- A metaadatok feldolgozhatók útválasztást ismerő köztes szoftver használatával.
- A metaadatok bármilyen .NET típusúak lehetnek.
Útválasztási fogalmak
Az útválasztási rendszer a közbenső szoftver folyamatára épül a hatékony végpontkoncepció hozzáadásával. A végpontok az alkalmazás funkcióinak azon egységeit jelölik, amelyek útválasztás, engedélyezés és ASP.NET Core-rendszerek tetszőleges száma tekintetében különböznek egymástól.
ASP.NET alapvető végpontdefiníció
Az ASP.NET Core-végpont a következő:
- Végrehajtható: rendelkezik egy RequestDelegate.
- Bővíthető: Metaadat-gyűjteménysel rendelkezik.
- Kiválasztható: Opcionálisan útválasztási információkkal rendelkezik.
- Enumerable: A végpontok gyűjteménye a EndpointDataSource való lekéréssel listázható.
Az alábbi kód bemutatja, hogyan kérheti le és vizsgálhatja meg az aktuális kérésnek megfelelő végpontot:
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseRouting();
app.Use(next => context =>
{
var endpoint = context.GetEndpoint();
if (endpoint is null)
{
return Task.CompletedTask;
}
Console.WriteLine($"Endpoint: {endpoint.DisplayName}");
if (endpoint is RouteEndpoint routeEndpoint)
{
Console.WriteLine("Endpoint has route pattern: " +
routeEndpoint.RoutePattern.RawText);
}
foreach (var metadata in endpoint.Metadata)
{
Console.WriteLine($"Endpoint has metadata: {metadata}");
}
return Task.CompletedTask;
});
app.UseEndpoints(endpoints =>
{
endpoints.MapGet("/", async context =>
{
await context.Response.WriteAsync("Hello World!");
});
});
}
Ha a végpont ki van választva, lekérhető a HttpContext. Tulajdonságai megvizsgálhatók. A végpontobjektumok nem módosíthatók, és a létrehozás után nem módosíthatók. A végpont leggyakoribb típusa a RouteEndpoint.
RouteEndpoint információkat tartalmaz, amelyek lehetővé teszik az útválasztási rendszer számára, hogy kiválaszthassa azt.
Az előző kódban a app.Use egy soron belüli közvetítő szoftvert konfigurál.
Az alábbi kód azt mutatja, hogy attól függően, hogy a folyamatban hol app.Use van meghívva, előfordulhat, hogy nincs végpont:
// Location 1: before routing runs, endpoint is always null here
app.Use(next => context =>
{
Console.WriteLine($"1. Endpoint: {context.GetEndpoint()?.DisplayName ?? "(null)"}");
return next(context);
});
app.UseRouting();
// Location 2: after routing runs, endpoint will be non-null if routing found a match
app.Use(next => context =>
{
Console.WriteLine($"2. Endpoint: {context.GetEndpoint()?.DisplayName ?? "(null)"}");
return next(context);
});
app.UseEndpoints(endpoints =>
{
// Location 3: runs when this endpoint matches
endpoints.MapGet("/", context =>
{
Console.WriteLine(
$"3. Endpoint: {context.GetEndpoint()?.DisplayName ?? "(null)"}");
return Task.CompletedTask;
}).WithDisplayName("Hello");
});
// Location 4: runs after UseEndpoints - will only run if there was no match
app.Use(next => context =>
{
Console.WriteLine($"4. Endpoint: {context.GetEndpoint()?.DisplayName ?? "(null)"}");
return next(context);
});
Ez az előző minta olyan utasításokat ad hozzá, amelyek megadják Console.WriteLine, hogy ki legyen-e jelölve egy végpont. Az egyértelműség kedvéért a minta megjelenítendő nevet rendel a megadott / végponthoz.
Ennek a kódnak a futtatása egy / URL-címmel megjeleníti:
1. Endpoint: (null)
2. Endpoint: Hello
3. Endpoint: Hello
A kód futtatása bármely más URL-címmel:
1. Endpoint: (null)
2. Endpoint: (null)
4. Endpoint: (null)
Ez a kimenet a következőt mutatja be:
- A végpont mindig null értékű, mielőtt
UseRoutingmeghívják. - Ha talál egyezést, a végpont nem null, és a
UseRoutingés UseEndpoints között van. - A
UseEndpointsköztes szoftver terminál , ha talál egyezést. A terminál köztes szoftver a dokumentum későbbi részében van definiálva. - A köztesréteg csak akkor fut, ha a
UseEndpointsvégrehajtása után nem található egyezés.
A UseRouting köztes szoftver a SetEndpoint metódus használatával csatolja a végpontot az aktuális környezethez. A köztes szoftvereket lecserélheti egyéni UseRouting logikára, és továbbra is élvezheti a végpontok használatának előnyeit. A végpontok alacsony szintű primitívek, például köztes szoftverek, és nem kapcsolódnak az útválasztási megvalósításhoz. A legtöbb alkalmazásnak nem kell egyéni logikára cserélnie UseRouting .
A UseEndpoints köztes szoftvert úgy alakították ki, hogy a UseRouting köztes szoftverrel tandem használatra legyen. A végpontok végrehajtásának alapvető logikája nem bonyolult. A végpont lekérésére GetEndpoint használata, majd annak RequestDelegate tulajdonságának meghívása.
Az alábbi kód bemutatja, hogy a köztes szoftver hogyan befolyásolhatja vagy reagálhat az útválasztásra:
public class IntegratedMiddlewareStartup
{
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
// Location 1: Before routing runs. Can influence request before routing runs.
app.UseHttpMethodOverride();
app.UseRouting();
// Location 2: After routing runs. Middleware can match based on metadata.
app.Use(next => context =>
{
var endpoint = context.GetEndpoint();
if (endpoint?.Metadata.GetMetadata<AuditPolicyAttribute>()?.NeedsAudit
== true)
{
Console.WriteLine($"ACCESS TO SENSITIVE DATA AT: {DateTime.UtcNow}");
}
return next(context);
});
app.UseEndpoints(endpoints =>
{
endpoints.MapGet("/", async context =>
{
await context.Response.WriteAsync("Hello world!");
});
// Using metadata to configure the audit policy.
endpoints.MapGet("/sensitive", async context =>
{
await context.Response.WriteAsync("sensitive data");
})
.WithMetadata(new AuditPolicyAttribute(needsAudit: true));
});
}
}
public class AuditPolicyAttribute : Attribute
{
public AuditPolicyAttribute(bool needsAudit)
{
NeedsAudit = needsAudit;
}
public bool NeedsAudit { get; }
}
Az előző példa két fontos fogalmat mutat be:
- A köztes szoftver előzetesen futtatható a
UseRoutingelőtt, hogy módosítsa azokat az adatokat, amelyeken az útválasztás működik.- Az útválasztás előtt megjelenő köztes szoftver általában módosítja a kérés bizonyos tulajdonságát, például UseRewriter: , UseHttpMethodOverridevagy UsePathBase.
- A middleware a
UseRoutingés UseEndpoints között futtatható annak érdekében, hogy az útválasztás eredményeit feldolgozza, mielőtt a végpont végrehajtásra kerül.- Köztes szoftver, amely a
UseRoutingésUseEndpointsközött fut:- A végpontok megértéséhez általában a metaadatokat vizsgálja meg.
- Gyakran hoz biztonsági döntéseket, mint a
UseAuthorizationésUseCors.
- A köztes szoftver és a metaadatok kombinációja lehetővé teszi a szabályzatok végpontonkénti konfigurálását.
- Köztes szoftver, amely a
Az előző kód egy végpontonkénti szabályzatokat támogató egyéni köztes szoftver példáját mutatja be. A köztes szoftver naplót ír a konzol bizalmas adataihoz való hozzáférésről. A köztes szoftver konfigurálható egy végpont metaadatokkal történő naplózásáraAuditPolicyAttribute. Ez a minta egy feliratkozásos mintát mutat be, amelyben csak a bizalmasként megjelölt végpontokat naplózzák. Ezt a logikát meg lehet határozni fordítottan, például naplózva mindent, ami nincs biztonságosként megjelölve. A végpont metaadat-rendszere rugalmas. Ez a logika bármilyen módon megtervezhető a használati esetnek megfelelően.
Az előző mintakód a végpontok alapfogalmait mutatja be. A minta nem éles használatra készült. A naplózási napló köztes szoftverének teljesebb verziója a következő lenne:
- Jelentkezzen be egy fájlba vagy adatbázisba.
- Adjon meg olyan részleteket, mint a felhasználó, az IP-cím, a bizalmas végpont neve stb.
A naplózási szabályzat metaadatai AuditPolicyAttribute egy Attribute-ként vannak definiálva a könnyebb használat érdekében olyan osztályalapú keretrendszerekkel, mint például a vezérlők és SignalR. A kódhoz vezető útvonal használata esetén:
- A metaadatok egy builder API-val vannak csatolva.
- Az osztályalapú keretrendszerek a végpontok létrehozásakor tartalmazzák a megfelelő metódus és osztály összes attribútumát.
A metaadat-típusok ajánlott eljárása, hogy interfészként vagy attribútumként definiálja őket. Az interfészek és attribútumok lehetővé teszik a kód újrafelhasználását. A metaadat-rendszer rugalmas, és nem ír elő korlátozásokat.
Terminál köztes szoftver és útválasztás összehasonlítása
Az alábbi kódminta összehasonlítja a köztes szoftver használatát az útválasztás használatával.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
// Approach 1: Writing a terminal middleware.
app.Use(next => async context =>
{
if (context.Request.Path == "/")
{
await context.Response.WriteAsync("Hello terminal middleware!");
return;
}
await next(context);
});
app.UseRouting();
app.UseEndpoints(endpoints =>
{
// Approach 2: Using routing.
endpoints.MapGet("/Movie", async context =>
{
await context.Response.WriteAsync("Hello routing!");
});
});
}
A Approach 1:-vel látható köztes szoftver stílusa a terminál köztes szoftver. Terminál köztes szoftvernek nevezzük, mert egyező műveletet hajt végre:
- Az előző mintában az illesztési művelet a
Path == "/"a köztes szoftverhez ésPath == "/Movie"az útválasztáshoz tartozik. - Ha egy egyezés sikeres, végrehajt néhány funkciót, és visszatér anélkül, hogy meghívná a
nextköztes szoftvert.
Terminál köztes szoftvernek nevezik, mert leállítja a keresést, végrehajt néhány funkciót, majd visszaadja.
Terminál köztes szoftver és útválasztás összehasonlítása:
- Mindkét módszer lehetővé teszi a feldolgozási folyamat leállítását:
- A köztes szoftver a
nextmeghívása helyett visszatéréssel leállítja a futószalagot. - A végpontok mindig terminálok.
- A köztes szoftver a
- A terminálközvetítő lehetővé teszi a köztes szoftver tetszőleges helyen való elhelyezését a folyamatban:
- A végpontok a UseEndpoints pozíción futnak.
- A terminál köztes réteg lehetővé teszi, hogy tetszőleges kód határozza meg, mikor egyezik a köztes szoftver.
- Az egyéni útvonalegyeztető kód részletes lehet, és nehezen írható helyesen.
- Az útválasztás egyszerű megoldásokat kínál a tipikus alkalmazásokhoz. A legtöbb alkalmazás nem igényel egyéni útvonalegyeztető kódot.
- A végpontok interfészei köztes szoftverekkel, mint például
UseAuthorizationésUseCors, kommunikálnak.- A
UseAuthorizationvagyUseCorsterminálközvetítő használata manuális beavatkozást igényel az engedélyezési rendszerbe való interfészépítés során.
- A
Egy végpont mindkettőt definiálja:
- A kérések feldolgozására jogosult meghatalmazott.
- Tetszőleges metaadatok gyűjteménye. A metaadatok az egyes végpontokhoz csatolt szabályzatokon és konfigurációkon alapuló, átfogó problémák megvalósítására szolgálnak.
A terminál köztes szoftver hatékony eszköz lehet, de a következőt igényelheti:
- Jelentős mennyiségű kódolás és tesztelés.
- Manuális integráció más rendszerekkel a kívánt rugalmasság elérése érdekében.
A terminál middleware megírása előtt fontolja meg az útvonalvezérléssel való integrálást.
A meglévő terminálközvetítmények, amelyek integrálódnak a Map-pal vagy a MapWhen, általában útválasztást támogató végponttá alakíthatók. MapHealthChecks a routerelem mintáját mutatja be:
- Bővítménymetódus írása a fájlra IEndpointRouteBuilder.
- Beágyazott köztes szoftverfolyamat létrehozása a következővel CreateApplicationBuilder: .
- Csatolja a köztes szoftvert az új folyamathoz. Ebben az esetben: UseHealthChecks.
- Build a köztes szoftverfolyamatot egy RequestDelegate.
- Hívja meg
Mapés adja meg az új köztes szoftverfolyamatot. - Adja vissza az
Mapáltal biztosított építőobjektumot a bővítménymetódusból.
Az alábbi kód a MapHealthChecks használatát mutatja be:
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
// Matches request to an endpoint.
app.UseRouting();
// Endpoint aware middleware.
// Middleware can use metadata from the matched endpoint.
app.UseAuthentication();
app.UseAuthorization();
// Execute the matched endpoint.
app.UseEndpoints(endpoints =>
{
// Configure the Health Check endpoint and require an authorized user.
endpoints.MapHealthChecks("/healthz").RequireAuthorization();
// Configure another endpoint, no authorization requirements.
endpoints.MapGet("/", async context =>
{
await context.Response.WriteAsync("Hello World!");
});
});
}
Az előző minta bemutatja, miért fontos az építő objektum visszaadása. A szerkesztőobjektum visszaadásával az alkalmazás fejlesztője olyan szabályzatokat konfigurálhat, mint a végpont engedélyezése. Ebben a példában az állapot-ellenőrző köztes szoftver nem rendelkezik közvetlen integrációval az engedélyezési rendszerrel.
A metaadat-rendszer a terminál köztes szoftvereket használó bővíthetőségi szerzők által tapasztalt problémákra válaszul jött létre. Minden köztes szoftver esetében problémás a saját integráció megvalósítása az engedélyezési rendszerrel.
URL-cím egyeztetése
- Az a folyamat, amellyel az útválasztás megfelel a végpontnak küldött bejövő kérésnek.
- Az URL-elérési út és a fejlécek adatain alapul.
- A kérelemben szereplő bármely adatra kiterjeszthető.
Az útvonalkezelő köztes szoftver végrehajtásakor beállít Endpoint és útvonali értékeket egy kérés tulajdonságához az HttpContext aktuális kérés alapján.
- A HttpContext.GetEndpoint hívása megkapja a végpontot.
-
HttpRequest.RouteValueslekéri az útvonalértékek gyűjteményét.
A köztes szoftver azután fut, hogy az útválasztási köztes szoftver megvizsgálhatja a végpontot, és végrehajthatja a műveletet. Egy engedélyezési köztes szoftver például kikérdezheti a végpont metaadatgyűjteményét egy engedélyezési szabályzathoz. A kérelemfeldolgozási folyamat összes köztes szoftverének végrehajtása után a rendszer meghívja a kijelölt végpont delegáltját.
A végponti útválasztás útválasztási rendszere felelős az összes irányítási döntésért. Mivel a köztes szoftver a kiválasztott végponton alapuló szabályzatokat alkalmaz, fontos, hogy:
- Minden olyan döntés, amely befolyásolhatja a küldést vagy a biztonsági szabályzatok alkalmazását, az útválasztási rendszeren belül történik.
Warning
A visszamenőleges kompatibilitás érdekében a Vezérlő vagy Razor a Lapok végpont delegáltjának végrehajtásakor a RouteContext.RouteData tulajdonságai az eddig végrehajtott kérésfeldolgozás alapján megfelelő értékekre vannak beállítva.
A RouteContext típus elavultként lesz megjelölve egy későbbi kiadásban:
- Migrálás
RouteData.ValuesHttpRequest.RouteValues-re. - Migrálás
RouteData.DataTokensaz IDataTokensMetadata végpont metaadataiból való lekéréséhez.
Az URL-egyeztetés konfigurálható fázisokban működik. Minden fázisban a kimenet egyezések halmaza. Az egyezések halmaza a következő szakaszban tovább szűkíthető. Az útválasztási implementáció nem garantálja az egyező végpontok feldolgozási sorrendjét. Az összes lehetséges találat feldolgozása egyszerre történik. Az URL-egyeztetési fázisok a következő sorrendben történnek. ASP.NET Core:
- Feldolgozza az URL-útvonalat a végpontok és útvonalsablonjaik alapján, és összegyűjti az összes egyezést.
- A megelőző listát veszi alapul, és eltávolítja azokat az egyezéseket, amelyek nem felelnek meg az útvonal-korlátozásoknak.
- Felveszi az előző listát, és eltávolítja azokat az egyezéseket, amelyek nem felelnek meg a MatcherPolicy-példányok készletének.
- Az EndpointSelector használatával végleges döntést hoz az előző listáról.
A végpontok listája a következő szempontok szerint van rangsorolva:
A rendszer minden fázisban feldolgoz minden egyező végpontot, amíg el nem éri azokat EndpointSelector . A EndpointSelector az utolsó fázis. A találatok közül a legmagasabb prioritású végpontot választja ki a legjobb egyezésként. Ha vannak olyan találatok, amelyek prioritása megegyezik a legjobb egyezésével, a rendszer nem egyértelmű egyezés-kivételt ad ki.
Az útvonal elsőbbsége egy pontosabb útvonalsablon alapján van kiszámítva, amely magasabb prioritást kap. Vegyük például a sablonokat /hello és /{message}:
- Mindkettő megfelel az URL-cím elérési útjának
/hello. -
/hellopontosabb, ezért magasabb prioritású.
Általánosságban elmondható, hogy az útvonalak prioritása hatékonyan kiválasztja a gyakorlatban használt URL-sémákhoz leginkább illő találatokat. A kétértelműség elkerülése érdekében csak akkor használja Order , ha szükséges.
Az útválasztás által biztosított bővíthetőség miatt nem lehetséges, hogy az útválasztási rendszer előre kiszámítsa a nem egyértelmű útvonalakat. Vegyük például az útvonalsablonokat /{message:alpha} és /{message:int}:
- A
alphakényszer csak alfabetikus karaktereket egyezik meg. - A
intkényszer csak a számoknak felel meg. - Ezek a sablonok ugyanazt az útvonal elsőbbséget élvezik, de nincs egyetlen URL-cím, amely mindkettőnek megfelel.
- Ha az útválasztási rendszer kétértelmű hibát jelentett az indításkor, az blokkolná ezt az érvényes használati esetet.
Warning
A belső UseEndpoints műveletek sorrendje egyetlen kivétellel nem befolyásolja az útválasztás viselkedését. MapControllerRoute és MapAreaRoute automatikusan rendelési értéket rendelnek a végpontokhoz a meghívásuk sorrendje alapján. Ez a vezérlők hosszú távú viselkedését szimulálja anélkül, hogy az útválasztási rendszer ugyanazokat a garanciákat nyújtja, mint a régebbi útválasztási implementációk.
Az útválasztás örökölt implementációjában olyan útválasztási bővíthetőség implementálható, amely függ az útvonalak feldolgozásának sorrendjétõl. Végpont-útválasztás a ASP.NET Core 3.0-s vagy újabb verziójában:
- Nincs fogalma az útvonalakról.
- Nem biztosít rendelési garanciát. A rendszer az összes végpontot egyszerre dolgozza fel.
Útvonalsablon elsőbbsége és végpontválasztási sorrend
Az útvonalsablonok elsőbbsége egy olyan rendszer, amely minden útvonalsablonhoz hozzárendel egy értéket az adottság alapján. Útvonalsablon elsőbbsége:
- Gyakori esetekben nem szükséges módosítani a végpontok sorrendjét.
- Kísérletek az útválasztási viselkedés józan észbeli elvárásainak való megfelelésre.
Fontolja meg például a sablonokat /Products/List és a /Products/{id}. Ésszerű lenne feltételezni, hogy /Products/List jobb választás, mint /Products/{id} az URL útvonal /Products/List számára. Ez azért működik, mert a konstans szegmensnek /List jobb elsőbbsége van a paraméterszegmensnél /{id}.
A sorrend működésének részletei az útvonalsablonok definiálásának módjával vannak összekapcsolva:
- A több szegmenst tartalmazó sablonok pontosabbnak tekinthetők.
- A literális szöveggel rendelkező szegmensek pontosabbak, mint a paraméterszegmensek.
- A korlátozással rendelkező paraméterszegmensek egynél specifikusabbnak tekinthetők anélkül.
- Az összetett szegmenseket kényszerrel rendelkező paraméterszegmensnek tekintjük.
- A catch-all paraméterek a legkevésbé specifikusak. Lásd a catch-all című részben a útvonalsablon referenciájában található fontos információkat a catch-all útvonalakról.
A pontos értékekre vonatkozó hivatkozásért tekintse meg a GitHub forráskódját .
AZ URL-létrehozás fogalmai
URL-cím létrehozása:
- Az a folyamat, amellyel az útválasztás létrehozhat egy URL-útvonalat az útvonalértékek készlete alapján.
- Lehetővé teszi a végpontok és a hozzájuk hozzáférő URL-címek logikai elkülönítését.
A végpont útválasztása tartalmazza az API-t LinkGenerator .
LinkGenerator egy egyszeri szolgáltatás, amely a DI-től érhető el. Az LinkGenerator API a végrehajtási kérelem környezetén kívül is használható.
Az Mvc.IUrlHelper és az olyan forgatókönyvek, mint IUrlHelpera Címkesegítők, a HTML-segítők és a műveleti eredmények, az API belső használatával biztosítják a LinkGenerator hivatkozásgeneráló képességeket.
A kapcsolatgenerátort a cím - és címsémák fogalma is alátámasztja. A címséma a hivatkozásgenerálás szempontjából megfontolandó végpontok meghatározásának módja. Az útvonalnév és az útvonalértékek forgatókönyvei például sok felhasználó számára ismerősek a vezérlőkből, a Razor Pages pedig címsémaként van implementálva.
A hivatkozásgenerátor a következő bővítménymódszerekkel hivatkozhat vezérlőkre és Razor lapokra:
Ezen metódusok túlterhelései olyan argumentumokat fogadnak el, amelyek tartalmazzák a HttpContext. Ezek a módszerek funkcionálisan egyenértékűek az Url.Action és a Url.Page, de további rugalmasságot és lehetőségeket kínálnak.
A GetPath* metódusok leginkább a Url.Action és Url.Page metódusokhoz hasonlítanak, mivel abszolút elérési utat tartalmazó URI-t hoznak létre. A GetUri* metódusok mindig egy sémát és kiszolgálót tartalmazó abszolút URI-t hoznak létre. Azok a metódusok, amelyek elfogadnak egy HttpContext-t, URI-t generálnak a végrehajtás alatt álló kérés kontextusában. A környezeti útvonalértékek, az URL alapelérési út, a séma és a gazdagép a végrehajtott kérelemből kerülnek felhasználásra, kivéve, ha felülbírálják őket.
LinkGenerator egy címmel kerül meghívásra. Az URI létrehozása két lépésben történik:
- Egy cím a címnek megfelelő végpontok listájához van kötve.
- Az egyes végpontok RoutePattern kiértékelése addig történik, amíg a megadott értékeknek megfelelő útvonalminta nem található. Az eredményül kapott kimenetet a hivatkozásgenerátorhoz megadott többi URI-résszel kombinálják, és visszaadják.
A LinkGenerator által biztosított metódusok támogatják a szabványos hivatkozáslétrehozási képességeket bármilyen címtípus esetén. A hivatkozásgenerátor használatának legkényelmesebb módja egy adott címtípus műveleteit végrehajtó bővítménymetelyek:
| Bővítménymetódus | Description |
|---|---|
| GetPathByAddress | A megadott értékek alapján abszolút elérési úttal rendelkező URI-t hoz létre. |
| GetUriByAddress | Abszolút URI-t hoz létre a megadott értékek alapján. |
Warning
Ügyeljen a hívási LinkGenerator módszerek alábbi következményeire:
Olyan alkalmazáskonfigurációkban körültekintően használjon
GetUri*bővítménymetelyeket, amelyek nem ellenőrzik aHostbejövő kérések fejlécét. Ha aHostbejövő kérések fejléce nincs érvényesítve, a nem megbízható kérések bemenete visszaküldhető az ügyfélnek egy nézetben vagy lapon lévő URI-kban. Javasoljuk, hogy minden éles alkalmazás konfigurálja a kiszolgálót aHostfejléc ismert érvényes értékekkel való ellenőrzésére.Óvatosan használja a LinkGenerator-t köztes rétegekben, különösen a
Map-el vagyMapWhen-el együtt.Map*módosítja a végrehajtási kérelem alap elérési útját, ami hatással van a hivatkozásgenerálás kimenetére. Az összes API lehetővé teszi egy LinkGenerator alap elérési út megadását. Adjon meg egy üres alap elérési utat a kapcsolatgenerálás hatásánakMap*visszavonásához.
Middleware-példa
A következő példában egy köztes szoftver az LinkGenerator API használatával hoz létre egy hivatkozást egy olyan műveletmetódusra, amely felsorolja a termékeket. A hivatkozásgenerátor használata az osztályba való injektálással és hívással GenerateLink az alkalmazás bármely osztálya számára elérhető:
public class ProductsLinkMiddleware
{
private readonly LinkGenerator _linkGenerator;
public ProductsLinkMiddleware(RequestDelegate next, LinkGenerator linkGenerator)
{
_linkGenerator = linkGenerator;
}
public async Task InvokeAsync(HttpContext httpContext)
{
var url = _linkGenerator.GetPathByAction("ListProducts", "Store");
httpContext.Response.ContentType = "text/plain";
await httpContext.Response.WriteAsync($"Go to {url} to see our products.");
}
}
Útvonalsablon referenciája
A tokenek {} definiálják az útvonalparamétereket, amelyek akkor vannak megkötve, ha az útvonal megfelel. Egy útvonalszakaszban több útvonalparaméter is definiálható, de az útvonalparamétereket literális értékkel kell elválasztani. Például {controller=Home}{action=Index} nem érvényes útvonal, mivel a kettő között {controller}{action}nincs literális érték. Az útvonalparamétereknek névvel kell rendelkezniük, és további attribútumokkal is rendelkezniük kell.
Az útvonalparamétereken (például {id}) és az elérési útelválasztón / kívüli literális szövegnek meg kell egyeznie az URL-címben szereplő szövegekkel. A szövegegyeztetés kis- és nagybetűkre nem érzékeny, és az URL-cím elérési útjának dekódolt ábrázolása alapján történik. Ha egy literális útvonalparaméter elválasztójelével { szeretne megegyezni, vagy }a karakter ismétlésével lépjen ki a határolóból. Például {{ vagy }}.
Csillag * vagy dupla csillag **:
- Az útvonalparaméter előtagjaként használható az URI többi részéhez való kötéshez.
- Az úgynevezett catch-all paraméterek. Például
blog/{**slug}:- Megfelel minden olyan URI-nak, amely a kezdőértékkel
/blogkezdődik, és bármilyen értéket követ. - Az alábbi
/blogérték hozzá van rendelve a slug route értékhez.
- Megfelel minden olyan URI-nak, amely a kezdőértékkel
Warning
A catch-all paraméter helytelenül felelhet meg az útvonalaknak egy útválasztási hiba miatt. A hiba által érintett alkalmazások jellemzői a következők:
- Egy mindent megragadó útvonal, például:
{**slug}" - A catch-all útvonal nem egyezik meg azokkal a kérésekkel, amelyeket meg kellene egyeznie.
- Ha eltávolít más útvonalakat, az összeset megfogó útvonal elkezd működni.
Tekintse meg a GitHub 18677 és 16579 hibáit a példaesetekért, amelyekben ez a hiba felmerül.
A hiba jóváhagyási javítása a .NET Core 3.1.301-ben vagy újabb SDK-ban található. A következő kód beállít egy belső kapcsolót, amely megoldja ezt a hibát:
public static void Main(string[] args)
{
AppContext.SetSwitch("Microsoft.AspNetCore.Routing.UseCorrectCatchAllBehavior",
true);
CreateHostBuilder(args).Build().Run();
}
// Remaining code removed for brevity.
Az általános paraméterek az üres sztringgel is egyezhetnek.
A catch-all paraméter kikerüli a megfelelő karaktereket, amikor az útvonal egy URL-cím létrehozásához van használva, beleértve az elérésiút-elválasztó / karaktereket is. Például a(z) foo/{*path} útvonalértékekkel rendelkező { path = "my/path" } útvonal generál foo/my%2Fpath. Figyelje meg a szökött perjelet. Az útvonal elválasztó karakterek körjáratbeli kezeléséhez használja az ** útvonalparaméter előtagot. Az foo/{**path} útvonal { path = "my/path" }foo/my/path generál.
További szempontokat is figyelembe kell vennie azoknak az URL-mintáknak, amelyek megkísérlik rögzíteni a fájlnevet egy opcionális fájlkiterjesztéssel. Vegyük például a sablont files/{filename}.{ext?}. Ha van érték mindkettő filename és ext számára, mindkettő ki lesz töltve. Ha az URL-címben csak egy érték filename szerepel, az útvonal megfelel, mert a végén a . opcionális. Az alábbi URL-címek egyeznek az útvonalon:
/files/myFile.txt/files/myFile
Előfordulhat, hogy az útvonalparaméterek alapértelmezett értékei úgy vannak meghatározva, hogy a paraméter neve után egy egyenlőségjel (=) választja el az alapértelmezett értéket. Például {controller=Home} úgy határozza meg Home-et, mint az alapértelmezett értéket controller számára. Az alapértelmezett érték akkor használatos, ha a paraméter URL-címében nincs érték. Az útvonalparaméterek megadása nem kötelező, ha hozzáfűz egy kérdőjelet (?) a paraméternév végéhez. Például: id?. A választható értékek és az alapértelmezett útvonalparaméterek közötti különbség a következő:
- Az alapértelmezett értékkel rendelkező útvonalparaméterek mindig létrehoznak egy értéket.
- Az opcionális paraméterek csak akkor tartalmazhatnak értéket, ha a kérelem URL-címe megad egy értéket.
Az útvonalparaméterek olyan korlátozásokkal rendelkezhetnek, amelyeknek meg kell felelniük az URL-címhez kötött útvonalértéknek. Az útvonalparaméter neve után a : és a feltétel neve hozzáadása egy útvonalparaméter beágyazott feltételét határozza meg. Ha a kényszer argumentumokat igényel, zárójelek (...) közé kerülnek a kényszer neve után. Egy másik és egy kényszernév hozzáfűzésével több : is megadható.
A kényszer nevét és argumentumait a rendszer átadja a IInlineConstraintResolver szolgáltatásnak, hogy létrehozhasson egy, az URL-feldolgozásban használandó példányt IRouteConstraint . Az útvonalsablon blog/{article:minlength(10)} például egy korlátozást minlength határoz meg az argumentummal 10. Az útvonalkorlátozásokról és a keretrendszer által biztosított korlátozások listájáról további információt az Útvonalkényszer hivatkozási szakaszában talál.
Az útvonalparaméterek paraméterátalakítókkal is rendelkezhetnek. A paraméterátalakítók átalakítják egy paraméter értékét, amikor hivatkozásokat és egyező műveleteket és oldalakat hoznak létre URL-címekhez. A kényszerekhez hasonlóan a paraméterátalakítók is hozzáadhatók az útvonalparaméteren belül azáltal, hogy a paraméternév után hozzáadnak egy '/' jelet és a transzformátornevet. Az útvonalsablon blog/{article:slugify} például egy transzformátort slugify határoz meg. A paraméterátalakítókkal kapcsolatos további információkért tekintse meg a Paraméterátalakító referenciaszakaszát .
Az alábbi táblázat a példaútvonalak sablonjait és viselkedését mutatja be:
| Útvonalsablon | Példa egyező URI-ra | A kérelem URI-ja... |
|---|---|---|
hello |
/hello |
Csak az egyetlen elérési út /hellofelel meg. |
{Page=Home} |
/ |
Egyezések és halmazok Page a következőre Home: . |
{Page=Home} |
/Contact |
Egyezések és halmazok Page a következőre Contact: . |
{controller}/{action}/{id?} |
/Products/List |
Megfelelteti a Products vezérlőt és a List műveletet. |
{controller}/{action}/{id?} |
/Products/Details/123 |
A Products vezérlőnek és a Details műveletnek felel meg, amelynél id 123-ra van állítva. |
{controller=Home}/{action=Index}/{id?} |
/ |
Leképezi a Home vezérlőt és a Index metódust. A id figyelmen kívül van hagyva. |
{controller=Home}/{action=Index}/{id?} |
/Products |
Leképezi a Products vezérlőt és a Index metódust. A id figyelmen kívül van hagyva. |
Általában a sablon használata a legegyszerűbb útválasztási módszer. Az útvonalsablonon kívül is megadhat kényszereket és alapértelmezett értékeket.
Összetett szegmensek
Az összetett szegmensek feldolgozása a literális elválasztójelek jobbról balra történő egyeztetésével történik , nem mohó módon. Például [Route("/a{b}c{d}")] egy összetett szegmens.
Az összetett szegmensek olyan módon működnek, amelyet meg kell érteni a sikeres használatukhoz. Az ebben a szakaszban található példa bemutatja, hogy az összetett szegmensek miért működnek igazán jól, ha az elválasztó szöveg nem jelenik meg a paraméterértékeken belül. Összetettebb esetekben regexet kell használni, majd manuálisan kinyerni az értékeket.
Warning
Amikor a System.Text.RegularExpressions-t használja nem megbízható bemenetek feldolgozására, meg kell adnia egy időtúllépési értéket. Egy rosszindulatú felhasználó adhat RegularExpressions bemenetet, ami szolgáltatásmegtagadásos támadást okozhat. ASP.NET Core keretrendszer API-k, amelyek RegularExpressions időtúllépést használnak.
Ez egy összefoglaló az /a{b}c{d} sablon és a /abcd URL-útvonal esetén végzett útválasztási lépésekről. Ez | segít az algoritmus működésének vizualizációjában:
- Az első literál, jobbról balra, az
c. Így/abcdkeres jobbról balra, és megtalálja/ab|c|d. - A jobb oldalon (
d) lévő összes elem megfelel az útvonalparaméternek{d}. - A következő karakter, jobbról balra, az
a. Így/ab|c|dkeresésével ott folytatjuk, ahol abbahagytuk, majdamegtalálható/|a|b|c|d. - A jobb oldali (
b) érték most már megfelel az útvonalparaméternek{b}. - Nincs fennmaradó szöveg és nincs fennmaradó útvonalsablon, így ez megfelelésnek számít.
Íme egy példa egy negatív esetre, amely ugyanazt a sablont /a{b}c{d} és az URL-címet /aabcdhasználja. Ez | segít az algoritmus működésének vizualizációjában. Ez az eset nem egyezik, amit ugyanaz az algoritmus magyaráz meg.
- Az első literál, jobbról balra, az
c. Így/aabcdkeres jobbról balra, és megtalálja/aab|c|d. - A jobb oldalon (
d) lévő összes elem megfelel az útvonalparaméternek{d}. - A következő karakter, jobbról balra, az
a. Így/aab|c|dkeresésével ott folytatjuk, ahol abbahagytuk, majdamegtalálható/a|a|b|c|d. - A jobb oldali (
b) érték most már megfelel az útvonalparaméternek{b}. - Ezen a ponton még van szöveg
a, de az algoritmus elfogyott az elemzésre használt útvonalsablonból, így ez nem egyezik.
Mivel a megfelelő algoritmus nem kapzsi:
- Ez megfelel az egyes lépésekben lehetséges legkisebb szövegmennyiségnek.
- Ha az elválasztó érték a paraméterértékek között jelenik meg, az eredmény nem egyezik.
A reguláris kifejezések sokkal jobban szabályozhatják az egyező viselkedésüket.
A mohó egyezés, más néven lusta egyezés, a lehető legnagyobb sztringhez illeszkedik. A nem mohó egyezik a lehető legkisebb sztringgel.
Útvonal-korlátozás referenciája
Az útvonalkorlátozások akkor lépnek érvénybe, amikor egyezés történt a bejövő URL-címhez, és az URL-elérési út tokenizálva van útvonalértékekké. Az útvonalkorlátozások általában ellenőrzik az útvonalsablonon keresztül társított útvonalértéket, és valós vagy hamis döntést hoznak arról, hogy az érték elfogadható-e. Egyes útvonalkorlátozások az útvonalértéken kívüli adatokat használnak annak megfontolására, hogy a kérés irányítható-e. A http-ige alapján például HttpMethodRouteConstraint elfogadhat vagy elutasíthat egy kérést. A korlátozások az útválasztási kérelmekben és a csatolások generálásában használatosak.
Warning
Ne használjon korlátozásokat a bemeneti ellenőrzéshez. Ha bemeneti érvényesítéshez kényszereket használnak, érvénytelen bemenet esetén "Nem található" választ kapunk 404. Az érvénytelen bemenetnek egy Bad Request 400 kell létrehoznia a megfelelő hibaüzenettel. Az útvonalkorlátozások a hasonló útvonalak egyértelműsítésére szolgálnak, nem pedig egy adott útvonal bemeneteinek ellenőrzésére.
Az alábbi táblázat a példaút-korlátozásokat és azok várható viselkedését mutatja be:
| korlátozás | Example | Példa egyezések | Notes |
|---|---|---|---|
int |
{id:int} |
123456789, -123456789 |
Bármely egész számnak megfelel |
bool |
{active:bool} |
true, FALSE |
Egyezések true vagy false. Case-insensitive |
datetime |
{dob:datetime} |
2016-12-31, 2016-12-31 7:32pm |
Megfelel az invariáns kultúra érvényes DateTime értékének. Lásd az előző figyelmeztetést. |
decimal |
{price:decimal} |
49.99, -1,000.01 |
Megfelel az invariáns kultúra érvényes decimal értékének. Lásd az előző figyelmeztetést. |
double |
{weight:double} |
1.234, -1,001.01e8 |
Megfelel az invariáns kultúra érvényes double értékének. Lásd az előző figyelmeztetést. |
float |
{weight:float} |
1.234, -1,001.01e8 |
Megfelel az invariáns kultúra érvényes float értékének. Lásd az előző figyelmeztetést. |
guid |
{id:guid} |
CD2C1638-1638-72D5-1638-DEADBEEF1638 |
Érvényes Guid érték egyező |
long |
{ticks:long} |
123456789, -123456789 |
Érvényes long érték egyező |
minlength(value) |
{username:minlength(4)} |
Rick |
A karakterláncnak legalább 4 karakter hosszúnak kell lennie. |
maxlength(value) |
{filename:maxlength(8)} |
MyFile |
A sztring legfeljebb 8 karakter hosszúságú lehet |
length(length) |
{filename:length(12)} |
somefile.txt |
A sztringnek pontosan 12 karakter hosszúnak kell lennie |
length(min,max) |
{filename:length(8,16)} |
somefile.txt |
A sztringnek legalább 8 és legfeljebb 16 karakter hosszúnak kell lennie |
min(value) |
{age:min(18)} |
19 |
Az egész szám értékének legalább 18-nak kell lennie |
max(value) |
{age:max(120)} |
91 |
Az egész szám értéke legfeljebb 120 lehet |
range(min,max) |
{age:range(18,120)} |
91 |
Az egész szám értéke legalább 18, de legfeljebb 120 lehet |
alpha |
{name:alpha} |
Rick |
A sztringnek egy vagy több betűből a-z kell állnia, függetlenül a kis- és nagybetűktől. |
regex(expression) |
{ssn:regex(^\\d{{3}}-\\d{{2}}-\\d{{4}}$)} |
123-45-6789 |
A karakterláncnak meg kell egyeznie a reguláris kifejezéssel. Tippek a reguláris kifejezés definiálásáról. |
required |
{name:required} |
Rick |
Arra szolgál, hogy kényszerítse, hogy egy nem paraméteres érték jelen legyen az URL-cím létrehozása során |
Warning
Amikor a System.Text.RegularExpressions-t használja nem megbízható bemenetek feldolgozására, meg kell adnia egy időtúllépési értéket. Egy rosszindulatú felhasználó adhat RegularExpressions bemenetet, ami szolgáltatásmegtagadásos támadást okozhat. ASP.NET Core keretrendszer API-k, amelyek RegularExpressions időtúllépést használnak.
Egy paraméterre több, kettőspontra tagolt korlátozás alkalmazható. A következő korlátozás például egy paramétert 1 vagy annál nagyobb egész számra korlátozza:
[Route("users/{id:int:min(1)}")]
public User GetUserById(int id) { }
Warning
Az URL-címet ellenőrző és CLR-típussá konvertált útvonalkorlátozások mindig az invariáns kultúrát használják. Például a CLR típus int vagy DateTime. Ezek a korlátozások feltételezik, hogy az URL-cím nem honosítható. A keretrendszer által biztosított útvonalkorlátozások nem módosítják az útvonalértékekben tárolt értékeket. Az URL-címből elemezett útvonalértékek sztringekként vannak tárolva. A kényszer például float megkísérli lebegőpontossá alakítani az útvonal értékét, de a konvertált érték csak annak ellenőrzésére szolgál, hogy az lebegőpontossá alakítható-e.
Reguláris kifejezések alkalmazása kényszerekben
Warning
Amikor a System.Text.RegularExpressions-t használja nem megbízható bemenetek feldolgozására, meg kell adnia egy időtúllépési értéket. Egy rosszindulatú felhasználó adhat RegularExpressions bemenetet, ami szolgáltatásmegtagadásos támadást okozhat. ASP.NET Core keretrendszer API-k, amelyek RegularExpressions időtúllépést használnak.
A reguláris kifejezések az útvonal-korlátozással regex(...) beágyazott kényszerként is megadhatóak. A MapControllerRoute család metódusai egy korlátozások objektumkonstansát is elfogadják. Ha ezt az űrlapot használja, a sztringértékeket a rendszer normál kifejezésként értelmezi.
A következő kód beágyazott regex kényszert használ:
app.UseEndpoints(endpoints =>
{
endpoints.MapGet("{message:regex(^\\d{{3}}-\\d{{2}}-\\d{{4}}$)}",
context =>
{
return context.Response.WriteAsync("inline-constraint match");
});
});
Az alábbi kód egy objektumkonstanst használ a regex kényszer megadásához:
app.UseEndpoints(endpoints =>
{
endpoints.MapControllerRoute(
name: "people",
pattern: "People/{ssn}",
constraints: new { ssn = "^\\d{3}-\\d{2}-\\d{4}$", },
defaults: new { controller = "People", action = "List", });
});
A ASP.NET Core-keretrendszer hozzáadja RegexOptions.IgnoreCase | RegexOptions.Compiled | RegexOptions.CultureInvariant a reguláris kifejezéskonstruktort. A tagok leírását itt tekinti meg RegexOptions .
A reguláris kifejezések az útválasztás és a C# nyelv által használthoz hasonló határolókat és mintákat használnak. A reguláris kifejezés elemeit escape-elve kell használni. Ha a reguláris kifejezést ^\d{3}-\d{2}-\d{4}$ beágyazott kényszerben szeretné használni, használja az alábbiak egyikét:
- Cserélje le
\a sztringben megadott karaktereket a C#-forrásfájlban szereplő karakterekre\\, hogy elkerülje a sztring-feloldó\karaktert. - Szó szerinti karakterlánckonstansok.
Az útvonal-paraméterek elválasztó karaktereinek, mint például a {, }, [, ], kifejezésben történő megduplázásával megszabadulhatunk, például {{, }}, [[, ]]. Az alábbi táblázat egy reguláris kifejezést és annak szökött verzióját mutatja be:
| Reguláris kifejezés | Megmenekült reguláris kifejezés |
|---|---|
^\d{3}-\d{2}-\d{4}$ |
^\\d{{3}}-\\d{{2}}-\\d{{4}}$ |
^[a-z]{2}$ |
^[[a-z]]{{2}}$ |
Az útválasztás során használt reguláris kifejezések gyakran a ^ karakterrel kezdődnek, és megfelelnek a sztring kezdőpozíciójának. A kifejezések gyakran a $ karakterrel végződnek, és illeszkednek a karaktersor végéhez. A ^ karakterek és $ a karakterek biztosítják, hogy a reguláris kifejezés megegyezik a teljes útvonalparaméter értékével. A ^ és $ karakterek nélkül a reguláris kifejezés bármelyik részsztringgel egyezik meg a sztringen belül, ami gyakran nem kívánatos. Az alábbi táblázat példákat tartalmaz, és elmagyarázza, hogy miért egyeznek vagy miért nem egyeznek:
| Expression | String | Match | Comment |
|---|---|---|---|
[a-z]{2} |
hello | Yes | Részszűrési egyezések |
[a-z]{2} |
123abc456 | Yes | Részszűrési egyezések |
[a-z]{2} |
mz | Yes | Kifejezés egyezése |
[a-z]{2} |
MZ | Yes | Nem érzékeny a kis- és nagybetűkre |
^[a-z]{2}$ |
hello | No | Lásd ^ és $ fent |
^[a-z]{2}$ |
123abc456 | No | Lásd ^ és $ fent |
A reguláris kifejezésszintaxissal kapcsolatos további információkért lásd a .NET-keretrendszer reguláris kifejezéseit.
Ha egy paramétert egy ismert lehetséges értékkészletre szeretne korlátozni, használjon egy reguláris kifejezést. Például {action:regex(^(list|get|create)$)} csak a action következő útvonalértéknek felel meglist: , vagy .getcreate Ha a kényszerszótárba kerül, a sztring ^(list|get|create)$ egyenértékű. A kényszerek szótárában megadott, az ismert kényszerek egyikével nem egyező kényszereket a rendszer normál kifejezésként is kezeli. A sablonon belül átadott, az ismert megkötések egyikével nem egyező kényszereket a rendszer nem kezeli normál kifejezésként.
Egyéni útvonalkorlátozások
Az interfész implementálásával IRouteConstraint egyéni útvonalkorlátozások hozhatók létre. Az IRouteConstraint interfész tartalmaz Match, amely akkor ad vissza true , ha a korlátozás teljesül, és false egyébként.
Ritkán van szükség egyéni útvonalkorlátozásokra. Egyéni útvonalkorlátozás implementálása előtt fontolja meg az alternatív megoldásokat, például a modellkötést.
A ASP.NET Alapvető korlátozások mappa jó példákat kínál a korlátozások létrehozására. Például GuidRouteConstraint.
Egyéni IRouteConstraintbeállítás használatához az útvonalkorlátozás típusát regisztrálni kell az alkalmazás szolgáltatástárolójában ConstraintMap . Egy ConstraintMap egy szótár, amely az útvonalkényszer kulcsokat olyan IRouteConstraint implementációkhoz rendeli, amelyek érvényesítik ezeket a kényszereket. Egy alkalmazás ConstraintMap frissíthető a Startup.ConfigureServices részeként egy services.AddRouting hívással, vagy közvetlenül a RouteOptionsservices.Configure<RouteOptions> konfigurálásával. Például:
public void ConfigureServices(IServiceCollection services)
{
services.AddControllers();
services.AddRouting(options =>
{
options.ConstraintMap.Add("customName", typeof(MyCustomConstraint));
});
}
Az előző korlátozás a következő kódban van alkalmazva:
[Route("api/[controller]")]
[ApiController]
public class TestController : ControllerBase
{
// GET /api/test/3
[HttpGet("{id:customName}")]
public IActionResult Get(string id)
{
return ControllerContext.MyDisplayRouteInfo(id);
}
// GET /api/test/my/3
[HttpGet("my/{id:customName}")]
public IActionResult Get(int id)
{
return ControllerContext.MyDisplayRouteInfo(id);
}
}
MyDisplayRouteInfo a Rick.Docs.Samples.RouteInfo NuGet-csomag biztosítja, és megjeleníti az útvonaladatokat.
MyCustomConstraint megakadályozza, hogy 0 alkalmazható legyen egy útvonalparaméterre.
class MyCustomConstraint : IRouteConstraint
{
private Regex _regex;
public MyCustomConstraint()
{
_regex = new Regex(@"^[1-9]*$",
RegexOptions.CultureInvariant | RegexOptions.IgnoreCase,
TimeSpan.FromMilliseconds(100));
}
public bool Match(HttpContext httpContext, IRouter route, string routeKey,
RouteValueDictionary values, RouteDirection routeDirection)
{
if (values.TryGetValue(routeKey, out object value))
{
var parameterValueString = Convert.ToString(value,
CultureInfo.InvariantCulture);
if (parameterValueString == null)
{
return false;
}
return _regex.IsMatch(parameterValueString);
}
return false;
}
}
Warning
Amikor a System.Text.RegularExpressions-t használja nem megbízható bemenetek feldolgozására, meg kell adnia egy időtúllépési értéket. Egy rosszindulatú felhasználó adhat RegularExpressions bemenetet, ami szolgáltatásmegtagadásos támadást okozhat. ASP.NET Core keretrendszer API-k, amelyek RegularExpressions időtúllépést használnak.
Az előző kód:
- Megakadályozza
0az{id}útvonal szegmensét. - Látható, hogy egy egyszerű példát mutat be egy egyéni korlátozás implementálására. Éles alkalmazásban nem használható.
Az alábbi kód jobb módszer arra, hogy megakadályozza a id-t tartalmazó 0 feldolgozását.
[HttpGet("{id}")]
public IActionResult Get(string id)
{
if (id.Contains('0'))
{
return StatusCode(StatusCodes.Status406NotAcceptable);
}
return ControllerContext.MyDisplayRouteInfo(id);
}
Az előző kód a következő előnyökkel rendelkezik a MyCustomConstraint megközelítéssel szemben:
- Nem igényel egyéni korlátozást.
- Leíróbb hibát ad vissza, ha az útvonalparaméter tartalmazza
0.
Paramétertranszformátor referenciája
Paramétertranszformátorok:
- Hajtson végre egy műveletet a hivatkozás létrehozásához a LinkGenerator használatával.
- Implementálás Microsoft.AspNetCore.Routing.IOutboundParameterTransformer.
- A(z) ConstraintMap használatával konfigurálható.
- Vegye át a paraméter útvonalértékét, és alakítsa át egy új sztringértékké.
- Ennek eredménye az átalakított érték használata a létrehozott hivatkozásban.
Például egy egyéni slugify paraméter-transzformátor az útvonalmintában blog\{article:slugify} a generált adatokkal Url.Action(new { article = "MyTestArticle" })blog\my-test-article.
Fontolja meg a következő IOutboundParameterTransformer megvalósítást:
public class SlugifyParameterTransformer : IOutboundParameterTransformer
{
public string TransformOutbound(object value)
{
if (value == null) { return null; }
return Regex.Replace(value.ToString(),
"([a-z])([A-Z])",
"$1-$2",
RegexOptions.CultureInvariant,
TimeSpan.FromMilliseconds(100)).ToLowerInvariant();
}
}
Ha paraméterátalakítót szeretne használni egy útvonalmintában, konfigurálja a következővel ConstraintMapStartup.ConfigureServices:
public void ConfigureServices(IServiceCollection services)
{
services.AddControllers();
services.AddRouting(options =>
{
options.ConstraintMap["slugify"] = typeof(SlugifyParameterTransformer);
});
}
Az ASP.NET Core keretrendszer paraméterátalakítókat használ, hogy átalakítsa az URI-t a végpont feloldása során. A paraméterátalakítók például átalakítják az útvonali értékeket, amelyeket a area, controller, action és page egyeztetésére használnak.
routes.MapControllerRoute(
name: "default",
template: "{controller:slugify=Home}/{action:slugify=Index}/{id?}");
Az előző útvonalsablon esetén a művelet SubscriptionManagementController.GetAll megfelel az URI-nak /subscription-management/get-all. A paraméter-átalakító nem módosítja a hivatkozás létrehozásához használt útvonalértékeket. Például a Url.Action("GetAll", "SubscriptionManagement") kimenetet ad /subscription-management/get-all.
ASP.NET Core API-konvenciókat biztosít a paraméterátalakítók generált útvonalakkal való használatához:
- Az Microsoft.AspNetCore.Mvc.ApplicationModels.RouteTokenTransformerConvention MVC-konvenció egy megadott paraméterátalakítót alkalmaz az alkalmazás összes attribútumútvonalára. A paraméter-transzformátor átalakítja az attribútumat útvonalának jogkivonatait, amikor lecserélésre kerülnek. További információért lásd: Paraméterátalakító használata a tokencserék testreszabására.
- Razor A Pages az API-konvenciót PageRouteTransformerConvention használja. Ez az egyezmény egy megadott paraméterátalakítót alkalmaz az összes automatikusan felderített Razor lapra. A paraméter-átalakító átalakítja a Pages-útvonalak mappa- és fájlnév-szegmenseit Razor . További információ: Oldalútvonalak testreszabása paraméterátalakítóval.
URL-létrehozási referencia
Ez a szakasz az URL-generálás által implementált algoritmusra mutató hivatkozást tartalmaz. A gyakorlatban az URL-létrehozás legösszetettebb példái vezérlőket vagy Razor oldalakat használnak. További információkért tekintse meg az útválasztást a vezérlőkben .
Az URL-létrehozási folyamat a LinkGenerator.GetPathByAddress vagy egy hasonló metódus hívásával kezdődik. A metódus címmel, útvonalértékekkel és opcionálisan az aktuális kéréssel HttpContextkapcsolatos információkkal rendelkezik.
Az első lépés az, hogy a cím segítségével, a cím típusának megfelelő IEndpointAddressScheme<TAddress> alkalmazásával megold egy jelölt végpontkészletet.
Miután a címséma megtalálta a jelölteket, a végpontok iteratív módon lesznek rendezve és feldolgozva, amíg egy URL-létrehozási művelet sikeres nem lesz. Az URL-generálás nem ellenőrzi a kétértelműségeket, az első eredmény a végeredmény.
URL-létrehozás hibaelhárítása naplózással
Az URL-létrehozás hibaelhárításának első lépése a naplózási szint Microsoft.AspNetCore.RoutingTRACE beállítása.
LinkGenerator a feldolgozással kapcsolatos számos részletet naplóz, amelyek hasznosak lehetnek a problémák elhárításához.
Az URL-címgenerálással kapcsolatos részletekért tekintse meg az URL-létrehozási referenciát .
Addresses
A címek az URL-generálás azon koncepciója, amellyel a hívásokat a hivatkozásgenerátorhoz kötik a jelölt végpontok halmazához.
A címek egy bővíthető fogalom, amely alapértelmezés szerint két implementációval rendelkezik:
-
Végpontnév (
string) használata címként:- Hasonló funkciókat biztosít az MVC útvonalnevéhez.
- IEndpointNameMetadata A metaadatok típusát használja.
- Feloldja a megadott sztringet az összes regisztrált végpont metaadataival.
- Kivételt jelez az indításkor, ha több végpont ugyanazt a nevet használja.
- Az általános célú használat a vezérlőkön és Razor lapokon kívül ajánlott.
-
Útvonalértékek (RouteValuesAddress) használata címként:
- Hasonló funkciókat biztosít a vezérlőkhöz és az örökölt Pages URL-címek generálásához.
- Nagyon összetett a bővítéshez és a hibakereséshez.
- Biztosítja az implementációt, amelyet a
IUrlHelperTag Helper-ek, a HTML-segítők, a műveleti eredmények stb. használják.
A címséma szerepe, hogy a cím és az egyező végpontok közötti társítás tetszőleges feltételek szerint történik:
- A végpontnévséma alapszintű szótárkeresést hajt végre.
- Az útvonalértékek sémája a beállítási algoritmus összetett legjobb részhalmazával rendelkezik.
Környezeti értékek és explicit értékek
Az aktuális kérésből az útválasztás az aktuális kérés HttpContext.Request.RouteValuesútvonalértékeit éri el. Az aktuális kéréshez társított értékeket környezeti értékeknek nevezzük. Az egyértelműség kedvéért a dokumentáció a metódusoknak átadott útvonalértékekre hivatkozik explicit értékekként.
Az alábbi példa környezeti értékeket és explicit értékeket mutat be. Környezeti értékeket biztosít az aktuális kérésből és explicit értékekből: { id = 17, }
public class WidgetController : Controller
{
private readonly LinkGenerator _linkGenerator;
public WidgetController(LinkGenerator linkGenerator)
{
_linkGenerator = linkGenerator;
}
public IActionResult Index()
{
var url = _linkGenerator.GetPathByAction(HttpContext,
null, null,
new { id = 17, });
return Content(url);
}
Az előző kód:
- Visszatér
/Widget/Index/17 - Meghajtást kap LinkGenerator által.
A következő kód nem tartalmaz környezeti értékeket és explicit értékeket: { controller = "Home", action = "Subscribe", id = 17, }
public IActionResult Index2()
{
var url = _linkGenerator.GetPathByAction("Subscribe", "Home",
new { id = 17, });
return Content(url);
}
Az előző metódus visszaadja /Home/Subscribe/17
A WidgetController a következőt adja vissza: /Widget/Subscribe/17
var url = _linkGenerator.GetPathByAction("Subscribe", null,
new { id = 17, });
A következő kód az aktuális kérelem környezeti értékeiből és explicit értékekből biztosítja a vezérlőt: { action = "Edit", id = 17, }
public class GadgetController : Controller
{
public IActionResult Index()
{
var url = Url.Action("Edit", new { id = 17, });
return Content(url);
}
Az előző kódban:
-
/Gadget/Edit/17vissza lesz adva. - Url lekéri a IUrlHelper.
-
Action Egy műveletmetódus abszolút elérési útját tartalmazó URL-címet hoz létre. Az URL-cím a megadott
actionnevet ésrouteértékeket tartalmazza.
A következő kód az aktuális kérelem környezeti értékeit és explicit értékeit tartalmazza: { page = "./Edit, id = 17, }
public class IndexModel : PageModel
{
public void OnGet()
{
var url = Url.Page("./Edit", new { id = 17, });
ViewData["URL"] = url;
}
}
Az előző kód beállítja a url értékét /Edit/17-re, ha a Lap szerkesztése Razor oldal az alábbi oldalirányelvet tartalmazza:
@page "{id:int}"
Ha a Szerkesztés lap nem tartalmazza az "{id:int}" útvonalsablont, akkor url a következő: /Edit?id=17.
Az MVC viselkedése IUrlHelper összetettségi réteget ad hozzá az itt leírt szabályok mellett:
-
IUrlHelpermindig környezeti értékként adja meg az aktuális kérés útvonalértékeit. -
Az IUrlHelper.Action mindig explicit értékként másolja át az aktuális
actionéscontrollerútvonalértékeket, kivéve, ha a fejlesztő felülírja. -
IUrlHelper.Page az aktuális
pageútvonalértéket mindig explicit értékként másolja, kivéve, ha felül van bírálva. -
IUrlHelper.Pagemindig explicit értékként felülbírálja az aktuálishandlerútvonal értékétnullhacsak nincs felülírva.
A felhasználókat gyakran meglepik a környezeti értékek viselkedési részletei, mert úgy tűnik, hogy az MVC nem követi a saját szabályait. Előzmény- és kompatibilitási okokból bizonyos útvonalértékek, például action, controller, pageés handler saját speciális eseti viselkedésük van.
A LinkGenerator.GetPathByAction és LinkGenerator.GetPathByPage által biztosított egyenértékű funkcionalitás a IUrlHelper ezen anomáliáit duplikálja a kompatibilitás érdekében.
URL-létrehozási folyamat
A jelölt végpontok készletének megtalálása után az URL-generáló algoritmus:
- Iteratív módon dolgozza fel a végpontokat.
- Az első sikeres eredményt adja vissza.
A folyamat első lépése az útvonalérték érvénytelenítése. Az útvonalérték érvénytelenítése az a folyamat, amellyel az útválasztás dönti el, hogy a környezeti értékekből melyik útvonalértékeket kell használni, és melyeket figyelmen kívül kell hagyni. A rendszer minden környezeti értéket figyelembe vesz, és kombinálja az explicit értékekkel, vagy figyelmen kívül hagyja.
A környezeti értékek szerepét úgy lehet a legjobban értelmezni, hogy azok célja az alkalmazásfejlesztők gépelési munkájának csökkentése néhány gyakori esetben. Hagyományosan az MVC-hez kapcsolódó forgatókönyvek, amelyekben a környezeti értékek hasznosak:
- Ha ugyanabban a vezérlőben egy másik művelethez kapcsolódik, a vezérlő nevét nem kell megadni.
- Ha ugyanazon a területen egy másik vezérlőhöz kapcsolódik, a terület nevét nem kell megadni.
- Ha ugyanahhoz a műveletmetódushoz kapcsolódik, az útvonalértékeket nem kell megadni.
- Amikor az alkalmazás egy másik részéhez kapcsolódik, nem szeretne olyan útvonalértékeket átvinni, amelyeknek nincs jelentésük az alkalmazás ezen részében.
A LinkGenerator vagy IUrlHelper hívások, amelyek null-t adnak vissza, általában az útvonalértékek érvénytelenítésének nem megfelelő megértése miatt fordulnak elő. Az útvonalértékek érvénytelenítésének hibaelhárításához explicit módon adjon meg több útvonalértéket, és ellenőrizze, hogy ez megoldja-e a problémát.
Az útvonalérték érvénytelenítése azzal a feltételezéssel működik, hogy az alkalmazás URL-sémája hierarchikus, a hierarchia balról jobbra épül fel. Fontolja meg az alapszintű vezérlőútvonal-sablont {controller}/{action}/{id?} , hogy intuitív módon értelmezhesse ennek működését a gyakorlatban. Az érték módosításaérvényteleníti a jobb oldalon megjelenő összes útvonalértéket. Ez tükrözi a hierarchia feltételezését. Ha az alkalmazásnak van egy környezeti értéke id, és a művelet egy másik értéket ad meg a controller számára:
-
idnem lesz újra felhasználva, mert{controller}a bal oldalon{id?}található.
Néhány példa az alapelv bemutatására:
- Ha az explicit értékek egy értéket
idtartalmaznak, a környezeti értékidfigyelmen kívül lesz hagyva. A(z)controllerésactionértékeit használhatjuk. - Ha az explicit értékek egy értéket
actiontartalmaznak, a rendszer figyelmen kívül hagyja a környezeti értékeketaction. Azcontrolleresetében a környezeti értékek felhasználhatók. Ha a explicit értékactioneltér a környezeti értéktőlaction, akkor azidérték nem lesz felhasználva. Ha az explicit értékactionmegegyezik a környezeti értékkelaction, akkor azidérték használható. - Ha az explicit értékek egy értéket
controllertartalmaznak, a rendszer figyelmen kívül hagyja a környezeti értékeketcontroller. Ha az explicit értékcontrollereltér a környezeti értéktőlcontroller, akkor nem használják azactionésidértékeket. Ha az explicit értékcontrollermegegyezik a környezeti értékkelcontroller, akkor azactionésidértékek használhatók.
Ezt a folyamatot tovább bonyolítja az attribútumútvonalak és a dedikált hagyományos útvonalak megléte. A vezérlő hagyományos útvonalai, mint például a {controller}/{action}/{id?}, egy hierarchiát határoznak meg útvonalparaméterekkel.
A vezérlőkhöz és lapokhoz tartozó dedikált hagyományos útvonalak és Razor esetén:
- Az útvonalértékek hierarchiája létezik.
- Nem jelennek meg a sablonban.
Ezekben az esetekben az URL-generálás határozza meg a szükséges értékek fogalmát. A vezérlők és Razor lapok által létrehozott végpontok olyan kötelező értékekkel rendelkeznek, amelyek lehetővé teszik az útvonalértékek érvénytelenítését.
Az útvonalérték érvénytelenítési algoritmusa részletesen:
- A szükséges értékneveket a rendszer kombinálja az útvonalparaméterekkel, majd balról jobbra dolgozza fel őket.
- Minden paraméter esetében a környezeti érték és az explicit érték összehasonlítása:
- Ha a környezeti érték és az explicit érték megegyezik, a folyamat folytatódik.
- Ha a környezeti érték jelen van, és az explicit érték nem, akkor a környezeti érték lesz használva az URL-cím létrehozásakor.
- Ha a környezeti érték nem jelenik meg, és az explicit érték az, utasítsa el a környezeti értéket és az összes további környezeti értéket.
- Ha a környezeti érték és az explicit érték jelen van, és a két érték eltérő, utasítsa el a környezeti értéket és az összes további környezeti értéket.
Ezen a ponton az URL-létrehozási művelet készen áll az útvonalkorlátozások kiértékelésére. Az elfogadott értékek halmaza az alapértelmezett paraméterértékekkel van kombinálva, amelyek a korlátozások számára biztosítottak. Ha a korlátozások mindegyike megfelel, a művelet folytatódik.
Ezután az elfogadott értékek használhatók az útvonalsablon kibontásához. Az útvonalsablon feldolgozása:
- Balról jobbra.
- Minden paraméterhez az elfogadott érték van behelyettesítve.
- A következő különleges esetek esetén:
- Ha az elfogadott értékekből hiányzik egy érték, és a paraméter alapértelmezett értékkel rendelkezik, a rendszer az alapértelmezett értéket használja.
- Ha az elfogadott értékekből hiányzik egy érték, és a paraméter nem kötelező, a feldolgozás folytatódik.
- Ha egy hiányzó opcionális paraméter jobb oldalán található útvonalparaméter rendelkezik értékkel, a művelet meghiúsul.
- Ha lehetséges, összecsukja az egybefüggő alapértelmezett értékű paramétereket és az opcionális paramétereket.
A lekérdezési sztringhez explicit módon megadott értékek, amelyek nem egyeznek az útvonal egy szegmensével, hozzáadódnak a lekérdezési sztringhez. Az alábbi táblázat az útvonalsablon {controller}/{action}/{id?}használatakor mutatja be az eredményt.
| Környezeti értékek | Explicit értékek | Result |
|---|---|---|
| vezérlő = "Home" | action = "Névjegy" | /Home/About |
| vezérlő = "Home" | controller = "Order", action = "About" | /Order/About |
| controller = "Home", szín = "Vörös" | action = "Névjegy" | /Home/About |
| vezérlő = "Home" | action = "About", color = "Red" | /Home/About?color=Red |
Az útvonalérték érvénytelenítésével kapcsolatos problémák
ASP.NET Core 3.0 óta egyes URL-létrehozási sémák, amelyeket a korábbi ASP.NET Core-verziókban használtak, nem működnek jól az URL-címgenerálás során. A ASP.NET Core csapata olyan funkciókat tervez hozzáadni, amelyek kielégítik ezeket az igényeket egy későbbi kiadásban. Egyelőre a legjobb megoldás a régi útválasztás használata.
Az alábbi kód egy olyan URL-létrehozási sémát mutat be, amelyet az útválasztás nem támogat.
app.UseEndpoints(endpoints =>
{
endpoints.MapControllerRoute("default",
"{culture}/{controller=Home}/{action=Index}/{id?}");
endpoints.MapControllerRoute("blog", "{culture}/{**slug}",
new { controller = "Blog", action = "ReadPost", });
});
Az előző kódban a rendszer az culture útvonalparamétert használja a honosításhoz. A cél az, hogy a culture paraméter mindig környezeti értékként legyen elfogadva. A culture paraméter azonban nem fogadható el környezeti értékként a szükséges értékek működése miatt:
- Az
"default"útvonalparaméter acultureútvonalsablonbancontrollerbal oldalán található, így acontrollermódosításai nem érvénytelenítikculture. - Az
"blog"útvonalsablonban azcultureútvonalparaméter azcontroller-tól jobbra található, ahogy az a szükséges értékekben megjelenik.
Végpont metaadatainak konfigurálása
Az alábbi hivatkozások a végpont metaadatainak konfigurálásával kapcsolatos információkat tartalmaznak:
- Cors engedélyezése végponti útválasztással
-
IAuthorizationPolicyProvider-minta egyéni
[MinimumAgeAuthorize]attribútum használatával - Hitelesítés tesztelése az [Engedélyezés] attribútummal
- RequireAuthorization
- A séma kiválasztása az [Engedélyezés] attribútummal
- Szabályzatok alkalmazása az [Engedélyezés] attribútummal
- Szerepköralapú hitelesítés az ASP.NET Core-ban
Hosztok egyezése útvonalakban a RequireHost használatával
RequireHost korlátozást alkalmaz az útvonalra, amely megköveteli a megadott gazdagépet. A RequireHost paraméter vagy a [Host] következő lehet:
- Hoszt:
www.domain.com,www.domain.combármely porttal illik. - Gazdagép helyettesítő karakterrel:
*.domain.com, egyezéswww.domain.com,subdomain.domain.comvagywww.subdomain.domain.combármely porton. - Port:
*:5000, megegyezik az 5000-es porttal bármely gazdagépen. - Hoszt és port:
www.domain.com:5000vagy*.domain.com:5000, amely egyezik a hoszttal és a porttal.
Több paraméter is megadható RequireHost vagy [Host] használatával. A kényszer egyezik a paraméterek bármelyikére érvényes gazdagépekkel. Például [Host("domain.com", "*.domain.com")] megegyezik domain.com, www.domain.com és subdomain.domain.com.
Az alábbi kód RequireHost használja a megadott gazdagép megkövetelésére az útvonalon.
public void Configure(IApplicationBuilder app)
{
app.UseRouting();
app.UseEndpoints(endpoints =>
{
endpoints.MapGet("/", context => context.Response.WriteAsync("Hi Contoso!"))
.RequireHost("contoso.com");
endpoints.MapGet("/", context => context.Response.WriteAsync("AdventureWorks!"))
.RequireHost("adventure-works.com");
endpoints.MapHealthChecks("/healthz").RequireHost("*:8080");
});
}
A következő kód a [Host] vezérlő attribútumával követeli meg a megadott gazdagépek bármelyikét:
[Host("contoso.com", "adventure-works.com")]
public class ProductController : Controller
{
public IActionResult Index()
{
return ControllerContext.MyDisplayRouteInfo();
}
[Host("example.com:8080")]
public IActionResult Privacy()
{
return ControllerContext.MyDisplayRouteInfo();
}
}
Ha az attribútumot a [Host] vezérlőre és a műveleti módszerre is alkalmazza a rendszer:
- A műveleten szereplő attribútumot használja a rendszer.
- A vezérlőattribútum figyelmen kívül lesz hagyva.
Teljesítmény-útmutató útválasztáshoz
Az útválasztás nagy része a teljesítmény növelése érdekében ASP.NET Core 3.0-s verziójában frissült.
Ha egy alkalmazás teljesítményproblémával rendelkezik, az útválasztást gyakran gyanúsítják a problémaként. Azért feltételezik az útválasztás problémáját, mert a keretrendszerek, mint például a vezérlők és a Pages, a naplózási üzenetekben jelzik, mennyi időt töltenek a keretrendszeren belül. Ha jelentős különbség van a vezérlők által jelentett idő és a kérelem teljes időtartama között:
- A fejlesztők megszüntetik az alkalmazáskódjukat a probléma forrásaként.
- Gyakran feltételezzük, hogy az útválasztás az oka.
Az útválasztást több ezer végponton tesztelik. Nem valószínű, hogy egy tipikus alkalmazás teljesítményproblémába ütközik csak túl nagy mérete miatt. A lassú útválasztási teljesítmény leggyakoribb kiváltó oka általában egy rosszul viselkedő egyéni köztes szoftver.
Az alábbi kódminta a késés forrásának szűkítéséhez használható alapszintű technikát mutatja be:
public void Configure(IApplicationBuilder app, ILogger<Startup> logger)
{
app.Use(next => async context =>
{
var sw = Stopwatch.StartNew();
await next(context);
sw.Stop();
logger.LogInformation("Time 1: {ElapsedMilliseconds}ms", sw.ElapsedMilliseconds);
});
app.UseRouting();
app.Use(next => async context =>
{
var sw = Stopwatch.StartNew();
await next(context);
sw.Stop();
logger.LogInformation("Time 2: {ElapsedMilliseconds}ms", sw.ElapsedMilliseconds);
});
app.UseAuthorization();
app.Use(next => async context =>
{
var sw = Stopwatch.StartNew();
await next(context);
sw.Stop();
logger.LogInformation("Time 3: {ElapsedMilliseconds}ms", sw.ElapsedMilliseconds);
});
app.UseEndpoints(endpoints =>
{
endpoints.MapGet("/", async context =>
{
await context.Response.WriteAsync("Timing test.");
});
});
}
Útvonalak időzítése
- Az egyes köztes szoftvereket az előző kódban látható időzítő köztes szoftver egy-egy példányával kell beágyazni.
- Adjon hozzá egy egyedi azonosítót, amely korrelálja az időzítési adatokat a kóddal.
Ez egy alapvető módja annak, hogy szűkítse a késést, ha jelentős, például több mint 10ms. A Time 2 kivonása a Time 1 jelentésből a UseRouting köztes szoftverben töltött időt jelzi.
Az alábbi kód az előző időzítési kód tömörebb megközelítését használja:
public sealed class MyStopwatch : IDisposable
{
ILogger<Startup> _logger;
string _message;
Stopwatch _sw;
public MyStopwatch(ILogger<Startup> logger, string message)
{
_logger = logger;
_message = message;
_sw = Stopwatch.StartNew();
}
private bool disposed = false;
public void Dispose()
{
if (!disposed)
{
_logger.LogInformation("{Message }: {ElapsedMilliseconds}ms",
_message, _sw.ElapsedMilliseconds);
disposed = true;
}
}
}
public void Configure(IApplicationBuilder app, ILogger<Startup> logger)
{
int count = 0;
app.Use(next => async context =>
{
using (new MyStopwatch(logger, $"Time {++count}"))
{
await next(context);
}
});
app.UseRouting();
app.Use(next => async context =>
{
using (new MyStopwatch(logger, $"Time {++count}"))
{
await next(context);
}
});
app.UseAuthorization();
app.Use(next => async context =>
{
using (new MyStopwatch(logger, $"Time {++count}"))
{
await next(context);
}
});
app.UseEndpoints(endpoints =>
{
endpoints.MapGet("/", async context =>
{
await context.Response.WriteAsync("Timing test.");
});
});
}
Potenciálisan költséges útválasztási funkciók
Az alábbi lista betekintést nyújt az alapszintű útvonalsablonokhoz képest viszonylag költséges útválasztási funkciókba:
- Reguláris kifejezések: Olyan reguláris kifejezések írhatók, amelyek összetettek, vagy hosszú ideig futnak kis mennyiségű bemenettel.
- Összetett szegmensek (
{x}-{y}-{z}):- Lényegesen drágábbak, mint egy normál URL-elérési út szegmensének elemzése.
- Ez azt eredményezi, hogy a rendszer sokkal több alsztringet foglal le.
- Az összetett szegmenslogika nem frissült ASP.NET Core 3.0 útválasztási teljesítményfrissítésében.
- Szinkron adathozzáférés: Számos összetett alkalmazás rendelkezik adatbázis-hozzáféréssel az útválasztás részeként. ASP.NET Core 2.2 vagy korábbi útválasztás nem biztos, hogy megfelelő bővíthetőségi pontokat biztosít az adatbázis-hozzáférés útválasztásának támogatásához. Például, IRouteConstraintés IActionConstraint szinkronban vannak. A bővíthetőségi pontok, mint például a MatcherPolicy és EndpointSelectorContext, aszinkronok.
Útmutató könyvtárszerzőknek
Ez a szakasz útmutatást tartalmaz az útválasztásra alapuló könyvtárak szerzői számára. Ezek a részletek biztosítják, hogy az alkalmazásfejlesztők jól használják az útválasztást kiterjesztő kódtárakat és keretrendszereket.
Végpontok definiálása
Az útválasztást használó keretrendszer létrehozásához, amely az URL-ek egyeztetésére szolgál, kezdje azzal, hogy definiál egy felhasználói élményt, amely a UseEndpoints alapján épül fel.
ÉPÍTS a IEndpointRouteBuilder tetejére. Ez lehetővé teszi, hogy a felhasználók összekeverés nélkül más ASP.NET Core-funkciókkal is megírják a keretrendszert. Minden ASP.NET Core-sablon tartalmazza az útválasztást. Tegyük fel, hogy az útválasztás jelen van és ismerős a felhasználók számára.
app.UseEndpoints(endpoints =>
{
// Your framework
endpoints.MapMyFramework(...);
endpoints.MapHealthChecks("/healthz");
});
A DO egy lezárt betontípust ad vissza az adott implementálásra MapMyFramework(...)IEndpointConventionBuilderirányuló hívásból. A legtöbb keretrendszer-metódus Map... ezt a mintát követi. A IEndpointConventionBuilder felület:
- Lehetővé teszi a metaadatok kompatibilitását.
- Különféle bővítési módszerek célozzák meg.
A saját típus deklarálása lehetővé teszi saját keretrendszerspecifikus funkciók hozzáadását a szerkesztőhöz. Nem baj, ha egy keretrendszer által deklarált szerkesztőt burkolunk, és hívásokat továbbítunk neki.
app.UseEndpoints(endpoints =>
{
// Your framework
endpoints.MapMyFramework(...).RequireAuthorization()
.WithMyFrameworkFeature(awesome: true);
endpoints.MapHealthChecks("/healthz");
});
GONDOLKODJ azon, hogy megírod a saját EndpointDataSource.
EndpointDataSource a végpontok gyűjteményének deklarálására és frissítésére szolgáló alacsony szintű primitív.
EndpointDataSource egy hatékony API, amelyet a vezérlők és Razor a Pages használnak.
Az útválasztási tesztek egy alapvető példával rendelkeznek egy nem frissített adatforrásra.
NE próbáljon meg alapértelmezés szerint egy objektumot regisztrálni.EndpointDataSource Követelje meg a felhasználóktól, hogy regisztrálják a keretrendszert UseEndpoints. Az útválasztás filozófiája, hogy alapértelmezés szerint semmi nem szerepel benne, és ez UseEndpoints a végpontok regisztrálásának helye.
Útvonalválasztással integrált köztes szoftver létrehozása
FONTOLJA meg a metaadat-típusok interfészként való meghatározását.
A DO lehetővé teszi a metaadat-típusok attribútumként való használatát osztályokon és metódusokon.
public interface ICoolMetadata
{
bool IsCool { get; }
}
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
public class CoolMetadataAttribute : Attribute, ICoolMetadata
{
public bool IsCool => true;
}
Az olyan keretrendszerek, mint a vezérlők és Razor a Lapok, támogatják a metaadat-attribútumok típusokra és metódusokra való alkalmazását. Metaadattípusok deklarálása esetén:
- Elérhetővé teheti őket attribútumként.
- A felhasználók többsége ismeri az attribútumok alkalmazását.
A metaadat-típus felületként való deklarálása további rugalmassági réteget ad:
- A felületek összeállíthatók.
- A fejlesztők deklarálhatják a saját típusaikat, amelyek több szabályzatot kombinálnak.
A DO lehetővé teszi a metaadatok felülbírálását az alábbi példában látható módon:
public interface ICoolMetadata
{
bool IsCool { get; }
}
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
public class CoolMetadataAttribute : Attribute, ICoolMetadata
{
public bool IsCool => true;
}
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
public class SuppressCoolMetadataAttribute : Attribute, ICoolMetadata
{
public bool IsCool => false;
}
[CoolMetadata]
public class MyController : Controller
{
public void MyCool() { }
[SuppressCoolMetadata]
public void Uncool() { }
}
Az alábbi irányelvek követésének legjobb módja, ha elkerüli a jelölő metaadatainak meghatározását:
- Ne csak a metaadat-típus jelenlétét keresse.
- Definiáljon egy tulajdonságot a metaadatokon, és ellenőrizze a tulajdonságot.
A metaadat-gyűjtemény rendezett, és támogatja a prioritás szerinti felülrendelést. Vezérlők esetében a műveletmetódus metaadatai a legspecifikusak.
TEGYE hasznossá a köztes szoftvereket útválasztással és anélkül.
app.UseRouting();
app.UseAuthorization(new AuthorizationPolicy() { ... });
app.UseEndpoints(endpoints =>
{
// Your framework
endpoints.MapMyFramework(...).RequireAuthorization();
});
Ennek az útmutatónak a példájaként vegye figyelembe a köztes UseAuthorization szoftvereket. Az engedélyezési köztes szoftver lehetővé teszi, hogy tartalék szabályzatot adjon át.
A tartalék szabályzat, ha meg van adva, mindkettőre vonatkozik:
- Meghatározott szabályzat nélküli végpontok.
- A végpontnak nem megfelelő kérések.
Ez hasznossá teszi az engedélyezési köztes szoftvereket az útválasztás környezetén kívül. Az engedélyezési köztes szoftver használható a hagyományos köztes szoftver programozásához.
Hibakeresési diagnosztika
A részletes útválasztási diagnosztikai kimenethez állítsa be a Logging:LogLevel:Microsoft értékét Debug-re. A fejlesztési környezetben állítsa be a naplószintet: appsettings.Development.json
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft": "Debug",
"Microsoft.Hosting.Lifetime": "Information"
}
}
}