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

Ryan Nowak, Kirk Larkin a Rick Anderson

Note

Toto není nejnovější verze tohoto článku. Aktuální verzi článku pro .NET 10 najdete v .

Warning

Tato verze ASP.NET Core se už nepodporuje. Další informace najdete v .NET a .NET základních zásadách podpory. Aktuální verzi článku pro .NET 10 najdete v .

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

  • Jsou definovány při spuštění v Program.cs 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ď směrovány konvencí, nebo směrovány atributy. 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í jako na systém směrování koncových bodů. Řadiče můžete použít s předchozí verzí směrování pro účely kompatibility. Pokyny najdete v průvodci migrací verze 2.2-3.0.

Nastavení konvenční trasy

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

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

Slouží MapControllerRoute k vytvoření jedné trasy. Jedinou trasou je trasa default. 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 atributové směrování.

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

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

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

  • Extrahuje hodnoty trasy { controller = Products, action = Details, id = 5 } tokenizací cesty. Extrakce hodnot tras vede k nalezení shody, pokud má aplikace řadič s názvem ProductsController a akci Details:

    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 naváže hodnotu id = 5 tak, aby byl parametr id nastaven na 5. Další informace naleznete v tématu Svazování modelu.

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

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

  • Znak ? v {id?} určuje id jako volitelný prvek.

  • Odpovídá cestě /URL .

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

Hodnoty pro controller a action používají výchozí hodnoty. id nevytvoří hodnotu, protože v cestě URL neexistuje žádný odpovídající segment. / odpovídá pouze tehdy, pokud existuje akce HomeController a 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í kontroler Home a akci Index šablony trasy. Cesta URL /Home používá výchozí akci šablony trasy Index.

Pomocná metoda MapDefaultControllerRoute:

app.MapDefaultControllerRoute();

Replaces:

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

Important

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

Aplikace obvykle nemusí volat UseRouting ani UseEndpoints. WebApplicationBuilder konfiguruje kanál middlewaru, který obaluje middleware přidaný v Program.cs pomocí UseRouting a UseEndpoints. Další informace najdete v tématu Routing v ASP.NET Core.

Konvenční směrování

Používejte konvenční směrování s řadiči a zobrazeními. Trasa default je:

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

Předchozí kód 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}, odpovídá názvu kontroleru.
  • Druhý segment, {action=Index}, odpovídá názvu action.
  • Třetí segment, {id?}, slouží pro volitelný id. ? v {id?} značí, že je volitelné. id odpovídá entitě modelu.

Pomocí této default trasy cesta URL:

  • /Products/List je mapován na akci ProductsController.List.
  • /Blog/Article/17 se mapuje na BlogController.Article a model obvykle sváže parametr id s hodnotou 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.

Pomocí konvenčního směrování s výchozí trasou nemusíte pro každou akci vytvářet nový vzor adresy URL. U aplikace s akcemi ve stylu CRUD: zachovat konzistenci adres URL ve všech kontrolerech:

  • Pomáhá zjednodušit kód.
  • Zpřehledňuje uživatelské rozhraní, aby bylo předvídatelnější.

Warning

Šablona trasy definuje id jako volitelné. 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:

  • Vazby modelu se nastaví id na 0.
  • V databázi nebyla nalezena žádná entita odpovídající id == 0.

Směrování atributů umožňuje podrobně určit, pro které akce je ID vyžadováno a pro které ne. 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í s webovým uživatelským rozhraním často stačí jen jiný přístup využívající Areas.

MapControllerRoute a MapAreaRoute :

  • Automaticky přiřaďte jejich koncovým bodům hodnotu pořadí na základě pořadí, v jakém jsou volány.

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

  • Nemá koncept tras.
  • Neposkytuje záruky pořadí pro provádění rozšiřitelných funkcí. 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

Můžete nakonfigurovat více konvenčních tras přidáním dalších volání do MapControllerRoute a MapAreaControllerRoute. Když přidáte tato volání, můžete 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. Jedná se o vyhrazenou konvenční trasu, protože:

Protože šablona trasy "blog/{*article}" neobsahuje controller a action jako parametry:

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

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

V předchozím příkladu:

  • Trasa blog má při porovnávání vyšší prioritu než trasa default, protože ji přidáte nejdříve.
  • Je to příklad směrování stylu Slug , kde je typické mít název článku jako součást adresy URL.

Warning

Směrování v ASP.NET Core 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.
  • Poskytujte záruky ohledně pořadí spouštění rozšíření, například IRouteConstraint nebo IActionConstraint.

Viz Směrování, kde najdete referenční informace o směrování.

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

Konvenční směrování odpovídá pouze kombinaci akce a kontroleru, kterou aplikace definuje. Tento přístup zjednodušuje případy, kdy se běžné trasy překrývají. Když přidáte trasy pomocí MapControllerRoute, MapDefaultControllerRoute a MapAreaControllerRoute, endpointy automaticky získají hodnotu pořadí na základě pořadí, v jakém tyto metody voláte. Shody z trasy, která se zobrazí dříve v seznamu, mají vyšší prioritu. Konvenční směrování závisí na pořadí. Obecně umístěte trasy s oblastmi dříve, protože jsou konkrétnější než trasy bez oblasti. Vyhrazené konvenční trasy s parametry typu catch-all, například {*article}, mohou způsobit, že trasa bude příliš nenasytná. Cesta greedy odpovídá adresám URL, které jste chtěli shodovat s jinými trasami. Umístěte nenasytné trasy později ve směrovací tabulce, aby se zabránilo nenasytným shodám.

Warning

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 univerzální trasa {**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ávací trasa.

Podívejte se na GitHub chyby 18677 a 16579 pro příklady, kdy k této chybě dojde.

Oprava výslovného souhlasu s touto chybou je obsažena ve .NET Core 3.1.301 nebo novější sadě SDK. 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 mezi dvěma koncovými body naváže spojení prostřednictvím směrování, musí být proveden jeden z následujících kroků:

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

Napří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ěrování dat { 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 metoda HTTP jakákoli jiná. Edit(int) se obvykle volá prostřednictvím GET.

, HttpPostAttribute[HttpPost]je poskytována pro směrování tak, aby mohl zvolit na základě metody HTTP požadavku. HttpPostAttribute činí z Edit(int, Product) vhodnější volbu než z Edit(int).

Je důležité pochopit roli atributů, jako je HttpPostAttribute. Podobné atributy jsou definovány pro jiné příkazy HTTP. V konvenčním směrování akce často používají stejný název, když jsou součástí pracovního postupu pro zobrazení a odeslání formuláře. Například viz Prozkoumejte dvě metody akce Upravit.

Pokud směrování nemůže vybrat nejlepšího kandidáta, vyvolá AmbiguousMatchException a uvede více odpovídajících koncových bodů.

Konvenční názvy tras

Řetězce "blog" a "default" v následujících příkladech 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. Pojmy název trasy 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ů pro modelování funkčnosti aplikace jako sady zdrojů, ve které jsou operace reprezentovány metodami 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 voláte MapControllers, aby se namapovaly kontrolery se směrováním atributy.

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

  • HomeController odpovídá sadě adres URL podobné té, které odpovídá výchozí konvenční cesta {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 kteroukoli 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. Tradiční výchozí trasa zpracovává trasy stručněji. 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í pomocí atributů nehrají názvy kontroleru a akce žádnou roli při určování, která akce se vybere, 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 musí šablony metod Index před šablony tras přidat předponu / nebo ~/. Šablony tras použité u akce, které začínají na / nebo ~/, se nekombinují se šablonami tras použitými u řadiče.

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 pro názvy parametrů trasy při použití kontrolerů nebo stránek Razor:

  • action
  • area
  • controller
  • handler
  • page

Použití page jako parametru trasy se směrováním atributů je běžnou chybou. Výsledkem této volby 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);
    }
}

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

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

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

Tato klíčová slova nepoužívejte 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 obsahuje 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, takže id se připojí k "api/[controller]" šabloně na kontroleru. Šablona metody je "api/[controller]/{id}". Proto tato akce odpovídá pouze požadavkům GET pro formulář /api/test2/xyz, /api/test2/123, /api/test2/{any string}a tak dále.
    [HttpGet("{id}")]   // GET /api/test2/xyz
    public IActionResult GetProduct(string id)
    {
       return ControllerContext.MyDisplayRouteInfo(id);
    }
    
  • Akce GetIntProduct obsahuje "int/{id:int}" šablonu. Část šablony :int omezuje hodnoty trasy id 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.
    • Při vazbě modelu nelze převést abc na celé číslo. Parametr id metody je celé číslo.
    • Vrátí chybu 400 Bad Request, protože se při vazbě modelu 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í pomocí atributů může používat atributy, jako jsou HttpMethodAttribute, HttpPostAttribute, HttpPutAttribute a 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 URL /products3:

  • Akce MyProductsController.ListProducts se spustí, když je metoda HTTPGET.
  • Akce MyProductsController.CreateProduct se spustí, když je metoda HTTPPOST.

Při vytváření rozhraní API REST je zřídkakdy potřeba použít [Route(...)] u metody akce, protože akce přijímá všechny metody HTTP. Pomocí konkrétnějšího atributu příkazu HTTP můžete přesně určit, co vaše rozhraní API podporuje. REST Od klientů rozhraní API se očekává, že budou vědět, které cesty a metody HTTP odpovídají konkrétním logickým operacím.

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. Tento návrh znamená, že mnoho operací, jako je GET a POST ve stejném logickém prostředku, používá stejnou adresu URL. Směrování atributů poskytuje úroveň řízení potřebnou 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
  • Nespouští se s cestou URL /products2.

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

Pomocí názvů tras vygenerujte adresu URL na základě konkrétní trasy. Názvy tras:

  • Nemá žádný vliv na chování odpovídající URL v rámci routingu.
  • 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ě definovat rozhraní API má své výhody, například umožňuje, aby /products a /products/5 byly směrovány k různým akcím.

Kombinování tras atributů

Pokud chcete, aby směrování atributů bylo méně opakované, zkombinujte atributy směrování na kontroleru s atributy směrování na jednotlivých akcích. Šablony tras, které definujete na kontroleru, jsou předem nasměrované na šablony akcí. Když umístíte atribut trasy na kontroler, všechny akce v kontroleru používají směrování atributů.

[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 URL /products může odpovídat ProductsApi.ListProducts
  • Cesta URL /products/5 může odpovídat ProductsApi.GetProduct(int).

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

Směrovací šablony, které se vztahují na akci, a které začínají / nebo ~/ se nezkombinují se šablonami tras, které použijete u kontroleru. 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.

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

Pořadí pro trasování podle 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í.
  • Nejspecifičtější trasy mohou být vykonány před obecnějšími trasami.

Například atributová trasa, jako blog/search/{topic}, je specifičtější než atributová trasa, jako blog/{*article}. 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 tras poskytované rámcem obsahují Order . Trasy se zpracovávají podle vzestupného řazení Order vlastnosti. Výchozí pořadí je 0. Trasa nastavená pomocí Order = -1 se zpracuje před trasami, které nemají nastavené pořadí. Nastavení trasy pomocí Order = 1 se provede až po výchozím pořadí tras.

Vyhněte se závislosti na Order. Pokud prostor adres URL aplikace vyžaduje explicitní pořadí hodnot pro správné směrování, je to pravděpodobně matoucí i 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í URL nefunguje, bývá obvykle jednodušší použít jako alternativu název routy než vlastnost Order.

Zvažte následující dva kontrolery, které oba definují shodu trasy /home:

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 pomocí předchozího kódu 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();
}

Pomocí předchozího kódu /home volá koncový bod HomeController.Index. Chcete-li se dostat k MyDemoController.MyIndex, vyžádejte si /home/MyIndex. Poznámka:

  • Předchozí kód je příkladem špatného návrhu směrování. Znázorňuje vlastnost Order.
  • Vlastnost Order vyřeší pouze nejednoznačnost. Tato šablona se nedá spárovat. Je lepší odebrat šablonu [Route("Home")].

Informace o pořadí tras v Razor Pages naleznete zde: Razor Konvence směrování a aplikací v Pages: Pořadí tras.

V některých případech se vrátí chyba HTTP 500 s nejednoznačnými trasami. Pomocí protokolování můžete zjistit, 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 a [action][area] jsou nahrazeny [controller]hodnotami názvu akce, názvu oblasti a názvu kontroleru z akce, ve které definujete trasu:

[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í tokenů 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í GitHub pokud chcete zobrazit komentáře ke kódu ve vašem nativním jazyce.

Trasy atributů můžete také kombinovat s dědičností. Tato kombinace je silná při použití náhrady 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 doslovně odpovídat oddělovači nahrazení doslovného tokenu [ nebo ], escapujte jej zopakováním znaku ([[ nebo ]]).

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

Nahrazení tokenu můžete 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á:

  • Aplikujte transformátor parametrů na všechny atributové trasy v aplikaci.
  • Přizpůsobí hodnoty tokenu trasového 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();

Definici pojmu slug najdete v webové dokumentaci MDN k pojmu slug.

Warning

Při zpracování nedůvěryhodného vstupu pomocí System.Text.RegularExpressions nastavte časový limit. Uživatel se zlými úmysly může poskytnout vstup do RegularExpressions, který způsobí útok typu Denial-of-Service. Rozhraní API architektury ASP.NET Core, která používají RegularExpressions, předávají časový limit.

Více atributových tras

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

Všechna omezení směrování pro HTTP verb implementují IActionConstraint.

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

  • Každé vytvořené omezení je kombinováno s šablonou 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 tématu Referenční informace 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 pro 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. Data z atributů trasy poskytuje implementace IRouteTemplateProvider. Conventions:

  • 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 zarovnává trasy tak, aby se zhruba shodovaly se strukturou 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 zabrání použití konvence namespace u kontrolerů, které používají směrování pomocí atributů:

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 řadičů na základě namespace, po odebrání základní 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.
  • NamespaceRoutingConvention nastaví šablonu kontrolerů na Admin/Controllers/Users/[action]/{id?.

NamespaceRoutingConvention lze také použít jako atribut u 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 Core aplikace můžou kombinovat použití konvenčního směrování a směrování atributů. Obvykle používáte konvenční směrování pro kontrolery, které vracejí prohlížečům stránky HTML, a atributové směrování pro kontrolery, které obsluhují rozhraní API REST.

Akce se směrují buď konvenčně, nebo jsou směrovány atributem. Když přiřadíte trasu ke kontroleru nebo akci, stane se směrováním pomocí atributu. Nemůžete dosáhnout akcí, které definují trasy atributů 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:

standard 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 u tohoto problému na GitHubu;

Generování adres URL a okolní hodnoty

Aplikace mohou pomocí funkcí pro generování směrovacích URL vytvářet odkazy 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 vlastnosti Url v kontrolerech, zobrazeních a komponentách zobrazení.

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

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 proměnné url je řetězec cesty URL /UrlGeneration/Destination. Směrování vytvoří tuto cestu URL zkombinováním:

  • Směrovací hodnoty z aktuálního požadavku, které se nazývají okolní hodnoty.
  • Hodnoty předané do Url.Action a jejich nahrazení v šabloně 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 z šablony trasy {controller}/{action}/{id?}.

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 se používají k rozšíření šablony.
  • Hodnoty tras pro controller a action obvykle se v této šabloně zobrazují. To funguje, protože adresy URL, které jsou směrováním přiřazeny, dodržují zavedený standard.

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 na IUrlHelper má také odpovídající skupinu metod na 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.

Při použití Url.Actionmodul runtime poskytuje aktuální hodnoty tras pro controller a action:

  • Hodnoty 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.
  • Pro d už není k dispozici žádná hodnota a generování adresy URL selže.
  • Je nutné zadat požadované hodnoty c a d vygenerovat adresu 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 přijímá objekt hodnot trasy pro zadání hodnot parametrů trasy jiných než controller a action. Objekt hodnot tras se často používá s id. Například: Url.Action("Buy", "Products", new { id = 17 }). Objekt pro hodnoty 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 uloží 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é metodě Url.Action, ale nekopírují aktuální hodnoty action a controller do hodnot tras. Nejběžnější použití Url.RouteUrl:

  • Určuje název trasy pro vygenerování adresy URL.
  • Obecně se nespecifikuje název kontroléru nebo 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

IHtmlHelper HtmlHelper poskytuje metody Html.BeginForm a Html.ActionLink pro generování prvků <form> a <a> v tomto 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 HtmlHelperHtml.BeginRouteForm a Html.RouteLink mají podobné funkce.

TagHelpers generují adresy URL prostřednictvím form tagHelperu a TagHelperu <a> . Oba tyto prvky používají IUrlHelper ke své implementaci. Další informace naleznete v tématu Tag Helpery ve formulářích.

V zobrazeních je IUrlHelper k dispozici prostřednictvím vlastnosti Url pro jakékoli ad hoc generování adres URL, na které se nevztahují předchozí metody.

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

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

Základní třídy ControllerBase a Controller poskytují pomocné metody 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);
}

Tovární metody pro výsledky akcí, jako jsou RedirectToAction a CreatedAtAction, se řídí podobným vzorem jako metody třídy 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 trasa s názvem blog vyhrazenou konvenční trasou:

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 tras Url.Action("Index", "Home") vygeneruje cestu URL / pomocí trasy default, ale proč? Můžete uhodnout, že hodnoty { controller = Home, action = Index } tras stačí k vygenerování adresy URL pomocí bloga výsledek bude /blog?action=Index&controller=Home.

Vyhrazené konvenční trasy spoléhají na zvláštní chování výchozích hodnot, které nemají odpovídající parametr trasy, a které brání tomu, aby byla trasa při generování URL příliš nenasytná. V tomto případě jsou { controller = Blog, action = Article }výchozí hodnoty a ani controlleraction se nezobrazují jako parametr trasy. Při generování adresy URL musí směrování zajistit, aby zadané hodnoty odpovídaly výchozím hodnotám. Generování adresy URL selže blog, protože hodnoty { controller = Home, action = Index } neodpovídají { controller = Blog, action = Article }. Směrování pak jako náhradní možnost zkusí default, což se podaří.

Areas

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

  • Jmenný prostor směrování pro akce kontroléru
  • 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žívalo výchozí konvenční trasu a trasu area pro area s názvem 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, například /Manage/Users/AddUser, generuje trasa "blog_route" hodnoty trasy { area = Blog, controller = Users, action = AddUser }. Hodnota area trasy pochází z výchozí hodnoty pro area. Trasa vytvořená MapAreaControllerRoute pomocí tohoto kódu odpovídá následujícímu kódu:

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 s použitím zadaného názvu oblasti, v tomto případě Blog. Výchozí hodnota zajišťuje, že trasa vždy vytvoří { area = Blog, ... }a 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 by měly být trasy s oblastmi 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] nepatří do žádné oblasti a neodpovídají, když směrování poskytne hodnotu trasy area. 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}");
        }
    }
}

Pro úplnost, obor názvů každého řadiče je zde zobrazen. 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í řadič nepatří do žádné oblasti a může odpovídat pouze tehdy, pokud směrování neposkytne žádnou hodnotu pro area.

Pokud jde o shodu s žádnou hodnotou, nepřítomnost hodnoty area je stejná, jako kdyby hodnota pro area 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 při generování adres URL chovají lepivě, jak ukazuje následující příklad.

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

Diagnostika ladění

Nastavte Logging:LogLevel:Microsoft na Debug pro podrobný výstup diagnostiky směrování. V prostředí Development nastavte úroveň protokolu v appsettings.Development.json:

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

ASP.NET Core kontrolery používají směrování middleware tak, aby odpovídaly adresám URL příchozích požadavků a mapovaly je na actions. Š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ď směrovány konvencí, nebo směrovány atributy. 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 Obvykle má kód podobný následujícímu příkladu při použití konvenčního směrování:

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

V rámci volání UseEndpoints se MapControllerRoute používá k vytvoření jedné trasy. Jediná trasa se jmenuje default route. 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 atributové směrování.

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

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

  • Extrahuje hodnoty trasy { controller = Products, action = Details, id = 5 } tokenizací cesty. Extrakce hodnot tras vede k nalezení shody, pokud má aplikace řadič s názvem ProductsController a akci Details:

    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 naváže hodnotu id = 5 tak, aby byl parametr id nastaven na 5. Další informace naleznete v tématu Svazování modelu.

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

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

  • Znak ? v {id?} určuje id jako volitelný prvek.

  • Není nutné, aby výchozí a volitelné parametry trasy byly v cestě URL pro dosažení shody. Podrobný popis syntaxe šablony trasy najdete v tématu Referenční informace k šabloně trasy.

  • Odpovídá cestě /URL .

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

Hodnoty pro controller a action používají výchozí hodnoty. id nevytvoří hodnotu, protože v cestě URL neexistuje žádný odpovídající segment. / odpovídá pouze tehdy, pokud existuje akce HomeController a 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í kontroler Home a akci Index šablony trasy. Cesta URL /Home používá výchozí akci šablony trasy Index.

Pomocná metoda MapDefaultControllerRoute:

endpoints.MapDefaultControllerRoute();

Replaces:

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

Important

Směrování se konfiguruje pomocí middlewaru UseRouting, MapControllerRoutea MapAreaControllerRoute . Použití kontrolerů:

Konvenční směrování

Používejte konvenční směrování s řadiči a zobrazeními. Trasa default je:

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

Předchozí kód 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}, odpovídá názvu kontroleru.
  • Druhý segment, {action=Index}, odpovídá názvu action.
  • Třetí segment, {id?}, slouží pro volitelný id. ? v {id?} značí, že je volitelné. id odpovídá entitě modelu.

Pomocí této default trasy cesta URL:

  • /Products/List je mapován na akci ProductsController.List.
  • /Blog/Article/17 se mapuje na BlogController.Article a model obvykle sváže parametr id s hodnotou 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.

Pomocí konvenčního směrování s výchozí trasou nemusíte pro každou akci vytvářet nový vzor adresy URL. U aplikace s akcemi ve stylu CRUD: zachovat konzistenci adres URL ve všech kontrolerech:

  • Pomáhá zjednodušit kód.
  • Zpřehledňuje uživatelské rozhraní, aby bylo předvídatelnější.

Warning

Šablona trasy definuje id jako volitelné. 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:

  • Vazby modelu se nastaví id na 0.
  • V databázi nebyla nalezena žádná entita odpovídající id == 0.

Směrování atributů umožňuje podrobně určit, pro které akce je ID vyžadováno a pro které ne. 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í s webovým uživatelským rozhraním často stačí jen jiný přístup využívající Areas.

MapControllerRoute a MapAreaRoute :

  • Automaticky přiřaďte jejich koncovým bodům hodnotu pořadí na základě pořadí, v jakém jsou volány.

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

  • Nemá koncept tras.
  • Neposkytuje záruky pořadí pro provádění rozšiřitelných funkcí. 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. Jedná se o vyhrazenou konvenční trasu, protože:

Protože šablona trasy "blog/{*article}" neobsahuje controller a action jako parametry:

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

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

V předchozím příkladu:

  • Trasa blog má při porovnávání vyšší prioritu než trasa default, protože ji přidáte nejdříve.
  • Je to příklad směrování stylu Slug , kde je typické mít název článku jako součást adresy URL.

Warning

V ASP.NET Core 3.0 nebo vyšší, 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.
  • Poskytujte záruky ohledně pořadí spouštění rozšíření, například IRouteConstraint nebo IActionConstraint.

Viz Směrování, kde najdete referenční informace o směrování.

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

Konvenční směrování odpovídá pouze kombinaci akce a kontroleru, kterou aplikace definuje. Tento přístup zjednodušuje případy, kdy se běžné trasy překrývají. Když přidáte trasy pomocí MapControllerRoute, MapDefaultControllerRoute a MapAreaControllerRoute, endpointy automaticky získají hodnotu pořadí na základě pořadí, v jakém tyto metody voláte. Shody z trasy, která se zobrazí dříve v seznamu, mají vyšší prioritu. Konvenční směrování závisí na pořadí. Obecně umístěte trasy s oblastmi dříve, protože jsou konkrétnější než trasy bez oblasti. Vyhrazené konvenční trasy s parametry typu catch-all, například {*article}, mohou způsobit, že trasa bude příliš nenasytná. Cesta greedy odpovídá adresám URL, které jste chtěli shodovat s jinými trasami. Umístěte nenasytné trasy později ve směrovací tabulce, aby se zabránilo nenasytným shodám.

Warning

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 univerzální trasa {**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ávací trasa.

Podívejte se na GitHub chyby 18677 a 16579 pro příklady, kdy k této chybě dojde.

Oprava výslovného souhlasu s touto chybou je obsažena ve .NET Core 3.1.301 nebo novější sadě SDK. 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 mezi dvěma koncovými body naváže spojení prostřednictvím směrování, musí být proveden jeden z následujících kroků:

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

Napří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ěrování dat { 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 metoda HTTP jakákoli jiná. Edit(int) se obvykle volá prostřednictvím GET.

, HttpPostAttribute[HttpPost]je poskytována pro směrování tak, aby mohl zvolit na základě metody HTTP požadavku. HttpPostAttribute činí z Edit(int, Product) vhodnější volbu než z Edit(int).

Je důležité pochopit roli atributů, jako je HttpPostAttribute. Podobné atributy jsou definovány pro jiné příkazy HTTP. V případě konvenčního směrování je běžné, že akce používají stejný název, pokud jsou součástí pracovního postupu zobrazení a odeslání formuláře. Například viz Prozkoumejte dvě metody akce Upravit.

Pokud směrování nemůže vybrat nejlepšího kandidáta, vyvolá AmbiguousMatchException a uvede více odpovídajících koncových bodů.

Konvenční názvy tras

Řetězce "blog" a "default" v následujících příkladech 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. Pojmy název trasy 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ů pro modelování funkčnosti aplikace jako sady zdrojů, ve které jsou operace reprezentovány metodami 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 ke mapování kontrolerů se směrováním atributů.

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

  • HomeController odpovídá sadě adres URL podobné té, které odpovídá výchozí konvenční cesta {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 kteroukoli 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. Tradiční výchozí trasa zpracovává trasy stručněji. 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í pomocí atributů nehrají názvy kontroleru a akce žádnou roli při určování, která akce se vybere, 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 musí šablony metod Index před šablony tras přidat předponu / nebo ~/. Šablony tras použité u akce, které začínají na / nebo ~/, se nekombinují se šablonami tras použitými u řadiče.

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 pro názvy parametrů trasy při použití kontrolerů nebo stránek Razor:

  • action
  • area
  • controller
  • handler
  • page

Použití page jako parametru trasy se směrováním atributů je běžnou chybou. Výsledkem této volby 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);
    }
}

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

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

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

Tato klíčová slova nepoužívejte 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 obsahuje 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, takže id se připojí k "api/[controller]" šabloně na kontroleru. Šablona metody je "api/[controller]/{id}". Proto tato akce odpovídá pouze požadavkům GET pro formulář /api/test2/xyz, /api/test2/123, /api/test2/{any string}a tak dále.
    [HttpGet("{id}")]   // GET /api/test2/xyz
    public IActionResult GetProduct(string id)
    {
       return ControllerContext.MyDisplayRouteInfo(id);
    }
    
  • Akce GetIntProduct obsahuje "int/{id:int}" šablonu. Část šablony :int omezuje hodnoty trasy id 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.
    • Při vazbě modelu nelze převést abc na celé číslo. Parametr id metody je celé číslo.
    • Vrátí chybu 400 Bad Request, protože se při vazbě modelu 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í pomocí atributů může používat atributy, jako jsou HttpMethodAttribute, HttpPostAttribute, HttpPutAttribute a 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 URL /products3:

  • Akce MyProductsController.ListProducts se spustí, když je metoda HTTPGET.
  • Akce MyProductsController.CreateProduct se spustí, když je metoda HTTPPOST.

Při vytváření rozhraní API REST je zřídka nutné použít [Route(...)] na metodě akce, protože akce přijímá požadavky všech metod HTTP. Je lepší použít konkrétnější atribut metody HTTP, abyste přesně určili, co vaše API podporuje. REST Od klientů rozhraní API se očekává, že budou vědět, které cesty a metody HTTP odpovídají konkrétním logickým operacím.

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. Tento návrh znamená, že mnoho operací, jako je GET a POST ve stejném logickém prostředku, používá stejnou adresu URL. Směrování atributů poskytuje úroveň řízení potřebnou 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
  • Nespouští se s cestou URL /products2.

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

Pomocí názvů tras vygenerujte adresu URL na základě konkrétní trasy. Názvy tras:

  • Nemá žádný vliv na chování odpovídající URL v rámci routingu.
  • 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ě definovat rozhraní API má své výhody, například umožňuje, aby /products a /products/5 byly směrovány k různým akcím.

Kombinování tras atributů

Pokud chcete, aby směrování atributů bylo méně opakované, zkombinujte atributy směrování na kontroleru s atributy směrování na jednotlivých akcích. Šablony tras, které definujete na kontroleru, jsou předem nasměrované na šablony akcí. Když umístíte atribut trasy na kontroler, všechny akce v kontroleru používají směrování atributů.

[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 URL /products může odpovídat ProductsApi.ListProducts
  • Cesta URL /products/5 může odpovídat ProductsApi.GetProduct(int).

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

Směrovací šablony, které se vztahují na akci, a které začínají / nebo ~/ se nezkombinují se šablonami tras, které použijete u kontroleru. 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.

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

Pořadí pro trasování podle 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í.
  • Nejspecifičtější trasy mohou být vykonány před obecnějšími trasami.

Například atributová trasa, jako blog/search/{topic}, je specifičtější než atributová trasa, jako blog/{*article}. Trasa blog/search/{topic} má ve výchozím nastavení vyšší prioritu, protože je konkrétnější. Při použití konvenčního směrování je vývojář odpovědný za seřazení tras v požadovaném pořadí.

Trasy atributů můžou nakonfigurovat pořadí pomocí Order vlastnosti. Všechny atributy tras poskytované rámcem obsahují Order . Trasy se zpracovávají podle vzestupného řazení Order vlastnosti. Výchozí pořadí je 0. Trasa nastavená pomocí Order = -1 se zpracuje před trasami, které nemají nastavené pořadí. Nastavení trasy pomocí Order = 1 se provede až po výchozím pořadí tras.

Vyhněte se závislosti na Order. Pokud prostor adres URL aplikace vyžaduje explicitní pořadí hodnot pro správné směrování, je to pravděpodobně matoucí i 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í URL nefunguje, bývá obvykle jednodušší použít jako alternativu název routy než vlastnost Order.

Zvažte následující dva kontrolery, které oba definují shodu trasy /home:

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 pomocí předchozího kódu 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();
}

Pomocí předchozího kódu /home volá koncový bod HomeController.Index. Chcete-li se dostat k MyDemoController.MyIndex, vyžádejte si /home/MyIndex. Poznámka:

  • Předchozí kód je příkladem špatného návrhu směrování. Znázorňuje vlastnost Order.
  • Vlastnost Order vyřeší pouze nejednoznačnost. Tato šablona se nedá spárovat. Je lepší odebrat šablonu [Route("Home")].

Informace o pořadí tras v Razor Pages naleznete zde: Razor Konvence směrování a aplikací v Pages: Pořadí tras.

V některých případech se vrátí chyba HTTP 500 s nejednoznačnými trasami. Pomocí protokolování můžete zjistit, 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 a [action][area] jsou nahrazeny [controller]hodnotami názvu akce, názvu oblasti a názvu kontroleru z akce, ve které definujete trasu:

[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í tokenů 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í GitHub pokud chcete zobrazit komentáře ke kódu ve vašem nativním jazyce.

Trasy atributů můžete také kombinovat s dědičností. Tato kombinace je silná při použití náhrady 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 doslovně odpovídat oddělovači nahrazení doslovného tokenu [ nebo ], escapujte jej zopakováním znaku ([[ nebo ]]).

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

Nahrazení tokenu můžete 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á:

  • Aplikujte transformátor parametrů na všechny atributové trasy v aplikaci.
  • Přizpůsobí hodnoty tokenu trasového 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.

RouteTokenTransformerConvention je zaregistrován jako volba v ConfigureServices.

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

Definici pojmu slug najdete v webové dokumentaci MDN k pojmu slug.

Warning

Při zpracování nedůvěryhodného vstupu pomocí System.Text.RegularExpressions nastavte časový limit. Uživatel se zlými úmysly může poskytnout vstup do RegularExpressions, který způsobí útok typu Denial-of-Service. Rozhraní API architektury ASP.NET Core, která používají RegularExpressions, předávají časový limit.

Více atributových tras

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

Všechna omezení směrování pro HTTP verb implementují IActionConstraint.

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

  • Každé vytvořené omezení je kombinováno s šablonou 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 tématu Referenční informace 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 pro 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. Data z atributů trasy poskytuje implementace IRouteTemplateProvider. Conventions:

  • 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 zarovnává trasy tak, aby se zhruba shodovaly se strukturou 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 zabrání použití konvence namespace u kontrolerů, které používají směrování pomocí atributů:

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 řadičů na základě namespace, po odebrání základní 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.
  • NamespaceRoutingConvention nastaví šablonu kontrolerů na Admin/Controllers/Users/[action]/{id?.

NamespaceRoutingConvention lze také použít jako atribut u 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 Core aplikace můžou kombinovat použití konvenčního směrování a směrování atributů. Obvykle používáte konvenční směrování pro kontrolery, které vracejí prohlížečům stránky HTML, a atributové směrování pro kontrolery, které obsluhují rozhraní API REST.

Akce se směrují buď konvenčně, nebo jsou směrovány atributem. Umístěním trasy na kontroler nebo akci znamená, že je směrováno přes 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 mohou pomocí funkcí pro generování směrovacích URL vytvářet odkazy na akce. Generování adres URL eliminuje pevně zakódované adresy URL, což činí kód robustnějším a udržovatelnější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 vlastnosti Url v kontrolerech, zobrazeních a komponentách zobrazení.

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

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 proměnné url je řetězec cesty URL /UrlGeneration/Destination. Směrování vytvoří tuto cestu URL zkombinováním:

  • Směrovací hodnoty z aktuálního požadavku, které se nazývají okolní hodnoty.
  • Hodnoty předané do Url.Action a jejich nahrazení v šabloně 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 z šablony trasy {controller}/{action}/{id?}.

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 se používají k rozšíření šablony.
  • Hodnoty tras pro controller a action obvykle se v této šabloně zobrazují. To funguje, protože adresy URL, které jsou směrováním přiřazeny, dodržují zavedený standard.

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 na IUrlHelper má také odpovídající skupinu metod na 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.

Při použití Url.Actionmodul runtime poskytuje aktuální hodnoty tras pro controller a action:

  • Hodnoty 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.
  • Pro d už není k dispozici žádná hodnota a generování adresy URL selže.
  • Je nutné zadat požadované hodnoty c a d vygenerovat adresu 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 přijímá objekt hodnot trasy pro zadání hodnot parametrů trasy jiných než controller a action. Objekt hodnot tras se často používá s id. Například: Url.Action("Buy", "Products", new { id = 17 }). Objekt pro hodnoty 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 uloží 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é metodě Url.Action, ale nekopírují aktuální hodnoty action a controller do hodnot tras. Nejběžnější použití Url.RouteUrl:

  • Určuje název trasy pro vygenerování adresy URL.
  • Obecně se nespecifikuje název kontroléru nebo 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

IHtmlHelper HtmlHelper poskytuje metody Html.BeginForm a Html.ActionLink pro generování prvků <form> a <a> v tomto 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 HtmlHelperHtml.BeginRouteForm a Html.RouteLink mají podobné funkce.

TagHelpers generují adresy URL prostřednictvím form tagHelperu a TagHelperu <a> . Oba tyto prvky používají IUrlHelper ke své implementaci. Další informace naleznete v tématu Tag Helpery ve formulářích.

V zobrazeních je IUrlHelper k dispozici prostřednictvím vlastnosti Url pro jakékoli ad hoc generování adres URL, na které se nevztahují předchozí metody.

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

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

Základní třídy ControllerBase a Controller poskytují pomocné metody 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);
}

Tovární metody pro výsledky akcí, jako jsou RedirectToAction a CreatedAtAction, se řídí podobným vzorem jako metody třídy 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 trasa s názvem blog vyhrazenou konvenční trasou:

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 tras Url.Action("Index", "Home") vygeneruje cestu URL / pomocí trasy default, ale proč? Můžete uhodnout, že hodnoty { controller = Home, action = Index } tras stačí k vygenerování adresy URL pomocí bloga výsledek bude /blog?action=Index&controller=Home.

Vyhrazené konvenční trasy spoléhají na zvláštní chování výchozích hodnot, které nemají odpovídající parametr trasy, a které brání tomu, aby byla trasa při generování URL příliš nenasytná. V tomto případě jsou { controller = Blog, action = Article }výchozí hodnoty a ani controlleraction se nezobrazují jako parametr trasy. Při generování adresy URL musí směrování zajistit, aby zadané hodnoty odpovídaly výchozím hodnotám. Generování adresy URL selže blog, protože hodnoty { controller = Home, action = Index } neodpovídají { controller = Blog, action = Article }. Směrování pak jako náhradní možnost zkusí default, což se podaří.

Areas

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

  • Jmenný prostor směrování pro akce kontroléru
  • 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žívalo výchozí konvenční trasu a trasu area pro area s názvem 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, například /Manage/Users/AddUser, generuje trasa "blog_route" hodnoty trasy { area = Blog, controller = Users, action = AddUser }. Hodnota area trasy pochází z výchozí hodnoty pro area. Trasa vytvořená MapAreaControllerRoute pomocí tohoto kódu odpovídá následujícímu kódu:

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 s použitím zadaného názvu oblasti, v tomto případě Blog. Výchozí hodnota zajišťuje, že trasa vždy vytvoří { area = Blog, ... }a 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 by měly být trasy s oblastmi 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] nepatří do žádné oblasti a neodpovídají, když směrování poskytne hodnotu trasy area. 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}");
        }
    }
}

Pro úplnost, obor názvů každého řadiče je zde zobrazen. 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í řadič nepatří do žádné oblasti a může odpovídat pouze tehdy, pokud směrování neposkytne žádnou hodnotu pro area.

Pokud jde o shodu s žádnou hodnotou, nepřítomnost hodnoty area je stejná, jako kdyby hodnota pro area 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 při generování adres URL chovají lepivě, jak ukazuje následující příklad.

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

Diagnostika ladění

Nastavte Logging:LogLevel:Microsoft na Debug pro podrobný výstup diagnostiky směrování. V prostředí Development nastavte úroveň protokolu v appsettings.Development.json:

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