Sdílet prostřednictvím


Směrování na akce kontroleru v ASP.NET Core

Ryan Nowak, Kirk Larkin a Rick Anderson

Poznámka:

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

Upozorňující

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

Důležité

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

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

ASP.NET kontrolery Core používají middleware směrování, aby odpovídaly adresám URL příchozích požadavků a mapovaly je na akce. Šablony tras:

  • Jsou definovány při spuštění v Program.cs atributech nebo v atributech.
  • Popište, jak se cesty URL shodují s akcemi.
  • Slouží ke generování adres URL pro odkazy. Vygenerované odkazy se obvykle vrací v odpovědích.

Akce jsou buď obvykle směrovány, nebo jsou směrovány atributem. Když umístíte trasu na kontroler nebo akci , bude směrovaná atributem. Další informace najdete v tématu Smíšené směrování .

Tento dokument:

  • Vysvětluje interakce mezi MVC a směrováním:
  • Odkazuje na výchozí systém směrování označovaný jako směrování koncového bodu. Pro účely kompatibility je možné používat kontrolery s předchozí verzí směrování. Pokyny najdete v průvodci migrací verze 2.2-3.0.

Nastavení konvenční trasy

Šablona ASP.NET Core MVC generuje konvenční směrovací kód podobný následujícímu:

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 slouží k vytvoření jedné trasy. Jedna trasa má název default trasy. Většina aplikací s kontrolery a zobrazeními používá šablonu trasy podobnou default této trase. REST Rozhraní API by měla používat směrování atributů.

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

Šablona "{controller=Home}/{action=Index}/{id?}"trasy:

  • Odpovídá cestě URL, jako je /Products/Details/5

  • Extrahuje hodnoty { controller = Products, action = Details, id = 5 } trasy tokenizací cesty. Extrahování hodnot tras vede ke shodě, pokud má aplikace pojmenovaný kontroler ProductsController a Details akci:

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

    MyDisplayRouteInfo poskytuje balíček NuGet Rick.Docs.Samples.RouteInfo a zobrazí informace o trase.

  • /Products/Details/5 model sváže hodnotu id = 5 nastavení parametru id na 5. Další podrobnosti najdete v tématu Vazby modelu.

  • {controller=Home} definuje Home jako výchozí controller.

  • {action=Index} definuje Index jako výchozí action.

  • Znak ? v {id?} definici je id volitelný.

  • Odpovídá cestě /URL .

  • Vytvoří hodnoty { controller = Home, action = Index }trasy .

Hodnoty pro controller výchozí hodnoty a action jejich použití. id nevytvoří hodnotu, protože v cestě URL neexistuje žádný odpovídající segment. /odpovídá pouze v případě, že existuje nějaká HomeController akce:Index

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

Pomocí předchozí definice kontroleru a šablony trasy se HomeController.Index akce spustí pro následující cesty URL:

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

Cesta / URL používá výchozí Home kontrolery a Index akci šablony trasy. Cesta URL /Home používá výchozí Index akci šablony trasy.

Metoda MapDefaultControllerRoutepohodlí:

app.MapDefaultControllerRoute();

Nahrazuje:

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

Důležité

Směrování se konfiguruje pomocí middlewaruUseRouting.UseEndpoints Použití kontrolerů:

Aplikace obvykle nemusí volat UseRouting ani UseEndpoints. WebApplicationBuilder konfiguruje middlewarový kanál, který zabalí middleware přidaný do Program.cs UseRouting a UseEndpoints. Další informace najdete v tématu Směrování v ASP.NET Core.

Konvenční směrování

Konvenční směrování se používá s řadiči a zobrazeními. Trasa default :

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

Předchozí příklad je příkladem konvenční trasy. Říká se tomu konvenční směrování , protože vytváří konvenci pro cesty url:

  • První segment cesty , {controller=Home}mapuje na název kontroleru.
  • Druhý segment, {action=Index}, mapuje na název akce .
  • Třetí segment se používá pro volitelný id. {id?} Hodnota ? in {id?} je volitelná. id slouží k mapování na entitu modelu.

Pomocí této default trasy cesta URL:

  • /Products/List se mapuje na ProductsController.List akci.
  • /Blog/Article/17mapuje id a BlogController.Article obvykle model sváže parametr na 17.

Toto mapování:

  • Je založen pouze na názvech kontroleru a akcí.
  • Není založená na oborech názvů, umístěních zdrojových souborů nebo parametrech metody.

Použití konvenčního směrování s výchozí trasou umožňuje vytvořit aplikaci, aniž by bylo nutné pro každou akci vytvořit nový vzor adresy URL. U aplikace s akcemi stylu CRUD mají konzistenci adres URL napříč řadiči:

  • Pomáhá zjednodušit kód.
  • Zpřístupňuje uživatelské rozhraní předvídatelněji.

Upozorňující

V id předchozím kódu je definována jako volitelná šablona trasy. Akce se můžou spouštět bez volitelného ID zadaného jako součást adresy URL. Obecně platí, že pokud id je vynechán z adresy URL:

  • id je nastavena 0 vazbou modelu.
  • V porovnávání id == 0databáze nebyla nalezena žádná entita .

Směrování atributů poskytuje jemně odstupňované řízení, aby se ID vyžadovalo pro některé akce, a ne pro jiné. Podle konvence obsahuje dokumentace volitelné parametry, jako id když se pravděpodobně objeví ve správném použití.

Většina aplikací by měla zvolit základní a popisné schéma směrování, aby adresy URL byly čitelné a smysluplné. Výchozí konvenční trasa {controller=Home}/{action=Index}/{id?}:

  • Podporuje základní a popisné schéma směrování.
  • Je užitečný výchozí bod pro aplikace založené na uživatelském rozhraní.
  • Je jediná šablona trasy potřebná pro mnoho aplikací webového uživatelského rozhraní. U větších aplikací webového uživatelského rozhraní je další trasa využívající oblasti často všechna potřebná.

MapControllerRoute a MapAreaRoute :

  • Automaticky přiřaďte jejich koncovým bodům hodnotu objednávky na základě pořadí, ve které jsou vyvolány.

Směrování koncových bodů v ASP.NET Core:

  • Nemá koncept tras.
  • Neposkytuje záruky řazení pro provádění rozšiřitelnosti, všechny koncové body se zpracovávají najednou.

Povolte protokolování , abyste viděli, jak integrované implementace směrování, například Route, odpovídají požadavkům.

Směrování atributů je vysvětleno dále v tomto dokumentu.

Více konvenčních tras

Více konvenčních tras lze nakonfigurovat přidáním dalších volání do MapControllerRoute a MapAreaControllerRoute. To umožňuje definovat více konvencí nebo přidat konvenční trasy, které jsou vyhrazené pro konkrétní akci, například:

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

Trasa blog v předchozím kódu je vyhrazená konvenční trasa. Označuje se jako vyhrazená konvenční trasa, protože:

Vzhledem k tomu, controller že se action v šabloně "blog/{*article}" trasy nezobrazují jako parametry:

  • Mohou mít pouze výchozí hodnoty { controller = "Blog", action = "Article" }.
  • Tato trasa se vždy mapuje na akci BlogController.Article.

/Blog, /Blog/Articlea /Blog/{any-string} jsou jediné cesty URL, které odpovídají trase blogu.

Předchozí příklad:

  • blog trasa má vyšší prioritu default pro shody než trasa, protože je přidána jako první.
  • Je příkladem směrování stylu Slug , kde je typické mít název článku jako součást adresy URL.

Upozorňující

V ASP.NET Core směrování ne:

  • Definujte koncept označovaný jako trasa. UseRouting přidá trasu odpovídající kanálu middlewaru. Middleware UseRouting se podívá na sadu koncových bodů definovaných v aplikaci a vybere nejlepší shodu koncového bodu na základě požadavku.
  • Poskytovat záruky týkající se pořadí provádění rozšiřitelnosti, jako IRouteConstraint nebo IActionConstraint.

Viz Směrovací materiál pro směrování.

Konvenční pořadí směrování

Konvenční směrování odpovídá pouze kombinaci akce a kontroleru definované aplikací. Cílem je zjednodušit případy, kdy se běžné trasy překrývají. Přidání tras pomocí MapControllerRoutea MapDefaultControllerRouteMapAreaControllerRoute automatické přiřazení hodnoty objednávky ke svým koncovým bodům na základě pořadí, ve které jsou vyvolány. Shody z trasy, která se zobrazí dříve, mají vyšší prioritu. Konvenční směrování je závislé na pořadí. Obecně platí, že trasy s oblastmi by měly být umístěny dříve, protože jsou konkrétnější než trasy bez oblasti. Vyhrazené konvenční trasy s parametry trasy catch-all, jako {*article} je může vytvořit trasu příliš greedy, což znamená, že odpovídá adresám URL, které jste chtěli spárovat jinými trasami. Trasu greedy umístěte později do směrovací tabulky, aby se zabránilo shodám greedy.

Upozorňující

Parametr catch-all může nesprávně odpovídat trasám kvůli chybě při směrování. Aplikace ovlivněné touto chybou mají následující charakteristiky:

  • Například trasa pro zachytávání– vše {**slug}"
  • Trasa catch-all neodpovídá požadavkům, které by se měly shodovat.
  • Odebráním jiných tras začne fungovat zachytávání všech tras.

Podívejte se na chyby GitHubu 18677 a 16579 , například případy, které tuto chybu narazily.

Oprava výslovného souhlasu s touto chybou je obsažená v sadě .NET Core 3.1.301 SDK a novějších verzích. Následující kód nastaví interní přepínač, který tuto chybu opraví:

public static void Main(string[] args)
{
   AppContext.SetSwitch("Microsoft.AspNetCore.Routing.UseCorrectCatchAllBehavior", 
                         true);
   CreateHostBuilder(args).Build().Run();
}
// Remaining code removed for brevity.

Řešení nejednoznačných akcí

Když se dva koncové body shodují prostřednictvím směrování, musí směrování provést jednu z těchto věcí:

  • Vyberte nejlepšího kandidáta.
  • Vyvolá výjimku.

Příklad:

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

Předchozí kontroler definuje dvě akce, které odpovídají:

  • Cesta URL /Products33/Edit/17
  • Směrovat data { controller = Products33, action = Edit, id = 17 }.

Toto je typický vzor pro kontrolery MVC:

  • Edit(int) zobrazí formulář pro úpravu produktu.
  • Edit(int, Product) zpracuje vystavený formulář.

Řešení správné trasy:

  • Edit(int, Product) je vybrána, pokud je požadavek HTTP POST.
  • Edit(int) je vybrána, pokud je příkaz HTTP cokoli jiného. Edit(int) je obecně volána prostřednictvím GET.

, HttpPostAttribute[HttpPost]je poskytována pro směrování tak, aby mohl zvolit na základě metody HTTP požadavku. Edit(int, Product) Dělá HttpPostAttribute lepší shodu než Edit(int).

Je důležité pochopit roli atributů, jako HttpPostAttributeje . Podobné atributy jsou definovány pro jiné příkazy HTTP. U konvenčního směrování je běžné, že akce používají stejný název akce, když jsou součástí formuláře pro zobrazení a odesílají pracovní postup formuláře. Podívejte se například na prozkoumání dvou metod akce Upravit.

Pokud směrování nemůže zvolit nejlepšího kandidáta, vyvolá AmbiguousMatchException se výpis několika odpovídajících koncových bodů.

Konvenční názvy tras

Řetězce a "default" v následujících příkladech "blog" jsou konvenční názvy tras:

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

Názvy tras dávají této trase logický název. Pojmenovanou trasu lze použít pro generování adres URL. Použití pojmenované trasy zjednodušuje vytváření adres URL, když řazení tras může komplikovat generování adres URL. Názvy tras musí být jedinečné pro celou aplikaci.

Názvy tras:

  • Nemá žádný vliv na porovnávání adres URL ani zpracování požadavků.
  • Používají se jenom pro generování adres URL.

Koncept názvu trasy je reprezentován ve směrování jako IEndpointNameMetadata. Název trasy termínů a název koncového bodu:

  • Jsou zaměnitelné.
  • Který z nich se používá v dokumentaci a kódu, závisí na popsaném rozhraní API.

Směrování atributů pro REST rozhraní API

REST Rozhraní API by měla používat směrování atributů k modelování funkčnosti aplikace jako sady prostředků, ve kterých jsou operace reprezentovány příkazy HTTP.

Směrování atributů používá sadu atributů k mapování akcí přímo na šablony směrování. Následující kód je typický pro REST rozhraní API a používá se v další ukázce:

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddControllers();

var app = builder.Build();

app.UseHttpsRedirection();

app.UseAuthorization();

app.MapControllers();

app.Run();

V předchozím kódu se MapControllers volá k mapování směrovaných kontrolerů atributů.

V následujícím příkladu:

  • HomeController odpovídá sadě adres URL podobných výchozím běžným trasám {controller=Home}/{action=Index}/{id?} .
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);
    }
}

Akce HomeController.Index se spustí pro některou z cest /URL , /Home, /Home/Index, nebo /Home/Index/3.

Tento příklad zvýrazňuje klíčový programovací rozdíl mezi směrováním atributů a konvenčním směrováním. Směrování atributů vyžaduje k zadání trasy další vstup. Konvenční výchozí trasa zpracovává trasy rychleji. Směrování atributů však umožňuje a vyžaduje přesnou kontrolu nad tím, které šablony tras se vztahují na každou akci.

Při směrování atributů nehrají názvy kontroleru a akcí žádnou roli, ve které se akce shoduje, pokud se nepoužije nahrazení tokenu. Následující příklad odpovídá stejným adresám URL jako v předchozím příkladu:

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

Následující kód používá nahrazení tokenu pro action a controller:

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

Následující kód se vztahuje [Route("[controller]/[action]")] na kontroler:

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

V předchozím kódu Index musí šablony metod předcházet / nebo ~/ směrovat šablony. Směrovací šablony použité na akci, která začíná / nebo ~/ se nezkombinuje se šablonami tras použitými na kontroler.

Informace o výběru šablony trasy najdete v tématu Priorita šablony trasy.

Rezervované názvy směrování

Následující klíčová slova jsou vyhrazena názvy parametrů trasy při použití kontrolerů nebo Razor stránek:

  • action
  • area
  • controller
  • handler
  • page

Použití page jako parametru trasy se směrováním atributů je běžnou chybou. Výsledkem je nekonzistentní a matoucí chování při generování adresy URL.

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

Speciální názvy parametrů používají generování adresy URL k určení, jestli operace generování adresy URL odkazuje na Razor stránku nebo na kontroler.

Následující klíčová slova jsou vyhrazena v kontextu Razor zobrazení nebo Razor stránky:

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

Tato klíčová slova by se neměla používat pro generace propojení, parametry vázané na model ani vlastnosti nejvyšší úrovně.

Šablony příkazů HTTP

ASP.NET Core obsahuje následující šablony příkazů HTTP:

Šablony tras

ASP.NET Core má následující šablony tras:

Směrování atributů s atributy příkazů HTTP

Vezměte v úvahu následující kontroler:

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

V předchozím kódu:

  • Každá akce obsahuje [HttpGet] atribut, který omezuje pouze porovnávání požadavků HTTP GET.
  • Akce GetProduct obsahuje "{id}" šablonu, proto id je připojena k "api/[controller]" šabloně na kontroleru. Šablona metod je "api/[controller]/{id}". Tato akce proto odpovídá pouze požadavkům GET pro formulář /api/test2/xyz,/api/test2/123,/api/test2/{any string}, atd.
    [HttpGet("{id}")]   // GET /api/test2/xyz
    public IActionResult GetProduct(string id)
    {
       return ControllerContext.MyDisplayRouteInfo(id);
    }
    
  • Akce GetIntProduct obsahuje "int/{id:int}" šablonu. Část :int šablony omezuje směrovací id hodnoty na řetězce, které lze převést na celé číslo. Požadavek GET na /api/test2/int/abc:
    • Neodpovídá této akci.
    • Vrátí chybu 404 Nenalezena.
      [HttpGet("int/{id:int}")] // GET /api/test2/int/3
      public IActionResult GetIntProduct(int id)
      {
          return ControllerContext.MyDisplayRouteInfo(id);
      }
      
  • Akce GetInt2Product obsahuje {id} v šabloně, ale neomezuje id na hodnoty, které lze převést na celé číslo. Požadavek GET na /api/test2/int2/abc:
    • Odpovídá této trase.
    • Vazba modelu se nepodaří převést abc na celé číslo. Parametr id metody je celé číslo.
    • Vrátí chybu 400 Chybný požadavek , protože vazbu modelu se nepodařilo převést abc na celé číslo.
      [HttpGet("int2/{id}")]  // GET /api/test2/int2/3
      public IActionResult GetInt2Product(int id)
      {
          return ControllerContext.MyDisplayRouteInfo(id);
      }
      

Směrování atributů může používat HttpMethodAttribute atributy, jako HttpPostAttributeje , HttpPutAttributea HttpDeleteAttribute. Všechny atributy příkazu HTTP přijímají šablonu trasy. Následující příklad ukazuje dvě akce, které odpovídají stejné šabloně trasy:

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

Pomocí cesty /products3URL:

  • Akce MyProductsController.ListProducts se spustí, když je GETpříkaz HTTP .
  • Akce MyProductsController.CreateProduct se spustí, když je POSTpříkaz HTTP .

Při vytváření REST rozhraní API je vzácné, že budete muset použít [Route(...)] metodu akce, protože akce přijímá všechny metody HTTP. Lepší je použít konkrétnější atribut příkazu HTTP, aby byl přesný o tom, co vaše rozhraní API podporuje. REST Očekává se, že klienti rozhraní API vědí, jaké cesty a příkazy HTTP se mapují na konkrétní logické operace.

REST Rozhraní API by měla používat směrování atributů k modelování funkčnosti aplikace jako sady prostředků, ve kterých jsou operace reprezentovány příkazy HTTP. To znamená, že mnoho operací, například GET a POST ve stejném logickém prostředku, používá stejnou adresu URL. Směrování atributů poskytuje úroveň řízení, která je nutná k pečlivému návrhu rozložení veřejného koncového bodu rozhraní API.

Vzhledem k tomu, že trasa atributu se vztahuje na konkrétní akci, je snadné nastavit parametry vyžadované jako součást definice šablony trasy. V následujícím příkladu id se vyžaduje jako součást cesty URL:

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

Akce Products2ApiController.GetProduct(int) :

  • Spouští se s cestou URL, jako je /products2/3
  • Nejde spustit s cestou /products2URL .

Atribut [Consumes] umožňuje akci omezit podporované typy obsahu požadavku. Další informace najdete v tématu Definování podporovaných typů obsahu požadavku pomocí atributu Consumes.

Úplný popis šablon tras a souvisejících možností najdete v tématu Směrování .

Další informace o [ApiController], viz ApiController atribut.

Název trasy

Následující kód definuje název Products_Listtrasy:

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

Názvy tras se dají použít k vygenerování adresy URL na základě konkrétní trasy. Názvy tras:

  • Nemá žádný vliv na chování přiřazování adres URL směrování.
  • Používají se jenom pro generování adres URL.

Názvy tras musí být jedinečné pro celou aplikaci.

Porovnejte předchozí kód s konvenční výchozí trasou, která definuje id parametr jako volitelný ({id?}). Schopnost přesně specifikovat rozhraní API má výhody, jako je povolení /products a /products/5 odeslání do různých akcí.

Kombinování tras atributů

Aby směrování atributů bylo méně opakované, atributy směrování na kontroleru se zkombinují s atributy trasy u jednotlivých akcí. Všechny šablony tras definované v kontroleru jsou předem nastavené tak, aby směrovaly šablony akcí. Umístění atributu trasy na kontroler provede všechny akce ve směrování atributů kontroleru.

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

V předchozím příkladu:

  • Cesta /products url se může shodovat. ProductsApi.ListProducts
  • Cesta /products/5 url se může shodovat ProductsApi.GetProduct(int).

Obě tyto akce odpovídají protokolu HTTP GET , protože jsou označené atributem [HttpGet] .

Směrovací šablony použité na akci, která začíná / nebo ~/ se nezkombinuje se šablonami tras použitými na kontroler. Následující příklad odpovídá sadě cest URL podobných výchozí trase.

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

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

Následující tabulka vysvětluje [Route] atributy v předchozím kódu:

Atribut Kombinuje s [Route("Home")] Definuje šablonu trasy.
[Route("")] Ano "Home"
[Route("Index")] Ano "Home/Index"
[Route("/")] Ne ""
[Route("About")] Ano "Home/About"

Pořadí tras atributů

Směrování vytvoří strom a odpovídá všem koncovým bodům současně:

  • Položky trasy se chovají tak, jako by byly umístěny v ideálním pořadí.
  • Nejvýraznější trasy mají možnost spustit před obecnějšími trasami.

Například trasa atributu, jako blog/search/{topic} je konkrétnější než trasa atributu, jako blog/{*article}je . Trasa blog/search/{topic} má ve výchozím nastavení vyšší prioritu, protože je konkrétnější. Pomocí konvenčního směrování zodpovídá vývojář za umístění tras do požadovaného pořadí.

Trasy atributů můžou nakonfigurovat pořadí pomocí Order vlastnosti. Všechny atributy trasy poskytované architekturou zahrnují Order . Trasy se zpracovávají podle vzestupného řazení Order vlastnosti. Výchozí pořadí je 0. Nastavení trasy pomocí Order = -1 spuštění před trasami, které nenastavují pořadí Nastavení trasy pomocí Order = 1 spuštění po výchozím pořadí tras

Vyhněte se v závislosti na Order. Pokud prostor adres URL aplikace vyžaduje správné směrování explicitních hodnot objednávek, pravděpodobně je také matoucí pro klienty. Obecně platí, že směrování atributů vybere správnou trasu s odpovídající adresou URL. Pokud výchozí pořadí použité pro generování adresy URL nefunguje, použití názvu trasy jako přepsání je obvykle jednodušší než použití Order vlastnosti.

Vezměte v úvahu následující dva kontrolery, které definují porovnávání /hometras:

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

/home Požadavek s předchozím kódem vyvolá výjimku podobnou následující:

AmbiguousMatchException: The request matched multiple endpoints. Matches:

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

Přidání Order do jednoho z atributů trasy vyřeší nejednoznačnost:

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

S předchozím kódem /home spustí HomeController.Index koncový bod. Chcete-li se dostat k MyDemoController.MyIndexžádosti /home/MyIndex. Poznámka:

  • Předchozí kód je příkladem nebo špatným návrhem směrování. Byla použita k ilustraci Order vlastnosti.
  • Vlastnost Order přeloží pouze nejednoznačnost, kterou nelze shodovat. Bylo by lepší šablonu odebrat [Route("Home")] .

Viz Razor Zásady směrování stránek a aplikací: Pořadí tras pro informace o pořadí tras pomocí Razor stránek.

V některých případech se vrátí chyba HTTP 500 s nejednoznačnými trasami. Pomocí protokolování zjistíte, které koncové body způsobily AmbiguousMatchException.

Výměna tokenů v šablonách tras [kontroler], [akce], [oblast]

Pro usnadnění práce trasy atributů podporují nahrazení tokenu uzavřením tokenu do hranatých závorek ([, ]). Tokeny , [area]a [controller] jsou nahrazeny [action]hodnotami názvu akce, název oblasti a název kontroleru z akce, kde je trasa definována:

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

V předchozím kódu:

[HttpGet]
public IActionResult List()
{
    return ControllerContext.MyDisplayRouteInfo();
}
  • Zápasy /Products0/List
[HttpGet("{id}")]
public IActionResult Edit(int id)
{
    return ControllerContext.MyDisplayRouteInfo(id);
}
  • Zápasy /Products0/Edit/{id}

Nahrazení tokenu probíhá jako poslední krok sestavení tras atributů. Předchozí příklad se chová stejně jako následující 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);
    }
}

Pokud to čtete v jiném jazyce než v angličtině, dejte nám vědět v tomto problému s diskuzí na GitHubu, pokud chcete vidět komentáře ke kódu ve vašem nativním jazyce.

Trasy atributů lze také kombinovat s dědičností. Jedná se o výkonnou kombinaci s nahrazením tokenů. Nahrazení tokenu se vztahuje také na názvy tras definovaných trasami atributů. [Route("[controller]/[action]", Name="[controller]_[action]")]vygeneruje jedinečný název trasy pro každou akci:

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

Chcete-li se shodovat s oddělovačem [ nahrazení literálového tokenu nebo ]ho umistit opakováním znaku ([[ nebo ]]).

Přizpůsobení nahrazení tokenu pomocí transformátoru parametrů

Nahrazení tokenů lze přizpůsobit pomocí transformátoru parametrů. Transformátor parametrů implementuje IOutboundParameterTransformer a transformuje hodnotu parametrů. Například vlastní SlugifyParameterTransformer transformátor parametru SubscriptionManagement změní hodnotu trasy na 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();
    }
}

Jedná se RouteTokenTransformerConvention o konvenci modelu aplikace, která:

  • Použije transformátor parametrů na všechny trasy atributů v aplikaci.
  • Přizpůsobí hodnoty tokenu trasy atributu při jejich nahrazení.
public class SubscriptionManagementController : Controller
{
    [HttpGet("[controller]/[action]")]
    public IActionResult ListAll()
    {
        return ControllerContext.MyDisplayRouteInfo();
    }
}

Předchozí ListAll metoda odpovídá /subscription-management/list-all.

Tato RouteTokenTransformerConvention možnost je zaregistrovaná jako:

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

Definice Slug najdete ve webové dokumentaci MDN na Slug .

Upozorňující

Při zpracování System.Text.RegularExpressions nedůvěryhodného vstupu předejte vypršení časového limitu. Uživatel se zlými úmysly může poskytnout vstup, který RegularExpressions způsobí útok na dostupnost služby. ASP.NET rozhraní API architektury Core, která používají RegularExpressions vypršení časového limitu.

Více tras atributů

Směrování atributů podporuje definování více tras, které se dostanou ke stejné akci. Nejběžnějším použitím je napodobit chování výchozí konvenční trasy, jak je znázorněno v následujícím příkladu:

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

Umístění více atributů směrování na kontroler znamená, že každý z nich kombinuje s jednotlivými atributy trasy v metodách akce:

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

Implementují IActionConstraintse všechna omezení směrování příkazů HTTP .

Pokud je u akce umístěno více atributů trasy, které se implementují IActionConstraint :

  • Každé omezení akce kombinuje šablonu trasy použitou na kontroler.
[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();
    }
}

Použití více tras u akcí může vypadat jako užitečné a výkonné, je lepší zachovat základní a dobře definovaný prostor adres URL vaší aplikace. Pro akce používejte více tras pouze tam, kde je to potřeba, například pro podporu stávajících klientů.

Určení volitelných parametrů trasy atributů, výchozích hodnot a omezení

Trasy atributů podporují stejnou vloženou syntaxi jako běžné trasy a určují volitelné parametry, výchozí hodnoty a omezení.

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

V předchozím kódu [HttpPost("product14/{id:int}")] použije omezení trasy. Akce Products14Controller.ShowProduct se shoduje pouze s cestami URL, jako je /product14/3. Část šablony {id:int} trasy omezuje tento segment pouze na celá čísla.

Podrobný popis syntaxe šablony trasy najdete v referenčních informacích k šabloně trasy.

Vlastní atributy trasy pomocí IRouteTemplateProvider

Všechny atributy trasy implementují IRouteTemplateProvider. Modul runtime ASP.NET Core:

  • Vyhledá atributy tříd kontroleru a metod akcí při spuštění aplikace.
  • Používá atributy, které implementují IRouteTemplateProvider k sestavení počáteční sady tras.

Implementujte IRouteTemplateProvider definování vlastních atributů trasy. Každá IRouteTemplateProvider umožňuje definovat jednu trasu s vlastní šablonou trasy, pořadím a názvem:

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

Předchozí Get metoda vrátí Order = 2, Template = api/MyTestApi.

Přizpůsobení tras atributů pomocí aplikačního modelu

Aplikační model:

  • Je objektový model vytvořený při spuštění v Program.cs.
  • Obsahuje všechna metadata používaná ASP.NET Core ke směrování a provádění akcí v aplikaci.

Aplikační model zahrnuje všechna data shromážděná z atributů trasy. Implementace poskytuje IRouteTemplateProvider data z atributů trasy. Konvence:

  • Lze napsat a upravit aplikační model tak, aby přizpůsobil chování směrování.
  • Čtou se při spuštění aplikace.

Tato část ukazuje základní příklad přizpůsobení směrování pomocí aplikačního modelu. Následující kód vytváří trasy zhruba zarovná do struktury složek projektu.

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

Následující kód zabraňuje namespace použití konvence na kontrolery, které jsou směrovány atributem:

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

Například následující kontroler nepoužívá NamespaceRoutingConvention:

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

Metoda NamespaceRoutingConvention.Apply:

  • Nedělá nic, pokud je kontroler směrován atributem.
  • Nastaví šablonu kontrolerů na namespacezákladě , s odebranou základnou namespace .

Lze použít NamespaceRoutingConvention v Program.cs:

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

Představte si například následující kontroler:

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

V předchozím kódu:

  • Základ namespace je My.Application.
  • Úplný název předchozího kontroleru je My.Application.Admin.Controllers.UsersController.
  • Nastaví NamespaceRoutingConvention šablonu kontrolerů na Admin/Controllers/Users/[action]/{id?.

NamespaceRoutingConvention se také použít jako atribut na kontroleru:

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

Smíšené směrování: Směrování atributů vs. konvenční směrování

ASP.NET základní aplikace můžou kombinovat použití konvenčního směrování a směrování atributů. Pro kontrolery obsluhující stránky HTML pro prohlížeče a směrování atributů pro kontrolery, které obsluhují REST rozhraní API, je typické použití konvenčních tras.

Akce se směrují buď konvenčně, nebo jsou směrovány atributem. Umístěním trasy na kontroler nebo akci se směruje atribut. Akce, které definují trasy atributů, nelze dosáhnout prostřednictvím konvenčních tras a naopak. Jakýkoli atribut trasy na kontroleru provede všechny akce ve směrovaném atributu kontroleru.

Směrování atributů a konvenční směrování používají stejný směrovací modul.

Směrování se speciálními znaky

Směrování se speciálními znaky může vést k neočekávaným výsledkům. Představte si například kontroler s následující metodou akce:

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

Pokud string id obsahuje následující kódované hodnoty, mohou dojít k neočekávaným výsledkům:

ASCII Encoded
/ %2F
+

Parametry trasy nejsou vždy dekódovány adresou URL. Tento problém může být vyřešen v budoucnu. Další informace najdete v tomto problému na GitHubu.

Generování adres URL a okolní hodnoty

Aplikace můžou pomocí funkcí generování adres URL směrování generovat odkazy na adresy URL na akce. Generování adres URL eliminuje pevně zakódované adresy URL, takže je kód robustnější a udržovatelný. Tato část se zaměřuje na funkce generování adres URL, které poskytuje MVC, a zabývá se jenom základy fungování generování adres URL. Podrobný popis generování adres URL najdete v tématu Směrování .

Rozhraní IUrlHelper je základní prvek infrastruktury mezi MVC a směrováním pro generování adres URL. Instance IUrlHelper je k dispozici prostřednictvím Url vlastnosti v kontrolerů, zobrazeních a komponentách zobrazení.

V následujícím příkladu se IUrlHelper rozhraní používá prostřednictvím Controller.Url vlastnosti k vygenerování adresy URL jiné akce.

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

Pokud aplikace používá výchozí konvenční trasu, hodnota url proměnné je řetězec /UrlGeneration/Destinationcesty url . Tuto cestu URL vytvoří směrováním zkombinováním:

  • Směrovací hodnoty z aktuálního požadavku, které se nazývají okolní hodnoty.
  • Hodnoty předané Url.Action a nahrazující tyto hodnoty do šablony trasy:
ambient values: { controller = "UrlGeneration", action = "Source" }
values passed to Url.Action: { controller = "UrlGeneration", action = "Destination" }
route template: {controller}/{action}/{id?}

result: /UrlGeneration/Destination

Každý parametr trasy v šabloně trasy má hodnotu nahrazenou odpovídajícími názvy s hodnotami a okolními hodnotami. Parametr trasy, který nemá hodnotu, může:

  • Pokud má výchozí hodnotu, použijte ji.
  • Pokud je nepovinný, přeskočí se. Například id ze šablony {controller}/{action}/{id?}trasy .

Generování adresy URL selže, pokud některý parametr požadované trasy nemá odpovídající hodnotu. Pokud generování adresy URL pro trasu selže, zkusí se další trasa, dokud se nezkouší všechny trasy nebo se nenajde shoda.

Předchozí příklad Url.Action předpokládá konvenční směrování. Generování adres URL funguje podobně se směrováním atributů, i když se koncepty liší. S konvenčním směrováním:

  • Hodnoty tras slouží k rozbalení šablony.
  • Hodnoty tras pro controller a action obvykle se v této šabloně zobrazují. To funguje, protože adresy URL odpovídající směrováním dodržují konvenci.

Následující příklad používá směrování atributů:

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

Akce Source v předchozím kódu vygeneruje custom/url/to/destination.

LinkGenerator byl přidán v ASP.NET Core 3.0 jako alternativu k IUrlHelper. LinkGenerator nabízí podobné, ale flexibilnější funkce. Každá metoda má IUrlHelper také odpovídající řadu metod LinkGenerator .

Generování adres URL podle názvu akce

Url.Action, LinkGenerator.GetPathByAction a všechna související přetížení jsou navržena tak, aby vygenerovala cílový koncový bod zadáním názvu kontroleru a názvu akce.

Pokud používáte Url.Action, aktuální hodnoty tras pro controller a action jsou poskytovány modulem runtime:

  • Hodnota controller a action jsou součástí okolních hodnot i hodnot. Metoda Url.Action vždy používá aktuální hodnoty action a controller generuje cestu URL, která směruje na aktuální akci.

Směrování se pokusí použít hodnoty v okolních hodnotách k vyplnění informací, které nebyly poskytnuty při generování adresy URL. Představte si trasu jako {a}/{b}/{c}/{d} s okolními hodnotami { a = Alice, b = Bob, c = Carol, d = David }:

  • Směrování má dostatek informací k vygenerování adresy URL bez dalších hodnot.
  • Směrování má dostatek informací, protože všechny parametry trasy mají hodnotu.

Pokud se hodnota { d = Donovan } přidá:

  • Hodnota { d = David } se ignoruje.
  • Vygenerovaná cesta URL je Alice/Bob/Carol/Donovan.

Upozornění: Cesty url jsou hierarchické. Pokud se v předchozím příkladu přidá hodnota { c = Cheryl } :

  • Obě hodnoty { c = Carol, d = David } jsou ignorovány.
  • Generování adresy URL už nemá hodnotu d a generování adresy URL se nezdaří.
  • Požadované hodnoty c a d musí být zadány pro vygenerování adresy URL.

U výchozí trasy {controller}/{action}/{id?}můžete očekávat, že dojde k tomuto problému . Tento problém je v praxi vzácný, protože Url.Action vždy explicitně určuje controller hodnotu a action hodnotu.

Několik přetížení Url.Action provede objekt směrovacích hodnot, který poskytuje hodnoty pro parametry trasy jiné než controller a action. Objekt hodnot tras se často používá s id. Například Url.Action("Buy", "Products", new { id = 17 }). Objekt hodnot trasy:

  • Podle konvence je obvykle objekt anonymního typu.
  • Může to být IDictionary<> nebo POCO).

Všechny další hodnoty tras, které neodpovídají parametrům trasy, se vloží do řetězce dotazu.

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

Předchozí kód vygeneruje /Products/Buy/17?color=red.

Následující kód vygeneruje absolutní adresu URL:

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

Pokud chcete vytvořit absolutní adresu URL, použijte jednu z následujících možností:

  • Přetížení, které přijímá .protocol Například předchozí kód.
  • LinkGenerator.GetUriByAction, který ve výchozím nastavení generuje absolutní identifikátory URI.

Generování adres URL podle trasy

Předchozí kód demonstroval generování adresy URL předáním názvu kontroleru a akce. IUrlHelper poskytuje také řadu metod Url.RouteUrl . Tyto metody jsou podobné url.Action, ale nekopírují aktuální hodnoty action a controller směrovací hodnoty. Nejběžnější použití Url.RouteUrl:

  • Určuje název trasy pro vygenerování adresy URL.
  • Obecně se nezadá název kontroleru ani akce.
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();
    }

Následující Razor soubor vygeneruje odkaz HTML na Destination_Route:

<h1>Test Links</h1>

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

Generování adres URL ve formátu HTML a Razor

IHtmlHelperHtmlHelper poskytuje metody Html.BeginForm a Html.ActionLink pro generování <form> a <a> elementy v uvedeném pořadí. Tyto metody používají metodu Url.Action k vygenerování adresy URL a přijímají podobné argumenty. Společníci Url.RouteUrl jsou HtmlHelper Html.BeginRouteForm a Html.RouteLink mají podobné funkce.

TagHelpers generují adresy URL prostřednictvím form tagHelperu a TagHelperu <a> . Obě tyto možnosti se používají IUrlHelper pro jejich implementaci. Další informace najdete v tématu Pomocné rutiny značek ve formulářích .

Uvnitř zobrazení IUrlHelper je k dispozici prostřednictvím Url vlastnosti pro jakékoli generování ad hoc adres URL, které nejsou popsány výše.

Generování adres URL ve výsledcích akce

Předchozí příklady ukázaly použití IUrlHelper v kontroleru. Nejběžnějším použitím kontroleru je vygenerovat adresu URL jako součást výsledku akce.

Controller Základní ControllerBase třídy poskytují metody usnadnění pro výsledky akcí, které odkazují na jinou akci. Jedním z typických použití je přesměrování po přijetí uživatelského vstupu:

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

Akce výsledky factory metody, jako RedirectToAction CreatedAtAction a sledovat podobný vzor jako metody na IUrlHelper.

Speciální případ pro vyhrazené konvenční trasy

Konvenční směrování může používat speciální druh definice trasy označované jako vyhrazená konvenční trasa. V následujícím příkladu je pojmenovaná blog trasa vyhrazená konvenční trasa:

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

Pomocí předchozích definic Url.Action("Index", "Home") tras vygeneruje cestu / URL pomocí default trasy, ale proč? Můžete uhodnout, že hodnoty { controller = Home, action = Index } trasy budou stačit k vygenerování adresy URL pomocí bloga výsledek bude /blog?action=Index&controller=Home.

Vyhrazené konvenční trasy spoléhají na speciální chování výchozích hodnot, které nemají odpovídající parametr trasy, který brání příliš greedy trasy při generování adresy URL. V tomto případě jsou { controller = Blog, action = Article }výchozí hodnoty a ani controller action se nezobrazují jako parametr trasy. Při generování adresy URL směrování musí zadané hodnoty odpovídat výchozím hodnotám. Generování adresy URL selhává blog , protože hodnoty { controller = Home, action = Index } se neshodovaly { controller = Blog, action = Article }. Směrování se pak vrátí k vyzkoušení default, což bude úspěšné.

Oblasti

Oblasti jsou funkce MVC sloužící k uspořádání souvisejících funkcí do skupiny jako samostatné:

  • Obor názvů směrování pro akce kontroleru
  • Struktura složek pro zobrazení

Použití oblastí umožňuje aplikaci mít více kontrolerů se stejným názvem, pokud mají různé oblasti. Použití oblastí vytvoří hierarchii pro účely směrování přidáním dalšího parametru area trasy do controller a action. Tato část popisuje, jak směrování komunikuje s oblastmi. Podrobnosti o tom, jak se oblasti používají se zobrazeními, najdete v části Oblasti .

Následující příklad nakonfiguruje MVC tak, aby používal výchozí konvenční trasu a trasu area pro pojmenovanou area Blog:

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

V předchozím kódu je MapAreaControllerRoute volána k vytvoření "blog_route". Druhý parametr, "Blog"je název oblasti.

Při porovnávání cesty URL, jako /Manage/Users/AddUserje , "blog_route" trasa generuje hodnoty { area = Blog, controller = Users, action = AddUser }trasy . Hodnota area trasy je vytvořena výchozí hodnotou pro area. Trasa vytvořená MapAreaControllerRoute pomocí je ekvivalentní následujícímu:

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

MapAreaControllerRoute vytvoří trasu pomocí výchozí hodnoty i omezení pro area použití zadaného názvu oblasti, v tomto případě Blog. Výchozí hodnota zajišťuje, že trasa vždy vytvoří { area = Blog, ... }, omezení vyžaduje hodnotu { area = Blog, ... } pro generování adresy URL.

Konvenční směrování je závislé na pořadí. Obecně platí, že trasy s oblastmi by měly být umístěny dříve, protože jsou konkrétnější než trasy bez oblasti.

V předchozím příkladu se hodnoty { area = Blog, controller = Users, action = AddUser } tras shodují s následující akcí:

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

Atribut [Area] označuje kontroler jako součást oblasti. Tento kontroler je v Blog oblasti. Kontrolery bez atributu [Area] nejsou členy žádné oblasti a neodpovídají, pokud area je hodnota trasy poskytována směrováním. V následujícím příkladu může pouze první uvedený kontroler odpovídat hodnotám { area = Blog, controller = Users, action = AddUser }trasy .

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

Obor názvů každého kontroleru je zde zobrazen pro úplnost. Pokud předchozí kontrolery používaly stejný obor názvů, vygenerovala by se chyba kompilátoru. Obory názvů tříd nemají žádný vliv na směrování MVC.

První dva kontrolery jsou členy oblastí a shodují se pouze v případě, že je jejich název oblasti zadaný area hodnotou trasy. Třetí kontroler není členem žádné oblasti a může se shodovat pouze v případě, že směrování neposkytuje žádnou hodnotu area .

Pokud jde o odpovídající žádnou hodnotu, absence area hodnoty je stejná, jako kdyby hodnota pro area hodnotu byla null nebo prázdný řetězec.

Při provádění akce uvnitř oblasti je hodnota area trasy dostupná jako okolní hodnota pro směrování, která se má použít pro generování adresy URL. To znamená, že ve výchozím nastavení se oblasti chovají jako rychlé pro generování adres URL, jak ukazuje následující ukázka.

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

Následující kód vygeneruje adresu URL pro /Zebra/Users/AddUser:

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

Definice akce

Veřejné metody v kontroleru s výjimkou těch s atributem NonAction jsou akce.

Ukázkový kód

Ladění diagnostiky

Podrobný výstup diagnostiky směrování nastavíte Logging:LogLevel:Microsoft na Debughodnotu . Ve vývojovém prostředí nastavte úroveň protokolu v appsettings.Development.json:

{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft": "Debug",
      "Microsoft.Hosting.Lifetime": "Information"
    }
  }
}

ASP.NET kontrolery Core používají middleware směrování, aby odpovídaly adresám URL příchozích požadavků a mapovaly je na akce. Šablony tras:

  • Jsou definovány ve spouštěcím kódu nebo atributech.
  • Popište, jak se cesty URL shodují s akcemi.
  • Slouží ke generování adres URL pro odkazy. Vygenerované odkazy se obvykle vrací v odpovědích.

Akce jsou buď obvykle směrovány, nebo jsou směrovány atributem. Když umístíte trasu na kontroler nebo akci , bude směrovaná atributem. Další informace najdete v tématu Smíšené směrování .

Tento dokument:

Nastavení konvenční trasy

Startup.Configure Při použití konvenčního směrování má obvykle kód podobný následujícímu:

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

Uvnitř volání UseEndpointsMapControllerRoute se používá k vytvoření jedné trasy. Jedna trasa má název default trasy. Většina aplikací s kontrolery a zobrazeními používá šablonu trasy podobnou default této trase. REST Rozhraní API by měla používat směrování atributů.

Šablona "{controller=Home}/{action=Index}/{id?}"trasy:

  • Odpovídá cestě URL, jako je /Products/Details/5

  • Extrahuje hodnoty { controller = Products, action = Details, id = 5 } trasy tokenizací cesty. Extrahování hodnot tras vede ke shodě, pokud má aplikace pojmenovaný kontroler ProductsController a Details akci:

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

    MyDisplayRouteInfo poskytuje balíček NuGet Rick.Docs.Samples.RouteInfo a zobrazí informace o trase.

  • /Products/Details/5 model sváže hodnotu id = 5 nastavení parametru id na 5. Další podrobnosti najdete v tématu Vazby modelu.

  • {controller=Home} definuje Home jako výchozí controller.

  • {action=Index} definuje Index jako výchozí action.

  • Znak ? v {id?} definici je id volitelný.

  • Výchozí a volitelné parametry trasy nemusí být v cestě URL pro shodu. Podrobný popis syntaxe šablony trasy najdete v referenčních informacích k šabloně trasy.

  • Odpovídá cestě /URL .

  • Vytvoří hodnoty { controller = Home, action = Index }trasy .

Hodnoty pro controller výchozí hodnoty a action jejich použití. id nevytvoří hodnotu, protože v cestě URL neexistuje žádný odpovídající segment. /odpovídá pouze v případě, že existuje nějaká HomeController akce:Index

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

Pomocí předchozí definice kontroleru a šablony trasy se HomeController.Index akce spustí pro následující cesty URL:

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

Cesta / URL používá výchozí Home kontrolery a Index akci šablony trasy. Cesta URL /Home používá výchozí Index akci šablony trasy.

Metoda MapDefaultControllerRoutepohodlí:

endpoints.MapDefaultControllerRoute();

Nahrazuje:

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

Důležité

Směrování je nakonfigurováno pomocí UseRoutingnástroje , MapControllerRoutea MapAreaControllerRoute middleware . Použití kontrolerů:

Konvenční směrování

Konvenční směrování se používá s řadiči a zobrazeními. Trasa default :

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

Předchozí příklad je příkladem konvenční trasy. Říká se tomu konvenční směrování , protože vytváří konvenci pro cesty url:

  • První segment cesty , {controller=Home}mapuje na název kontroleru.
  • Druhý segment, {action=Index}, mapuje na název akce .
  • Třetí segment se používá pro volitelný id. {id?} Hodnota ? in {id?} je volitelná. id slouží k mapování na entitu modelu.

Pomocí této default trasy cesta URL:

  • /Products/List se mapuje na ProductsController.List akci.
  • /Blog/Article/17mapuje id a BlogController.Article obvykle model sváže parametr na 17.

Toto mapování:

  • Je založen pouze na názvech kontroleru a akcí.
  • Není založená na oborech názvů, umístěních zdrojových souborů nebo parametrech metody.

Použití konvenčního směrování s výchozí trasou umožňuje vytvořit aplikaci, aniž by bylo nutné pro každou akci vytvořit nový vzor adresy URL. U aplikace s akcemi stylu CRUD mají konzistenci adres URL napříč řadiči:

  • Pomáhá zjednodušit kód.
  • Zpřístupňuje uživatelské rozhraní předvídatelněji.

Upozorňující

V id předchozím kódu je definována jako volitelná šablona trasy. Akce se můžou spouštět bez volitelného ID zadaného jako součást adresy URL. Obecně platí, že pokud id je vynechán z adresy URL:

  • id je nastavena 0 vazbou modelu.
  • V porovnávání id == 0databáze nebyla nalezena žádná entita .

Směrování atributů poskytuje jemně odstupňované řízení, aby se ID vyžadovalo pro některé akce, a ne pro jiné. Podle konvence obsahuje dokumentace volitelné parametry, jako id když se pravděpodobně objeví ve správném použití.

Většina aplikací by měla zvolit základní a popisné schéma směrování, aby adresy URL byly čitelné a smysluplné. Výchozí konvenční trasa {controller=Home}/{action=Index}/{id?}:

  • Podporuje základní a popisné schéma směrování.
  • Je užitečný výchozí bod pro aplikace založené na uživatelském rozhraní.
  • Je jediná šablona trasy potřebná pro mnoho aplikací webového uživatelského rozhraní. U větších aplikací webového uživatelského rozhraní je další trasa využívající oblasti často všechna potřebná.

MapControllerRoute a MapAreaRoute :

  • Automaticky přiřaďte jejich koncovým bodům hodnotu objednávky na základě pořadí, ve které jsou vyvolány.

Směrování koncových bodů v ASP.NET Core 3.0 a novější:

  • Nemá koncept tras.
  • Neposkytuje záruky řazení pro provádění rozšiřitelnosti, všechny koncové body se zpracovávají najednou.

Povolte protokolování , abyste viděli, jak integrované implementace směrování, například Route, odpovídají požadavkům.

Směrování atributů je vysvětleno dále v tomto dokumentu.

Více konvenčních tras

Více konvenčních tras lze přidat dovnitř UseEndpoints přidáním dalších volání do MapControllerRoute a MapAreaControllerRoute. To umožňuje definovat více konvencí nebo přidat konvenční trasy, které jsou vyhrazené pro konkrétní akci, například:

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

Trasa blog v předchozím kódu je vyhrazená konvenční trasa. Označuje se jako vyhrazená konvenční trasa, protože:

Vzhledem k tomu, controller že se action v šabloně "blog/{*article}" trasy nezobrazují jako parametry:

  • Mohou mít pouze výchozí hodnoty { controller = "Blog", action = "Article" }.
  • Tato trasa se vždy mapuje na akci BlogController.Article.

/Blog, /Blog/Articlea /Blog/{any-string} jsou jediné cesty URL, které odpovídají trase blogu.

Předchozí příklad:

  • blog trasa má vyšší prioritu default pro shody než trasa, protože je přidána jako první.
  • Je příkladem směrování stylu Slug , kde je typické mít název článku jako součást adresy URL.

Upozorňující

V ASP.NET Core 3.0 a novějším směrování ne:

  • Definujte koncept označovaný jako trasa. UseRouting přidá trasu odpovídající kanálu middlewaru. Middleware UseRouting se podívá na sadu koncových bodů definovaných v aplikaci a vybere nejlepší shodu koncového bodu na základě požadavku.
  • Poskytovat záruky týkající se pořadí provádění rozšiřitelnosti, jako IRouteConstraint nebo IActionConstraint.

Viz Směrovací materiál pro směrování.

Konvenční pořadí směrování

Konvenční směrování odpovídá pouze kombinaci akce a kontroleru definované aplikací. Cílem je zjednodušit případy, kdy se běžné trasy překrývají. Přidání tras pomocí MapControllerRoutea MapDefaultControllerRouteMapAreaControllerRoute automatické přiřazení hodnoty objednávky ke svým koncovým bodům na základě pořadí, ve které jsou vyvolány. Shody z trasy, která se zobrazí dříve, mají vyšší prioritu. Konvenční směrování je závislé na pořadí. Obecně platí, že trasy s oblastmi by měly být umístěny dříve, protože jsou konkrétnější než trasy bez oblasti. Vyhrazené konvenční trasy s parametry trasy catch-all, jako {*article} je může vytvořit trasu příliš greedy, což znamená, že odpovídá adresám URL, které jste chtěli spárovat jinými trasami. Trasu greedy umístěte později do směrovací tabulky, aby se zabránilo shodám greedy.

Upozorňující

Parametr catch-all může nesprávně odpovídat trasám kvůli chybě při směrování. Aplikace ovlivněné touto chybou mají následující charakteristiky:

  • Například trasa pro zachytávání– vše {**slug}"
  • Trasa catch-all neodpovídá požadavkům, které by se měly shodovat.
  • Odebráním jiných tras začne fungovat zachytávání všech tras.

Podívejte se na chyby GitHubu 18677 a 16579 , například případy, které tuto chybu narazily.

Oprava výslovného souhlasu s touto chybou je obsažená v sadě .NET Core 3.1.301 SDK a novějších verzích. Následující kód nastaví interní přepínač, který tuto chybu opraví:

public static void Main(string[] args)
{
   AppContext.SetSwitch("Microsoft.AspNetCore.Routing.UseCorrectCatchAllBehavior", 
                         true);
   CreateHostBuilder(args).Build().Run();
}
// Remaining code removed for brevity.

Řešení nejednoznačných akcí

Když se dva koncové body shodují prostřednictvím směrování, musí směrování provést jednu z těchto věcí:

  • Vyberte nejlepšího kandidáta.
  • Vyvolá výjimku.

Příklad:

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

Předchozí kontroler definuje dvě akce, které odpovídají:

  • Cesta URL /Products33/Edit/17
  • Směrovat data { controller = Products33, action = Edit, id = 17 }.

Toto je typický vzor pro kontrolery MVC:

  • Edit(int) zobrazí formulář pro úpravu produktu.
  • Edit(int, Product) zpracuje vystavený formulář.

Řešení správné trasy:

  • Edit(int, Product) je vybrána, pokud je požadavek HTTP POST.
  • Edit(int) je vybrána, pokud je příkaz HTTP cokoli jiného. Edit(int) je obecně volána prostřednictvím GET.

, HttpPostAttribute[HttpPost]je poskytována pro směrování tak, aby mohl zvolit na základě metody HTTP požadavku. Edit(int, Product) Dělá HttpPostAttribute lepší shodu než Edit(int).

Je důležité pochopit roli atributů, jako HttpPostAttributeje . Podobné atributy jsou definovány pro jiné příkazy HTTP. U konvenčního směrování je běžné, že akce používají stejný název akce, když jsou součástí formuláře pro zobrazení a odesílají pracovní postup formuláře. Podívejte se například na prozkoumání dvou metod akce Upravit.

Pokud směrování nemůže zvolit nejlepšího kandidáta, vyvolá AmbiguousMatchException se výpis několika odpovídajících koncových bodů.

Konvenční názvy tras

Řetězce a "default" v následujících příkladech "blog" jsou konvenční názvy tras:

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

Názvy tras dávají této trase logický název. Pojmenovanou trasu lze použít pro generování adres URL. Použití pojmenované trasy zjednodušuje vytváření adres URL, když řazení tras může komplikovat generování adres URL. Názvy tras musí být jedinečné pro celou aplikaci.

Názvy tras:

  • Nemá žádný vliv na porovnávání adres URL ani zpracování požadavků.
  • Používají se jenom pro generování adres URL.

Koncept názvu trasy je reprezentován ve směrování jako IEndpointNameMetadata. Název trasy termínů a název koncového bodu:

  • Jsou zaměnitelné.
  • Který z nich se používá v dokumentaci a kódu, závisí na popsaném rozhraní API.

Směrování atributů pro REST rozhraní API

REST Rozhraní API by měla používat směrování atributů k modelování funkčnosti aplikace jako sady prostředků, ve kterých jsou operace reprezentovány příkazy HTTP.

Směrování atributů používá sadu atributů k mapování akcí přímo na šablony směrování. Následující StartUp.Configure kód je typický pro REST rozhraní API a používá se v další ukázce:

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

V předchozím kódu se MapControllers volá uvnitř UseEndpoints mapovat směrované kontrolery atributů.

V následujícím příkladu:

  • HomeController odpovídá sadě adres URL podobných výchozím běžným trasám {controller=Home}/{action=Index}/{id?} .
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);
    }
}

Akce HomeController.Index se spustí pro některou z cest /URL , /Home, /Home/Index, nebo /Home/Index/3.

Tento příklad zvýrazňuje klíčový programovací rozdíl mezi směrováním atributů a konvenčním směrováním. Směrování atributů vyžaduje k zadání trasy další vstup. Konvenční výchozí trasa zpracovává trasy rychleji. Směrování atributů však umožňuje a vyžaduje přesnou kontrolu nad tím, které šablony tras se vztahují na každou akci.

Při směrování atributů nehrají názvy kontroleru a akcí žádnou roli, ve které se akce shoduje, pokud se nepoužije nahrazení tokenu. Následující příklad odpovídá stejným adresám URL jako v předchozím příkladu:

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

Následující kód používá nahrazení tokenu pro action a controller:

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

Následující kód se vztahuje [Route("[controller]/[action]")] na kontroler:

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

V předchozím kódu Index musí šablony metod předcházet / nebo ~/ směrovat šablony. Směrovací šablony použité na akci, která začíná / nebo ~/ se nezkombinuje se šablonami tras použitými na kontroler.

Informace o výběru šablony trasy najdete v tématu Priorita šablony trasy.

Rezervované názvy směrování

Následující klíčová slova jsou vyhrazena názvy parametrů trasy při použití kontrolerů nebo Razor stránek:

  • action
  • area
  • controller
  • handler
  • page

Použití page jako parametru trasy se směrováním atributů je běžnou chybou. Výsledkem je nekonzistentní a matoucí chování při generování adresy URL.

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

Speciální názvy parametrů používají generování adresy URL k určení, jestli operace generování adresy URL odkazuje na Razor stránku nebo na kontroler.

Následující klíčová slova jsou vyhrazena v kontextu Razor zobrazení nebo Razor stránky:

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

Tato klíčová slova by se neměla používat pro generace propojení, parametry vázané na model ani vlastnosti nejvyšší úrovně.

Šablony příkazů HTTP

ASP.NET Core obsahuje následující šablony příkazů HTTP:

Šablony tras

ASP.NET Core má následující šablony tras:

Směrování atributů s atributy příkazů HTTP

Vezměte v úvahu následující kontroler:

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

V předchozím kódu:

  • Každá akce obsahuje [HttpGet] atribut, který omezuje pouze porovnávání požadavků HTTP GET.
  • Akce GetProduct obsahuje "{id}" šablonu, proto id je připojena k "api/[controller]" šabloně na kontroleru. Šablona metod je "api/[controller]/{id}". Tato akce proto odpovídá pouze požadavkům GET pro formulář /api/test2/xyz,/api/test2/123,/api/test2/{any string}, atd.
    [HttpGet("{id}")]   // GET /api/test2/xyz
    public IActionResult GetProduct(string id)
    {
       return ControllerContext.MyDisplayRouteInfo(id);
    }
    
  • Akce GetIntProduct obsahuje "int/{id:int}" šablonu. Část :int šablony omezuje směrovací id hodnoty na řetězce, které lze převést na celé číslo. Požadavek GET na /api/test2/int/abc:
    • Neodpovídá této akci.
    • Vrátí chybu 404 Nenalezena.
      [HttpGet("int/{id:int}")] // GET /api/test2/int/3
      public IActionResult GetIntProduct(int id)
      {
          return ControllerContext.MyDisplayRouteInfo(id);
      }
      
  • Akce GetInt2Product obsahuje {id} v šabloně, ale neomezuje id na hodnoty, které lze převést na celé číslo. Požadavek GET na /api/test2/int2/abc:
    • Odpovídá této trase.
    • Vazba modelu se nepodaří převést abc na celé číslo. Parametr id metody je celé číslo.
    • Vrátí chybu 400 Chybný požadavek , protože vazbu modelu se nepodařilo převést abc na celé číslo.
      [HttpGet("int2/{id}")]  // GET /api/test2/int2/3
      public IActionResult GetInt2Product(int id)
      {
          return ControllerContext.MyDisplayRouteInfo(id);
      }
      

Směrování atributů může používat HttpMethodAttribute atributy, jako HttpPostAttributeje , HttpPutAttributea HttpDeleteAttribute. Všechny atributy příkazu HTTP přijímají šablonu trasy. Následující příklad ukazuje dvě akce, které odpovídají stejné šabloně trasy:

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

Pomocí cesty /products3URL:

  • Akce MyProductsController.ListProducts se spustí, když je GETpříkaz HTTP .
  • Akce MyProductsController.CreateProduct se spustí, když je POSTpříkaz HTTP .

Při vytváření REST rozhraní API je vzácné, že budete muset použít [Route(...)] metodu akce, protože akce přijímá všechny metody HTTP. Lepší je použít konkrétnější atribut příkazu HTTP, aby byl přesný o tom, co vaše rozhraní API podporuje. REST Očekává se, že klienti rozhraní API vědí, jaké cesty a příkazy HTTP se mapují na konkrétní logické operace.

REST Rozhraní API by měla používat směrování atributů k modelování funkčnosti aplikace jako sady prostředků, ve kterých jsou operace reprezentovány příkazy HTTP. To znamená, že mnoho operací, například GET a POST ve stejném logickém prostředku, používá stejnou adresu URL. Směrování atributů poskytuje úroveň řízení, která je nutná k pečlivému návrhu rozložení veřejného koncového bodu rozhraní API.

Vzhledem k tomu, že trasa atributu se vztahuje na konkrétní akci, je snadné nastavit parametry vyžadované jako součást definice šablony trasy. V následujícím příkladu id se vyžaduje jako součást cesty URL:

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

Akce Products2ApiController.GetProduct(int) :

  • Spouští se s cestou URL, jako je /products2/3
  • Nejde spustit s cestou /products2URL .

Atribut [Consumes] umožňuje akci omezit podporované typy obsahu požadavku. Další informace najdete v tématu Definování podporovaných typů obsahu požadavku pomocí atributu Consumes.

Úplný popis šablon tras a souvisejících možností najdete v tématu Směrování .

Další informace o [ApiController], viz ApiController atribut.

Název trasy

Následující kód definuje název Products_Listtrasy:

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

Názvy tras se dají použít k vygenerování adresy URL na základě konkrétní trasy. Názvy tras:

  • Nemá žádný vliv na chování přiřazování adres URL směrování.
  • Používají se jenom pro generování adres URL.

Názvy tras musí být jedinečné pro celou aplikaci.

Porovnejte předchozí kód s konvenční výchozí trasou, která definuje id parametr jako volitelný ({id?}). Schopnost přesně specifikovat rozhraní API má výhody, jako je povolení /products a /products/5 odeslání do různých akcí.

Kombinování tras atributů

Aby směrování atributů bylo méně opakované, atributy směrování na kontroleru se zkombinují s atributy trasy u jednotlivých akcí. Všechny šablony tras definované v kontroleru jsou předem nastavené tak, aby směrovaly šablony akcí. Umístění atributu trasy na kontroler provede všechny akce ve směrování atributů kontroleru.

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

V předchozím příkladu:

  • Cesta /products url se může shodovat. ProductsApi.ListProducts
  • Cesta /products/5 url se může shodovat ProductsApi.GetProduct(int).

Obě tyto akce odpovídají protokolu HTTP GET , protože jsou označené atributem [HttpGet] .

Směrovací šablony použité na akci, která začíná / nebo ~/ se nezkombinuje se šablonami tras použitými na kontroler. Následující příklad odpovídá sadě cest URL podobných výchozí trase.

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

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

Následující tabulka vysvětluje [Route] atributy v předchozím kódu:

Atribut Kombinuje s [Route("Home")] Definuje šablonu trasy.
[Route("")] Ano "Home"
[Route("Index")] Ano "Home/Index"
[Route("/")] Ne ""
[Route("About")] Ano "Home/About"

Pořadí tras atributů

Směrování vytvoří strom a odpovídá všem koncovým bodům současně:

  • Položky trasy se chovají tak, jako by byly umístěny v ideálním pořadí.
  • Nejvýraznější trasy mají možnost spustit před obecnějšími trasami.

Například trasa atributu, jako blog/search/{topic} je konkrétnější než trasa atributu, jako blog/{*article}je . Trasa blog/search/{topic} má ve výchozím nastavení vyšší prioritu, protože je konkrétnější. Pomocí konvenčního směrování zodpovídá vývojář za umístění tras do požadovaného pořadí.

Trasy atributů můžou nakonfigurovat pořadí pomocí Order vlastnosti. Všechny atributy trasy poskytované architekturou zahrnují Order . Trasy se zpracovávají podle vzestupného řazení Order vlastnosti. Výchozí pořadí je 0. Nastavení trasy pomocí Order = -1 spuštění před trasami, které nenastavují pořadí Nastavení trasy pomocí Order = 1 spuštění po výchozím pořadí tras

Vyhněte se v závislosti na Order. Pokud prostor adres URL aplikace vyžaduje správné směrování explicitních hodnot objednávek, pravděpodobně je také matoucí pro klienty. Obecně platí, že směrování atributů vybere správnou trasu s odpovídající adresou URL. Pokud výchozí pořadí použité pro generování adresy URL nefunguje, použití názvu trasy jako přepsání je obvykle jednodušší než použití Order vlastnosti.

Vezměte v úvahu následující dva kontrolery, které definují porovnávání /hometras:

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

/home Požadavek s předchozím kódem vyvolá výjimku podobnou následující:

AmbiguousMatchException: The request matched multiple endpoints. Matches:

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

Přidání Order do jednoho z atributů trasy vyřeší nejednoznačnost:

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

S předchozím kódem /home spustí HomeController.Index koncový bod. Chcete-li se dostat k MyDemoController.MyIndexžádosti /home/MyIndex. Poznámka:

  • Předchozí kód je příkladem nebo špatným návrhem směrování. Byla použita k ilustraci Order vlastnosti.
  • Vlastnost Order přeloží pouze nejednoznačnost, kterou nelze shodovat. Bylo by lepší šablonu odebrat [Route("Home")] .

Viz Razor Zásady směrování stránek a aplikací: Pořadí tras pro informace o pořadí tras pomocí Razor stránek.

V některých případech se vrátí chyba HTTP 500 s nejednoznačnými trasami. Pomocí protokolování zjistíte, které koncové body způsobily AmbiguousMatchException.

Výměna tokenů v šablonách tras [kontroler], [akce], [oblast]

Pro usnadnění práce trasy atributů podporují nahrazení tokenu uzavřením tokenu do hranatých závorek ([, ]). Tokeny , [area]a [controller] jsou nahrazeny [action]hodnotami názvu akce, název oblasti a název kontroleru z akce, kde je trasa definována:

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

V předchozím kódu:

[HttpGet]
public IActionResult List()
{
    return ControllerContext.MyDisplayRouteInfo();
}
  • Zápasy /Products0/List
[HttpGet("{id}")]
public IActionResult Edit(int id)
{
    return ControllerContext.MyDisplayRouteInfo(id);
}
  • Zápasy /Products0/Edit/{id}

Nahrazení tokenu probíhá jako poslední krok sestavení tras atributů. Předchozí příklad se chová stejně jako následující 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);
    }
}

Pokud to čtete v jiném jazyce než v angličtině, dejte nám vědět v tomto problému s diskuzí na GitHubu, pokud chcete vidět komentáře ke kódu ve vašem nativním jazyce.

Trasy atributů lze také kombinovat s dědičností. Jedná se o výkonnou kombinaci s nahrazením tokenů. Nahrazení tokenu se vztahuje také na názvy tras definovaných trasami atributů. [Route("[controller]/[action]", Name="[controller]_[action]")]vygeneruje jedinečný název trasy pro každou akci:

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

Chcete-li se shodovat s oddělovačem [ nahrazení literálového tokenu nebo ]ho umistit opakováním znaku ([[ nebo ]]).

Přizpůsobení nahrazení tokenu pomocí transformátoru parametrů

Nahrazení tokenů lze přizpůsobit pomocí transformátoru parametrů. Transformátor parametrů implementuje IOutboundParameterTransformer a transformuje hodnotu parametrů. Například vlastní SlugifyParameterTransformer transformátor parametru SubscriptionManagement změní hodnotu trasy na 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();
    }
}

Jedná se RouteTokenTransformerConvention o konvenci modelu aplikace, která:

  • Použije transformátor parametrů na všechny trasy atributů v aplikaci.
  • Přizpůsobí hodnoty tokenu trasy atributu při jejich nahrazení.
public class SubscriptionManagementController : Controller
{
    [HttpGet("[controller]/[action]")]
    public IActionResult ListAll()
    {
        return ControllerContext.MyDisplayRouteInfo();
    }
}

Předchozí ListAll metoda odpovídá /subscription-management/list-all.

Je RouteTokenTransformerConvention registrován jako možnost v ConfigureServices.

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

Definice Slug najdete ve webové dokumentaci MDN na Slug .

Upozorňující

Při zpracování System.Text.RegularExpressions nedůvěryhodného vstupu předejte vypršení časového limitu. Uživatel se zlými úmysly může poskytnout vstup, který RegularExpressions způsobí útok na dostupnost služby. ASP.NET rozhraní API architektury Core, která používají RegularExpressions vypršení časového limitu.

Více tras atributů

Směrování atributů podporuje definování více tras, které se dostanou ke stejné akci. Nejběžnějším použitím je napodobit chování výchozí konvenční trasy, jak je znázorněno v následujícím příkladu:

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

Umístění více atributů směrování na kontroler znamená, že každý z nich kombinuje s jednotlivými atributy trasy v metodách akce:

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

Implementují IActionConstraintse všechna omezení směrování příkazů HTTP .

Pokud je u akce umístěno více atributů trasy, které se implementují IActionConstraint :

  • Každé omezení akce kombinuje šablonu trasy použitou na kontroler.
[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();
    }
}

Použití více tras u akcí může vypadat jako užitečné a výkonné, je lepší zachovat základní a dobře definovaný prostor adres URL vaší aplikace. Pro akce používejte více tras pouze tam, kde je to potřeba, například pro podporu stávajících klientů.

Určení volitelných parametrů trasy atributů, výchozích hodnot a omezení

Trasy atributů podporují stejnou vloženou syntaxi jako běžné trasy a určují volitelné parametry, výchozí hodnoty a omezení.

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

V předchozím kódu [HttpPost("product14/{id:int}")] použije omezení trasy. Akce Products14Controller.ShowProduct se shoduje pouze s cestami URL, jako je /product14/3. Část šablony {id:int} trasy omezuje tento segment pouze na celá čísla.

Podrobný popis syntaxe šablony trasy najdete v referenčních informacích k šabloně trasy.

Vlastní atributy trasy pomocí IRouteTemplateProvider

Všechny atributy trasy implementují IRouteTemplateProvider. Modul runtime ASP.NET Core:

  • Vyhledá atributy tříd kontroleru a metod akcí při spuštění aplikace.
  • Používá atributy, které implementují IRouteTemplateProvider k sestavení počáteční sady tras.

Implementujte IRouteTemplateProvider definování vlastních atributů trasy. Každá IRouteTemplateProvider umožňuje definovat jednu trasu s vlastní šablonou trasy, pořadím a názvem:

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

Předchozí Get metoda vrátí Order = 2, Template = api/MyTestApi.

Přizpůsobení tras atributů pomocí aplikačního modelu

Aplikační model:

  • Je objektový model vytvořený při spuštění.
  • Obsahuje všechna metadata používaná ASP.NET Core ke směrování a provádění akcí v aplikaci.

Aplikační model zahrnuje všechna data shromážděná z atributů trasy. Implementace poskytuje IRouteTemplateProvider data z atributů trasy. Konvence:

  • Lze napsat a upravit aplikační model tak, aby přizpůsobil chování směrování.
  • Čtou se při spuštění aplikace.

Tato část ukazuje základní příklad přizpůsobení směrování pomocí aplikačního modelu. Následující kód vytváří trasy zhruba zarovná do struktury složek projektu.

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

Následující kód zabraňuje namespace použití konvence na kontrolery, které jsou směrovány atributem:

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

Například následující kontroler nepoužívá NamespaceRoutingConvention:

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

Metoda NamespaceRoutingConvention.Apply:

  • Nedělá nic, pokud je kontroler směrován atributem.
  • Nastaví šablonu kontrolerů na namespacezákladě , s odebranou základnou namespace .

Lze použít NamespaceRoutingConvention v Startup.ConfigureServices:

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.

Představte si například následující kontroler:

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

V předchozím kódu:

  • Základ namespace je My.Application.
  • Úplný název předchozího kontroleru je My.Application.Admin.Controllers.UsersController.
  • Nastaví NamespaceRoutingConvention šablonu kontrolerů na Admin/Controllers/Users/[action]/{id?.

NamespaceRoutingConvention se také použít jako atribut na kontroleru:

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

Smíšené směrování: Směrování atributů vs. konvenční směrování

ASP.NET základní aplikace můžou kombinovat použití konvenčního směrování a směrování atributů. Pro kontrolery obsluhující stránky HTML pro prohlížeče a směrování atributů pro kontrolery, které obsluhují REST rozhraní API, je typické použití konvenčních tras.

Akce se směrují buď konvenčně, nebo jsou směrovány atributem. Umístěním trasy na kontroler nebo akci se směruje atribut. Akce, které definují trasy atributů, nelze dosáhnout prostřednictvím konvenčních tras a naopak. Jakýkoli atribut trasy na kontroleru provede všechny akce ve směrovaném atributu kontroleru.

Směrování atributů a konvenční směrování používají stejný směrovací modul.

Generování adres URL a okolní hodnoty

Aplikace můžou pomocí funkcí generování adres URL směrování generovat odkazy na adresy URL na akce. Generování adres URL eliminuje pevně zakódované adresy URL, což zpřístupňuje kód robustnějším a udržovatelným. Tato část se zaměřuje na funkce generování adres URL, které poskytuje MVC, a zabývá se jenom základy fungování generování adres URL. Podrobný popis generování adres URL najdete v tématu Směrování .

Rozhraní IUrlHelper je základní prvek infrastruktury mezi MVC a směrováním pro generování adres URL. Instance IUrlHelper je k dispozici prostřednictvím Url vlastnosti v kontrolerů, zobrazeních a komponentách zobrazení.

V následujícím příkladu se IUrlHelper rozhraní používá prostřednictvím Controller.Url vlastnosti k vygenerování adresy URL jiné akce.

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

Pokud aplikace používá výchozí konvenční trasu, hodnota url proměnné je řetězec /UrlGeneration/Destinationcesty url . Tuto cestu URL vytvoří směrováním zkombinováním:

  • Směrovací hodnoty z aktuálního požadavku, které se nazývají okolní hodnoty.
  • Hodnoty předané Url.Action a nahrazující tyto hodnoty do šablony trasy:
ambient values: { controller = "UrlGeneration", action = "Source" }
values passed to Url.Action: { controller = "UrlGeneration", action = "Destination" }
route template: {controller}/{action}/{id?}

result: /UrlGeneration/Destination

Každý parametr trasy v šabloně trasy má hodnotu nahrazenou odpovídajícími názvy s hodnotami a okolními hodnotami. Parametr trasy, který nemá hodnotu, může:

  • Pokud má výchozí hodnotu, použijte ji.
  • Pokud je nepovinný, přeskočí se. Například id ze šablony {controller}/{action}/{id?}trasy .

Generování adresy URL selže, pokud některý parametr požadované trasy nemá odpovídající hodnotu. Pokud generování adresy URL pro trasu selže, zkusí se další trasa, dokud se nezkouší všechny trasy nebo se nenajde shoda.

Předchozí příklad Url.Action předpokládá konvenční směrování. Generování adres URL funguje podobně se směrováním atributů, i když se koncepty liší. S konvenčním směrováním:

  • Hodnoty tras slouží k rozbalení šablony.
  • Hodnoty tras pro controller a action obvykle se v této šabloně zobrazují. To funguje, protože adresy URL odpovídající směrováním dodržují konvenci.

Následující příklad používá směrování atributů:

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

Akce Source v předchozím kódu vygeneruje custom/url/to/destination.

LinkGenerator byl přidán v ASP.NET Core 3.0 jako alternativu k IUrlHelper. LinkGenerator nabízí podobné, ale flexibilnější funkce. Každá metoda má IUrlHelper také odpovídající řadu metod LinkGenerator .

Generování adres URL podle názvu akce

Url.Action, LinkGenerator.GetPathByAction a všechna související přetížení jsou navržena tak, aby vygenerovala cílový koncový bod zadáním názvu kontroleru a názvu akce.

Pokud používáte Url.Action, aktuální hodnoty tras pro controller a action jsou poskytovány modulem runtime:

  • Hodnota controller a action jsou součástí okolních hodnot i hodnot. Metoda Url.Action vždy používá aktuální hodnoty action a controller generuje cestu URL, která směruje na aktuální akci.

Směrování se pokusí použít hodnoty v okolních hodnotách k vyplnění informací, které nebyly poskytnuty při generování adresy URL. Představte si trasu jako {a}/{b}/{c}/{d} s okolními hodnotami { a = Alice, b = Bob, c = Carol, d = David }:

  • Směrování má dostatek informací k vygenerování adresy URL bez dalších hodnot.
  • Směrování má dostatek informací, protože všechny parametry trasy mají hodnotu.

Pokud se hodnota { d = Donovan } přidá:

  • Hodnota { d = David } se ignoruje.
  • Vygenerovaná cesta URL je Alice/Bob/Carol/Donovan.

Upozornění: Cesty url jsou hierarchické. Pokud se v předchozím příkladu přidá hodnota { c = Cheryl } :

  • Obě hodnoty { c = Carol, d = David } jsou ignorovány.
  • Generování adresy URL už nemá hodnotu d a generování adresy URL se nezdaří.
  • Požadované hodnoty c a d musí být zadány pro vygenerování adresy URL.

U výchozí trasy {controller}/{action}/{id?}můžete očekávat, že dojde k tomuto problému . Tento problém je v praxi vzácný, protože Url.Action vždy explicitně určuje controller hodnotu a action hodnotu.

Několik přetížení Url.Action provede objekt směrovacích hodnot, který poskytuje hodnoty pro parametry trasy jiné než controller a action. Objekt hodnot tras se často používá s id. Například Url.Action("Buy", "Products", new { id = 17 }). Objekt hodnot trasy:

  • Podle konvence je obvykle objekt anonymního typu.
  • Může to být IDictionary<> nebo POCO).

Všechny další hodnoty tras, které neodpovídají parametrům trasy, se vloží do řetězce dotazu.

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

Předchozí kód vygeneruje /Products/Buy/17?color=red.

Následující kód vygeneruje absolutní adresu URL:

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

Pokud chcete vytvořit absolutní adresu URL, použijte jednu z následujících možností:

  • Přetížení, které přijímá .protocol Například předchozí kód.
  • LinkGenerator.GetUriByAction, který ve výchozím nastavení generuje absolutní identifikátory URI.

Generování adres URL podle trasy

Předchozí kód demonstroval generování adresy URL předáním názvu kontroleru a akce. IUrlHelper poskytuje také řadu metod Url.RouteUrl . Tyto metody jsou podobné url.Action, ale nekopírují aktuální hodnoty action a controller směrovací hodnoty. Nejběžnější použití Url.RouteUrl:

  • Určuje název trasy pro vygenerování adresy URL.
  • Obecně se nezadá název kontroleru ani akce.
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();
    }

Následující Razor soubor vygeneruje odkaz HTML na Destination_Route:

<h1>Test Links</h1>

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

Generování adres URL ve formátu HTML a Razor

IHtmlHelperHtmlHelper poskytuje metody Html.BeginForm a Html.ActionLink pro generování <form> a <a> elementy v uvedeném pořadí. Tyto metody používají metodu Url.Action k vygenerování adresy URL a přijímají podobné argumenty. Společníci Url.RouteUrl jsou HtmlHelper Html.BeginRouteForm a Html.RouteLink mají podobné funkce.

TagHelpers generují adresy URL prostřednictvím form tagHelperu a TagHelperu <a> . Obě tyto možnosti se používají IUrlHelper pro jejich implementaci. Další informace najdete v tématu Pomocné rutiny značek ve formulářích .

Uvnitř zobrazení IUrlHelper je k dispozici prostřednictvím Url vlastnosti pro jakékoli generování ad hoc adres URL, které nejsou popsány výše.

Generování adres URL ve výsledcích akce

Předchozí příklady ukázaly použití IUrlHelper v kontroleru. Nejběžnějším použitím kontroleru je vygenerovat adresu URL jako součást výsledku akce.

Controller Základní ControllerBase třídy poskytují metody usnadnění pro výsledky akcí, které odkazují na jinou akci. Jedním z typických použití je přesměrování po přijetí uživatelského vstupu:

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

Akce výsledky factory metody, jako RedirectToAction CreatedAtAction a sledovat podobný vzor jako metody na IUrlHelper.

Speciální případ pro vyhrazené konvenční trasy

Konvenční směrování může používat speciální druh definice trasy označované jako vyhrazená konvenční trasa. V následujícím příkladu je pojmenovaná blog trasa vyhrazená konvenční trasa:

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

Pomocí předchozích definic Url.Action("Index", "Home") tras vygeneruje cestu / URL pomocí default trasy, ale proč? Můžete uhodnout, že hodnoty { controller = Home, action = Index } trasy budou stačit k vygenerování adresy URL pomocí bloga výsledek bude /blog?action=Index&controller=Home.

Vyhrazené konvenční trasy spoléhají na speciální chování výchozích hodnot, které nemají odpovídající parametr trasy, který brání příliš greedy trasy při generování adresy URL. V tomto případě jsou { controller = Blog, action = Article }výchozí hodnoty a ani controller action se nezobrazují jako parametr trasy. Při generování adresy URL směrování musí zadané hodnoty odpovídat výchozím hodnotám. Generování adresy URL selhává blog , protože hodnoty { controller = Home, action = Index } se neshodovaly { controller = Blog, action = Article }. Směrování se pak vrátí k vyzkoušení default, což bude úspěšné.

Oblasti

Oblasti jsou funkce MVC sloužící k uspořádání souvisejících funkcí do skupiny jako samostatné:

  • Obor názvů směrování pro akce kontroleru
  • Struktura složek pro zobrazení

Použití oblastí umožňuje aplikaci mít více kontrolerů se stejným názvem, pokud mají různé oblasti. Použití oblastí vytvoří hierarchii pro účely směrování přidáním dalšího parametru area trasy do controller a action. Tato část popisuje, jak směrování komunikuje s oblastmi. Podrobnosti o tom, jak se oblasti používají se zobrazeními, najdete v části Oblasti .

Následující příklad nakonfiguruje MVC tak, aby používal výchozí konvenční trasu a trasu area pro pojmenovanou area Blog:

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

V předchozím kódu je MapAreaControllerRoute volána k vytvoření "blog_route". Druhý parametr, "Blog"je název oblasti.

Při porovnávání cesty URL, jako /Manage/Users/AddUserje , "blog_route" trasa generuje hodnoty { area = Blog, controller = Users, action = AddUser }trasy . Hodnota area trasy je vytvořena výchozí hodnotou pro area. Trasa vytvořená MapAreaControllerRoute pomocí je ekvivalentní následujícímu:

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 vytvoří trasu pomocí výchozí hodnoty i omezení pro area použití zadaného názvu oblasti, v tomto případě Blog. Výchozí hodnota zajišťuje, že trasa vždy vytvoří { area = Blog, ... }, omezení vyžaduje hodnotu { area = Blog, ... } pro generování adresy URL.

Konvenční směrování je závislé na pořadí. Obecně platí, že trasy s oblastmi by měly být umístěny dříve, protože jsou konkrétnější než trasy bez oblasti.

V předchozím příkladu se hodnoty { area = Blog, controller = Users, action = AddUser } tras shodují s následující akcí:

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

Atribut [Area] označuje kontroler jako součást oblasti. Tento kontroler je v Blog oblasti. Kontrolery bez atributu [Area] nejsou členy žádné oblasti a neodpovídají, pokud area je hodnota trasy poskytována směrováním. V následujícím příkladu může pouze první uvedený kontroler odpovídat hodnotám { area = Blog, controller = Users, action = AddUser }trasy .

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

Obor názvů každého kontroleru je zde zobrazen pro úplnost. Pokud předchozí kontrolery používaly stejný obor názvů, vygenerovala by se chyba kompilátoru. Obory názvů tříd nemají žádný vliv na směrování MVC.

První dva kontrolery jsou členy oblastí a shodují se pouze v případě, že je jejich název oblasti zadaný area hodnotou trasy. Třetí kontroler není členem žádné oblasti a může se shodovat pouze v případě, že směrování neposkytuje žádnou hodnotu area .

Pokud jde o odpovídající žádnou hodnotu, absence area hodnoty je stejná, jako kdyby hodnota pro area hodnotu byla null nebo prázdný řetězec.

Při provádění akce uvnitř oblasti je hodnota area trasy dostupná jako okolní hodnota pro směrování, která se má použít pro generování adresy URL. To znamená, že ve výchozím nastavení se oblasti chovají jako rychlé pro generování adres URL, jak ukazuje následující ukázka.

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

Následující kód vygeneruje adresu URL pro /Zebra/Users/AddUser:

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

Definice akce

Veřejné metody v kontroleru s výjimkou těch s atributem NonAction jsou akce.

Ukázkový kód

Ladění diagnostiky

Podrobný výstup diagnostiky směrování nastavíte Logging:LogLevel:Microsoft na Debughodnotu . Ve vývojovém prostředí nastavte úroveň protokolu v appsettings.Development.json:

{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft": "Debug",
      "Microsoft.Hosting.Lifetime": "Information"
    }
  }
}