Megosztás a következőn keresztül:


Útválasztás vezérlőműveletek számára a ASP.NET Core-ban

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 .

ASP.NET Core vezérlők az Útválasztás köztes szoftvert használják, hogy összepárosítsák a bejövő kérések URL-címeit, és műveletekhez rendeljék őket. Útvonalsablonok:

  • Az indításkor Program.cs vagy attribútumokban vannak definiálva.
  • Írja le, hogyan illeszkednek az URL-útvonalak a műveletekhez.
  • A hivatkozások URL-címeinek létrehozására szolgál. A létrehozott hivatkozások általában válaszokban jelennek meg.

A műveletek hagyományosan irányítottak vagy attribútumalapúak. Ha egy útvonalat helyez el a vezérlőn vagy a műveleten , az attribútumalapúvá válik. További információt a Vegyes útválasztás című témakörben talál.

Ez a dokumentum:

  • Az MVC és az útválasztás közötti interakciókat ismerteti:
  • Az alapértelmezett útválasztási rendszerre, az úgynevezett végpont-útválasztásra hivatkozik. Kompatibilitási okokból az útválasztás előző verziójával rendelkező vezérlőket is használhat. Útmutatásért tekintse meg a 2.2-3.0 migrálási útmutatót .

Hagyományos útvonal beállítása

A ASP.NET Core MVC-sablon a következőhöz hasonló hagyományos útválasztási kódot hoz létre:

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddControllersWithViews();

var app = builder.Build();

if (!app.Environment.IsDevelopment())
{
    app.UseExceptionHandler("/Home/Error");
    app.UseHsts();
}

app.UseHttpsRedirection();
app.UseStaticFiles();

app.UseRouting();

app.UseAuthorization();

app.MapControllerRoute(
    name: "default",
    pattern: "{controller=Home}/{action=Index}/{id?}");

app.Run();

MapControllerRoute egyetlen útvonal létrehozásához használható. Az egyetlen útvonal neve default útvonal. A vezérlőkkel és nézetekkel rendelkező alkalmazások többsége az default útvonalhoz hasonló útvonalsablont használ. REST Az API-knak attribútum-útválasztást kell használniuk.

app.MapControllerRoute(
    name: "default",
    pattern: "{controller=Home}/{action=Index}/{id?}");

Az útvonalsablon "{controller=Home}/{action=Index}/{id?}":

  • Megfelel egy URL-címnek, például: /Products/Details/5

  • Kinyeri az útvonal értékeit { controller = Products, action = Details, id = 5 } az elérési út tokenizálásával. Az útvonalértékek kinyerése akkor eredményez egyezést, ha az alkalmazásnak van egy ProductsController nevű vezérlője és egy Details nevű művelete.

    public class ProductsController : Controller
    {
        public IActionResult Details(int id)
        {
            return ControllerContext.MyDisplayRouteInfo(id);
        }
    }
    

    MyDisplayRouteInfo a Rick.Docs.Samples.RouteInfo NuGet-csomag biztosítja, és megjeleníti az útvonaladatokat.

  • /Products/Details/5 modell a(z) id = 5 értéket használja a(z) id paraméter 5 értékre való kötéséhez. További részletekért tekintse meg a modellkötést .

  • {controller=Home} a Home alapértelmezettként controllerdefiniálja.

  • {action=Index} a Index alapértelmezettként actiondefiniálja.

  • A ? karakter a {id?} területen opcionálisként határozza meg a id-t.

    • Az alapértelmezett és az opcionális útvonalparamétereknek nem kell szerepelnie az egyezés URL-címében. Az útvonalsablon szintaxisának részletes leírását az útvonalsablon-referencia című témakörben találja.
  • Megfelel az URL-cím elérési útvonalának /.

  • Létrehozza az útvonalértékeket { controller = Home, action = Index }.

A controller és action alapértelmezett értékeket használnak. id nem hoz létre értéket, mivel az URL-elérési útnak nincs megfelelő szegmense. / csak akkor egyezik, ha létezik egy HomeController és Index művelet:

public class HomeController : Controller
{
    public IActionResult Index() { ... }
}

Az előző vezérlődefiníció és útvonalsablon használatával a művelet a HomeController.Index következő URL-útvonalakon fut:

  • /Home/Index/17
  • /Home/Index
  • /Home
  • /

Az URL-elérési út / az útvonalsablon alapértelmezett Home vezérlőit és Index műveleteit használja. Az URL-elérési út /Home az útvonalsablon alapértelmezett Index műveletét használja.

A kényelmi módszer MapDefaultControllerRoute:

app.MapDefaultControllerRoute();

Replaces:

app.MapControllerRoute(
    name: "default",
    pattern: "{controller=Home}/{action=Index}/{id?}");

Important

Az útválasztás a UseRouting és a UseEndpoints köztes szoftverekkel van konfigurálva. Vezérlők használata:

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. További információkért lásd: Útvonalkezelés az ASP.NET Core-ban.

Hagyományos útválasztás

A hagyományos útválasztás vezérlőkkel és nézetekkel használható. Az default útvonal:

app.MapControllerRoute(
    name: "default",
    pattern: "{controller=Home}/{action=Index}/{id?}");

Az előző példa egy hagyományos útvonalra mutat. Ezt hagyományos útválasztásnak nevezik, mert konvenciót hoz létre az URL-útvonalakhoz:

  • Az első útvonal szegmens {controller=Home} a vezérlő nevére lesz leképezve.
  • A második szegmens a {action=Index}művelet nevére képeződik le.
  • A harmadik szegmens {id?} opcionális id-ként használatos. A ? a {id?} tegében választhatóvá teszi. A id a modellentitásra való leképezéshez használható.

Ezzel az default útvonallal az URL-cím útvonala:

  • /Products/List leképez a ProductsController.List művelethez.
  • /Blog/Article/17 leképez BlogController.Article és általában a modell leköti a id paramétert a 17-es értékhez.

Ez a leképezés:

  • Csak a vezérlőn és a műveletnevekenalapul.
  • Nem névtereken, forrásfájl-helyeken vagy metódusparamétereken alapul.

A hagyományos útválasztás alapértelmezett útvonallal való használata lehetővé teszi az alkalmazás létrehozását anélkül, hogy minden művelethez új URL-mintát kellene létrehoznia. CRUD stílusműveleteket tartalmazó alkalmazás esetén, amely konzisztenciával rendelkezik a vezérlők URL-címeivel kapcsolatban:

  • Segít leegyszerűsíteni a kódot.
  • A felhasználói felület kiszámíthatóbbá válik.

Warning

Az id előző kódban szereplő kódot az útvonalsablon nem kötelezőként határozza meg. A műveletek az URL-cím részeként megadott opcionális azonosító nélkül is végrehajthatók. Általában, ha id kihagyva van az URL-ből:

  • id modellkötés szerint van beállítva 0 .
  • Az adatbázisban a id == 0 nem egyezik egyetlen entitással sem.

Az attribútum-útválasztás részletes vezérlést biztosít, amely lehetővé teszi, hogy az azonosító bizonyos műveletekhez szükséges legyen, nem pedig mások számára. A konvenció szerint a dokumentáció tartalmazza az olyan választható paramétereket, mint a id, amikor azok valószínűleg a helyes használat során jelennek meg.

A legtöbb alkalmazásnak alapszintű és leíró útválasztási sémát kell választania, hogy az URL-címek olvashatók és értelmezhetők legyenek. Az alapértelmezett hagyományos útvonal {controller=Home}/{action=Index}/{id?}:

  • Alapszintű és leíró útválasztási sémát támogat.
  • Hasznos kiindulópont a felhasználói felületalapú alkalmazásokhoz.
  • Ez az egyetlen útválasztási sablon, amely sok webes felhasználói felületi alkalmazáshoz szükséges. A nagyobb webes felhasználói felületi alkalmazások esetében gyakran csak a Területeket használó másik útvonalra van szükség.

MapControllerRoute és MapAreaRoute :

  • Automatikusan rendeljen hozzá sorrendi értéket a végpontokhoz a meghívás sorrendje alapján.

Végpont-útválasztás a ASP.NET Core-ban:

  • Nincs fogalma az útvonalakról.
  • Nem biztosít rendelési garanciákat a bővíthetőség végrehajtásához, az összes végpont egyszerre lesz feldolgozva.

Engedélyezze a naplózást, hogy megtekintse, hogyan illeszkednek a beépített útválasztási implementációk, mint például Route, a kérésekhez.

Az attribútumok útválasztását a dokumentum későbbi részében ismertetik.

Több hagyományos útvonal

Több hagyományos útvonal is konfigurálható további hívások MapControllerRoute hozzáadásával.MapAreaControllerRoute Ez lehetővé teszi több konvenció meghatározását, vagy egy adott művelethez dedikált hagyományos útvonalak hozzáadását, például:

app.MapControllerRoute(name: "blog",
                pattern: "blog/{*article}",
                defaults: new { controller = "Blog", action = "Article" });
app.MapControllerRoute(name: "default",
               pattern: "{controller=Home}/{action=Index}/{id?}");

Az blog előző kódban szereplő útvonal egy dedikált hagyományos útvonal. Ez az úgynevezett dedikált hagyományos útvonal, mert:

Azért, mert a controller és action nem jelenik meg a "blog/{*article}" útvonalsablonban paraméterekként:

  • Csak az alapértelmezett értékekkel { controller = "Blog", action = "Article" }rendelkezhetnek.
  • Ez az útvonal mindig a művelethez lesz megfeleltetve BlogController.Article.

/Blog, /Blog/Articleés /Blog/{any-string} ezek az egyetlen URL-elérési utak, amelyek megfelelnek a blog útvonalának.

Az előző példa:

  • blog az útvonal nagyobb prioritással rendelkezik az egyezésekhez, mint az default útvonal, mert az elsőként van hozzáadva.
  • Példa a Slug-stílus útválasztására, ahol általában egy cikknév szerepel az URL-cím részeként.

Warning

A ASP.NET Core-ban az útválasztás nem:

  • Definiáljon egy útvonalnak nevezett fogalmat. UseRouting A köztesszoftver-folyamatnak megfelelő útvonalat ad hozzá. A UseRouting köztes szoftver megvizsgálja az alkalmazásban definiált végpontokat, és a kérés alapján kiválasztja a legjobb végpontegyezést.
  • Biztosítson garanciákat a bővíthetőség végrehajtási sorrendjére, például IRouteConstraint vagy IActionConstraint.

Az útválasztással kapcsolatos referenciaanyagokért tekintse meg az Útválasztás című témakört.

Hagyományos útválasztási sorrend

A hagyományos útválasztás csak az alkalmazás által meghatározott művelet és vezérlő kombinációjával egyezik meg. Ez leegyszerűsíti azokat az eseteket, amikor a hagyományos útvonalak átfedésben vannak. Útvonalak hozzáadása a MapControllerRoute, MapDefaultControllerRoute és MapAreaControllerRoute használatával automatikusan rendelési értéket ad a végpontokhoz a meghívásuk sorrendje alapján. Az útvonal, amely korábban jelenik meg, egyezései magasabb prioritással rendelkeznek. A hagyományos útválasztás sorrendfüggő. Általánosságban elmondható, hogy a területekkel rendelkező útvonalakat korábban kell elhelyezni, mivel ezek pontosabbak, mint a terület nélküli útvonalak. Az olyan hagyományos útvonalak, mint például {*article} a catch-all útvonalparaméterek, túl mohóvá tehetik az útvonalakat, ami azt jelenti, hogy megegyezik a más útvonalakkal egyeztetni kívánt URL-címekkel. A kapzsi útvonalakat később helyezze el az útvonaltáblában, hogy megakadályozza a kapzsi egyezéseket.

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.

Nem egyértelmű műveletek feloldása

Ha két végpont egyezik az útválasztással, az útválasztásnak az alábbiak egyikét kell elvégeznie:

  • Válassza ki a legjobb jelöltet.
  • Kivételt kell kivenni.

Például:

public class Products33Controller : Controller
{
    public IActionResult Edit(int id)
    {
        return ControllerContext.MyDisplayRouteInfo(id);
    }

    [HttpPost]
    public IActionResult Edit(int id, Product product)
    {
        return ControllerContext.MyDisplayRouteInfo(id, product.name);
    }
}

Az előző vezérlő két, egyező műveletet határoz meg:

  • Az URL-cím elérési útja /Products33/Edit/17
  • Útvonaladatok { controller = Products33, action = Edit, id = 17 }.

Ez az MVC-vezérlők tipikus mintája:

  • Edit(int) egy termék szerkesztéséhez használandó űrlapot jelenít meg.
  • Edit(int, Product) feldolgozza a közzétett űrlapot.

Az útvonal helyes kijelölése:

  • Edit(int, Product) akkor van kiválasztva, ha a kérés HTTP POST.
  • Edit(int) akkor van kiválasztva, ha a HTTP-ige bármi más. Edit(int)-t általában GET használatával hívjuk meg.

A HttpPostAttribute, [HttpPost]az útválasztáshoz van megadva, hogy a kérés HTTP-metódusa alapján válasszon. Az HttpPostAttribute jobban megteszi Edit(int, Product)-t megfelelőbbé, mint a Edit(int).

Fontos megérteni az olyan attribútumok szerepét, mint HttpPostAttributea . Más HTTP-parancsokhoz hasonló attribútumok vannak definiálva. A hagyományos útválasztásban gyakran előfordul, hogy a műveletek ugyanazt a műveletnevet használják, amikor egy megjelenítési űrlap részei, és űrlap-munkafolyamatot küldenek. Lásd például a két szerkesztési művelet módszerét.

Ha az útválasztás nem tudja kiválasztani a legjobb jelöltet, AmbiguousMatchException a több egyező végpontot listázó üzenet megjelenik.

Hagyományos útvonalnevek

A "blog" és "default" karakterláncok az alábbi példákban a hagyományos útvonalnevek:

app.MapControllerRoute(name: "blog",
                pattern: "blog/{*article}",
                defaults: new { controller = "Blog", action = "Article" });
app.MapControllerRoute(name: "default",
               pattern: "{controller=Home}/{action=Index}/{id?}");

Az útvonalnevek logikai nevet adnak az útvonalnak. A névvel ellátott útvonal használható AZ URL-cím létrehozásához. A névvel ellátott útvonalak használata egyszerűbbé teszi az URL-címek létrehozását, ha az útvonalak sorrendje megnehezítheti az URL-címek létrehozását. Az útvonalneveknek egyedi alkalmazásszintűnek kell lenniük.

Útvonalnevek:

  • Nincs hatással az URL-címek egyeztetésére vagy a kérések kezelésére.
  • Csak AZ URL-cím generálásához használhatók.

Az útvonalnév fogalma az útválasztásban IEndpointNameMetadata néven jelenik meg. Az útvonalnév és a végpont neve:

  • Felcserélhetők.
  • Hogy melyik kerül felhasználásra a dokumentációban és a kódban, az a leírt API-tól függ.

API-k attribútum alapú útválasztása REST

REST Az API-knak attribútumalapú útválasztással kell modelleznie az alkalmazás funkcióit olyan erőforrások készleteként, ahol a műveleteket HTTP-parancsok jelölik.

Az attribútum-útválasztás egy sor attribútum segítségével közvetlenül hozzárendeli a műveleteket az útvonal sablonokhoz. Az API-k esetében REST a következő kód jellemző, és a következő mintában használatos:

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddControllers();

var app = builder.Build();

app.UseHttpsRedirection();

app.UseAuthorization();

app.MapControllers();

app.Run();

Az előző kódban MapControllers az attribútumalapú vezérlők leképezésére van meghívva.

Az alábbi példában:

  • HomeController egyezik az alapértelmezett hagyományos útvonalhoz {controller=Home}/{action=Index}/{id?} hasonló URL-címekkel.
public class HomeController : Controller
{
    [Route("")]
    [Route("Home")]
    [Route("Home/Index")]
    [Route("Home/Index/{id?}")]
    public IActionResult Index(int? id)
    {
        return ControllerContext.MyDisplayRouteInfo(id);
    }

    [Route("Home/About")]
    [Route("Home/About/{id?}")]
    public IActionResult About(int? id)
    {
        return ControllerContext.MyDisplayRouteInfo(id);
    }
}

A HomeController.Index művelet az URL-címek //Homebármelyikén fut, /Home/Indexvagy /Home/Index/3.

Ez a példa kiemeli az attribútum-útválasztás és a hagyományos útválasztás közötti kulcsfontosságú programozási különbséget. Az attribútum-útválasztáshoz több bemenetre van szükség az útvonal megadásához. A hagyományos alapértelmezett útvonal tömörebben kezeli az útvonalakat. Az attribútumalapú útválasztás azonban lehetővé teszi és megköveteli annak pontos szabályozását, hogy mely útvonalsablonok vonatkozzanak az egyes műveletekre.

Attribútum alapú útválasztás esetén a vezérlő és az akciónevek nem játszanak szerepet az akció egyeztetésében, kivéve, ha kivonatcsere történik. Az alábbi példa megegyezik az előző példával megegyező URL-címekkel:

public class MyDemoController : Controller
{
    [Route("")]
    [Route("Home")]
    [Route("Home/Index")]
    [Route("Home/Index/{id?}")]
    public IActionResult MyIndex(int? id)
    {
        return ControllerContext.MyDisplayRouteInfo(id);
    }

    [Route("Home/About")]
    [Route("Home/About/{id?}")]
    public IActionResult MyAbout(int? id)
    {
        return ControllerContext.MyDisplayRouteInfo(id);
    }
}

Az alábbi kód token helyettesítést alkalmaz a action és a controller esetében:

public class HomeController : Controller
{
    [Route("")]
    [Route("Home")]
    [Route("[controller]/[action]")]
    public IActionResult Index()
    {
        return ControllerContext.MyDisplayRouteInfo();
    }

    [Route("[controller]/[action]")]
    public IActionResult About()
    {
        return ControllerContext.MyDisplayRouteInfo();
    }
}

A vezérlőre a következő kód vonatkozik [Route("[controller]/[action]")] :

[Route("[controller]/[action]")]
public class HomeController : Controller
{
    [Route("~/")]
    [Route("/Home")]
    [Route("~/Home/Index")]
    public IActionResult Index()
    {
        return ControllerContext.MyDisplayRouteInfo();
    }

    public IActionResult About()
    {
        return ControllerContext.MyDisplayRouteInfo();
    }
}

Az előző kódban a Index metódussablonok előtt el kell helyezni a / vagy ~/ útvonalsablonokat. Olyan műveletre alkalmazott útvonalsablonok, amelyek a vezérlőre alkalmazott útvonalsablonokkal kezdődnek / vagy ~/ nem kombinálódnak.

Az útvonalsablon kiválasztásával kapcsolatos információkért tekintse meg az Útvonalsablon elsőbbsége című témakört.

Fenntartott útválasztási nevek

A következő kulcsszavak fenntartott útvonalparaméternevek a vezérlők vagy Razor lapok használatakor:

  • action
  • area
  • controller
  • handler
  • page

Az attribútumalapú útválasztással rendelkező útvonalparaméter használata page gyakori hiba. Ez inkonzisztens és zavaró viselkedést eredményez az URL-generálással.

public class MyDemo2Controller : Controller
{
    [Route("/articles/{page}")]
    public IActionResult ListArticles(int page)
    {
        return ControllerContext.MyDisplayRouteInfo(page);
    }
}

Az URL-generáció a speciális paraméterneveket használja annak megállapítására, hogy egy URL-létrehozási művelet egy lapra vagy egy Razor vezérlőre hivatkozik-e.

A következő kulcsszavak egy Razor nézet vagy egy Razor oldal kontextusában vannak fenntartva.

  • page
  • using
  • namespace
  • inject
  • section
  • inherits
  • model
  • addTagHelper
  • removeTagHelper

Ezeket a kulcsszavakat nem szabad hivatkozásgenerációkhoz, modellhez kötött paraméterekhez vagy legfelső szintű tulajdonságokhoz használni.

HTTP-parancssablonok

ASP.NET Core a következő HTTP-igesablonokkal rendelkezik:

Útvonalsablonok

ASP.NET Core a következő útvonalsablonokkal rendelkezik:

Attribútum-útválasztás Http ige attribútumokkal

Vegye figyelembe a következő vezérlőt:

[Route("api/[controller]")]
[ApiController]
public class Test2Controller : ControllerBase
{
    [HttpGet]   // GET /api/test2
    public IActionResult ListProducts()
    {
        return ControllerContext.MyDisplayRouteInfo();
    }

    [HttpGet("{id}")]   // GET /api/test2/xyz
    public IActionResult GetProduct(string id)
    {
       return ControllerContext.MyDisplayRouteInfo(id);
    }

    [HttpGet("int/{id:int}")] // GET /api/test2/int/3
    public IActionResult GetIntProduct(int id)
    {
        return ControllerContext.MyDisplayRouteInfo(id);
    }

    [HttpGet("int2/{id}")]  // GET /api/test2/int2/3
    public IActionResult GetInt2Product(int id)
    {
        return ControllerContext.MyDisplayRouteInfo(id);
    }
}

Az előző kódban:

  • Minden művelet tartalmazza az [HttpGet] attribútumot, amely csak a HTTP GET-kérelmeknek való megfelelést korlátozza.
  • A GetProduct művelet tartalmazza a "{id}" sablont, ezért id hozzá van fűzve a "api/[controller]" sablonhoz a vezérlőn. A metódussablon a következő "api/[controller]/{id}": . Ezért ez a művelet csak az űrlap /api/test2/xyz GET kéréseinek felel meg, /api/test2/123, /api/test2/{any string}, stb.
    [HttpGet("{id}")]   // GET /api/test2/xyz
    public IActionResult GetProduct(string id)
    {
       return ControllerContext.MyDisplayRouteInfo(id);
    }
    
  • A GetIntProduct művelet tartalmazza a sablont "int/{id:int}" . A :int sablon része az id útvonalértékeket egész számmá konvertálható sztringekre korlátozza. GET kérés a következőhöz /api/test2/int/abc:
    • Nem egyezik ezzel a művelettel.
    • 404 Nem található hibát ad vissza.
      [HttpGet("int/{id:int}")] // GET /api/test2/int/3
      public IActionResult GetIntProduct(int id)
      {
          return ControllerContext.MyDisplayRouteInfo(id);
      }
      
  • A GetInt2Product művelet tartalmazza a sablonban {id} , de nem korlátozza id azokra az értékekre, amelyeket egész számmá lehet konvertálni. GET kérés a következőhöz /api/test2/int2/abc:
    • Megfelel ennek az útvonalnak.
    • A modellkötés nem konvertálható abc egész számmá. A id metódus paramétere egész szám.
    • 400-os hibás kérést ad vissza, mert a modellkötést nem sikerült egész számmá alakítaniabc.
      [HttpGet("int2/{id}")]  // GET /api/test2/int2/3
      public IActionResult GetInt2Product(int id)
      {
          return ControllerContext.MyDisplayRouteInfo(id);
      }
      

Az attribútum-útválasztás olyan attribútumokat használhat, mint az HttpMethodAttribute, HttpPostAttribute, HttpPutAttribute és HttpDeleteAttribute. Az összes HTTP-igeattribútum elfogad egy útvonalsablont. Az alábbi példa két olyan műveletet mutat be, amelyek azonos útvonalsablonnak felelnek meg:

[ApiController]
public class MyProductsController : ControllerBase
{
    [HttpGet("/products3")]
    public IActionResult ListProducts()
    {
        return ControllerContext.MyDisplayRouteInfo();
    }

    [HttpPost("/products3")]
    public IActionResult CreateProduct(MyProduct myProduct)
    {
        return ControllerContext.MyDisplayRouteInfo(myProduct.Name);
    }
}

Az URL-elérési út /products3használata:

  • A MyProductsController.ListProducts művelet akkor fut, ha a HTTP-igeGET.
  • A MyProductsController.CreateProduct művelet akkor fut, ha a HTTP-igePOST.

API-k készítésekor ritka, hogy egy metóduson használnia kell REST, mert a metódus minden HTTP-metódust elfogad. Érdemes a pontosabb HTTP használati attribútumot használni, hogy egyértelműen jelezze, mit támogat az API. REST Az API-k ügyfeleinek várhatóan tudniuk kell, hogy milyen elérési utak és HTTP-igék vannak leképezve adott logikai műveletekre.

REST Az API-knak attribútumalapú útválasztással kell modelleznie az alkalmazás funkcióit olyan erőforrások készleteként, ahol a műveleteket HTTP-parancsok jelölik. Ez azt jelenti, hogy számos művelet, például a GET és a POST ugyanazon a logikai erőforráson ugyanazt az URL-címet használja. Az attribútum-útválasztás olyan szintű vezérlést biztosít, amely az API nyilvános végpontelrendezésének gondos tervezéséhez szükséges.

Mivel az attribútumútvonalak egy adott műveletre vonatkoznak, az útvonalsablon definíciójának részeként könnyen megkövetelhetőek a paraméterek. A következő példában id az URL-elérési út részeként szükséges:

[ApiController]
public class Products2ApiController : ControllerBase
{
    [HttpGet("/products2/{id}", Name = "Products_List")]
    public IActionResult GetProduct(int id)
    {
        return ControllerContext.MyDisplayRouteInfo(id);
    }
}

A Products2ApiController.GetProduct(int) művelet:

  • Olyan URL-címmel futtatható, mint /products2/3
  • Az URL-cím elérési útvonalával /products2 nincs futtatva.

A [Felhasználás] attribútum lehetővé teszi, hogy egy művelet korlátozza a támogatott kérelem tartalomtípusait. További információ: Támogatott kérések tartalomtípusainak definiálása az Consumes attribútummal.

Az útvonalsablonok és a kapcsolódó beállítások teljes leírását az Útválasztás című témakörben talál.

További információ: [ApiController]ApiController attribútum.

Útvonal neve

Az alábbi kód a következő útvonalnevet Products_Listhatározza meg:

[ApiController]
public class Products2ApiController : ControllerBase
{
    [HttpGet("/products2/{id}", Name = "Products_List")]
    public IActionResult GetProduct(int id)
    {
        return ControllerContext.MyDisplayRouteInfo(id);
    }
}

Az útvonalnevek egy adott útvonalon alapuló URL-cím létrehozásához használhatók. Útvonalnevek:

  • Nincs hatással az útválasztás URL-címmegfeleltetési viselkedésére.
  • Csak URL-címek létrehozására használatos.

Az útvonalneveknek alkalmazásszintű egyedinek kell lenniük.

Határozd szembe az előző kódot a hagyományos alapértelmezett útvonallal, amely a id paramétert opcionálisként ({id?}) határozza meg. Az API-k pontos meghatározásának lehetősége előnyökkel jár, mint például az, hogy a /products és /products/5 különböző műveletekhez való továbbítását lehetővé teszi.

Attribútumútvonalak kombinálása

Az attribútum-útválasztás kevésbé ismétlődővé tétele érdekében a vezérlő útvonalattribútumait a rendszer az egyes műveletek útvonalattribútumaival kombinálja. A vezérlőben definiált útvonalsablonok előre fel vannak függve a műveletek útvonalsablonjaira. Ha egy útvonalattribútumot helyez el a vezérlőn, a vezérlőben lévő összes művelet attribútumalapú útválasztást használ.

[ApiController]
[Route("products")]
public class ProductsApiController : ControllerBase
{
    [HttpGet]
    public IActionResult ListProducts()
    {
        return ControllerContext.MyDisplayRouteInfo();
    }

    [HttpGet("{id}")]
    public IActionResult GetProduct(int id)
    {
        return ControllerContext.MyDisplayRouteInfo(id);
    }
}

Az előző példában:

  • Az URL-cím megegyezhet /productsProductsApi.ListProducts
  • Az URL-cím megegyezhet /products/5ProductsApi.GetProduct(int).

Mindkét művelet csak a HTTP-nek GET felel meg, mert az [HttpGet] attribútummal vannak megjelölve.

Olyan műveletre alkalmazott útvonalsablonok, amelyek a vezérlőre alkalmazott útvonalsablonokkal kezdődnek / vagy ~/ nem kombinálódnak. Az alábbi példa az alapértelmezett útvonalhoz hasonló URL-útvonalakat tartalmaz.

[Route("Home")]
public class HomeController : Controller
{
    [Route("")]
    [Route("Index")]
    [Route("/")]
    public IActionResult Index()
    {
        return ControllerContext.MyDisplayRouteInfo();
    }

    [Route("About")]
    public IActionResult About()
    {
        return ControllerContext.MyDisplayRouteInfo();
    }
}

Az alábbi táblázat az [Route] előző kód attribútumait ismerteti:

Attribute Kombinálva [Route("Home")]-vel Útvonalsablon definiálása
[Route("")] Yes "Home"
[Route("Index")] Yes "Home/Index"
[Route("/")] No ""
[Route("About")] Yes "Home/About"

Attribútumútvonal sorrendje

Az útválasztás létrehoz egy fát, és az összes végpontot egyidejűleg összekapcsolja.

  • Az útvonalbejegyzések úgy viselkednek, mintha ideális sorrendbe helyezték volna.
  • A legspecifikusabb útvonalak az általánosabb útvonalak előtt hajthatók végre.

Például egy attribútumútvonal blog/search/{topic} pontosabb, mint egy attribútumútvonal, például blog/{*article}. Az blog/search/{topic} útvonal alapértelmezés szerint magasabb prioritással rendelkezik, mert pontosabb. A hagyományos útválasztás használatával a fejlesztő felelős az útvonalak kívánt sorrendbe helyezéséért.

Az attribútumútvonalak konfigurálhatják a rendelést a Order tulajdonság használatával. Az összes keretrendszer által biztosított útvonalattribútum tartalmazza . Az útvonalak feldolgozása a Order tulajdonság növekvő sorrendje szerint történik. Az alapértelmezett sorrend a következő 0: . Az útvonal beállítása a Order = -1 használatával azok előtt történik meg, amelyek nem rendelkeznek sorrenddel. Az útvonal beállítása a(z) Order = 1 használatával az alapértelmezett útvonalrendezés után történik.

Kerülje a függést . Ha egy alkalmazás URL-címe explicit rendelési értékeket igényel a helyes útválasztáshoz, az valószínűleg az ügyfelek számára is zavaró. Az attribútum-útválasztás általában a megfelelő útvonalat választja ki URL-egyezéssel. Ha az URL-létrehozáshoz használt alapértelmezett sorrend nem működik, az útvonalnév felülbírálásként való használata általában egyszerűbb, mint a Order tulajdonság alkalmazása.

Vegye figyelembe az alábbi két vezérlőt, amelyek mindkettő az útvonalegyezést /homehatározzák meg:

public class HomeController : Controller
{
    [Route("")]
    [Route("Home")]
    [Route("Home/Index")]
    [Route("Home/Index/{id?}")]
    public IActionResult Index(int? id)
    {
        return ControllerContext.MyDisplayRouteInfo(id);
    }

    [Route("Home/About")]
    [Route("Home/About/{id?}")]
    public IActionResult About(int? id)
    {
        return ControllerContext.MyDisplayRouteInfo(id);
    }
}
public class MyDemoController : Controller
{
    [Route("")]
    [Route("Home")]
    [Route("Home/Index")]
    [Route("Home/Index/{id?}")]
    public IActionResult MyIndex(int? id)
    {
        return ControllerContext.MyDisplayRouteInfo(id);
    }

    [Route("Home/About")]
    [Route("Home/About/{id?}")]
    public IActionResult MyAbout(int? id)
    {
        return ControllerContext.MyDisplayRouteInfo(id);
    }
}

Az előző kóddal való kérés /home a következőhöz hasonló kivételt eredményez:

AmbiguousMatchException: The request matched multiple endpoints. Matches:

 WebMvcRouting.Controllers.HomeController.Index
 WebMvcRouting.Controllers.MyDemoController.MyIndex

Az útvonalattribútumok egyikének hozzáadása Order feloldja a kétértelműséget:

[Route("")]
[Route("Home", Order = 2)]
[Route("Home/MyIndex")]
public IActionResult MyIndex()
{
    return ControllerContext.MyDisplayRouteInfo();
}

Az előző kóddal /home futtatja a végpontot HomeController.Index . Az MyDemoController.MyIndex eléréséhez kérje /home/MyIndex. Note:

  • Az előző kód egy példa vagy rossz útválasztási terv. A Order a tulajdonság szemléltetésére szolgált.
  • A Order tulajdonság csak a kétértelműséget oldja fel, a sablon nem feleltethető meg. Jobb lenne eltávolítani a sablont [Route("Home")] .

Lásd aRazor Oldalak útvonal- és alkalmazáskonvencióit: Útvonal sorrend a Pages alkalmazással Razor kapcsolatos útvonal sorrend információkért.

Bizonyos esetekben egy HTTP 500-as hibát ad vissza, amikor útvonalak nem egyértelműek. A naplózás használatával megtekintheti, hogy mely végpontok okozták a AmbiguousMatchException.

Jogkivonat cseréje útvonalsablonokban [vezérlő], [művelet], [terület]

A kényelem érdekében az attribútumútvonalak támogatják a jogkivonatok cseréjét úgy, hogy szögletes zárójelekbe ([, ]) foglalnak egy jogkivonatot. A jogkivonatok [action], [area] és [controller] a műveletnév, a területnév és a vezérlő nevének értékeire cserélődnek a műveletből, ahol az útvonal definiálva van.

[Route("[controller]/[action]")]
public class Products0Controller : Controller
{
    [HttpGet]
    public IActionResult List()
    {
        return ControllerContext.MyDisplayRouteInfo();
    }


    [HttpGet("{id}")]
    public IActionResult Edit(int id)
    {
        return ControllerContext.MyDisplayRouteInfo(id);
    }
}

Az előző kódban:

[HttpGet]
public IActionResult List()
{
    return ControllerContext.MyDisplayRouteInfo();
}
  • Mérkőzések /Products0/List
[HttpGet("{id}")]
public IActionResult Edit(int id)
{
    return ControllerContext.MyDisplayRouteInfo(id);
}
  • Mérkőzések /Products0/Edit/{id}

A token cseréje az attribute útvonalak építésének utolsó lépése. Az előző példa ugyanúgy viselkedik, mint a következő kód:

public class Products20Controller : Controller
{
    [HttpGet("[controller]/[action]")]  // Matches '/Products20/List'
    public IActionResult List()
    {
        return ControllerContext.MyDisplayRouteInfo();
    }

    [HttpGet("[controller]/[action]/{id}")]   // Matches '/Products20/Edit/{id}'
    public IActionResult Edit(int id)
    {
        return ControllerContext.MyDisplayRouteInfo(id);
    }
}

Ha ezt nem angol nyelven olvassa, ebben a GitHub-vitafórumban tudassa velünk, ha meg szeretné tekinteni a kód megjegyzéseit az anyanyelvén.

Az attribútumútvonalak örökléssel is kombinálhatók. Ez a tokencserével kombinálva erős. A jelölő cseréje az attribútum útvonalak által definiált útvonalnevekre is vonatkozik. [Route("[controller]/[action]", Name="[controller]_[action]")]minden művelethez létrehoz egy egyedi útvonalnevet:

[ApiController]
[Route("api/[controller]/[action]", Name = "[controller]_[action]")]
public abstract class MyBase2Controller : ControllerBase
{
}

public class Products11Controller : MyBase2Controller
{
    [HttpGet]                      // /api/products11/list
    public IActionResult List()
    {
        return ControllerContext.MyDisplayRouteInfo();
    }

    [HttpGet("{id}")]             //    /api/products11/edit/3
    public IActionResult Edit(int id)
    {
        return ControllerContext.MyDisplayRouteInfo(id);
    }
}

A [ vagy ] literális token helyettesítő elválasztójának megadásához ismételje meg a karaktert ([[ vagy ]]) a kilépéshez.

Paraméterátalakító használata a tokenek cseréjének testreszabásához

A tokencsere paraméterátalakítóval testre szabható. A paraméterátalakító implementálja IOutboundParameterTransformer és átalakítja a paraméterek értékét. Egy egyéni SlugifyParameterTransformer paraméterátalakító például a következőre módosítja az SubscriptionManagement útvonal értékét subscription-management:

using System.Text.RegularExpressions;

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

A RouteTokenTransformerConvention egy olyan alkalmazásmodell-konvenció, amely:

  • Paraméterátalakítót alkalmaz az alkalmazás összes attribútumútvonalára.
  • A csere során testre szabja az attribútumútvonal-jogkivonat értékeit.
public class SubscriptionManagementController : Controller
{
    [HttpGet("[controller]/[action]")]
    public IActionResult ListAll()
    {
        return ControllerContext.MyDisplayRouteInfo();
    }
}

Az előző ListAll metódus egyezik /subscription-management/list-all.

A RouteTokenTransformerConvention beállítás a következőként van regisztrálva:

using Microsoft.AspNetCore.Mvc.ApplicationModels;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddControllersWithViews(options =>
{
    options.Conventions.Add(new RouteTokenTransformerConvention(
                                 new SlugifyParameterTransformer()));
});

var app = builder.Build();

if (!app.Environment.IsDevelopment())
{
    app.UseExceptionHandler("/Home/Error");
    app.UseHsts();
}

app.UseHttpsRedirection();
app.UseStaticFiles();

app.UseRouting();

app.UseAuthorization();

app.MapControllerRoute(name: "default",
               pattern: "{controller=Home}/{action=Index}/{id?}");

app.Run();

A Slug definícióját a Slug MDN webes dokumentációja tartalmazza.

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.

Több attribútumútvonal

Az attribútumalapú útválasztás támogatja az azonos műveletet elérő útvonalak meghatározását. Ennek leggyakrabban az alapértelmezett hagyományos útvonal viselkedését kell utánoznia az alábbi példában látható módon:

[Route("[controller]")]
public class Products13Controller : Controller
{
    [Route("")]     // Matches 'Products13'
    [Route("Index")] // Matches 'Products13/Index'
    public IActionResult Index()
    {
        return ControllerContext.MyDisplayRouteInfo();
    }

Ha több útvonalattribútumot helyez el a vezérlőn, az azt jelenti, hogy mindegyik egyesül a műveleti módszerek útvonalattribútumaival:

[Route("Store")]
[Route("[controller]")]
public class Products6Controller : Controller
{
    [HttpPost("Buy")]       // Matches 'Products6/Buy' and 'Store/Buy'
    [HttpPost("Checkout")]  // Matches 'Products6/Checkout' and 'Store/Checkout'
    public IActionResult Buy()
    {
        return ControllerContext.MyDisplayRouteInfo();
    }
}

Az összes HTTP-igeútvonal-korlátozás implementálva IActionConstraintvan.

Ha több útvonalattribútum, amely implementálja IActionConstraint-t, kerül egy akcióra:

  • Minden műveletkényszer kombinálva van a vezérlőre alkalmazott útvonalsablonnal.
[Route("api/[controller]")]
public class Products7Controller : ControllerBase
{
    [HttpPut("Buy")]        // Matches PUT 'api/Products7/Buy'
    [HttpPost("Checkout")]  // Matches POST 'api/Products7/Checkout'
    public IActionResult Buy()
    {
        return ControllerContext.MyDisplayRouteInfo();
    }
}

Ha több útvonalat használ a műveletekhez, hasznosnak és hatékonynak tűnhet, jobb, ha az alkalmazás URL-címterét alapszintűen és jól definiálva tartja. Csak akkor használjon több útvonalat a műveleteken, ha szükséges, például a meglévő ügyfelek támogatására.

Attribútumútvonal opcionális paramétereinek, alapértelmezett értékeinek és kényszereinek megadása

Az attribútumútvonalak ugyanazt a beágyazott szintaxist támogatják, mint a hagyományos útvonalak, hogy opcionális paramétereket, alapértelmezett értékeket és korlátozásokat adjanak meg.

public class Products14Controller : Controller
{
    [HttpPost("product14/{id:int}")]
    public IActionResult ShowProduct(int id)
    {
        return ControllerContext.MyDisplayRouteInfo(id);
    }
}

Az előző kódban [HttpPost("product14/{id:int}")] alkalmaz egy útvonalkorlátozást. A Products14Controller.ShowProduct művelet csak azokkal az URL-címekkel egyezik meg, mint például /product14/3. Az útvonalsablon része {id:int} csak egész számokra korlátozza a szegmenst.

Az útvonalsablon szintaxisának részletes leírását az útvonalsablon-referencia című témakörben találja.

Egyéni útvonalattribútumok az IRouteTemplateProvider használatával

Az összes útvonalattribútumIRouteTemplateProvider-t implementál. A ASP.NET Core-futtatókörnyezet:

  • Attribútumokat keres a vezérlőosztályokon és a műveleti módszereken az alkalmazás indításakor.
  • A implementálandó IRouteTemplateProvider attribútumokkal hozza létre a kezdeti útvonalakat.

Egyéni útvonalattribútumok definiálásához implementálható IRouteTemplateProvider . Mindegyik IRouteTemplateProvider lehetővé teszi egyetlen útvonal egyéni útvonalsablon, sorrend és név megadását:

public class MyApiControllerAttribute : Attribute, IRouteTemplateProvider
{
    public string Template => "api/[controller]";
    public int? Order => 2;
    public string Name { get; set; } = string.Empty;
}

[MyApiController]
[ApiController]
public class MyTestApiController : ControllerBase
{
    // GET /api/MyTestApi
    [HttpGet]
    public IActionResult Get()
    {
        return ControllerContext.MyDisplayRouteInfo();
    }
}

Az előző Get metódus ad vissza Order = 2, Template = api/MyTestApi.

Attribútumútvonalak testreszabása alkalmazásmodell használatával

Az alkalmazásmodell:

  • Az Program.cs indításakor létrejön egy objektum modell.
  • Az ASP.NET Core által az alkalmazásokban végzett műveletek irányításához és végrehajtásához használt összes metaadatot tartalmazza.

Az alkalmazásmodell tartalmazza az útvonalattribútumokból összegyűjtött összes adatot. Az útvonalattribútumokból származó adatokat a IRouteTemplateProvider megvalósítás biztosítja. Conventions:

  • Meg lehet írni az alkalmazás modelljét úgy, hogy az útválasztás viselkedése testreszabható legyen.
  • Az alkalmazás indításakor kerülnek beolvasásra.

Ez a szakasz egy egyszerű példát mutat be az útválasztás alkalmazásmodell használatával történő testreszabására. Az alábbi kód hozzávetőlegesen igazodik a projekt mappastruktúrájához.

public class NamespaceRoutingConvention : Attribute, IControllerModelConvention
{
    private readonly string _baseNamespace;

    public NamespaceRoutingConvention(string baseNamespace)
    {
        _baseNamespace = baseNamespace;
    }

    public void Apply(ControllerModel controller)
    {
        var hasRouteAttributes = controller.Selectors.Any(selector =>
                                                selector.AttributeRouteModel != null);
        if (hasRouteAttributes)
        {
            return;
        }

        var namespc = controller.ControllerType.Namespace;
        if (namespc == null)
            return;
        var template = new StringBuilder();
        template.Append(namespc, _baseNamespace.Length + 1,
                        namespc.Length - _baseNamespace.Length - 1);
        template.Replace('.', '/');
        template.Append("/[controller]/[action]/{id?}");

        foreach (var selector in controller.Selectors)
        {
            selector.AttributeRouteModel = new AttributeRouteModel()
            {
                Template = template.ToString()
            };
        }
    }
}

Az alábbi kód megakadályozza, hogy a namespace konvenció az attribútummal ellátott vezérlőkre vonatkozzon.

public void Apply(ControllerModel controller)
{
    var hasRouteAttributes = controller.Selectors.Any(selector =>
                                            selector.AttributeRouteModel != null);
    if (hasRouteAttributes)
    {
        return;
    }

A következő vezérlő például nem használja a NamespaceRoutingConvention jelet:

[Route("[controller]/[action]/{id?}")]
public class ManagersController : Controller
{
    // /managers/index
    public IActionResult Index()
    {
        var template = ControllerContext.ActionDescriptor.AttributeRouteInfo?.Template;
        return Content($"Index- template:{template}");
    }

    public IActionResult List(int? id)
    {
        var path = Request.Path.Value;
        return Content($"List- Path:{path}");
    }
}

A NamespaceRoutingConvention.Apply módszer:

  • Nem tesz semmit, ha a vezérlő attribútum-alapú útvonalakat használ.
  • Beállítja a vezérlősablont az namespace alapján, az namespace alap eltávolításával.

A NamespaceRoutingConvention következő helyen Program.csalkalmazható:

using My.Application.Controllers;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddControllersWithViews(options =>
{
    options.Conventions.Add(
     new NamespaceRoutingConvention(typeof(HomeController).Namespace!));
});

var app = builder.Build();

Vegyük például a következő vezérlőt:

using Microsoft.AspNetCore.Mvc;

namespace My.Application.Admin.Controllers
{
    public class UsersController : Controller
    {
        // GET /admin/controllers/users/index
        public IActionResult Index()
        {
            var fullname = typeof(UsersController).FullName;
            var template = 
                ControllerContext.ActionDescriptor.AttributeRouteInfo?.Template;
            var path = Request.Path.Value;

            return Content($"Path: {path} fullname: {fullname}  template:{template}");
        }

        public IActionResult List(int? id)
        {
            var path = Request.Path.Value;
            return Content($"Path: {path} ID:{id}");
        }
    }
}

Az előző kódban:

  • Az alap namespace a .My.Application
  • Az előző vezérlő teljes neve .My.Application.Admin.Controllers.UsersController
  • A NamespaceRoutingConvention a vezérlősablont Admin/Controllers/Users/[action]/{id?-ra állítja be.

A NamespaceRoutingConvention vezérlők attribútumaként is alkalmazhatók:

[NamespaceRoutingConvention("My.Application")]
public class TestController : Controller
{
    // /admin/controllers/test/index
    public IActionResult Index()
    {
        var template = ControllerContext.ActionDescriptor.AttributeRouteInfo?.Template;
        var actionname = ControllerContext.ActionDescriptor.ActionName;
        return Content($"Action- {actionname} template:{template}");
    }

    public IActionResult List(int? id)
    {
        var path = Request.Path.Value;
        return Content($"List- Path:{path}");
    }
}

Vegyes útválasztás: Attribútum-útválasztás és hagyományos útválasztás

ASP.NET Core-alkalmazások vegyesen használhatják a hagyományos útválasztást és az attribútumalapú útválasztást. Általában hagyományos útvonalakat használnak a böngészők html lapjait kiszolgáló vezérlőkhöz, az API-kat kiszolgáló REST vezérlők attribútum-útválasztásához.

A műveletek vagy hagyományos útvonalra vannak állítva, vagy attribútumok alapján vannak irányítva. Ha egy útvonalat helyez el a vezérlőn vagy a műveleten, az attribútum átirányítva lesz. Az attribútumútvonalakat meghatározó műveletek nem érhetőek el a hagyományos útvonalakon keresztül, és fordítva. A vezérlő bármely útvonalattribútuma a vezérlő attribútumában található összes műveletet átirányítja.

Az attribútum-útválasztás és a hagyományos útválasztás ugyanazt az útválasztási motort használja.

Ú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;

URL-létrehozási és környezeti értékek

Az alkalmazások útválasztási URL-címgenerálási funkciókkal hozhatnak létre URL-hivatkozásokat a műveletekhez. Az URL-címek létrehozása megszünteti a szigorú kódolású URL-címeket , így a kód robusztusabb és karbantarthatóbb lesz. Ez a szakasz az MVC által biztosított URL-létrehozási funkciókra összpontosít, és csak az URL-létrehozás működésének alapjait ismerteti. Az URL-cím generálásának részletes leírását az Útválasztás című témakörben találja.

Az IUrlHelper interfész az MVC és az URL-generálás útválasztása közötti infrastruktúra mögöttes eleme. A IUrlHelper példány elérhető a Url tulajdonságon keresztül a vezérlőkben, nézetekben és nézetösszetevőkben.

Az alábbi példában a rendszer a tulajdonságon keresztül használja az IUrlHelperController.Url interfészt egy URL-cím létrehozásához egy másik művelethez.

public class UrlGenerationController : Controller
{
    public IActionResult Source()
    {
        // Generates /UrlGeneration/Destination
        var url = Url.Action("Destination");
        return ControllerContext.MyDisplayRouteInfo("", $" URL = {url}");
    }

    public IActionResult Destination()
    {
        return ControllerContext.MyDisplayRouteInfo();
    }
}

Ha az alkalmazás az alapértelmezett hagyományos útvonalat használja, a url változó értéke az URL-elérési út sztringje /UrlGeneration/Destination. Ez az URL-elérési út útválasztással van létrehozva az alábbiak kombinálásával:

  • Az aktuális kérés útvonalértékei, amelyeket környezeti értékeknek neveznek.
  • Az értékek átadása a Url.Action részére és azoknak az értékeknek a helyettesítése az útvonalsablonban:
ambient values: { controller = "UrlGeneration", action = "Source" }
values passed to Url.Action: { controller = "UrlGeneration", action = "Destination" }
route template: {controller}/{action}/{id?}

result: /UrlGeneration/Destination

Az útvonalsablonban minden útvonalparaméter értéke lecserélődik oly módon, hogy a nevek össze vannak párosítva a paraméterértékekkel és a környezeti értékekkel. Egy olyan útvonalparaméter, amely nem rendelkezik értékkel, a következőt teheti:

  • Használjon alapértelmezett értéket, ha rendelkezik ilyen értékkel.
  • Kihagyható, ha nem kötelező. Például az id útvonalsablonból {controller}/{action}/{id?}.

Az URL-cím létrehozása meghiúsul, ha a szükséges útvonalparaméter nem rendelkezik megfelelő értékkel. Ha egy útvonal URL-generálása sikertelen, a következő útvonal mindaddig próbálkozik, amíg az összes útvonal ki nem próbálva, vagy nem talál egyezést.

Az előző példa Url.Action a hagyományos útválasztást feltételezi. Az URL-generálás hasonlóan működik az attribútum-útválasztással, bár a fogalmak eltérnek. Hagyományos útválasztással:

  • Az útvonalértékek egy sablon kibontására szolgálnak.
  • A controller és action útvonalértékei általában megjelennek ebben a sablonban. Ez azért működik, mert az útválasztással egyező URL-címek megfelelnek egy konvenciónak.

Az alábbi példa attribútum-útválasztást használ:

public class UrlGenerationAttrController : Controller
{
    [HttpGet("custom")]
    public IActionResult Source()
    {
        var url = Url.Action("Destination");
        return ControllerContext.MyDisplayRouteInfo("", $" URL = {url}");
    }

    [HttpGet("custom/url/to/destination")]
    public IActionResult Destination()
    {
       return ControllerContext.MyDisplayRouteInfo();
    }
}

Az Source előző kódban szereplő művelet generálja a következőt custom/url/to/destination: .

LinkGenerator ASP.NET Core 3.0-ban lett hozzáadva IUrlHelper alternatívájaként. LinkGenerator hasonló, de rugalmasabb funkciókat kínál. Minden metódushoz IUrlHelper tartozik egy megfelelő metóduscsalád LinkGenerator is.

URL-címek létrehozása műveletnév alapján

Az URL.Action, a LinkGenerator.GetPathByAction és a kapcsolódó túlterhelések mindegyike úgy van kialakítva, hogy létrehozhassa a célvégpontot egy vezérlőnév és műveletnév megadásával.

Használat Url.Action esetén a futtatókörnyezet biztosítja a controller és action aktuális útvonalértékeit.

  • controller és action értéke mind a környezeti értékek, mind pedig az általános értékek része. A metódus Url.Action mindig az aktuális értékeket action használja, és controller létrehoz egy URL-útvonalat, amely az aktuális művelethez vezet.

Az útválasztás a környezeti értékek értékeit használja az URL-cím létrehozásakor nem megadott információk kitöltésére. Fontoljon meg egy útvonalat, mint például {a}/{b}/{c}/{d}, a környezeti értékekkel { a = Alice, b = Bob, c = Carol, d = David }.

  • Az útválasztás elegendő információval rendelkezik ahhoz, hogy további értékek nélkül hozzon létre URL-címet.
  • Az útválasztás elegendő információval rendelkezik, mert minden útvonalparaméternek van értéke.

Ha az érték { d = Donovan } hozzáadva van:

  • Az érték { d = David } figyelmen kívül lesz hagyva.
  • A létrehozott URL-elérési út a következő Alice/Bob/Carol/Donovan: .

Figyelmeztetés: Az URL-elérési utak hierarchikusak. Az előző példában, ha az érték { c = Cheryl } hozzá van adva:

  • A rendszer mindkét értéket { c = Carol, d = David } figyelmen kívül hagyja.
  • A d számára már nincs érték, ezért az URL-cím létrehozása meghiúsul.
  • Az URL-cím létrehozásához meg kell adni a kívánt értékeket c és d.

Előfordulhat, hogy az alapértelmezett útvonallal {controller}/{action}/{id?}kapcsolatos problémát tapasztalja. Ez a probléma a gyakorlatban ritkán fordul elő, mert Url.Action mindig explicit módon meghatározza a controller és action értéket.

Az Url.Action számos túlterhelése elfogad egy útvonali értékek objektumot, hogy más útvonalparaméterek értékeit adja meg, mint controller és action. A rendszer gyakran használja az útvonalérték-objektumot id. Például: Url.Action("Buy", "Products", new { id = 17 }). Az útvonalértékek objektuma:

  • Konvenció szerint általában névtelen típusú objektum.
  • Lehet egy IDictionary<> vagy POCO).

Az útvonalparamétereknek nem megfelelő további útvonalértékek a lekérdezési sztringbe kerülnek.

public IActionResult Index()
{
    var url = Url.Action("Buy", "Products", new { id = 17, color = "red" });
    return Content(url!);
}

Az előző kód generálja a következőt /Products/Buy/17?color=red: .

A következő kód abszolút URL-címet hoz létre:

public IActionResult Index2()
{
    var url = Url.Action("Buy", "Products", new { id = 17 }, protocol: Request.Scheme);
    // Returns https://localhost:5001/Products/Buy/17
    return Content(url!);
}

Abszolút URL-cím létrehozásához használja az alábbiak egyikét:

  • Egy túlterhelés, amely elfogadja a protocol. Például az előző kód.
  • LinkGenerator.GetUriByAction, amely alapértelmezés szerint abszolút URI-kat hoz létre.

URL-címek létrehozása útvonal szerint

Az előző kód bemutatta egy URL-cím létrehozását a vezérlő és a művelet név megadásával. IUrlHelper Az Url.RouteUrl metóduscsaládot is tartalmazza. Ezek a metódusok hasonlóak az Url.Action metódushoz, de nem másolja az aktuális értékeket a action és controller az útvonalértékekhez. A leggyakoribb használat a Url.RouteUrl a következő:

  • Megadja az URL-cím létrehozásához tartozó útvonalnevet.
  • Általában nem ad meg vezérlőt vagy műveletnevet.
public class UrlGeneration2Controller : Controller
{
    [HttpGet("")]
    public IActionResult Source()
    {
        var url = Url.RouteUrl("Destination_Route");
        return ControllerContext.MyDisplayRouteInfo("", $" URL = {url}");
    }

    [HttpGet("custom/url/to/destination2", Name = "Destination_Route")]
    public IActionResult Destination()
    {
        return ControllerContext.MyDisplayRouteInfo();
    }

A következő Razor fájl létrehoz egy HTML-hivatkozást a Destination_Routekövetkezőre:

<h1>Test Links</h1>

<ul>
    <li><a href="@Url.RouteUrl("Destination_Route")">Test Destination_Route</a></li>
</ul>

URL-címek létrehozása HTML-ben és Razor

IHtmlHelper a HtmlHelper módszereket, a Html.BeginForm és a Html.ActionLink használja a megfelelő <form> és <a> elemek generálásához. Ezek a metódusok az URL.Action metódussal hoznak létre URL-címet, és hasonló argumentumokat fogadnak el. Az Url.RouteUrl társai HtmlHelper és Html.BeginRouteForm, amelyek hasonló funkciókkal rendelkeznek.

A TagHelpers URL-címeket hoz létre a form TagHelper és a <a> TagHelper használatával. Mindkét megvalósítás során IUrlHelper-et használnak. További információkért tekintse meg az űrlapok címkesegítőit .

A belső nézetekben a IUrlHelper tulajdonság révén érhető el minden olyan ad-hoc URL-generálás, amelyre a fentiek nem vonatkoznak.

URL-generálás a műveleteredményekben

Az előző példák bemutatták a IUrlHelper használatát a vezérlőben. A vezérlők leggyakoribb használata egy URL-cím létrehozása egy művelet eredményének részeként.

Az ControllerBase és Controller az alaposztályok kényelmi módszereket biztosítanak egy másik műveletre hivatkozó műveleti eredményekhez. Az egyik jellemző használat az átirányítás a felhasználói bemenet elfogadása után:

[HttpPost]
[ValidateAntiForgeryToken]
public IActionResult Edit(int id, Customer customer)
{
    if (ModelState.IsValid)
    {
        // Update DB with new details.
        ViewData["Message"] = $"Successful edit of customer {id}";
        return RedirectToAction("Index");
    }
    return View(customer);
}

Az olyan akció-eredmény gyári metódusok, mint a RedirectToAction és a CreatedAtAction, hasonló mintát követnek, mint a IUrlHelper metódusok.

Speciális eset dedikált hagyományos útvonalakhoz

A hagyományos útválasztás egy speciális útvonaldefiníciót, az úgynevezett dedikált hagyományos útvonalat használhat. A következő példában a névvel ellátott blog útvonal egy dedikált hagyományos útvonal:

app.MapControllerRoute(name: "blog",
                pattern: "blog/{*article}",
                defaults: new { controller = "Blog", action = "Article" });
app.MapControllerRoute(name: "default",
               pattern: "{controller=Home}/{action=Index}/{id?}");

Az előző útvonaldefiníciók Url.Action("Index", "Home") használatával hozza létre az URL-címet / az default útvonal használatával, de miért? Előfordulhat, hogy az útvonalértékek { controller = Home, action = Index } elegendőek egy URL generálásához blog használatával, és az eredmény az lesz /blog?action=Index&controller=Home.

A dedikált hagyományos útvonalak az alapértelmezett értékek speciális viselkedésére támaszkodnak, amelyek nem rendelkeznek megfelelő útvonalparaméterrel, amely megakadályozza, hogy az útvonal túlságosan mohó legyen az URL-cím generálása során. Ebben az esetben az alapértelmezett értékek a következők { controller = Blog, action = Article }, és sem controller sem action nem jelenik meg útvonalparaméterként. Ha az útválasztás URL-címet generál, a megadott értékeknek meg kell egyeznie az alapértelmezett értékekkel. Az URL-cím létrehozása blog sikertelen, mert az értékek { controller = Home, action = Index } nem egyeznek { controller = Blog, action = Article }. Az útválasztás ezután visszatér default próbálkozásra, ami sikerrel jár.

Areas

A területek egy MVC-funkció, amellyel a kapcsolódó funkciók külön csoportba rendezhetőek:

  • Útválasztási névtér vezérlőműveletekhez.
  • A nézetek mappastruktúrája.

A területek használata lehetővé teszi, hogy az alkalmazások több, azonos nevű vezérlővel rendelkezzenek, feltéve, hogy különböző területekkel rendelkeznek. A területek használata hierarchiát hoz létre az útválasztás céljából egy másik útvonalparaméter hozzáadásával a area és controller elemekhez. Ez a szakasz azt ismerteti, hogyan lép kölcsönhatásba az útválasztás a területekkel. Részletekért lásd a Területek című témakört, ahol a területek nézetekkel való használatáról olvashat.

Az alábbi példa úgy konfigurálja az MVC-t, hogy az alapértelmezett hagyományos útvonalat és egy areaarea elnevezett Blogútvonalat használja:

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddControllersWithViews();

var app = builder.Build();

if (!app.Environment.IsDevelopment())
{    
    app.UseExceptionHandler("/Home/Error");
    app.UseHsts();
}

app.UseHttpsRedirection();
app.UseStaticFiles();

app.UseRouting();

app.UseAuthorization();

app.MapAreaControllerRoute("blog_route", "Blog",
        "Manage/{controller}/{action}/{id?}");
app.MapControllerRoute("default_route", "{controller}/{action}/{id?}");

app.Run();

Az előző kódban a MapAreaControllerRoute meghívásával létrehozzák a "blog_route". A második paraméter a "Blog"terület neve.

Ha egy URL-útvonalhoz hasonlót /Manage/Users/AddUser illeszt, az "blog_route" útvonal létrehozza az útvonalértékeket { area = Blog, controller = Users, action = AddUser }. Az area útvonal értékét a rendszer a következő alapértelmezett értékével areahozza létre: . A létrehozott MapAreaControllerRoute útvonal egyenértékű a következővel:

app.MapControllerRoute("blog_route", "Manage/{controller}/{action}/{id?}",
        defaults: new { area = "Blog" }, constraints: new { area = "Blog" });
app.MapControllerRoute("default_route", "{controller}/{action}/{id?}");

MapAreaControllerRoute létrehoz egy útvonalat, amely az alapértelmezett értéket és a megadott területnév használatára vonatkozó area korlátozást is használja, ebben az esetben Blog. Az alapértelmezett érték biztosítja, hogy az útvonal mindig { area = Blog, ... }-t hoz létre, a kényszer megköveteli a { area = Blog, ... } értéket az URL generálásához.

A hagyományos útválasztás sorrendfüggő. Általánosságban elmondható, hogy a területekkel rendelkező útvonalakat korábban kell elhelyezni, mivel ezek pontosabbak, mint a terület nélküli útvonalak.

Az előző példában szereplő útvonalértékek { area = Blog, controller = Users, action = AddUser } a következő műveletnek felelnek meg:

using Microsoft.AspNetCore.Mvc;

namespace MyApp.Namespace1
{
    [Area("Blog")]
    public class UsersController : Controller
    {
        // GET /manage/users/adduser
        public IActionResult AddUser()
        {
            var area = ControllerContext.ActionDescriptor.RouteValues["area"];
            var actionName = ControllerContext.ActionDescriptor.ActionName;
            var controllerName = ControllerContext.ActionDescriptor.ControllerName;

            return Content($"area name:{area}" +
                $" controller:{controllerName}  action name: {actionName}");
        }        
    }
}

A [Terület] attribútum az, amely egy vezérlőt egy terület részeként jelöl. Ez a vezérlő a Blog környéken található. Az attribútummal nem rendelkező [Area] vezérlők nem tagjai egyik területnek sem, és nem egyeznek meg, ha az útvonal értékét útválasztás area biztosítja. Az alábbi példában csak az első vezérlő felelhet meg az útvonalértéknek { area = Blog, controller = Users, action = AddUser }.

using Microsoft.AspNetCore.Mvc;

namespace MyApp.Namespace1
{
    [Area("Blog")]
    public class UsersController : Controller
    {
        // GET /manage/users/adduser
        public IActionResult AddUser()
        {
            var area = ControllerContext.ActionDescriptor.RouteValues["area"];
            var actionName = ControllerContext.ActionDescriptor.ActionName;
            var controllerName = ControllerContext.ActionDescriptor.ControllerName;

            return Content($"area name:{area}" +
                $" controller:{controllerName}  action name: {actionName}");
        }        
    }
}
using Microsoft.AspNetCore.Mvc;

namespace MyApp.Namespace2
{
    // Matches { area = Zebra, controller = Users, action = AddUser }
    [Area("Zebra")]
    public class UsersController : Controller
    {
        // GET /zebra/users/adduser
        public IActionResult AddUser()
        {
            var area = ControllerContext.ActionDescriptor.RouteValues["area"];
            var actionName = ControllerContext.ActionDescriptor.ActionName;
            var controllerName = ControllerContext.ActionDescriptor.ControllerName;

            return Content($"area name:{area}" +
                $" controller:{controllerName}  action name: {actionName}");
        }        
    }
}
using Microsoft.AspNetCore.Mvc;

namespace MyApp.Namespace3
{
    // Matches { area = string.Empty, controller = Users, action = AddUser }
    // Matches { area = null, controller = Users, action = AddUser }
    // Matches { controller = Users, action = AddUser }
    public class UsersController : Controller
    {
        // GET /users/adduser
        public IActionResult AddUser()
        {
            var area = ControllerContext.ActionDescriptor.RouteValues["area"];
            var actionName = ControllerContext.ActionDescriptor.ActionName;
            var controllerName = ControllerContext.ActionDescriptor.ControllerName;

            return Content($"area name:{area}" +
                $" controller:{controllerName}  action name: {actionName}");
        }
    }
}

Az egyes vezérlők névtere itt látható a teljesség érdekében. Ha az előző vezérlők ugyanazt a névteret használták, fordítóhiba jön létre. Az osztálynévterek nincsenek hatással az MVC útválasztására.

Az első két vezérlő a területek tagjai, és csak akkor egyeznek meg, ha a megfelelő terület nevét az area útvonal értéke adja meg. A harmadik vezérlő nem tartozik egyetlen területhez sem, és csak akkor felel meg, ha az útválasztás nem ad meg értéket a area számára.

A nincs érték egyezés szempontjából az area érték hiánya ugyanaz, mintha a area érték null vagy üres sztring lenne.

Ha egy műveletet egy területen hajt végre, az útvonal értéke areakörnyezeti értékként érhető el az URL-generáláshoz használandó útválasztáshoz. Ez azt jelenti, hogy alapértelmezés szerint a területek ragadósak az URL-generáláshoz, ahogy azt az alábbi minta is mutatja.

app.MapAreaControllerRoute(name: "duck_route",
                                     areaName: "Duck",
                                     pattern: "Manage/{controller}/{action}/{id?}");
app.MapControllerRoute(name: "default",
                             pattern: "Manage/{controller=Home}/{action=Index}/{id?}");
using Microsoft.AspNetCore.Mvc;

namespace MyApp.Namespace4
{
    [Area("Duck")]
    public class UsersController : Controller
    {
        // GET /Manage/users/GenerateURLInArea
        public IActionResult GenerateURLInArea()
        {
            // Uses the 'ambient' value of area.
            var url = Url.Action("Index", "Home");
            // Returns /Manage/Home/Index
            return Content(url);
        }

        // GET /Manage/users/GenerateURLOutsideOfArea
        public IActionResult GenerateURLOutsideOfArea()
        {
            // Uses the empty value for area.
            var url = Url.Action("Index", "Home", new { area = "" });
            // Returns /Manage
            return Content(url);
        }
    }
}

Az alábbi kód egy URL-címet hoz létre a következő címre /Zebra/Users/AddUser:

public class HomeController : Controller
{
    public IActionResult About()
    {
        var url = Url.Action("AddUser", "Users", new { Area = "Zebra" });
        return Content($"URL: {url}");
    }

Műveletdefiníció

A vezérlő nyilvános metódusai a NonAction attribútummal rendelkezők kivételével műveletek.

Mintakód

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

ASP.NET Core vezérlők az Útválasztás köztes szoftvert használják, hogy összepárosítsák a bejövő kérések URL-címeit, és műveletekhez rendeljék őket. Útvonalsablonok:

  • Az indítási kódban vagy attribútumokban vannak definiálva.
  • Írja le, hogyan illeszkednek az URL-útvonalak a műveletekhez.
  • A hivatkozások URL-címeinek létrehozására szolgál. A létrehozott hivatkozások általában válaszokban jelennek meg.

A műveletek hagyományosan irányítottak vagy attribútumalapúak. Ha egy útvonalat helyez el a vezérlőn vagy a műveleten , az attribútumalapúvá válik. További információt a Vegyes útválasztás című témakörben talál.

Ez a dokumentum:

  • Az MVC és az útválasztás közötti interakciókat ismerteti:
  • A ASP.NET Core 3.0-ban hozzáadott alapértelmezett útválasztási rendszerre, az úgynevezett végpont-útválasztásra hivatkozik. Kompatibilitási okokból az útválasztás előző verziójával rendelkező vezérlőket is használhat. Útmutatásért tekintse meg a 2.2-3.0 migrálási útmutatót . Tekintse meg a dokumentum 2.2-es verzióját a korábbi útválasztási rendszerrel kapcsolatos referenciaanyagokért.

Hagyományos útvonal beállítása

Startup.Configure a hagyományos útválasztás használatakor általában a következőhöz hasonló kóddal rendelkezik:

app.UseEndpoints(endpoints =>
{
    endpoints.MapControllerRoute(
        name: "default",
        pattern: "{controller=Home}/{action=Index}/{id?}");
});

A UseEndpoints hívásakor a MapControllerRoute egyetlen útvonalat hoz létre. Az egyetlen útvonal neve default útvonal. A vezérlőkkel és nézetekkel rendelkező alkalmazások többsége az default útvonalhoz hasonló útvonalsablont használ. REST Az API-knak attribútum-útválasztást kell használniuk.

Az útvonalsablon "{controller=Home}/{action=Index}/{id?}":

  • Megfelel egy URL-címnek, például: /Products/Details/5

  • Kinyeri az útvonal értékeit { controller = Products, action = Details, id = 5 } az elérési út tokenizálásával. Az útvonalértékek kinyerése akkor eredményez egyezést, ha az alkalmazásnak van egy ProductsController nevű vezérlője és egy Details nevű művelete.

    public class ProductsController : Controller
    {
        public IActionResult Details(int id)
        {
            return ControllerContext.MyDisplayRouteInfo(id);
        }
    }
    

    MyDisplayRouteInfo a Rick.Docs.Samples.RouteInfo NuGet-csomag biztosítja, és megjeleníti az útvonaladatokat.

  • /Products/Details/5 modell a(z) id = 5 értéket használja a(z) id paraméter 5 értékre való kötéséhez. További részletekért tekintse meg a modellkötést .

  • {controller=Home} a Home alapértelmezettként controllerdefiniálja.

  • {action=Index} a Index alapértelmezettként actiondefiniálja.

  • A ? karakter a {id?} területen opcionálisként határozza meg a id-t.

  • Az alapértelmezett és az opcionális útvonalparamétereknek nem kell szerepelnie az egyezés URL-címében. Az útvonalsablon szintaxisának részletes leírását az útvonalsablon-referencia című témakörben találja.

  • Megfelel az URL-cím elérési útvonalának /.

  • Létrehozza az útvonalértékeket { controller = Home, action = Index }.

A controller és action alapértelmezett értékeket használnak. id nem hoz létre értéket, mivel az URL-elérési útnak nincs megfelelő szegmense. / csak akkor egyezik, ha létezik egy HomeController és Index művelet:

public class HomeController : Controller
{
  public IActionResult Index() { ... }
}

Az előző vezérlődefiníció és útvonalsablon használatával a művelet a HomeController.Index következő URL-útvonalakon fut:

  • /Home/Index/17
  • /Home/Index
  • /Home
  • /

Az URL-elérési út / az útvonalsablon alapértelmezett Home vezérlőit és Index műveleteit használja. Az URL-elérési út /Home az útvonalsablon alapértelmezett Index műveletét használja.

A kényelmi módszer MapDefaultControllerRoute:

endpoints.MapDefaultControllerRoute();

Replaces:

endpoints.MapControllerRoute("default", "{controller=Home}/{action=Index}/{id?}");

Important

Az útválasztás a UseRouting, MapControllerRoute és MapAreaControllerRoute köztes szoftver használatával konfigurálható. Vezérlők használata:

Hagyományos útválasztás

A hagyományos útválasztás vezérlőkkel és nézetekkel használható. Az default útvonal:

endpoints.MapControllerRoute(
    name: "default",
    pattern: "{controller=Home}/{action=Index}/{id?}");

Az előző példa egy hagyományos útvonalra mutat. Ezt hagyományos útválasztásnak nevezik, mert konvenciót hoz létre az URL-útvonalakhoz:

  • Az első útvonal szegmens {controller=Home} a vezérlő nevére lesz leképezve.
  • A második szegmens a {action=Index}művelet nevére képeződik le.
  • A harmadik szegmens {id?} opcionális id-ként használatos. A ? a {id?} tegében választhatóvá teszi. A id a modellentitásra való leképezéshez használható.

Ezzel az default útvonallal az URL-cím útvonala:

  • /Products/List leképez a ProductsController.List művelethez.
  • /Blog/Article/17 leképez BlogController.Article és általában a modell leköti a id paramétert a 17-es értékhez.

Ez a leképezés:

  • Csak a vezérlőn és a műveletnevekenalapul.
  • Nem névtereken, forrásfájl-helyeken vagy metódusparamétereken alapul.

A hagyományos útválasztás alapértelmezett útvonallal való használata lehetővé teszi az alkalmazás létrehozását anélkül, hogy minden művelethez új URL-mintát kellene létrehoznia. CRUD stílusműveleteket tartalmazó alkalmazás esetén, amely konzisztenciával rendelkezik a vezérlők URL-címeivel kapcsolatban:

  • Segít leegyszerűsíteni a kódot.
  • A felhasználói felület kiszámíthatóbbá válik.

Warning

Az id előző kódban szereplő kódot az útvonalsablon nem kötelezőként határozza meg. A műveletek az URL-cím részeként megadott opcionális azonosító nélkül is végrehajthatók. Általában, ha id kihagyva van az URL-ből:

  • id modellkötés szerint van beállítva 0 .
  • Az adatbázisban a id == 0 nem egyezik egyetlen entitással sem.

Az attribútum-útválasztás részletes vezérlést biztosít, amely lehetővé teszi, hogy az azonosító bizonyos műveletekhez szükséges legyen, nem pedig mások számára. A konvenció szerint a dokumentáció tartalmazza az olyan választható paramétereket, mint a id, amikor azok valószínűleg a helyes használat során jelennek meg.

A legtöbb alkalmazásnak alapszintű és leíró útválasztási sémát kell választania, hogy az URL-címek olvashatók és értelmezhetők legyenek. Az alapértelmezett hagyományos útvonal {controller=Home}/{action=Index}/{id?}:

  • Alapszintű és leíró útválasztási sémát támogat.
  • Hasznos kiindulópont a felhasználói felületalapú alkalmazásokhoz.
  • Ez az egyetlen útválasztási sablon, amely sok webes felhasználói felületi alkalmazáshoz szükséges. A nagyobb webes felhasználói felületi alkalmazások esetében gyakran csak a Területeket használó másik útvonalra van szükség.

MapControllerRoute és MapAreaRoute :

  • Automatikusan rendeljen hozzá sorrendi értéket a végpontokhoz a meghívás sorrendje alapján.

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ákat a bővíthetőség végrehajtásához, az összes végpont egyszerre lesz feldolgozva.

Engedélyezze a naplózást, hogy megtekintse, hogyan illeszkednek a beépített útválasztási implementációk, mint például Route, a kérésekhez.

Az attribútumok útválasztását a dokumentum későbbi részében ismertetik.

Több hagyományos útvonal

Több hagyományos útvonal is hozzáadható, UseEndpoints ha további hívásokat ad hozzá.MapControllerRouteMapAreaControllerRoute Ez lehetővé teszi több konvenció meghatározását, vagy egy adott művelethez dedikált hagyományos útvonalak hozzáadását, például:

app.UseEndpoints(endpoints =>
{
    endpoints.MapControllerRoute(name: "blog",
                pattern: "blog/{*article}",
                defaults: new { controller = "Blog", action = "Article" });
    endpoints.MapControllerRoute(name: "default",
                pattern: "{controller=Home}/{action=Index}/{id?}");
});

Az blog előző kódban szereplő útvonal egy dedikált hagyományos útvonal. Ez az úgynevezett dedikált hagyományos útvonal, mert:

Azért, mert a controller és action nem jelenik meg a "blog/{*article}" útvonalsablonban paraméterekként:

  • Csak az alapértelmezett értékekkel { controller = "Blog", action = "Article" }rendelkezhetnek.
  • Ez az útvonal mindig a művelethez lesz megfeleltetve BlogController.Article.

/Blog, /Blog/Articleés /Blog/{any-string} ezek az egyetlen URL-elérési utak, amelyek megfelelnek a blog útvonalának.

Az előző példa:

  • blog az útvonal nagyobb prioritással rendelkezik az egyezésekhez, mint az default útvonal, mert az elsőként van hozzáadva.
  • Példa a Slug-stílus útválasztására, ahol általában egy cikknév szerepel az URL-cím részeként.

Warning

A ASP.NET Core 3.0-s vagy újabb verziójában az útválasztás nem:

  • Definiáljon egy útvonalnak nevezett fogalmat. UseRouting A köztesszoftver-folyamatnak megfelelő útvonalat ad hozzá. A UseRouting köztes szoftver megvizsgálja az alkalmazásban definiált végpontokat, és a kérés alapján kiválasztja a legjobb végpontegyezést.
  • Biztosítson garanciákat a bővíthetőség végrehajtási sorrendjére, például IRouteConstraint vagy IActionConstraint.

Az útválasztással kapcsolatos referenciaanyagokért tekintse meg az Útválasztás című témakört.

Hagyományos útválasztási sorrend

A hagyományos útválasztás csak az alkalmazás által meghatározott művelet és vezérlő kombinációjával egyezik meg. Ez leegyszerűsíti azokat az eseteket, amikor a hagyományos útvonalak átfedésben vannak. Útvonalak hozzáadása a MapControllerRoute, MapDefaultControllerRoute és MapAreaControllerRoute használatával automatikusan rendelési értéket ad a végpontokhoz a meghívásuk sorrendje alapján. Az útvonal, amely korábban jelenik meg, egyezései magasabb prioritással rendelkeznek. A hagyományos útválasztás sorrendfüggő. Általánosságban elmondható, hogy a területekkel rendelkező útvonalakat korábban kell elhelyezni, mivel ezek pontosabbak, mint a terület nélküli útvonalak. Az olyan hagyományos útvonalak, mint például {*article} a catch-all útvonalparaméterek, túl mohóvá tehetik az útvonalakat, ami azt jelenti, hogy megegyezik a más útvonalakkal egyeztetni kívánt URL-címekkel. A kapzsi útvonalakat később helyezze el az útvonaltáblában, hogy megakadályozza a kapzsi egyezéseket.

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.

Nem egyértelmű műveletek feloldása

Ha két végpont egyezik az útválasztással, az útválasztásnak az alábbiak egyikét kell elvégeznie:

  • Válassza ki a legjobb jelöltet.
  • Kivételt kell kivenni.

Például:

    public class Products33Controller : Controller
    {
        public IActionResult Edit(int id)
        {
            return ControllerContext.MyDisplayRouteInfo(id);
        }

        [HttpPost]
        public IActionResult Edit(int id, Product product)
        {
            return ControllerContext.MyDisplayRouteInfo(id, product.name);
        }
    }
}

Az előző vezérlő két, egyező műveletet határoz meg:

  • Az URL-cím elérési útja /Products33/Edit/17
  • Útvonaladatok { controller = Products33, action = Edit, id = 17 }.

Ez az MVC-vezérlők tipikus mintája:

  • Edit(int) egy termék szerkesztéséhez használandó űrlapot jelenít meg.
  • Edit(int, Product) feldolgozza a közzétett űrlapot.

Az útvonal helyes kijelölése:

  • Edit(int, Product) akkor van kiválasztva, ha a kérés HTTP POST.
  • Edit(int) akkor van kiválasztva, ha a HTTP-ige bármi más. Edit(int)-t általában GET használatával hívjuk meg.

A HttpPostAttribute, [HttpPost]az útválasztáshoz van megadva, hogy a kérés HTTP-metódusa alapján válasszon. Az HttpPostAttribute jobban megteszi Edit(int, Product)-t megfelelőbbé, mint a Edit(int).

Fontos megérteni az olyan attribútumok szerepét, mint HttpPostAttributea . Más HTTP-parancsokhoz hasonló attribútumok vannak definiálva. A hagyományos útválasztásban gyakran előfordul, hogy a műveletek ugyanazt a műveletnevet használják, amikor egy megjelenítési űrlap részei, és űrlap-munkafolyamatot küldenek. Lásd például a két szerkesztési művelet módszerét.

Ha az útválasztás nem tudja kiválasztani a legjobb jelöltet, AmbiguousMatchException a több egyező végpontot listázó üzenet megjelenik.

Hagyományos útvonalnevek

A "blog" és "default" karakterláncok az alábbi példákban a hagyományos útvonalnevek:

app.UseEndpoints(endpoints =>
{
    endpoints.MapControllerRoute(name: "blog",
                pattern: "blog/{*article}",
                defaults: new { controller = "Blog", action = "Article" });
    endpoints.MapControllerRoute(name: "default",
                pattern: "{controller=Home}/{action=Index}/{id?}");
});

Az útvonalnevek logikai nevet adnak az útvonalnak. A névvel ellátott útvonal használható AZ URL-cím létrehozásához. A névvel ellátott útvonalak használata egyszerűbbé teszi az URL-címek létrehozását, ha az útvonalak sorrendje megnehezítheti az URL-címek létrehozását. Az útvonalneveknek egyedi alkalmazásszintűnek kell lenniük.

Útvonalnevek:

  • Nincs hatással az URL-címek egyeztetésére vagy a kérések kezelésére.
  • Csak AZ URL-cím generálásához használhatók.

Az útvonalnév fogalma az útválasztásban IEndpointNameMetadata néven jelenik meg. Az útvonalnév és a végpont neve:

  • Felcserélhetők.
  • Hogy melyik kerül felhasználásra a dokumentációban és a kódban, az a leírt API-tól függ.

API-k attribútum alapú útválasztása REST

REST Az API-knak attribútumalapú útválasztással kell modelleznie az alkalmazás funkcióit olyan erőforrások készleteként, ahol a műveleteket HTTP-parancsok jelölik.

Az attribútum-útválasztás egy sor attribútum segítségével közvetlenül hozzárendeli a műveleteket az útvonal sablonokhoz. A következő StartUp.Configure kód jellemző egy REST API-ra, és a következő példában kerül felhasználásra:

public void ConfigureServices(IServiceCollection services)
{
    services.AddControllers();
}

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    if (env.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
    }

    app.UseHttpsRedirection();

    app.UseRouting();

    app.UseAuthorization();

    app.UseEndpoints(endpoints =>
    {
        endpoints.MapControllers();
    });
}

Az előző kódban az MapControllers hívódik meg a UseEndpoints belsejében az attribútumalapú vezérlők leképezéséhez.

Az alábbi példában:

  • HomeController egyezik az alapértelmezett hagyományos útvonalhoz {controller=Home}/{action=Index}/{id?} hasonló URL-címekkel.
public class HomeController : Controller
{
    [Route("")]
    [Route("Home")]
    [Route("Home/Index")]
    [Route("Home/Index/{id?}")]
    public IActionResult Index(int? id)
    {
        return ControllerContext.MyDisplayRouteInfo(id);
    }

    [Route("Home/About")]
    [Route("Home/About/{id?}")]
    public IActionResult About(int? id)
    {
        return ControllerContext.MyDisplayRouteInfo(id);
    }
}

A HomeController.Index művelet az URL-címek //Homebármelyikén fut, /Home/Indexvagy /Home/Index/3.

Ez a példa kiemeli az attribútum-útválasztás és a hagyományos útválasztás közötti kulcsfontosságú programozási különbséget. Az attribútum-útválasztáshoz több bemenetre van szükség az útvonal megadásához. A hagyományos alapértelmezett útvonal tömörebben kezeli az útvonalakat. Az attribútumalapú útválasztás azonban lehetővé teszi és megköveteli annak pontos szabályozását, hogy mely útvonalsablonok vonatkozzanak az egyes műveletekre.

Attribútum alapú útválasztás esetén a vezérlő és az akciónevek nem játszanak szerepet az akció egyeztetésében, kivéve, ha kivonatcsere történik. Az alábbi példa megegyezik az előző példával megegyező URL-címekkel:

public class MyDemoController : Controller
{
    [Route("")]
    [Route("Home")]
    [Route("Home/Index")]
    [Route("Home/Index/{id?}")]
    public IActionResult MyIndex(int? id)
    {
        return ControllerContext.MyDisplayRouteInfo(id);
    }

    [Route("Home/About")]
    [Route("Home/About/{id?}")]
    public IActionResult MyAbout(int? id)
    {
        return ControllerContext.MyDisplayRouteInfo(id);
    }
}

Az alábbi kód token helyettesítést alkalmaz a action és a controller esetében:

public class HomeController : Controller
{
    [Route("")]
    [Route("Home")]
    [Route("[controller]/[action]")]
    public IActionResult Index()
    {
        return ControllerContext.MyDisplayRouteInfo();
    }

    [Route("[controller]/[action]")]
    public IActionResult About()
    {
        return ControllerContext.MyDisplayRouteInfo();
    }
}

A vezérlőre a következő kód vonatkozik [Route("[controller]/[action]")] :

[Route("[controller]/[action]")]
public class HomeController : Controller
{
    [Route("~/")]
    [Route("/Home")]
    [Route("~/Home/Index")]
    public IActionResult Index()
    {
        return ControllerContext.MyDisplayRouteInfo();
    }

    public IActionResult About()
    {
        return ControllerContext.MyDisplayRouteInfo();
    }
}

Az előző kódban a Index metódussablonok előtt el kell helyezni a / vagy ~/ útvonalsablonokat. Olyan műveletre alkalmazott útvonalsablonok, amelyek a vezérlőre alkalmazott útvonalsablonokkal kezdődnek / vagy ~/ nem kombinálódnak.

Az útvonalsablon kiválasztásával kapcsolatos információkért tekintse meg az Útvonalsablon elsőbbsége című témakört.

Fenntartott útválasztási nevek

A következő kulcsszavak fenntartott útvonalparaméternevek a vezérlők vagy Razor lapok használatakor:

  • action
  • area
  • controller
  • handler
  • page

Az attribútumalapú útválasztással rendelkező útvonalparaméter használata page gyakori hiba. Ez inkonzisztens és zavaró viselkedést eredményez az URL-generálással.

public class MyDemo2Controller : Controller
{
    [Route("/articles/{page}")]
    public IActionResult ListArticles(int page)
    {
        return ControllerContext.MyDisplayRouteInfo(page);
    }
}

Az URL-generáció a speciális paraméterneveket használja annak megállapítására, hogy egy URL-létrehozási művelet egy lapra vagy egy Razor vezérlőre hivatkozik-e.

A következő kulcsszavak egy Razor nézet vagy egy Razor oldal kontextusában vannak fenntartva.

  • page
  • using
  • namespace
  • inject
  • section
  • inherits
  • model
  • addTagHelper
  • removeTagHelper

Ezeket a kulcsszavakat nem szabad hivatkozásgenerációkhoz, modellhez kötött paraméterekhez vagy legfelső szintű tulajdonságokhoz használni.

HTTP-parancssablonok

ASP.NET Core a következő HTTP-igesablonokkal rendelkezik:

Útvonalsablonok

ASP.NET Core a következő útvonalsablonokkal rendelkezik:

Attribútum-útválasztás Http ige attribútumokkal

Vegye figyelembe a következő vezérlőt:

[Route("api/[controller]")]
[ApiController]
public class Test2Controller : ControllerBase
{
    [HttpGet]   // GET /api/test2
    public IActionResult ListProducts()
    {
        return ControllerContext.MyDisplayRouteInfo();
    }

    [HttpGet("{id}")]   // GET /api/test2/xyz
    public IActionResult GetProduct(string id)
    {
       return ControllerContext.MyDisplayRouteInfo(id);
    }

    [HttpGet("int/{id:int}")] // GET /api/test2/int/3
    public IActionResult GetIntProduct(int id)
    {
        return ControllerContext.MyDisplayRouteInfo(id);
    }

    [HttpGet("int2/{id}")]  // GET /api/test2/int2/3
    public IActionResult GetInt2Product(int id)
    {
        return ControllerContext.MyDisplayRouteInfo(id);
    }
}

Az előző kódban:

  • Minden művelet tartalmazza az [HttpGet] attribútumot, amely csak a HTTP GET-kérelmeknek való megfelelést korlátozza.
  • A GetProduct művelet tartalmazza a "{id}" sablont, ezért id hozzá van fűzve a "api/[controller]" sablonhoz a vezérlőn. A metódussablon a következő "api/[controller]/{id}": . Ezért ez a művelet csak az űrlap /api/test2/xyz GET kéréseinek felel meg, /api/test2/123, /api/test2/{any string}, stb.
    [HttpGet("{id}")]   // GET /api/test2/xyz
    public IActionResult GetProduct(string id)
    {
       return ControllerContext.MyDisplayRouteInfo(id);
    }
    
  • A GetIntProduct művelet tartalmazza a sablont "int/{id:int}" . A :int sablon része az id útvonalértékeket egész számmá konvertálható sztringekre korlátozza. GET kérés a következőhöz /api/test2/int/abc:
    • Nem egyezik ezzel a művelettel.
    • 404 Nem található hibát ad vissza.
      [HttpGet("int/{id:int}")] // GET /api/test2/int/3
      public IActionResult GetIntProduct(int id)
      {
          return ControllerContext.MyDisplayRouteInfo(id);
      }
      
  • A GetInt2Product művelet tartalmazza a sablonban {id} , de nem korlátozza id azokra az értékekre, amelyeket egész számmá lehet konvertálni. GET kérés a következőhöz /api/test2/int2/abc:
    • Megfelel ennek az útvonalnak.
    • A modellkötés nem konvertálható abc egész számmá. A id metódus paramétere egész szám.
    • 400-os hibás kérést ad vissza, mert a modellkötést nem sikerült egész számmá alakítaniabc.
      [HttpGet("int2/{id}")]  // GET /api/test2/int2/3
      public IActionResult GetInt2Product(int id)
      {
          return ControllerContext.MyDisplayRouteInfo(id);
      }
      

Az attribútum-útválasztás olyan attribútumokat használhat, mint az HttpMethodAttribute, HttpPostAttribute, HttpPutAttribute és HttpDeleteAttribute. Az összes HTTP-igeattribútum elfogad egy útvonalsablont. Az alábbi példa két olyan műveletet mutat be, amelyek azonos útvonalsablonnak felelnek meg:

[ApiController]
public class MyProductsController : ControllerBase
{
    [HttpGet("/products3")]
    public IActionResult ListProducts()
    {
        return ControllerContext.MyDisplayRouteInfo();
    }

    [HttpPost("/products3")]
    public IActionResult CreateProduct(MyProduct myProduct)
    {
        return ControllerContext.MyDisplayRouteInfo(myProduct.Name);
    }
}

Az URL-elérési út /products3használata:

  • A MyProductsController.ListProducts művelet akkor fut, ha a HTTP-igeGET.
  • A MyProductsController.CreateProduct művelet akkor fut, ha a HTTP-igePOST.

API-k készítésekor ritka, hogy egy metóduson használnia kell REST, mert a metódus minden HTTP-metódust elfogad. Érdemes a pontosabb HTTP használati attribútumot használni, hogy egyértelműen jelezze, mit támogat az API. REST Az API-k ügyfeleinek várhatóan tudniuk kell, hogy milyen elérési utak és HTTP-igék vannak leképezve adott logikai műveletekre.

REST Az API-knak attribútumalapú útválasztással kell modelleznie az alkalmazás funkcióit olyan erőforrások készleteként, ahol a műveleteket HTTP-parancsok jelölik. Ez azt jelenti, hogy számos művelet, például a GET és a POST ugyanazon a logikai erőforráson ugyanazt az URL-címet használja. Az attribútum-útválasztás olyan szintű vezérlést biztosít, amely az API nyilvános végpontelrendezésének gondos tervezéséhez szükséges.

Mivel az attribútumútvonalak egy adott műveletre vonatkoznak, az útvonalsablon definíciójának részeként könnyen megkövetelhetőek a paraméterek. A következő példában id az URL-elérési út részeként szükséges:

[ApiController]
public class Products2ApiController : ControllerBase
{
    [HttpGet("/products2/{id}", Name = "Products_List")]
    public IActionResult GetProduct(int id)
    {
        return ControllerContext.MyDisplayRouteInfo(id);
    }
}

A Products2ApiController.GetProduct(int) művelet:

  • Olyan URL-címmel futtatható, mint /products2/3
  • Az URL-cím elérési útvonalával /products2 nincs futtatva.

A [Felhasználás] attribútum lehetővé teszi, hogy egy művelet korlátozza a támogatott kérelem tartalomtípusait. További információ: Támogatott kérések tartalomtípusainak definiálása az Consumes attribútummal.

Az útvonalsablonok és a kapcsolódó beállítások teljes leírását az Útválasztás című témakörben talál.

További információ: [ApiController]ApiController attribútum.

Útvonal neve

Az alábbi kód a következő útvonalnevet Products_Listhatározza meg:

[ApiController]
public class Products2ApiController : ControllerBase
{
    [HttpGet("/products2/{id}", Name = "Products_List")]
    public IActionResult GetProduct(int id)
    {
        return ControllerContext.MyDisplayRouteInfo(id);
    }
}

Az útvonalnevek egy adott útvonalon alapuló URL-cím létrehozásához használhatók. Útvonalnevek:

  • Nincs hatással az útválasztás URL-címmegfeleltetési viselkedésére.
  • Csak URL-címek létrehozására használatos.

Az útvonalneveknek alkalmazásszintű egyedinek kell lenniük.

Határozd szembe az előző kódot a hagyományos alapértelmezett útvonallal, amely a id paramétert opcionálisként ({id?}) határozza meg. Az API-k pontos meghatározásának lehetősége előnyökkel jár, mint például az, hogy a /products és /products/5 különböző műveletekhez való továbbítását lehetővé teszi.

Attribútumútvonalak kombinálása

Az attribútum-útválasztás kevésbé ismétlődővé tétele érdekében a vezérlő útvonalattribútumait a rendszer az egyes műveletek útvonalattribútumaival kombinálja. A vezérlőben definiált útvonalsablonok előre fel vannak függve a műveletek útvonalsablonjaira. Ha egy útvonalattribútumot helyez el a vezérlőn, a vezérlőben lévő összes művelet attribútumalapú útválasztást használ.

[ApiController]
[Route("products")]
public class ProductsApiController : ControllerBase
{
    [HttpGet]
    public IActionResult ListProducts()
    {
        return ControllerContext.MyDisplayRouteInfo();
    }

    [HttpGet("{id}")]
    public IActionResult GetProduct(int id)
    {
        return ControllerContext.MyDisplayRouteInfo(id);
    }
}

Az előző példában:

  • Az URL-cím megegyezhet /productsProductsApi.ListProducts
  • Az URL-cím megegyezhet /products/5ProductsApi.GetProduct(int).

Mindkét művelet csak a HTTP-nek GET felel meg, mert az [HttpGet] attribútummal vannak megjelölve.

Olyan műveletre alkalmazott útvonalsablonok, amelyek a vezérlőre alkalmazott útvonalsablonokkal kezdődnek / vagy ~/ nem kombinálódnak. Az alábbi példa az alapértelmezett útvonalhoz hasonló URL-útvonalakat tartalmaz.

[Route("Home")]
public class HomeController : Controller
{
    [Route("")]
    [Route("Index")]
    [Route("/")]
    public IActionResult Index()
    {
        return ControllerContext.MyDisplayRouteInfo();
    }

    [Route("About")]
    public IActionResult About()
    {
        return ControllerContext.MyDisplayRouteInfo();
    }
}

Az alábbi táblázat az [Route] előző kód attribútumait ismerteti:

Attribute Kombinálva [Route("Home")]-vel Útvonalsablon definiálása
[Route("")] Yes "Home"
[Route("Index")] Yes "Home/Index"
[Route("/")] No ""
[Route("About")] Yes "Home/About"

Attribútumútvonal sorrendje

Az útválasztás létrehoz egy fát, és az összes végpontot egyidejűleg összekapcsolja.

  • Az útvonalbejegyzések úgy viselkednek, mintha ideális sorrendbe helyezték volna.
  • A legspecifikusabb útvonalak az általánosabb útvonalak előtt hajthatók végre.

Például egy attribútumútvonal blog/search/{topic} pontosabb, mint egy attribútumútvonal, például blog/{*article}. Az blog/search/{topic} útvonal alapértelmezés szerint magasabb prioritással rendelkezik, mert pontosabb. A hagyományos útválasztás használatával a fejlesztő felelős az útvonalak kívánt sorrendbe helyezéséért.

Az attribútumútvonalak konfigurálhatják a rendelést a Order tulajdonság használatával. Az összes keretrendszer által biztosított útvonalattribútum tartalmazza . Az útvonalak feldolgozása a Order tulajdonság növekvő sorrendje szerint történik. Az alapértelmezett sorrend a következő 0: . Az útvonal beállítása a Order = -1 használatával azok előtt történik meg, amelyek nem rendelkeznek sorrenddel. Az útvonal beállítása a(z) Order = 1 használatával az alapértelmezett útvonalrendezés után történik.

Kerülje a függést . Ha egy alkalmazás URL-címe explicit rendelési értékeket igényel a helyes útválasztáshoz, az valószínűleg az ügyfelek számára is zavaró. Az attribútum-útválasztás általában a megfelelő útvonalat választja ki URL-egyezéssel. Ha az URL-létrehozáshoz használt alapértelmezett sorrend nem működik, az útvonalnév felülbírálásként való használata általában egyszerűbb, mint a Order tulajdonság alkalmazása.

Vegye figyelembe az alábbi két vezérlőt, amelyek mindkettő az útvonalegyezést /homehatározzák meg:

public class HomeController : Controller
{
    [Route("")]
    [Route("Home")]
    [Route("Home/Index")]
    [Route("Home/Index/{id?}")]
    public IActionResult Index(int? id)
    {
        return ControllerContext.MyDisplayRouteInfo(id);
    }

    [Route("Home/About")]
    [Route("Home/About/{id?}")]
    public IActionResult About(int? id)
    {
        return ControllerContext.MyDisplayRouteInfo(id);
    }
}
public class MyDemoController : Controller
{
    [Route("")]
    [Route("Home")]
    [Route("Home/Index")]
    [Route("Home/Index/{id?}")]
    public IActionResult MyIndex(int? id)
    {
        return ControllerContext.MyDisplayRouteInfo(id);
    }

    [Route("Home/About")]
    [Route("Home/About/{id?}")]
    public IActionResult MyAbout(int? id)
    {
        return ControllerContext.MyDisplayRouteInfo(id);
    }
}

Az előző kóddal való kérés /home a következőhöz hasonló kivételt eredményez:

AmbiguousMatchException: The request matched multiple endpoints. Matches:

 WebMvcRouting.Controllers.HomeController.Index
 WebMvcRouting.Controllers.MyDemoController.MyIndex

Az útvonalattribútumok egyikének hozzáadása Order feloldja a kétértelműséget:

[Route("")]
[Route("Home", Order = 2)]
[Route("Home/MyIndex")]
public IActionResult MyIndex()
{
    return ControllerContext.MyDisplayRouteInfo();
}

Az előző kóddal /home futtatja a végpontot HomeController.Index . Az MyDemoController.MyIndex eléréséhez kérje /home/MyIndex. Note:

  • Az előző kód egy példa vagy rossz útválasztási terv. A Order a tulajdonság szemléltetésére szolgált.
  • A Order tulajdonság csak a kétértelműséget oldja fel, a sablon nem feleltethető meg. Jobb lenne eltávolítani a sablont [Route("Home")] .

Lásd aRazor Oldalak útvonal- és alkalmazáskonvencióit: Útvonal sorrend a Pages alkalmazással Razor kapcsolatos útvonal sorrend információkért.

Bizonyos esetekben egy HTTP 500-as hibát ad vissza, amikor útvonalak nem egyértelműek. A naplózás használatával megtekintheti, hogy mely végpontok okozták a AmbiguousMatchException.

Jogkivonat cseréje útvonalsablonokban [vezérlő], [művelet], [terület]

A kényelem érdekében az attribútumútvonalak támogatják a jogkivonatok cseréjét úgy, hogy szögletes zárójelekbe ([, ]) foglalnak egy jogkivonatot. A jogkivonatok [action], [area] és [controller] a műveletnév, a területnév és a vezérlő nevének értékeire cserélődnek a műveletből, ahol az útvonal definiálva van.

[Route("[controller]/[action]")]
public class Products0Controller : Controller
{
    [HttpGet]
    public IActionResult List()
    {
        return ControllerContext.MyDisplayRouteInfo();
    }


    [HttpGet("{id}")]
    public IActionResult Edit(int id)
    {
        return ControllerContext.MyDisplayRouteInfo(id);
    }
}

Az előző kódban:

[HttpGet]
public IActionResult List()
{
    return ControllerContext.MyDisplayRouteInfo();
}
  • Mérkőzések /Products0/List
[HttpGet("{id}")]
public IActionResult Edit(int id)
{
    return ControllerContext.MyDisplayRouteInfo(id);
}
  • Mérkőzések /Products0/Edit/{id}

A token cseréje az attribute útvonalak építésének utolsó lépése. Az előző példa ugyanúgy viselkedik, mint a következő kód:

public class Products20Controller : Controller
{
    [HttpGet("[controller]/[action]")]  // Matches '/Products20/List'
    public IActionResult List()
    {
        return ControllerContext.MyDisplayRouteInfo();
    }

    [HttpGet("[controller]/[action]/{id}")]   // Matches '/Products20/Edit/{id}'
    public IActionResult Edit(int id)
    {
        return ControllerContext.MyDisplayRouteInfo(id);
    }
}

Ha ezt nem angol nyelven olvassa, ebben a GitHub-vitafórumban tudassa velünk, ha meg szeretné tekinteni a kód megjegyzéseit az anyanyelvén.

Az attribútumútvonalak örökléssel is kombinálhatók. Ez a tokencserével kombinálva erős. A jelölő cseréje az attribútum útvonalak által definiált útvonalnevekre is vonatkozik. [Route("[controller]/[action]", Name="[controller]_[action]")]minden művelethez létrehoz egy egyedi útvonalnevet:

[ApiController]
[Route("api/[controller]/[action]", Name = "[controller]_[action]")]
public abstract class MyBase2Controller : ControllerBase
{
}

public class Products11Controller : MyBase2Controller
{
    [HttpGet]                      // /api/products11/list
    public IActionResult List()
    {
        return ControllerContext.MyDisplayRouteInfo();
    }

    [HttpGet("{id}")]             //    /api/products11/edit/3
    public IActionResult Edit(int id)
    {
        return ControllerContext.MyDisplayRouteInfo(id);
    }
}

A [ vagy ] literális token helyettesítő elválasztójának megadásához ismételje meg a karaktert ([[ vagy ]]) a kilépéshez.

Paraméterátalakító használata a tokenek cseréjének testreszabásához

A tokencsere paraméterátalakítóval testre szabható. A paraméterátalakító implementálja IOutboundParameterTransformer és átalakítja a paraméterek értékét. Egy egyéni SlugifyParameterTransformer paraméterátalakító például a következőre módosítja az SubscriptionManagement útvonal értékét subscription-management:

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

A RouteTokenTransformerConvention egy olyan alkalmazásmodell-konvenció, amely:

  • Paraméterátalakítót alkalmaz az alkalmazás összes attribútumútvonalára.
  • A csere során testre szabja az attribútumútvonal-jogkivonat értékeit.
public class SubscriptionManagementController : Controller
{
    [HttpGet("[controller]/[action]")]
    public IActionResult ListAll()
    {
        return ControllerContext.MyDisplayRouteInfo();
    }
}

Az előző ListAll metódus egyezik /subscription-management/list-all.

A RouteTokenTransformerConvention lehetőségként van regisztrálva a ConfigureServices rendszerben.

public void ConfigureServices(IServiceCollection services)
{
    services.AddControllersWithViews(options =>
    {
        options.Conventions.Add(new RouteTokenTransformerConvention(
                                     new SlugifyParameterTransformer()));
    });
}

A Slug definícióját a Slug MDN webes dokumentációja tartalmazza.

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.

Több attribútumútvonal

Az attribútumalapú útválasztás támogatja az azonos műveletet elérő útvonalak meghatározását. Ennek leggyakrabban az alapértelmezett hagyományos útvonal viselkedését kell utánoznia az alábbi példában látható módon:

[Route("[controller]")]
public class Products13Controller : Controller
{
    [Route("")]     // Matches 'Products13'
    [Route("Index")] // Matches 'Products13/Index'
    public IActionResult Index()
    {
        return ControllerContext.MyDisplayRouteInfo();
    }

Ha több útvonalattribútumot helyez el a vezérlőn, az azt jelenti, hogy mindegyik egyesül a műveleti módszerek útvonalattribútumaival:

[Route("Store")]
[Route("[controller]")]
public class Products6Controller : Controller
{
    [HttpPost("Buy")]       // Matches 'Products6/Buy' and 'Store/Buy'
    [HttpPost("Checkout")]  // Matches 'Products6/Checkout' and 'Store/Checkout'
    public IActionResult Buy()
    {
        return ControllerContext.MyDisplayRouteInfo();
    }
}

Az összes HTTP-igeútvonal-korlátozás implementálva IActionConstraintvan.

Ha több útvonalattribútum, amely implementálja IActionConstraint-t, kerül egy akcióra:

  • Minden műveletkényszer kombinálva van a vezérlőre alkalmazott útvonalsablonnal.
[Route("api/[controller]")]
public class Products7Controller : ControllerBase
{
    [HttpPut("Buy")]        // Matches PUT 'api/Products7/Buy'
    [HttpPost("Checkout")]  // Matches POST 'api/Products7/Checkout'
    public IActionResult Buy()
    {
        return ControllerContext.MyDisplayRouteInfo();
    }
}

Ha több útvonalat használ a műveletekhez, hasznosnak és hatékonynak tűnhet, jobb, ha az alkalmazás URL-címterét alapszintűen és jól definiálva tartja. Csak akkor használjon több útvonalat a műveleteken, ha szükséges, például a meglévő ügyfelek támogatására.

Attribútumútvonal opcionális paramétereinek, alapértelmezett értékeinek és kényszereinek megadása

Az attribútumútvonalak ugyanazt a beágyazott szintaxist támogatják, mint a hagyományos útvonalak, hogy opcionális paramétereket, alapértelmezett értékeket és korlátozásokat adjanak meg.

public class Products14Controller : Controller
{
    [HttpPost("product14/{id:int}")]
    public IActionResult ShowProduct(int id)
    {
        return ControllerContext.MyDisplayRouteInfo(id);
    }
}

Az előző kódban [HttpPost("product14/{id:int}")] alkalmaz egy útvonalkorlátozást. A Products14Controller.ShowProduct művelet csak azokkal az URL-címekkel egyezik meg, mint például /product14/3. Az útvonalsablon része {id:int} csak egész számokra korlátozza a szegmenst.

Az útvonalsablon szintaxisának részletes leírását az útvonalsablon-referencia című témakörben találja.

Egyéni útvonalattribútumok az IRouteTemplateProvider használatával

Az összes útvonalattribútumIRouteTemplateProvider-t implementál. A ASP.NET Core-futtatókörnyezet:

  • Attribútumokat keres a vezérlőosztályokon és a műveleti módszereken az alkalmazás indításakor.
  • A implementálandó IRouteTemplateProvider attribútumokkal hozza létre a kezdeti útvonalakat.

Egyéni útvonalattribútumok definiálásához implementálható IRouteTemplateProvider . Mindegyik IRouteTemplateProvider lehetővé teszi egyetlen útvonal egyéni útvonalsablon, sorrend és név megadását:

public class MyApiControllerAttribute : Attribute, IRouteTemplateProvider
{
    public string Template => "api/[controller]";
    public int? Order => 2;
    public string Name { get; set; }
}

[MyApiController]
[ApiController]
public class MyTestApiController : ControllerBase
{
    // GET /api/MyTestApi
    [HttpGet]
    public IActionResult Get()
    {
        return ControllerContext.MyDisplayRouteInfo();
    }
}

Az előző Get metódus ad vissza Order = 2, Template = api/MyTestApi.

Attribútumútvonalak testreszabása alkalmazásmodell használatával

Az alkalmazásmodell:

  • Az indításkor létrehozott objektummodell.
  • Az ASP.NET Core által az alkalmazásokban végzett műveletek irányításához és végrehajtásához használt összes metaadatot tartalmazza.

Az alkalmazásmodell tartalmazza az útvonalattribútumokból összegyűjtött összes adatot. Az útvonalattribútumokból származó adatokat a IRouteTemplateProvider megvalósítás biztosítja. Conventions:

  • Meg lehet írni az alkalmazás modelljét úgy, hogy az útválasztás viselkedése testreszabható legyen.
  • Az alkalmazás indításakor kerülnek beolvasásra.

Ez a szakasz egy egyszerű példát mutat be az útválasztás alkalmazásmodell használatával történő testreszabására. Az alábbi kód hozzávetőlegesen igazodik a projekt mappastruktúrájához.

public class NamespaceRoutingConvention : Attribute, IControllerModelConvention
{
    private readonly string _baseNamespace;

    public NamespaceRoutingConvention(string baseNamespace)
    {
        _baseNamespace = baseNamespace;
    }

    public void Apply(ControllerModel controller)
    {
        var hasRouteAttributes = controller.Selectors.Any(selector =>
                                                selector.AttributeRouteModel != null);
        if (hasRouteAttributes)
        {
            return;
        }

        var namespc = controller.ControllerType.Namespace;
        if (namespc == null)
            return;
        var template = new StringBuilder();
        template.Append(namespc, _baseNamespace.Length + 1,
                        namespc.Length - _baseNamespace.Length - 1);
        template.Replace('.', '/');
        template.Append("/[controller]/[action]/{id?}");

        foreach (var selector in controller.Selectors)
        {
            selector.AttributeRouteModel = new AttributeRouteModel()
            {
                Template = template.ToString()
            };
        }
    }
}

Az alábbi kód megakadályozza, hogy a namespace konvenció az attribútummal ellátott vezérlőkre vonatkozzon.

public void Apply(ControllerModel controller)
{
    var hasRouteAttributes = controller.Selectors.Any(selector =>
                                            selector.AttributeRouteModel != null);
    if (hasRouteAttributes)
    {
        return;
    }

A következő vezérlő például nem használja a NamespaceRoutingConvention jelet:

[Route("[controller]/[action]/{id?}")]
public class ManagersController : Controller
{
    // /managers/index
    public IActionResult Index()
    {
        var template = ControllerContext.ActionDescriptor.AttributeRouteInfo?.Template;
        return Content($"Index- template:{template}");
    }

    public IActionResult List(int? id)
    {
        var path = Request.Path.Value;
        return Content($"List- Path:{path}");
    }
}

A NamespaceRoutingConvention.Apply módszer:

  • Nem tesz semmit, ha a vezérlő attribútum-alapú útvonalakat használ.
  • Beállítja a vezérlősablont az namespace alapján, az namespace alap eltávolításával.

A NamespaceRoutingConvention következő helyen Startup.ConfigureServicesalkalmazható:

namespace My.Application
{
    public class Startup
    {
        public Startup(IConfiguration configuration)
        {
            Configuration = configuration;
        }

        public IConfiguration Configuration { get; }

        public void ConfigureServices(IServiceCollection services)
        {
            services.AddControllersWithViews(options =>
            {
                options.Conventions.Add(
                    new NamespaceRoutingConvention(typeof(Startup).Namespace));
            });
        }
        // Remaining code ommitted for brevity.

Vegyük például a következő vezérlőt:

using Microsoft.AspNetCore.Mvc;

namespace My.Application.Admin.Controllers
{
    public class UsersController : Controller
    {
        // GET /admin/controllers/users/index
        public IActionResult Index()
        {
            var fullname = typeof(UsersController).FullName;
            var template = 
                ControllerContext.ActionDescriptor.AttributeRouteInfo?.Template;
            var path = Request.Path.Value;

            return Content($"Path: {path} fullname: {fullname}  template:{template}");
        }

        public IActionResult List(int? id)
        {
            var path = Request.Path.Value;
            return Content($"Path: {path} ID:{id}");
        }
    }
}

Az előző kódban:

  • Az alap namespace a .My.Application
  • Az előző vezérlő teljes neve .My.Application.Admin.Controllers.UsersController
  • A NamespaceRoutingConvention a vezérlősablont Admin/Controllers/Users/[action]/{id?-ra állítja be.

A NamespaceRoutingConvention vezérlők attribútumaként is alkalmazhatók:

[NamespaceRoutingConvention("My.Application")]
public class TestController : Controller
{
    // /admin/controllers/test/index
    public IActionResult Index()
    {
        var template = ControllerContext.ActionDescriptor.AttributeRouteInfo?.Template;
        var actionname = ControllerContext.ActionDescriptor.ActionName;
        return Content($"Action- {actionname} template:{template}");
    }

    public IActionResult List(int? id)
    {
        var path = Request.Path.Value;
        return Content($"List- Path:{path}");
    }
}

Vegyes útválasztás: Attribútum-útválasztás és hagyományos útválasztás

ASP.NET Core-alkalmazások vegyesen használhatják a hagyományos útválasztást és az attribútumalapú útválasztást. Általában hagyományos útvonalakat használnak a böngészők html lapjait kiszolgáló vezérlőkhöz, az API-kat kiszolgáló REST vezérlők attribútum-útválasztásához.

A műveletek vagy hagyományos útvonalra vannak állítva, vagy attribútumok alapján vannak irányítva. Ha egy útvonalat helyez el a vezérlőn vagy a műveleten, az attribútum átirányítva lesz. Az attribútumútvonalakat meghatározó műveletek nem érhetőek el a hagyományos útvonalakon keresztül, és fordítva. A vezérlő bármely útvonalattribútuma a vezérlő attribútumában található összes műveletet átirányítja.

Az attribútum-útválasztás és a hagyományos útválasztás ugyanazt az útválasztási motort használja.

URL-létrehozási és környezeti értékek

Az alkalmazások útválasztási URL-címgenerálási funkciókkal hozhatnak létre URL-hivatkozásokat a műveletekhez. Az URL-címek létrehozása kiküszöböli a keménykódolási URL-címeket, így a kód robusztusabbá és karbantarthatóbbá válik. Ez a szakasz az MVC által biztosított URL-létrehozási funkciókra összpontosít, és csak az URL-létrehozás működésének alapjait ismerteti. Az URL-cím generálásának részletes leírását az Útválasztás című témakörben találja.

Az IUrlHelper interfész az MVC és az URL-generálás útválasztása közötti infrastruktúra mögöttes eleme. A IUrlHelper példány elérhető a Url tulajdonságon keresztül a vezérlőkben, nézetekben és nézetösszetevőkben.

Az alábbi példában a rendszer a tulajdonságon keresztül használja az IUrlHelperController.Url interfészt egy URL-cím létrehozásához egy másik művelethez.

public class UrlGenerationController : Controller
{
    public IActionResult Source()
    {
        // Generates /UrlGeneration/Destination
        var url = Url.Action("Destination");
        return ControllerContext.MyDisplayRouteInfo("", $" URL = {url}");
    }

    public IActionResult Destination()
    {
        return ControllerContext.MyDisplayRouteInfo();
    }
}

Ha az alkalmazás az alapértelmezett hagyományos útvonalat használja, a url változó értéke az URL-elérési út sztringje /UrlGeneration/Destination. Ez az URL-elérési út útválasztással van létrehozva az alábbiak kombinálásával:

  • Az aktuális kérés útvonalértékei, amelyeket környezeti értékeknek neveznek.
  • Az értékek átadása a Url.Action részére és azoknak az értékeknek a helyettesítése az útvonalsablonban:
ambient values: { controller = "UrlGeneration", action = "Source" }
values passed to Url.Action: { controller = "UrlGeneration", action = "Destination" }
route template: {controller}/{action}/{id?}

result: /UrlGeneration/Destination

Az útvonalsablonban minden útvonalparaméter értéke lecserélődik oly módon, hogy a nevek össze vannak párosítva a paraméterértékekkel és a környezeti értékekkel. Egy olyan útvonalparaméter, amely nem rendelkezik értékkel, a következőt teheti:

  • Használjon alapértelmezett értéket, ha rendelkezik ilyen értékkel.
  • Kihagyható, ha nem kötelező. Például az id útvonalsablonból {controller}/{action}/{id?}.

Az URL-cím létrehozása meghiúsul, ha a szükséges útvonalparaméter nem rendelkezik megfelelő értékkel. Ha egy útvonal URL-generálása sikertelen, a következő útvonal mindaddig próbálkozik, amíg az összes útvonal ki nem próbálva, vagy nem talál egyezést.

Az előző példa Url.Action a hagyományos útválasztást feltételezi. Az URL-generálás hasonlóan működik az attribútum-útválasztással, bár a fogalmak eltérnek. Hagyományos útválasztással:

  • Az útvonalértékek egy sablon kibontására szolgálnak.
  • A controller és action útvonalértékei általában megjelennek ebben a sablonban. Ez azért működik, mert az útválasztással egyező URL-címek megfelelnek egy konvenciónak.

Az alábbi példa attribútum-útválasztást használ:

public class UrlGenerationAttrController : Controller
{
    [HttpGet("custom")]
    public IActionResult Source()
    {
        var url = Url.Action("Destination");
        return ControllerContext.MyDisplayRouteInfo("", $" URL = {url}");
    }

    [HttpGet("custom/url/to/destination")]
    public IActionResult Destination()
    {
       return ControllerContext.MyDisplayRouteInfo();
    }
}

Az Source előző kódban szereplő művelet generálja a következőt custom/url/to/destination: .

LinkGenerator ASP.NET Core 3.0-ban lett hozzáadva IUrlHelper alternatívájaként. LinkGenerator hasonló, de rugalmasabb funkciókat kínál. Minden metódushoz IUrlHelper tartozik egy megfelelő metóduscsalád LinkGenerator is.

URL-címek létrehozása műveletnév alapján

Az URL.Action, a LinkGenerator.GetPathByAction és a kapcsolódó túlterhelések mindegyike úgy van kialakítva, hogy létrehozhassa a célvégpontot egy vezérlőnév és műveletnév megadásával.

Használat Url.Action esetén a futtatókörnyezet biztosítja a controller és action aktuális útvonalértékeit.

  • controller és action értéke mind a környezeti értékek, mind pedig az általános értékek része. A metódus Url.Action mindig az aktuális értékeket action használja, és controller létrehoz egy URL-útvonalat, amely az aktuális művelethez vezet.

Az útválasztás a környezeti értékek értékeit használja az URL-cím létrehozásakor nem megadott információk kitöltésére. Fontoljon meg egy útvonalat, mint például {a}/{b}/{c}/{d}, a környezeti értékekkel { a = Alice, b = Bob, c = Carol, d = David }.

  • Az útválasztás elegendő információval rendelkezik ahhoz, hogy további értékek nélkül hozzon létre URL-címet.
  • Az útválasztás elegendő információval rendelkezik, mert minden útvonalparaméternek van értéke.

Ha az érték { d = Donovan } hozzáadva van:

  • Az érték { d = David } figyelmen kívül lesz hagyva.
  • A létrehozott URL-elérési út a következő Alice/Bob/Carol/Donovan: .

Figyelmeztetés: Az URL-elérési utak hierarchikusak. Az előző példában, ha az érték { c = Cheryl } hozzá van adva:

  • A rendszer mindkét értéket { c = Carol, d = David } figyelmen kívül hagyja.
  • A d számára már nincs érték, ezért az URL-cím létrehozása meghiúsul.
  • Az URL-cím létrehozásához meg kell adni a kívánt értékeket c és d.

Előfordulhat, hogy az alapértelmezett útvonallal {controller}/{action}/{id?}kapcsolatos problémát tapasztalja. Ez a probléma a gyakorlatban ritkán fordul elő, mert Url.Action mindig explicit módon meghatározza a controller és action értéket.

Az Url.Action számos túlterhelése elfogad egy útvonali értékek objektumot, hogy más útvonalparaméterek értékeit adja meg, mint controller és action. A rendszer gyakran használja az útvonalérték-objektumot id. Például: Url.Action("Buy", "Products", new { id = 17 }). Az útvonalértékek objektuma:

  • Konvenció szerint általában névtelen típusú objektum.
  • Lehet egy IDictionary<> vagy POCO).

Az útvonalparamétereknek nem megfelelő további útvonalértékek a lekérdezési sztringbe kerülnek.

public IActionResult Index()
{
    var url = Url.Action("Buy", "Products", new { id = 17, color = "red" });
    return Content(url);
}

Az előző kód generálja a következőt /Products/Buy/17?color=red: .

A következő kód abszolút URL-címet hoz létre:

public IActionResult Index2()
{
    var url = Url.Action("Buy", "Products", new { id = 17 }, protocol: Request.Scheme);
    // Returns https://localhost:5001/Products/Buy/17
    return Content(url);
}

Abszolút URL-cím létrehozásához használja az alábbiak egyikét:

  • Egy túlterhelés, amely elfogadja a protocol. Például az előző kód.
  • LinkGenerator.GetUriByAction, amely alapértelmezés szerint abszolút URI-kat hoz létre.

URL-címek létrehozása útvonal szerint

Az előző kód bemutatta egy URL-cím létrehozását a vezérlő és a művelet név megadásával. IUrlHelper Az Url.RouteUrl metóduscsaládot is tartalmazza. Ezek a metódusok hasonlóak az Url.Action metódushoz, de nem másolja az aktuális értékeket a action és controller az útvonalértékekhez. A leggyakoribb használat a Url.RouteUrl a következő:

  • Megadja az URL-cím létrehozásához tartozó útvonalnevet.
  • Általában nem ad meg vezérlőt vagy műveletnevet.
public class UrlGeneration2Controller : Controller
{
    [HttpGet("")]
    public IActionResult Source()
    {
        var url = Url.RouteUrl("Destination_Route");
        return ControllerContext.MyDisplayRouteInfo("", $" URL = {url}");
    }

    [HttpGet("custom/url/to/destination2", Name = "Destination_Route")]
    public IActionResult Destination()
    {
        return ControllerContext.MyDisplayRouteInfo();
    }

A következő Razor fájl létrehoz egy HTML-hivatkozást a Destination_Routekövetkezőre:

<h1>Test Links</h1>

<ul>
    <li><a href="@Url.RouteUrl("Destination_Route")">Test Destination_Route</a></li>
</ul>

URL-címek létrehozása HTML-ben és Razor

IHtmlHelper a HtmlHelper módszereket, a Html.BeginForm és a Html.ActionLink használja a megfelelő <form> és <a> elemek generálásához. Ezek a metódusok az URL.Action metódussal hoznak létre URL-címet, és hasonló argumentumokat fogadnak el. Az Url.RouteUrl társai HtmlHelper és Html.BeginRouteForm, amelyek hasonló funkciókkal rendelkeznek.

A TagHelpers URL-címeket hoz létre a form TagHelper és a <a> TagHelper használatával. Mindkét megvalósítás során IUrlHelper-et használnak. További információkért tekintse meg az űrlapok címkesegítőit .

A belső nézetekben a IUrlHelper tulajdonság révén érhető el minden olyan ad-hoc URL-generálás, amelyre a fentiek nem vonatkoznak.

URL-generálás a műveleteredményekben

Az előző példák bemutatták a IUrlHelper használatát a vezérlőben. A vezérlők leggyakoribb használata egy URL-cím létrehozása egy művelet eredményének részeként.

Az ControllerBase és Controller az alaposztályok kényelmi módszereket biztosítanak egy másik műveletre hivatkozó műveleti eredményekhez. Az egyik jellemző használat az átirányítás a felhasználói bemenet elfogadása után:

[HttpPost]
[ValidateAntiForgeryToken]
public IActionResult Edit(int id, Customer customer)
{
    if (ModelState.IsValid)
    {
        // Update DB with new details.
        ViewData["Message"] = $"Successful edit of customer {id}";
        return RedirectToAction("Index");
    }
    return View(customer);
}

Az olyan akció-eredmény gyári metódusok, mint a RedirectToAction és a CreatedAtAction, hasonló mintát követnek, mint a IUrlHelper metódusok.

Speciális eset dedikált hagyományos útvonalakhoz

A hagyományos útválasztás egy speciális útvonaldefiníciót, az úgynevezett dedikált hagyományos útvonalat használhat. A következő példában a névvel ellátott blog útvonal egy dedikált hagyományos útvonal:

app.UseEndpoints(endpoints =>
{
    endpoints.MapControllerRoute(name: "blog",
                pattern: "blog/{*article}",
                defaults: new { controller = "Blog", action = "Article" });
    endpoints.MapControllerRoute(name: "default",
                pattern: "{controller=Home}/{action=Index}/{id?}");
});

Az előző útvonaldefiníciók Url.Action("Index", "Home") használatával hozza létre az URL-címet / az default útvonal használatával, de miért? Előfordulhat, hogy az útvonalértékek { controller = Home, action = Index } elegendőek egy URL generálásához blog használatával, és az eredmény az lesz /blog?action=Index&controller=Home.

A dedikált hagyományos útvonalak az alapértelmezett értékek speciális viselkedésére támaszkodnak, amelyek nem rendelkeznek megfelelő útvonalparaméterrel, amely megakadályozza, hogy az útvonal túlságosan mohó legyen az URL-cím generálása során. Ebben az esetben az alapértelmezett értékek a következők { controller = Blog, action = Article }, és sem controller sem action nem jelenik meg útvonalparaméterként. Ha az útválasztás URL-címet generál, a megadott értékeknek meg kell egyeznie az alapértelmezett értékekkel. Az URL-cím létrehozása blog sikertelen, mert az értékek { controller = Home, action = Index } nem egyeznek { controller = Blog, action = Article }. Az útválasztás ezután visszatér default próbálkozásra, ami sikerrel jár.

Areas

A területek egy MVC-funkció, amellyel a kapcsolódó funkciók külön csoportba rendezhetőek:

  • Útválasztási névtér vezérlőműveletekhez.
  • A nézetek mappastruktúrája.

A területek használata lehetővé teszi, hogy az alkalmazások több, azonos nevű vezérlővel rendelkezzenek, feltéve, hogy különböző területekkel rendelkeznek. A területek használata hierarchiát hoz létre az útválasztás céljából egy másik útvonalparaméter hozzáadásával a area és controller elemekhez. Ez a szakasz azt ismerteti, hogyan lép kölcsönhatásba az útválasztás a területekkel. Részletekért lásd a Területek című témakört, ahol a területek nézetekkel való használatáról olvashat.

Az alábbi példa úgy konfigurálja az MVC-t, hogy az alapértelmezett hagyományos útvonalat és egy areaarea elnevezett Blogútvonalat használja:

app.UseEndpoints(endpoints =>
{
    endpoints.MapAreaControllerRoute("blog_route", "Blog",
        "Manage/{controller}/{action}/{id?}");
    endpoints.MapControllerRoute("default_route", "{controller}/{action}/{id?}");
});

Az előző kódban a MapAreaControllerRoute meghívásával létrehozzák a "blog_route". A második paraméter a "Blog"terület neve.

Ha egy URL-útvonalhoz hasonlót /Manage/Users/AddUser illeszt, az "blog_route" útvonal létrehozza az útvonalértékeket { area = Blog, controller = Users, action = AddUser }. Az area útvonal értékét a rendszer a következő alapértelmezett értékével areahozza létre: . A létrehozott MapAreaControllerRoute útvonal egyenértékű a következővel:

app.UseEndpoints(endpoints =>
{
    endpoints.MapControllerRoute("blog_route", "Manage/{controller}/{action}/{id?}",
        defaults: new { area = "Blog" }, constraints: new { area = "Blog" });
    endpoints.MapControllerRoute("default_route", "{controller}/{action}/{id?}");
});

MapAreaControllerRoute létrehoz egy útvonalat, amely az alapértelmezett értéket és a megadott területnév használatára vonatkozó area korlátozást is használja, ebben az esetben Blog. Az alapértelmezett érték biztosítja, hogy az útvonal mindig { area = Blog, ... }-t hoz létre, a kényszer megköveteli a { area = Blog, ... } értéket az URL generálásához.

A hagyományos útválasztás sorrendfüggő. Általánosságban elmondható, hogy a területekkel rendelkező útvonalakat korábban kell elhelyezni, mivel ezek pontosabbak, mint a terület nélküli útvonalak.

Az előző példában szereplő útvonalértékek { area = Blog, controller = Users, action = AddUser } a következő műveletnek felelnek meg:

using Microsoft.AspNetCore.Mvc;

namespace MyApp.Namespace1
{
    [Area("Blog")]
    public class UsersController : Controller
    {
        // GET /manage/users/adduser
        public IActionResult AddUser()
        {
            var area = ControllerContext.ActionDescriptor.RouteValues["area"];
            var actionName = ControllerContext.ActionDescriptor.ActionName;
            var controllerName = ControllerContext.ActionDescriptor.ControllerName;

            return Content($"area name:{area}" +
                $" controller:{controllerName}  action name: {actionName}");
        }        
    }
}

A [Terület] attribútum az, amely egy vezérlőt egy terület részeként jelöl. Ez a vezérlő a Blog környéken található. Az attribútummal nem rendelkező [Area] vezérlők nem tagjai egyik területnek sem, és nem egyeznek meg, ha az útvonal értékét útválasztás area biztosítja. Az alábbi példában csak az első vezérlő felelhet meg az útvonalértéknek { area = Blog, controller = Users, action = AddUser }.

using Microsoft.AspNetCore.Mvc;

namespace MyApp.Namespace1
{
    [Area("Blog")]
    public class UsersController : Controller
    {
        // GET /manage/users/adduser
        public IActionResult AddUser()
        {
            var area = ControllerContext.ActionDescriptor.RouteValues["area"];
            var actionName = ControllerContext.ActionDescriptor.ActionName;
            var controllerName = ControllerContext.ActionDescriptor.ControllerName;

            return Content($"area name:{area}" +
                $" controller:{controllerName}  action name: {actionName}");
        }        
    }
}
using Microsoft.AspNetCore.Mvc;

namespace MyApp.Namespace2
{
    // Matches { area = Zebra, controller = Users, action = AddUser }
    [Area("Zebra")]
    public class UsersController : Controller
    {
        // GET /zebra/users/adduser
        public IActionResult AddUser()
        {
            var area = ControllerContext.ActionDescriptor.RouteValues["area"];
            var actionName = ControllerContext.ActionDescriptor.ActionName;
            var controllerName = ControllerContext.ActionDescriptor.ControllerName;

            return Content($"area name:{area}" +
                $" controller:{controllerName}  action name: {actionName}");
        }        
    }
}
using Microsoft.AspNetCore.Mvc;

namespace MyApp.Namespace3
{
    // Matches { area = string.Empty, controller = Users, action = AddUser }
    // Matches { area = null, controller = Users, action = AddUser }
    // Matches { controller = Users, action = AddUser }
    public class UsersController : Controller
    {
        // GET /users/adduser
        public IActionResult AddUser()
        {
            var area = ControllerContext.ActionDescriptor.RouteValues["area"];
            var actionName = ControllerContext.ActionDescriptor.ActionName;
            var controllerName = ControllerContext.ActionDescriptor.ControllerName;

            return Content($"area name:{area}" +
                $" controller:{controllerName}  action name: {actionName}");
        }
    }
}

Az egyes vezérlők névtere itt látható a teljesség érdekében. Ha az előző vezérlők ugyanazt a névteret használták, fordítóhiba jön létre. Az osztálynévterek nincsenek hatással az MVC útválasztására.

Az első két vezérlő a területek tagjai, és csak akkor egyeznek meg, ha a megfelelő terület nevét az area útvonal értéke adja meg. A harmadik vezérlő nem tartozik egyetlen területhez sem, és csak akkor felel meg, ha az útválasztás nem ad meg értéket a area számára.

A nincs érték egyezés szempontjából az area érték hiánya ugyanaz, mintha a area érték null vagy üres sztring lenne.

Ha egy műveletet egy területen hajt végre, az útvonal értéke areakörnyezeti értékként érhető el az URL-generáláshoz használandó útválasztáshoz. Ez azt jelenti, hogy alapértelmezés szerint a területek ragadósak az URL-generáláshoz, ahogy azt az alábbi minta is mutatja.

app.UseEndpoints(endpoints =>
{
    endpoints.MapAreaControllerRoute(name: "duck_route", 
                                     areaName: "Duck",
                                     pattern: "Manage/{controller}/{action}/{id?}");
    endpoints.MapControllerRoute(name: "default",
                                 pattern: "Manage/{controller=Home}/{action=Index}/{id?}");
});
using Microsoft.AspNetCore.Mvc;

namespace MyApp.Namespace4
{
    [Area("Duck")]
    public class UsersController : Controller
    {
        // GET /Manage/users/GenerateURLInArea
        public IActionResult GenerateURLInArea()
        {
            // Uses the 'ambient' value of area.
            var url = Url.Action("Index", "Home");
            // Returns /Manage/Home/Index
            return Content(url);
        }

        // GET /Manage/users/GenerateURLOutsideOfArea
        public IActionResult GenerateURLOutsideOfArea()
        {
            // Uses the empty value for area.
            var url = Url.Action("Index", "Home", new { area = "" });
            // Returns /Manage
            return Content(url);
        }
    }
}

Az alábbi kód egy URL-címet hoz létre a következő címre /Zebra/Users/AddUser:

public class HomeController : Controller
{
    public IActionResult About()
    {
        var url = Url.Action("AddUser", "Users", new { Area = "Zebra" });
        return Content($"URL: {url}");
    }

Műveletdefiníció

A vezérlő nyilvános metódusai a NonAction attribútummal rendelkezők kivételével műveletek.

Mintakód

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