Routing do akcji kontrolera w ASP.NET CoreRouting to controller actions in ASP.NET Core

Ryan Nowak, Kirka Larkini Rick AndersonBy Ryan Nowak, Kirk Larkin, and Rick Anderson

Kontrolery ASP.NET Core używają oprogramowania pośredniczącego routingu do dopasowywania adresów URL żądań przychodzących i mapują je na Akcje.ASP.NET Core controllers use the Routing middleware to match the URLs of incoming requests and map them to actions. Szablony tras:Routes templates:

  • Są zdefiniowane w kodzie startowym lub atrybutów.Are defined in startup code or attributes.
  • Opisz, w jaki sposób ścieżki URL są dopasowywane do akcji.Describe how URL paths are matched to actions.
  • Służy do generowania adresów URL dla łączy.Are used to generate URLs for links. Wygenerowane linki są zwykle zwracane w odpowiedziach.The generated links are typically returned in responses.

Akcje są albo podkierowane do Konwencji lub kierowane przez atrybut.Actions are either conventionally-routed or attribute-routed. Umieszczenie trasy na kontrolerze lub akcji sprawia, że jest ona kierowana przez atrybut.Placing a route on the controller or action makes it attribute-routed. Aby uzyskać więcej informacji, zobacz Routing mieszany .See Mixed routing for more information.

Ten dokument:This document:

  • Wyjaśnia interakcje między MVC i Routing:Explains the interactions between MVC and routing:
    • Jak typowe aplikacje MVC używają funkcji routingu.How typical MVC apps make use of routing features.
    • Obejmuje zarówno:Covers both:
    • Szczegóły dotyczące routingu zaawansowanego znajdują się w temacie Routing .See Routing for advanced routing details.
  • Odnosi się do domyślnego systemu routingu dodanego w ASP.NET Core 3,0, nazywanego routingiem punktu końcowego.Refers to the default routing system added in ASP.NET Core 3.0, called endpoint routing. Możliwe jest używanie kontrolerów z poprzednią wersją routingu w celu zapewnienia zgodności.It's possible to use controllers with the previous version of routing for compatibility purposes. Instrukcje można znaleźć w przewodniku migracji 2.2-3.0 .See the 2.2-3.0 migration guide for instructions. Zapoznaj się z wersją 2,2 tego dokumentu dotyczącą materiałów referencyjnych w starszym systemie routingu.Refer to the 2.2 version of this document for reference material on the legacy routing system.

Konfigurowanie trasy konwencjonalnejSet up conventional route

Startup.Configure w przypadku korzystania z konwencjonalnego routinguzazwyczaj ma kod podobny do poniższego:Startup.Configure typically has code similar to the following when using conventional routing:

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

Wewnątrz wywołania do UseEndpoints , służy MapControllerRoute do tworzenia pojedynczej trasy.Inside the call to UseEndpoints, MapControllerRoute is used to create a single route. Pojedyncza trasa ma nazwę default Route.The single route is named default route. Większość aplikacji z kontrolerami i widokami używa szablonu trasy podobnego do default trasy.Most apps with controllers and views use a route template similar to the default route. Interfejsy API REST powinny używać routingu atrybutów.REST APIs should use attribute routing.

Szablon trasy "{controller=Home}/{action=Index}/{id?}" :The route template "{controller=Home}/{action=Index}/{id?}":

  • Dopasowuje ścieżkę URL, taką jak /Products/Details/5Matches a URL path like /Products/Details/5

  • Wyodrębnia wartości trasy { controller = Products, action = Details, id = 5 } przez tokenizowanie ścieżki.Extracts the route values { controller = Products, action = Details, id = 5 } by tokenizing the path. Wyodrębnienie wartości tras powoduje dopasowanie, jeśli aplikacja ma kontroler o nazwie ProductsController i Details akcję:The extraction of route values results in a match if the app has a controller named ProductsController and a Details action:

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

    MyDisplayRouteInfo jest dostarczany przez pakiet NuGet Rick. docs. Samples. RouteInfo i wyświetla informacje o trasie.MyDisplayRouteInfo is provided by the Rick.Docs.Samples.RouteInfo NuGet package and displays route information.

  • /Products/Details/5 Model wiąże wartość, id = 5 Aby ustawić parametr jako id 5 ./Products/Details/5 model binds the value of id = 5 to set the id parameter to 5. Aby uzyskać więcej informacji, zobacz powiązanie modelu .See Model Binding for more details.

  • {controller=Home} definiuje Home jako domyślny controller .{controller=Home} defines Home as the default controller.

  • {action=Index} definiuje Index jako domyślny action .{action=Index} defines Index as the default action.

  • ?Znak w {id?} definiuje id jako opcjonalny.The ? character in {id?} defines id as optional.

  • Domyślne i opcjonalne parametry trasy nie muszą być obecne w ścieżce URL dla dopasowania.Default and optional route parameters don't need to be present in the URL path for a match. Aby uzyskać szczegółowy opis składni szablonu trasy, zobacz odwołanie do szablonu trasy .See Route Template Reference for a detailed description of route template syntax.

  • Dopasowuje ścieżkę URL / .Matches the URL path /.

  • Tworzy wartości trasy { controller = Home, action = Index } .Produces the route values { controller = Home, action = Index }.

Wartości dla controller i action używają wartości domyślnych.The values for controller and action make use of the default values. id nie produkuje wartości, ponieważ nie ma odpowiedniego segmentu w ścieżce adresu URL.id doesn't produce a value since there's no corresponding segment in the URL path. / dopasowuje się tylko wtedy, gdy istnieje HomeController Index Akcja i:/ only matches if there exists a HomeController and Index action:

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

Przy użyciu definicji kontrolera i szablonu trasy, HomeController.Index Akcja jest uruchamiana dla następujących ścieżek URL:Using the preceding controller definition and route template, the HomeController.Index action is run for the following URL paths:

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

Ścieżka adresu URL / używa domyślnych Home kontrolerów i akcji szablonu trasy Index .The URL path / uses the route template default Home controllers and Index action. Ścieżka adresu URL /Home używa domyślnej akcji szablonu trasy Index .The URL path /Home uses the route template default Index action.

Wygodna metoda MapDefaultControllerRoute :The convenience method MapDefaultControllerRoute:

endpoints.MapDefaultControllerRoute();

ZastępującReplaces:

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

Ważne

Routing jest konfigurowany przy użyciu programu UseRouting i UseEndpoints oprogramowania pośredniczącego.Routing is configured using the UseRouting and UseEndpoints middleware. Aby użyć kontrolerów:To use controllers:

Routing konwencjonalnyConventional routing

Routing konwencjonalny jest używany z kontrolerami i widokami.Conventional routing is used with controllers and views. defaultTrasa:The default route:

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

jest przykładem konwencjonalnego routingu.is an example of a conventional routing. Jest on nazywany konwencjonalnym routingiem , ponieważ ustanawia Konwencję dla ścieżek adresów URL:It's called conventional routing because it establishes a convention for URL paths:

  • Pierwszy segment ścieżki, {controller=Home} mapuje na nazwę kontrolera.The first path segment, {controller=Home}, maps to the controller name.
  • Drugi segment, {action=Index} , mapuje na nazwę akcji .The second segment, {action=Index}, maps to the action name.
  • Trzeci segment {id?} jest używany jako opcjonalny id .The third segment, {id?} is used for an optional id. ?W programie w programie {id?} jest to opcjonalne.The ? in {id?} makes it optional. id służy do mapowania na jednostkę modelu.id is used to map to a model entity.

Przy użyciu tej default trasy ścieżka URL:Using this default route, the URL path:

  • /Products/List mapuje do ProductsController.List akcji./Products/List maps to the ProductsController.List action.
  • /Blog/Article/17 mapowanie na BlogController.Article model i zwykle wiąże się z id parametrem 17./Blog/Article/17 maps to BlogController.Article and typically model binds the id parameter to 17.

To mapowanie:This mapping:

  • Jest oparty tylko na nazwach kontrolera i akcji .Is based on the controller and action names only.
  • Nie jest oparty na przestrzeniach nazw, lokalizacjach plików źródłowych ani parametrach metod.Isn't based on namespaces, source file locations, or method parameters.

Użycie konwencjonalnego routingu z domyślną trasą umożliwia tworzenie aplikacji bez konieczności korzystania z nowego wzorca adresu URL dla każdej akcji.Using conventional routing with the default route allows creating the app without having to come up with a new URL pattern for each action. W przypadku aplikacji z akcjami w stylu CRUD mających spójność dla adresów URL między kontrolerami:For an app with CRUD style actions, having consistency for the URLs across controllers:

  • Upraszcza kod.Helps simplify the code.
  • Sprawia, że interfejs użytkownika jest bardziej przewidywalny.Makes the UI more predictable.

Ostrzeżenie

idW powyższym kodzie jest zdefiniowany jako opcjonalny przez szablon trasy.The id in the preceding code is defined as optional by the route template. Akcje można wykonać bez opcjonalnego identyfikatora podanego w ramach adresu URL.Actions can execute without the optional ID provided as part of the URL. Ogólnie mówiąc, gdy id pominięto w adresie URL:Generally, whenid is omitted from the URL:

  • id jest ustawiony na 0 przez powiązanie modelu.id is set to 0 by model binding.
  • Nie znaleziono jednostki w dopasowaniu do bazy danych id == 0 .No entity is found in the database matching id == 0.

Routing atrybutu zawiera szczegółowy formant, który umożliwia określanie identyfikatora wymaganego dla niektórych akcji, a nie dla innych.Attribute routing provides fine-grained control to make the ID required for some actions and not for others. Zgodnie z Konwencją, dokumentacja zawiera opcjonalne parametry, takie jak, id gdy prawdopodobnie pojawi się w prawidłowym użyciu.By convention, the documentation includes optional parameters like id when they're likely to appear in correct usage.

Większość aplikacji powinna wybrać podstawowy i opisowy schemat routingu, aby adresy URL były czytelne i zrozumiałe.Most apps should choose a basic and descriptive routing scheme so that URLs are readable and meaningful. Domyślna trasa konwencjonalna {controller=Home}/{action=Index}/{id?} :The default conventional route {controller=Home}/{action=Index}/{id?}:

  • Obsługuje podstawowy i opisowy schemat routingu.Supports a basic and descriptive routing scheme.
  • Jest użytecznym punktem wyjścia dla aplikacji opartych na interfejsie użytkownika.Is a useful starting point for UI-based apps.
  • Jest jedynym szablonem trasy wymaganym przez wiele aplikacji interfejsu użytkownika sieci Web.Is the only route template needed for many web UI apps. W przypadku większych aplikacji interfejsu użytkownika sieci Web inna trasa przy użyciu obszarów jest często wymagana.For larger web UI apps, another route using Areas is frequently all that's needed.

MapControllerRoute i MapAreaRoute :MapControllerRoute and MapAreaRoute :

  • Automatycznie Przypisz wartość zamówienia do punktów końcowych na podstawie kolejności, w której są wywoływane.Automatically assign an order value to their endpoints based on the order they are invoked.

Routing punktów końcowych w ASP.NET Core 3,0 i nowszych:Endpoint routing in ASP.NET Core 3.0 and later:

  • Nie ma koncepcji tras.Doesn't have a concept of routes.
  • Nie oferuje gwarancji porządkowania dla wykonywania rozszerzalności, wszystkie punkty końcowe są przetwarzane jednocześnie.Doesn't provide ordering guarantees for the execution of extensibility, all endpoints are processed at once.

Włącz Rejestrowanie , aby zobaczyć, jak wbudowane implementacje routingu, takie jak Route , dopasowują żądania.Enable Logging to see how the built-in routing implementations, such as Route, match requests.

Routing atrybutów został wyjaśniony w dalszej części tego dokumentu.Attribute routing is explained later in this document.

Wiele konwencjonalnych trasMultiple conventional routes

Wewnątrz można dodać wiele konwencjonalnych tras UseEndpoints , dodając więcej wywołań do MapControllerRoute i MapAreaControllerRoute .Multiple conventional routes can be added inside UseEndpoints by adding more calls to MapControllerRoute and MapAreaControllerRoute. Dzięki temu można definiować wiele Konwencji lub dodać do nich trasy konwencjonalne, które są przeznaczone dla konkretnej akcji, na przykład:Doing so allows defining multiple conventions, or to adding conventional routes that are dedicated to a specific action, such as:

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

blogTrasa w powyższym kodzie jest dedykowaną konwencjonalną trasą.The blog route in the preceding code is a dedicated conventional route. Jest on nazywany dedykowaną trasą konwencjonalną, ponieważ:It's called a dedicated conventional route because:

Ponieważ controller i action nie pojawiają się w szablonie trasy "blog/{*article}" jako parametry:Because controller and action don't appear in the route template "blog/{*article}" as parameters:

  • Mogą mieć tylko wartości domyślne { controller = "Blog", action = "Article" } .They can only have the default values { controller = "Blog", action = "Article" }.
  • Ta trasa zawsze jest mapowana na akcję BlogController.Article .This route always maps to the action BlogController.Article.

/Blog, /Blog/Article i /Blog/{any-string} są jedynymi ŚCIEŻKAmi URL, które pasują do trasy blogu./Blog, /Blog/Article, and /Blog/{any-string} are the only URL paths that match the blog route.

Powyższy przykład:The preceding example:

  • blog trasa ma wyższy priorytet dla dopasowania niż trasa, default ponieważ jest dodawana jako pierwsza.blog route has a higher priority for matches than the default route because it is added first.
  • Jest przykładem routingu stylów informacji o miejscu, w którym typowym jest nazwa artykułu w ramach adresu URL.Is an example of Slug style routing where it's typical to have an article name as part of the URL.

Ostrzeżenie

W ASP.NET Core 3,0 i nowszych routingu nie są:In ASP.NET Core 3.0 and later, routing doesn't:

  • Zdefiniuj koncepcję o nazwie trasa.Define a concept called a route. UseRouting dodaje dopasowanie trasy do potoku programu pośredniczącego.UseRouting adds route matching to the middleware pipeline. UseRoutingOprogramowanie pośredniczące sprawdza zestaw punktów końcowych zdefiniowanych w aplikacji i wybiera najlepsze dopasowanie punktu końcowego na podstawie żądania.The UseRouting middleware looks at the set of endpoints defined in the app, and selects the best endpoint match based on the request.
  • Podaj gwarancje dotyczące kolejności wykonywania rozszerzalności, takich jak IRouteConstraint lub IActionConstraint .Provide guarantees about the execution order of extensibility like IRouteConstraint or IActionConstraint.

Zobacz Routing dla materiałów referencyjnych na trasie.See Routing for reference material on routing.

Tradycyjna kolejność routinguConventional routing order

Routing konwencjonalny pasuje do kombinacji akcji i kontrolera, które są zdefiniowane przez aplikację.Conventional routing only matches a combination of action and controller that are defined by the app. Jest to przeznaczone do uproszczenia sytuacji, w których trasy konwencjonalne nakładają się na siebie.This is intended to simplify cases where conventional routes overlap. Dodanie tras przy użyciu MapControllerRoute , MapDefaultControllerRoute i MapAreaControllerRoute automatycznie przypisanie wartości zamówienia do punktów końcowych w oparciu o kolejność, w której są wywoływane.Adding routes using MapControllerRoute, MapDefaultControllerRoute, and MapAreaControllerRoute automatically assign an order value to their endpoints based on the order they are invoked. Dopasowania z trasy, która pojawiła się wcześniej, mają wyższy priorytet.Matches from a route that appears earlier have a higher priority. Routowanie konwencjonalne jest zależne od kolejności.Conventional routing is order-dependent. Ogólnie rzecz biorąc, trasy z obszarami powinny być umieszczone wcześniej, ponieważ są bardziej specyficzne niż trasy bez obszaru.In general, routes with areas should be placed earlier as they're more specific than routes without an area. Dedykowane konwencjonalne trasy ze wszystkimi parametrami tras, takich jak, {*article} mogą spowodować zbyt zachłannetrasy, co oznacza, że pasuje do adresów URL, które mają być dopasowane przez inne trasy.Dedicated conventional routes with catch-all route parameters like {*article} can make a route too greedy, meaning that it matches URLs that you intended to be matched by other routes. Umieść trasy zachłanne w dalszej części tabeli tras, aby zapobiec dopasowania zachłanne.Put the greedy routes later in the route table to prevent greedy matches.

Ostrzeżenie

Parametr "catch-all" może być zgodny z niepoprawnymi trasami z powodu błędu w routingu.A catch-all parameter may match routes incorrectly due to a bug in routing. Aplikacje, na które ma wpływ ta usterka, mają następującą charakterystykę:Apps impacted by this bug have the following characteristics:

  • Trasa przechwycenia, na przykład {**slug}"A catch-all route, for example, {**slug}"
  • Trasa catch-all nie będzie zgodna z żądaniami, które powinny być zgodne.The catch-all route fails to match requests it should match.
  • Usunięcie innych tras spowoduje rozpoczęcie pracy z całą trasą.Removing other routes makes catch-all route start working.

Zobacz błędy usługi GitHub 18677 i 16579 , aby zobaczyć przykładowe przypadki, w których trafili ten błąd.See GitHub bugs 18677 and 16579 for example cases that hit this bug.

Poprawka dotycząca tej usterki jest zawarta w programie .NET Core 3.1.301 SDK i nowszych.An opt-in fix for this bug is contained in .NET Core 3.1.301 SDK and later. Poniższy kod ustawia przełącznik wewnętrzny, który naprawia tę usterkę:The following code sets an internal switch that fixes this bug:

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

Rozwiązywanie niejednoznacznych akcjiResolving ambiguous actions

Gdy dwa punkty końcowe pasują do routingu, routing musi wykonać jedną z następujących czynności:When two endpoints match through routing, routing must do one of the following:

  • Wybierz najlepszego kandydata.Choose the best candidate.
  • Zgłoś wyjątek.Throw an exception.

Na przykład:For example:

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

Poprzedni kontroler definiuje dwie akcje, które są zgodne:The preceding controller defines two actions that match:

  • Ścieżka adresu URL /Products33/Edit/17The URL path /Products33/Edit/17
  • Kierowanie danych { controller = Products33, action = Edit, id = 17 } .Route data { controller = Products33, action = Edit, id = 17 }.

Jest to typowy wzorzec dla kontrolerów MVC:This is a typical pattern for MVC controllers:

  • Edit(int) Wyświetla formularz, w którym można edytować produkt.Edit(int) displays a form to edit a product.
  • Edit(int, Product) przetwarza opublikowany formularz.Edit(int, Product) processes the posted form.

Aby rozwiązać poprawność trasy:To resolve the correct route:

  • Edit(int, Product) jest wybierany, gdy żądanie jest HTTP POST .Edit(int, Product) is selected when the request is an HTTP POST.
  • Edit(int) jest wybierany, gdy czasownik http jest inny.Edit(int) is selected when the HTTP verb is anything else. Edit(int) jest zazwyczaj wywoływany za pośrednictwem GET .Edit(int) is generally called via GET.

HttpPostAttribute, [HttpPost] ,, Jest dostarczany do routingu, aby można było wybrać oparty na metodzie HTTP żądania.The HttpPostAttribute, [HttpPost], is provided to routing so that it can choose based on the HTTP method of the request. HttpPostAttributeZapewnia Edit(int, Product) lepszy odpowiednik niż Edit(int) .The HttpPostAttribute makes Edit(int, Product) a better match than Edit(int).

Ważne jest, aby zrozumieć rolę atrybutów, takich jak HttpPostAttribute .It's important to understand the role of attributes like HttpPostAttribute. Podobne atrybuty są zdefiniowane dla innych czasowników HTTP.Similar attributes are defined for other HTTP verbs. W przypadku routingu konwencjonalnegotypowe dla akcji używanie tej samej nazwy akcji, gdy są one częścią formularza Pokaż, przesyłania formularza.In conventional routing, it's common for actions to use the same action name when they're part of a show form, submit form workflow. Na przykład zapoznaj się z tematem badanie dwóch metod akcji edycji.For example, see Examine the two Edit action methods.

Jeśli routingu nie można wybrać najlepszego kandydata, AmbiguousMatchException zostanie zgłoszony, zawierający wiele pasujących punktów końcowych.If routing can't choose a best candidate, an AmbiguousMatchException is thrown, listing the multiple matched endpoints.

Nazwy tras konwencjonalnychConventional route names

Ciągi "blog" i "default" w poniższych przykładach są nazwami konwencjonalnych tras:The strings "blog" and "default" in the following examples are conventional route names:

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

Nazwy tras nadają trasie nazwę logiczną.The route names give the route a logical name. Nazwana trasa może służyć do generowania adresów URL.The named route can be used for URL generation. Użycie nazwanej trasy upraszcza tworzenie adresów URL, gdy porządkowanie tras może spowodować skomplikowane generowanie adresów URL.Using a named route simplifies URL creation when the ordering of routes could make URL generation complicated. Nazwy tras muszą być unikatowe w całej aplikacji.Route names must be unique application wide.

Nazwy tras:Route names:

  • Nie mają wpływu na pasujące adresy URL ani obsługę żądań.Have no impact on URL matching or handling of requests.
  • Są używane tylko do generowania adresów URL.Are used only for URL generation.

Koncepcja nazwy trasy jest reprezentowana w obszarze Routing jako IEndpointNameMetadata.The route name concept is represented in routing as IEndpointNameMetadata. Nazwa trasy i nazwa punktu końcowego :The terms route name and endpoint name :

  • Są zamienne.Are interchangeable.
  • Który jest używany w dokumentacji i kodu zależy od opisanego interfejsu API.Which one is used in documentation and code depends on the API being described.

Routing atrybutów dla interfejsów API RESTAttribute routing for REST APIs

Interfejsy API REST powinny używać routingu atrybutów do modelowania funkcjonalności aplikacji jako zestawu zasobów, w których operacje są reprezentowane przez zlecenia http.REST APIs should use attribute routing to model the app's functionality as a set of resources where operations are represented by HTTP verbs.

Funkcja routingu atrybutów używa zestawu atrybutów do mapowania akcji bezpośrednio do szablonów tras.Attribute routing uses a set of attributes to map actions directly to route templates. Poniższy StartUp.Configure kod jest typowy dla interfejsu API REST i jest używany w następnym przykładzie:The following StartUp.Configure code is typical for a REST API and is used in the next sample:

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

W powyższym kodzie MapControllers jest wywoływana w UseEndpoints celu mapowania kontrolerów z routingiem atrybutu.In the preceding code, MapControllers is called inside UseEndpoints to map attribute routed controllers.

W poniższym przykładzie:In the following example:

  • Poprzednia Configure Metoda jest używana.The preceding Configure method is used.
  • HomeController dopasowuje zestaw adresów URL podobny do tego, co jest zgodne z domyślną trasą konwencjonalny {controller=Home}/{action=Index}/{id?} .HomeController matches a set of URLs similar to what the default conventional route {controller=Home}/{action=Index}/{id?} matches.
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);
    }
}

HomeController.IndexAkcja jest uruchamiana dla dowolnej ścieżki URL,, / /Home /Home/Index , lub /Home/Index/3 .The HomeController.Index action is run for any of the URL paths /, /Home, /Home/Index, or /Home/Index/3.

W tym przykładzie przedstawiono najważniejsze różnice programistyczne między routingiem atrybutów i routingiem konwencjonalnym.This example highlights a key programming difference between attribute routing and conventional routing. Routing atrybutów wymaga więcej danych wejściowych w celu określenia trasy.Attribute routing requires more input to specify a route. Konwencjonalne trasy domyślne obsługuje trasy bardziej zwięzłie.The conventional default route handles routes more succinctly. Jednak Routing atrybutu zezwala na ścisłą kontrolę nad tym, które szablony tras mają zastosowanie do poszczególnych akcji.However, attribute routing allows and requires precise control of which route templates apply to each action.

W przypadku routingu atrybutów nazwy kontrolerów i akcji nie odgrywają części, w której akcja jest dopasowywana, chyba że zostanie użyta Zastępowanie tokenu .With attribute routing, the controller and action names play no part in which action is matched, unless token replacement is used. Poniższy przykład dopasowuje te same adresy URL, co w poprzednim przykładzie:The following example matches the same URLs as the previous example:

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

Następujący kod używa zastąpienia tokenu dla action i controller :The following code uses token replacement for action and 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();
    }
}

Następujący kod ma zastosowanie [Route("[controller]/[action]")] do kontrolera:The following code applies [Route("[controller]/[action]")] to the controller:

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

W poprzednim kodzie, Index Szablony metod muszą być poprzedzone / lub ~/ do szablonów tras.In the preceding code, the Index method templates must prepend / or ~/ to the route templates. Szablony tras zastosowane do akcji rozpoczynającej się od / lub ~/ nie są połączone z szablonami tras zastosowanymi do kontrolera.Route templates applied to an action that begin with / or ~/ don't get combined with route templates applied to the controller.

Zobacz pierwszeństwo szablonu trasy , aby uzyskać informacje o wyborze szablonu trasy.See Route template precedence for information on route template selection.

Zastrzeżone nazwy routinguReserved routing names

Następujące słowa kluczowe są zastrzeżonymi nazwami parametrów trasy podczas korzystania z kontrolerów lub Razor stron:The following keywords are reserved route parameter names when using Controllers or Razor Pages:

  • action
  • area
  • controller
  • handler
  • page

Użycie page jako parametru trasy z routingiem atrybutu jest typowym błędem.Using page as a route parameter with attribute routing is a common error. Powoduje to niespójne i mylące zachowanie przy generowaniu adresów URL.Doing that results in inconsistent and confusing behavior with URL generation.

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

Specjalne nazwy parametrów są używane przez generowanie adresów URL w celu ustalenia, czy operacja generowania adresu URL odwołuje się do Razor strony lub do kontrolera.The special parameter names are used by the URL generation to determine if a URL generation operation refers to a Razor Page or to a Controller.

Szablony czasowników HTTPHTTP verb templates

ASP.NET Core ma następujące szablony czasowników HTTP:ASP.NET Core has the following HTTP verb templates:

Szablony trasRoute templates

ASP.NET Core ma następujące szablony tras:ASP.NET Core has the following route templates:

Routing atrybutów z atrybutami czasownik httpAttribute routing with Http verb attributes

Rozważmy następujący kontroler:Consider the following controller:

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

Powyższy kod ma następujące działanie:In the preceding code:

  • Każda akcja zawiera [HttpGet] atrybut, który ogranicza dopasowywanie do żądań HTTP GET.Each action contains the [HttpGet] attribute, which constrains matching to HTTP GET requests only.
  • GetProductAkcja obejmuje "{id}" szablon, dlatego id jest dołączany do "api/[controller]" szablonu na kontrolerze.The GetProduct action includes the "{id}" template, therefore id is appended to the "api/[controller]" template on the controller. Szablon metod to "api/[controller]/"{id}"" .The methods template is "api/[controller]/"{id}"". W związku z tym ta akcja dopasowuje tylko żądania GET dla formularza /api/test2/xyz , itp /api/test2/123 /api/test2/{any string} .Therefore this action only matches GET requests for the form /api/test2/xyz,/api/test2/123,/api/test2/{any string}, etc.
    [HttpGet("{id}")]   // GET /api/test2/xyz
    public IActionResult GetProduct(string id)
    {
       return ControllerContext.MyDisplayRouteInfo(id);
    }
    
  • GetIntProductAkcja zawiera "int/{id:int}") szablon.The GetIntProduct action contains the "int/{id:int}") template. :intCzęść szablonu ogranicza id wartości trasy do ciągów, które mogą być konwertowane na liczbę całkowitą.The :int portion of the template constrains the id route values to strings that can be converted to an integer. Żądanie GET /api/test2/int/abc :A GET request to /api/test2/int/abc:
    • Nie jest zgodna z tą akcją.Doesn't match this action.
    • Zwraca błąd nie znaleziono 404 .Returns a 404 Not Found error.
      [HttpGet("int/{id:int}")] // GET /api/test2/int/3
      public IActionResult GetIntProduct(int id)
      {
          return ControllerContext.MyDisplayRouteInfo(id);
      }
      
  • GetInt2ProductAkcja zawiera {id} w szablonie, ale nie ogranicza id wartości, które można przekonwertować na liczbę całkowitą.The GetInt2Product action contains {id} in the template, but doesn't constrain id to values that can be converted to an integer. Żądanie GET /api/test2/int2/abc :A GET request to /api/test2/int2/abc:
    • Pasuje do tej trasy.Matches this route.
    • Nie można przekonwertować powiązania modelu abc na liczbę całkowitą.Model binding fails to convert abc to an integer. idParametr metody jest liczbą całkowitą.The id parameter of the method is integer.
    • Zwraca 400 Nieprawidłowe żądanie , ponieważ nie można skonwertować powiązania modelu abc na liczbę całkowitą.Returns a 400 Bad Request because model binding failed to convertabc to an integer.
      [HttpGet("int2/{id}")]  // GET /api/test2/int2/3
      public IActionResult GetInt2Product(int id)
      {
          return ControllerContext.MyDisplayRouteInfo(id);
      }
      

Funkcja routingu atrybutów może używać HttpMethodAttribute atrybutów takich jak HttpPostAttribute , HttpPutAttribute , i HttpDeleteAttribute .Attribute routing can use HttpMethodAttribute attributes such as HttpPostAttribute, HttpPutAttribute, and HttpDeleteAttribute. Wszystkie atrybuty czasowników HTTP akceptują szablon trasy.All of the HTTP verb attributes accept a route template. Poniższy przykład przedstawia dwie akcje, które pasują do tego samego szablonu trasy:The following example shows two actions that match the same route template:

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

Przy użyciu ścieżki URL /products3 :Using the URL path /products3:

  • MyProductsController.ListProductsAkcja jest uruchamiana, gdy czasownik http to GET .The MyProductsController.ListProducts action runs when the HTTP verb is GET.
  • MyProductsController.CreateProductAkcja jest uruchamiana, gdy czasownik http to POST .The MyProductsController.CreateProduct action runs when the HTTP verb is POST.

Podczas kompilowania interfejsu API REST jest to rzadko konieczne, aby użyć [Route(...)] metody akcji, ponieważ akcja akceptuje wszystkie metody http.When building a REST API, it's rare that you'll need to use [Route(...)] on an action method because the action accepts all HTTP methods. Lepiej jest używać bardziej szczegółowego atrybutu zlecenia http , aby precyzyjnie dowiedzieć się, co obsługuje interfejs API.It's better to use the more specific HTTP verb attribute to be precise about what your API supports. Klienci interfejsów API REST powinni wiedzieć, jakie ścieżki i czasowniki HTTP mapują na określone operacje logiczne.Clients of REST APIs are expected to know what paths and HTTP verbs map to specific logical operations.

Interfejsy API REST powinny używać routingu atrybutów do modelowania funkcjonalności aplikacji jako zestawu zasobów, w których operacje są reprezentowane przez zlecenia HTTP.REST APIs should use attribute routing to model the app's functionality as a set of resources where operations are represented by HTTP verbs. Oznacza to, że wiele operacji, na przykład Pobierz i Opublikuj dla tego samego zasobu logicznego, użyj tego samego adresu URL.This means that many operations, for example, GET and POST on the same logical resource use the same URL. Routing atrybutu zapewnia poziom kontroli, który jest wymagany do dokładnego projektowania układu publicznego punktu końcowego interfejsu API.Attribute routing provides a level of control that's needed to carefully design an API's public endpoint layout.

Ponieważ atrybut Route ma zastosowanie do określonej akcji, można łatwo wprowadzić parametry wymagane jako część definicji szablonu trasy.Since an attribute route applies to a specific action, it's easy to make parameters required as part of the route template definition. W poniższym przykładzie id jest wymagane jako część ścieżki URL:In the following example, id is required as part of the URL path:

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

Products2ApiController.GetProduct(int)Akcja:The Products2ApiController.GetProduct(int) action:

  • Jest uruchamiany z ścieżką URL podobną do /products2/3Is run with URL path like /products2/3
  • Nie jest uruchamiany z ścieżką URL /products2 .Isn't run with the URL path /products2.

Atrybut [ Requests] umożliwia akcja ograniczenia obsługiwanych typów zawartości żądania.The [Consumes] attribute allows an action to limit the supported request content types. Aby uzyskać więcej informacji, zobacz Definiowanie obsługiwanych typów zawartości żądania przy użyciu atrybutu użycia.For more information, see Define supported request content types with the Consumes attribute.

Aby uzyskać pełny opis szablonów tras i powiązanych opcji, zobacz Routing .See Routing for a full description of route templates and related options.

Aby uzyskać więcej informacji na temat [ApiController] , zobacz ApiController Attribute.For more information on [ApiController], see ApiController attribute.

Nazwa trasyRoute name

Następujący kod definiuje nazwę trasy Products_List :The following code defines a route name of Products_List:

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

Nazwy tras mogą służyć do generowania adresów URL na podstawie określonej trasy.Route names can be used to generate a URL based on a specific route. Nazwy tras:Route names:

  • Nie ma wpływu na zachowanie w zakresie routingu zgodnego z adresem URL.Have no impact on the URL matching behavior of routing.
  • Są używane tylko na potrzeby generowania adresów URL.Are only used for URL generation.

Nazwy tras muszą być unikatowe w całej aplikacji.Route names must be unique application-wide.

Powyższy kod przy użyciu konwencjonalnej trasy domyślnej, która definiuje id parametr jako opcjonalny ( {id?} ).Contrast the preceding code with the conventional default route, which defines the id parameter as optional ({id?}). Możliwość precyzyjnego określania interfejsów API ma zalety, takie jak umożliwienie /products i /products/5 wysyłanie ich do różnych akcji.The ability to precisely specify APIs has advantages, such as allowing /products and /products/5 to be dispatched to different actions.

Łączenie tras atrybutówCombining attribute routes

Aby mniej powtarzać Routing atrybutów, atrybuty trasy na kontrolerze są łączone z atrybutami trasy dla poszczególnych akcji.To make attribute routing less repetitive, route attributes on the controller are combined with route attributes on the individual actions. Wszystkie szablony tras zdefiniowane na kontrolerze są poprzedzone w celu rozesłania szablonów w akcjach.Any route templates defined on the controller are prepended to route templates on the actions. Umieszczenie atrybutu trasy na kontrolerze powoduje, że wszystkie akcje w kontrolerze używają routingu atrybutów.Placing a route attribute on the controller makes all actions in the controller use attribute routing.

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

W powyższym przykładzie:In the preceding example:

  • Ścieżka adresu URL /products może być taka sama ProductsApi.ListProductsThe URL path /products can match ProductsApi.ListProducts
  • Ścieżka adresu URL /products/5 może być taka sama ProductsApi.GetProduct(int) .The URL path /products/5 can match ProductsApi.GetProduct(int).

Obie te akcje pasują tylko do protokołu HTTP, GET ponieważ są oznaczone [HttpGet] atrybutem.Both of these actions only match HTTP GET because they're marked with the [HttpGet] attribute.

Szablony tras zastosowane do akcji rozpoczynającej się od / lub ~/ nie są połączone z szablonami tras zastosowanymi do kontrolera.Route templates applied to an action that begin with / or ~/ don't get combined with route templates applied to the controller. Poniższy przykład dopasowuje zestaw ścieżek adresów URL podobny do trasy domyślnej.The following example matches a set of URL paths similar to the default route.

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

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

W poniższej tabeli opisano [Route] atrybuty w poprzednim kodzie:The following table explains the [Route] attributes in the preceding code:

AtrybutAttribute Łączy z [Route("Home")]Combines with [Route("Home")] Definiuje szablon trasyDefines route template
[Route("")] TakYes "Home"
[Route("Index")] TakYes "Home/Index"
[Route("/")] NieNo ""
[Route("About")] TakYes "Home/About"

Porządek trasy dla atrybutuAttribute route order

Routing kompiluje drzewo i dopasowuje wszystkie punkty końcowe jednocześnie:Routing builds a tree and matches all endpoints simultaneously:

  • Wpisy trasy zachowują się tak, jakby zostały umieszczone w idealnej kolejności.The route entries behave as if placed in an ideal ordering.
  • Najbardziej konkretne trasy mają możliwość wykonania przed bardziej ogólnymi trasami.The most specific routes have a chance to execute before the more general routes.

Na przykład, podobnie jak w przypadku blog/search/{topic} bardziej szczegółowych informacji niż trasie atrybutu blog/{*article} .For example, an attribute route like blog/search/{topic} is more specific than an attribute route like blog/{*article}. blog/search/{topic}Trasa ma wyższy priorytet, ponieważ jest domyślnie bardziej specyficzna.The blog/search/{topic} route has higher priority, by default, because it's more specific. Przy użyciu konwencjonalnego routingudeweloper jest odpowiedzialny za umieszczanie tras w odpowiedniej kolejności.Using conventional routing, the developer is responsible for placing routes in the desired order.

Trasy atrybutów mogą konfigurować zamówienie przy użyciu Order właściwości.Attribute routes can configure an order using the Order property. Wszystkie atrybuty trasy dostarczonej przez platformę obejmują Order .All of the framework provided route attributes include Order . Trasy są przetwarzane zgodnie z rosnącą sortowaniem Order właściwości.Routes are processed according to an ascending sort of the Order property. Kolejność domyślna to 0 .The default order is 0. Ustawianie trasy przy użyciu Order = -1 przebiegów przed trasami, które nie ustawiają kolejności.Setting a route using Order = -1 runs before routes that don't set an order. Ustawianie trasy przy użyciu Order = 1 przebiegu po domyślnej kolejności tras.Setting a route using Order = 1 runs after default route ordering.

Należy unikać w zależności od Order .Avoid depending on Order. Jeśli przestrzeń adresów URL aplikacji wymaga jawnych wartości kolejności, aby można było prawidłowo kierować trasy, prawdopodobnie również jest myląca dla klientów.If an app's URL-space requires explicit order values to route correctly, then it's likely confusing to clients as well. Ogólnie rzecz biorąc, routing atrybutów wybiera prawidłową trasę z dopasowywaniem adresów URL.In general, attribute routing selects the correct route with URL matching. Jeśli domyślna kolejność generowania adresów URL nie działa, użycie nazwy trasy jako przesłonięcia jest zwykle prostsze niż stosowanie Order właściwości.If the default order used for URL generation isn't working, using a route name as an override is usually simpler than applying the Order property.

Należy wziąć pod uwagę następujące dwa kontrolery, które definiują trasę zgodną z /home :Consider the following two controllers which both define the route matching /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);
    }
}

Żądanie /home z powyższym kodem zgłasza wyjątek podobny do następującego:Requesting /home with the preceding code throws an exception similar to the following:

AmbiguousMatchException: The request matched multiple endpoints. Matches:

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

Dodanie Order do jednego z atrybutów trasy rozwiązuje niejednoznaczność:Adding Order to one of the route attributes resolves the ambiguity:

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

Za pomocą powyższego kodu program /home uruchamia HomeController.Index punkt końcowy.With the preceding code, /home runs the HomeController.Index endpoint. , Aby przejść do MyDemoController.MyIndex żądania /home/MyIndex .To get to the MyDemoController.MyIndex, request /home/MyIndex. Uwaga :Note :

  • Poprzedni kod jest przykładem lub słabym projektem routingu.The preceding code is an example or poor routing design. Została użyta do zilustrowania Order właściwości.It was used to illustrate the Order property.
  • OrderWłaściwość rozwiązuje tylko niejednoznaczność, ale nie można dopasować tego szablonu.The Order property only resolves the ambiguity, that template cannot be matched. Lepszym rozwiązaniem jest usunięcie [Route("Home")] szablonu.It would be better to remove the [Route("Home")] template.

Zobacz Razor strony trasy i konwencje aplikacji: kolejność tras na potrzeby informacji o kolejności tras na Razor stronach.See Razor Pages route and app conventions: Route order for information on route order with Razor Pages.

W niektórych przypadkach błąd HTTP 500 jest zwracany z niejednoznacznych tras.In some cases, an HTTP 500 error is returned with ambiguous routes. Użyj rejestrowania , aby zobaczyć, które punkty końcowe spowodowały AmbiguousMatchException .Use logging to see which endpoints caused the AmbiguousMatchException.

Zastępowanie tokenu w szablonach tras [Controller], [Action], [obszar]Token replacement in route templates [controller], [action], [area]

Dla wygody atrybut trasy obsługują zastępowanie tokenów dla zarezerwowanych parametrów trasy przez załączanie tokenu w jednym z następujących:For convenience, attribute routes support token replacement for reserved route parameters by enclosing a token in one of the following:

  • Nawiasy kwadratowe: []Square brackets: []
  • Nawiasy klamrowe: {}Curly braces: {}

Tokeny [action] , [area] i [controller] są zastępowane wartościami nazwy akcji, obszaru i nazwy kontrolera z akcji, w której zdefiniowano trasę:The tokens [action], [area], and [controller] are replaced with the values of the action name, area name, and controller name from the action where the route is defined:

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

Powyższy kod ma następujące działanie:In the preceding code:

[HttpGet]
public IActionResult List()
{
    return ControllerContext.MyDisplayRouteInfo();
}
  • Prawdopodobny /Products0/ListMatches /Products0/List
[HttpGet("{id}")]
public IActionResult Edit(int id)
{
    return ControllerContext.MyDisplayRouteInfo(id);
}
  • Prawdopodobny /Products0/Edit/{id}Matches /Products0/Edit/{id}

Zastępowanie tokenu występuje jako ostatni krok tworzenia tras atrybutów.Token replacement occurs as the last step of building the attribute routes. Poprzedni przykład zachowuje się tak samo jak w poniższym kodzie:The preceding example behaves the same as the following code:

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

Jeśli czytasz ten kod w języku innym niż angielski, daj nam znać ten problem w dyskusji w witrynie GitHub, jeśli chcesz zobaczyć Komentarze do kodu w Twoim języku macierzystym.If you are reading this in a language other than English, let us know in this GitHub discussion issue if you'd like to see the code comments in your native language.

Trasy atrybutu można także łączyć z dziedziczeniem.Attribute routes can also be combined with inheritance. Jest to zaawansowane połączenie z zastępowaniem tokenu.This is powerful combined with token replacement. Zastępowanie tokenu dotyczy również nazw tras zdefiniowanych przez trasy atrybutów.Token replacement also applies to route names defined by attribute routes. [Route("[controller]/[action]", Name="[controller]_[action]")]generuje unikatową nazwę trasy dla każdej akcji:[Route("[controller]/[action]", Name="[controller]_[action]")]generates a unique route name for each action:

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

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

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

Zastępowanie tokenu dotyczy również nazw tras zdefiniowanych przez trasy atrybutów.Token replacement also applies to route names defined by attribute routes. [Route("[controller]/[action]", Name="[controller]_[action]")] generuje unikatową nazwę trasy dla każdej akcji.generates a unique route name for each action.

Aby dopasować ogranicznik zamiany tokenu literału [ lub ] , należy to zrobić, powtarzając znak ( [[ lub ]] ).To match the literal token replacement delimiter [ or ], escape it by repeating the character ([[ or ]]).

Używanie transformatora parametrów do dostosowywania zastępowania tokenuUse a parameter transformer to customize token replacement

Zastępowanie tokenu można dostosować za pomocą transformatora parametrów.Token replacement can be customized using a parameter transformer. Transformator parametrów implementuje IOutboundParameterTransformer i przekształca wartość parametrów.A parameter transformer implements IOutboundParameterTransformer and transforms the value of parameters. Na przykład niestandardowy SlugifyParameterTransformer transformator parametrów zmienia SubscriptionManagement wartość trasy na subscription-management :For example, a custom SlugifyParameterTransformer parameter transformer changes the SubscriptionManagement route value to 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();
    }
}

RouteTokenTransformerConventionJest konwencją modelu aplikacji, która:The RouteTokenTransformerConvention is an application model convention that:

  • Stosuje transformator parametrów do wszystkich tras atrybutów w aplikacji.Applies a parameter transformer to all attribute routes in an application.
  • Dostosowuje wartości tokenów tras w miarę ich wymiany.Customizes the attribute route token values as they are replaced.
public class SubscriptionManagementController : Controller
{
    [HttpGet("[controller]/[action]")]
    public IActionResult ListAll()
    {
        return ControllerContext.MyDisplayRouteInfo();
    }
}

Poprzednia ListAll Metoda pasuje /subscription-management/list-all .The preceding ListAll method matches /subscription-management/list-all.

RouteTokenTransformerConventionJest zarejestrowany jako opcja w ConfigureServices .The RouteTokenTransformerConvention is registered as an option in ConfigureServices.

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

Zobacz powiadomienia MDN Web docs , aby zapoznać się z definicją informacji o sobie.See MDN web docs on Slug for the definition of Slug.

Ostrzeżenie

Podczas używania System.Text.RegularExpressions do przetwarzania niezaufanych danych wejściowych należy przekazać limit czasu.When using System.Text.RegularExpressions to process untrusted input, pass a timeout. Złośliwy użytkownik może podać dane wejściowe RegularExpressions , aby spowodować atak typu "odmowa usługi".A malicious user can provide input to RegularExpressions causing a Denial-of-Service attack. Interfejsy API środowiska ASP.NET Core Framework RegularExpressions , które używają przekazywania limitu czasu.ASP.NET Core framework APIs that use RegularExpressions pass a timeout.

Wiele tras atrybutówMultiple attribute routes

Routing atrybutów obsługuje definiowanie wielu tras, które docierają do tej samej akcji.Attribute routing supports defining multiple routes that reach the same action. Najczęstszym sposobem użycia tej metody jest naśladowanie zachowania domyślnej trasy konwencjonalnej, jak pokazano w następującym przykładzie:The most common usage of this is to mimic the behavior of the default conventional route as shown in the following example:

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

Umieszczenie wielu atrybutów trasy na kontrolerze oznacza, że każda z nich łączy się z każdym z atrybutów tras w metodach akcji:Putting multiple route attributes on the controller means that each one combines with each of the route attributes on the action methods:

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

Wszystkie ograniczenia trasy http zlecenia są implementowane IActionConstraint .All the HTTP verb route constraints implement IActionConstraint.

Gdy wiele atrybutów trasy, które implementują IActionConstraint są umieszczane w akcji:When multiple route attributes that implement IActionConstraint are placed on an action:

  • Każde ograniczenie akcji łączy się z szablonem trasy zastosowanym do kontrolera.Each action constraint combines with the route template applied to the controller.
[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();
    }
}

Korzystanie z wielu tras w akcjach może wydawać się użyteczne i zaawansowane, dlatego lepiej jest zachować podstawową i dobrze zdefiniowaną przestrzeń adresów URL aplikacji.Using multiple routes on actions might seem useful and powerful, it's better to keep your app's URL space basic and well defined. Użyj wielu tras w przypadku akcji tylko wtedy , gdy jest to konieczne, na przykład w celu obsługi istniejących klientów.Use multiple routes on actions only where needed, for example, to support existing clients.

Określanie opcjonalnych parametrów trasy, wartości domyślnych i ograniczeńSpecifying attribute route optional parameters, default values, and constraints

Trasy atrybutów obsługują tę samą składnię wbudowaną co konwencjonalne trasy, aby określić parametry opcjonalne, wartości domyślne i ograniczenia.Attribute routes support the same inline syntax as conventional routes to specify optional parameters, default values, and constraints.

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

W poprzednim kodzie, [HttpPost("product/{id:int}")] stosuje ograniczenie trasy.In the preceding code, [HttpPost("product/{id:int}")] applies a route constraint. ProductsController.ShowProductAkcja jest dopasowywana tylko przez ścieżki URL, takie jak /product/3 .The ProductsController.ShowProduct action is matched only by URL paths like /product/3. Część szablonu trasy {id:int} ogranicza ten segment tylko do liczb całkowitych.The route template portion {id:int} constrains that segment to only integers.

Aby uzyskać szczegółowy opis składni szablonu trasy, zobacz odwołanie do szablonu trasy .See Route Template Reference for a detailed description of route template syntax.

Niestandardowe atrybuty trasy przy użyciu IRouteTemplateProviderCustom route attributes using IRouteTemplateProvider

Wszystkie atrybuty trasy implementują IRouteTemplateProvider .All of the route attributes implement IRouteTemplateProvider. Środowisko uruchomieniowe ASP.NET Core:The ASP.NET Core runtime:

  • Wyszukuje atrybuty klas kontrolera i metod akcji podczas uruchamiania aplikacji.Looks for attributes on controller classes and action methods when the app starts.
  • Używa atrybutów, które implementują IRouteTemplateProvider w celu utworzenia początkowego zestawu tras.Uses the attributes that implement IRouteTemplateProvider to build the initial set of routes.

Zaimplementuj IRouteTemplateProvider , aby zdefiniować niestandardowe atrybuty trasy.Implement IRouteTemplateProvider to define custom route attributes. Każdy IRouteTemplateProvider z nich umożliwia definiowanie pojedynczej trasy z niestandardowym szablonem trasy, kolejnością i nazwą:Each IRouteTemplateProvider allows you to define a single route with a custom route template, order, and name:

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

Poprzednia Get Metoda zwraca Order = 2, Template = api/MyTestApi .The preceding Get method returns Order = 2, Template = api/MyTestApi.

Dostosowywanie tras atrybutów przy użyciu modelu aplikacjiUse application model to customize attribute routes

Model aplikacji:The application model:

  • Jest modelem obiektu utworzonym podczas uruchamiania.Is an object model created at startup.
  • Zawiera wszystkie metadane używane przez ASP.NET Core do kierowania i wykonywania akcji w aplikacji.Contains all of the metadata used by ASP.NET Core to route and execute the actions in an app.

Model aplikacji zawiera wszystkie dane zebrane z atrybutów tras.The application model includes all of the data gathered from route attributes. Dane z atrybutów trasy są udostępniane przez IRouteTemplateProvider implementację.The data from route attributes is provided by the IRouteTemplateProvider implementation. ObowiązującyConventions:

  • Można napisać, aby zmodyfikować model aplikacji, aby dostosować sposób zachowania routingu.Can be written to modify the application model to customize how routing behaves.
  • Są odczytywane podczas uruchamiania aplikacji.Are read at app startup.

W tej sekcji przedstawiono podstawowy przykład dostosowywania routingu przy użyciu modelu aplikacji.This section shows a basic example of customizing routing using application model. Poniższy kod sprawia, że trasy są w przybliżeniu zgodne ze strukturą folderów projektu.The following code makes routes roughly line up with the folder structure of the project.

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

Poniższy kod uniemożliwia namespace stosowanie Konwencji do kontrolerów, które są kierowane przez atrybut:The following code prevents the namespace convention from being applied to controllers that are attribute routed:

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

Na przykład następujący kontroler nie używa NamespaceRoutingConvention :For example, the following controller doesn't use 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}");
    }
}

NamespaceRoutingConvention.ApplyMetoda:The NamespaceRoutingConvention.Apply method:

  • Nie robi nic, Jeśli kontroler ma przypisany atrybut.Does nothing if the controller is attribute routed.
  • Ustawia szablon szablonu oparty na namespace , z namespace usuniętym podstawowym.Sets the controllers template based on the namespace, with the base namespace removed.

NamespaceRoutingConventionMożna zastosować w Startup.ConfigureServices :The NamespaceRoutingConvention can be applied in 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.

Rozważmy na przykład następujący kontroler:For example, consider the following controller:

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

Powyższy kod ma następujące działanie:In the preceding code:

  • Podstawą namespace jest My.Application .The base namespace is My.Application.
  • Pełna nazwa poprzedniego kontrolera to My.Application.Admin.Controllers.UsersController .The full name of the preceding controller is My.Application.Admin.Controllers.UsersController.
  • NamespaceRoutingConventionUstawia szablon controllers na Admin/Controllers/Users/[action]/{id? .The NamespaceRoutingConvention sets the controllers template to Admin/Controllers/Users/[action]/{id?.

NamespaceRoutingConventionMożna również zastosować jako atrybut na kontrolerze:The NamespaceRoutingConvention can also be applied as an attribute on a controller:

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

Routing mieszany: Routing atrybutów a konwencjonalny RoutingMixed routing: Attribute routing vs conventional routing

Aplikacje ASP.NET Core mogą łączyć użycie konwencjonalnych routingu i routingu atrybutów.ASP.NET Core apps can mix the use of conventional routing and attribute routing. Typowym zastosowaniem są trasy konwencjonalne dla kontrolerów obsługujących strony HTML dla przeglądarek i routingu atrybutów dla kontrolerów obsługujących interfejsy API REST.It's typical to use conventional routes for controllers serving HTML pages for browsers, and attribute routing for controllers serving REST APIs.

Akcje są albo podkierowane do Konwencji lub kierowane przez atrybut.Actions are either conventionally routed or attribute routed. Umieszczenie trasy na kontrolerze lub akcja powoduje, że atrybut jest kierowany.Placing a route on the controller or the action makes it attribute routed. Akcje definiujące trasy atrybutów nie mogą być osiągane za pomocą konwencjonalnych tras i vice versa.Actions that define attribute routes cannot be reached through the conventional routes and vice-versa. Każdy atrybut trasy na kontrolerze powoduje kierowanie wszystkich akcji w atrybucie kontrolera.Any route attribute on the controller makes all actions in the controller attribute routed.

Routing atrybutów i Routing konwencjonalny używają tego samego aparatu routingu.Attribute routing and conventional routing use the same routing engine.

Generowanie adresów URL i wartości otoczeniaURL Generation and ambient values

Aplikacje mogą używać funkcji generowania adresów URL routingu do generowania linków URL do akcji.Apps can use routing URL generation features to generate URL links to actions. Generowanie adresów URL eliminuje adresy URL zakodowana, co sprawia, że kod jest bardziej niezawodny i konserwowany.Generating URLs eliminates hardcoding URLs, making code more robust and maintainable. Ta sekcja koncentruje się na funkcjach generowania adresów URL udostępnianych przez MVC i obejmuje jedynie podstawowe informacje na temat sposobu działania generowania adresów URL.This section focuses on the URL generation features provided by MVC and only cover basics of how URL generation works. Aby uzyskać szczegółowy opis generowania adresów URL, zobacz temat Routing .See Routing for a detailed description of URL generation.

IUrlHelperInterfejs jest podstawowym elementem infrastruktury między MVC i Routing na potrzeby generowania adresów URL.The IUrlHelper interface is the underlying element of infrastructure between MVC and routing for URL generation. Wystąpienie IUrlHelper jest dostępne za pomocą Url właściwości w kontrolerach, widokach i składnikach widoku.An instance of IUrlHelper is available through the Url property in controllers, views, and view components.

W poniższym przykładzie IUrlHelper interfejs jest używany przez Controller.Url Właściwość w celu WYGENEROWANIA adresu URL dla innej akcji.In the following example, the IUrlHelper interface is used through the Controller.Url property to generate a URL to another action.

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

Jeśli aplikacja używa domyślnej trasy konwencjonalnej, wartość url zmiennej jest ciągiem ścieżki URL /UrlGeneration/Destination .If the app is using the default conventional route, the value of the url variable is the URL path string /UrlGeneration/Destination. Ta ścieżka URL jest tworzona przez połączenie za pomocą routingu:This URL path is created by routing by combining:

  • Wartości trasy z bieżącego żądania, które są nazywane wartościami otoczenia.The route values from the current request, which are called ambient values.
  • Wartości przesyłane do Url.Action i podstawiające te wartości do szablonu trasy:The values passed to Url.Action and substituting those values into the route template:
ambient values: { controller = "UrlGeneration", action = "Source" }
values passed to Url.Action: { controller = "UrlGeneration", action = "Destination" }
route template: {controller}/{action}/{id?}

result: /UrlGeneration/Destination

Każdy parametr trasy w szablonie trasy ma swoją wartość zastępowaną przez pasujące nazwy wartościami i wartościami otoczenia.Each route parameter in the route template has its value substituted by matching names with the values and ambient values. Parametr trasy, który nie ma wartości, może:A route parameter that doesn't have a value can:

  • Użyj wartości domyślnej, jeśli ma ją.Use a default value if it has one.
  • Można pominąć, jeśli jest to opcjonalne.Be skipped if it's optional. Na przykład, id z szablonu trasy {controller}/{action}/{id?} .For example, the id from the route template {controller}/{action}/{id?}.

Generowanie adresu URL kończy się niepowodzeniem, jeśli którykolwiek z wymaganych parametrów trasy nie ma odpowiadającej mu wartości.URL generation fails if any required route parameter doesn't have a corresponding value. Jeśli generowanie adresów URL kończy się niepowodzeniem dla trasy, kolejna trasa zostanie ponowiona do momentu przetworzenia wszystkich tras lub znalezienia dopasowania.If URL generation fails for a route, the next route is tried until all routes have been tried or a match is found.

W poprzednim przykładzie Url.Action przyjęto założenie konwencjonalnego routingu.The preceding example of Url.Action assumes conventional routing. Generowanie adresów URL działa podobnie jak w przypadku routingu atrybutów, chociaż koncepcje różnią się.URL generation works similarly with attribute routing, though the concepts are different. Z routingiem konwencjonalnym:With conventional routing:

  • Wartości trasy służą do rozszerzania szablonu.The route values are used to expand a template.
  • Wartości trasy dla controller i action zwykle pojawiają się w tym szablonie.The route values for controller and action usually appear in that template. Dzieje się tak, ponieważ adresy URL dopasowane przez Routing są zgodne z Konwencją.This works because the URLs matched by routing adhere to a convention.

W poniższym przykładzie zastosowano Routing atrybutów:The following example uses attribute routing:

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

SourceAkcja w poprzednim kodzie generuje custom/url/to/destination .The Source action in the preceding code generates custom/url/to/destination.

LinkGenerator został dodany w ASP.NET Core 3,0 jako alternatywa dla IUrlHelper .LinkGenerator was added in ASP.NET Core 3.0 as an alternative to IUrlHelper. LinkGenerator oferuje podobne, ale bardziej elastyczne funkcje.LinkGenerator offers similar but more flexible functionality. Każda metoda w systemie IUrlHelper ma również odpowiednią rodzinę metod LinkGenerator .Each method on IUrlHelper has a corresponding family of methods on LinkGenerator as well.

Generowanie adresów URL według nazwy akcjiGenerating URLs by action name

Wartość URL. Action, LinkGenerator. GetPathByActioni wszystkie powiązane przeciążenia są przeznaczone do generowania docelowego punktu końcowego przez określenie nazwy kontrolera i nazwy akcji.Url.Action, LinkGenerator.GetPathByAction, and all related overloads all are designed to generate the target endpoint by specifying a controller name and action name.

W przypadku używania Url.Action , bieżąca wartość trasy dla controller i action jest udostępniana przez środowisko uruchomieniowe:When using Url.Action, the current route values for controller and action are provided by the runtime:

  • Wartość controller i action jest częścią zarówno wartości otoczenia , jak i wartości.The value of controller and action are part of both ambient values and values. Metoda Url.Action zawsze używa bieżących wartości action i controller i generuje ścieżkę URL, która jest przesyłana do bieżącej akcji.The method Url.Action always uses the current values of action and controller and generates a URL path that routes to the current action.

Funkcja routingu próbuje użyć wartości w otoczeniu wartości, aby podać informacje, które nie zostały dostarczone podczas generowania adresu URL.Routing attempts to use the values in ambient values to fill in information that wasn't provided when generating a URL. Rozważ użycie trasy podobnej do {a}/{b}/{c}/{d} wartości otoczenia { a = Alice, b = Bob, c = Carol, d = David } :Consider a route like {a}/{b}/{c}/{d} with ambient values { a = Alice, b = Bob, c = Carol, d = David }:

  • Routing ma wystarczającą ilość informacji do wygenerowania adresu URL bez dodatkowych wartości.Routing has enough information to generate a URL without any additional values.
  • Routing ma wystarczającą ilość informacji, ponieważ wszystkie parametry tras mają wartość.Routing has enough information because all route parameters have a value.

Jeśli wartość { d = Donovan } zostanie dodana:If the value { d = Donovan } is added:

  • Wartość { d = David } jest ignorowana.The value { d = David } is ignored.
  • Wygenerowana Ścieżka adresu URL to Alice/Bob/Carol/Donovan .The generated URL path is Alice/Bob/Carol/Donovan.

Ostrzeżenie : ścieżki URL są hierarchiczne.Warning : URL paths are hierarchical. W poprzednim przykładzie, jeśli wartość { c = Cheryl } jest dodawana:In the preceding example, if the value { c = Cheryl } is added:

  • Obie wartości { c = Carol, d = David } są ignorowane.Both of the values { c = Carol, d = David } are ignored.
  • Nie jest już dostępna wartość d i generowanie adresu URL nie powiodło się.There is no longer a value for d and URL generation fails.
  • Wymagane wartości c i d muszą być określone w celu WYGENEROWANIA adresu URL.The desired values of c and d must be specified to generate a URL.

Prawdopodobnie wystąpił problem z domyślną trasą {controller}/{action}/{id?} .You might expect to hit this problem with the default route {controller}/{action}/{id?}. Ten problem występuje rzadko Url.Action , ponieważ zawsze jawnie określa controller action wartość i.This problem is rare in practice because Url.Action always explicitly specifies a controller and action value.

Kilka przeciążeń adresu URL. akcja przyjmuje obiekt wartości trasy, aby podać wartości parametrów trasy innych niż controller i action .Several overloads of Url.Action take a route values object to provide values for route parameters other than controller and action. Obiekt wartości trasy jest często używany z id .The route values object is frequently used with id. Na przykład Url.Action("Buy", "Products", new { id = 17 }).For example, Url.Action("Buy", "Products", new { id = 17 }). Obiekt wartości trasy:The route values object:

  • Według Konwencji jest zwykle obiektem typu anonimowego.By convention is usually an object of anonymous type.
  • Może to być IDictionary<> lub poco).Can be an IDictionary<> or a POCO).

Wszystkie dodatkowe wartości trasy, które nie pasują do parametrów trasy, są umieszczane w ciągu zapytania.Any additional route values that don't match route parameters are put in the query string.

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

Poprzedni kod generuje /Products/Buy/17?color=red .The preceding code generates /Products/Buy/17?color=red.

Poniższy kod generuje bezwzględny adres URL:The following code generates an absolute 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);
}

Aby utworzyć bezwzględny adres URL, użyj jednego z następujących elementów:To create an absolute URL, use one of the following:

  • Przeciążenie, które akceptuje protocol .An overload that accepts a protocol. Na przykład poprzedzający kod.For example, the preceding code.
  • LinkGenerator. GetUriByAction, który domyślnie generuje bezwzględne identyfikatory URI.LinkGenerator.GetUriByAction, which generates absolute URIs by default.

Generuj adresy URL według trasyGenerate URLs by route

Poprzedni kod wykazał wygenerowanie adresu URL przez przekazanie go do kontrolera i nazwy akcji.The preceding code demonstrated generating a URL by passing in the controller and action name. IUrlHelper zapewnia także rodzinę adresów URL. RouteUrl .IUrlHelper also provides the Url.RouteUrl family of methods. Te metody są podobne do adresu URL. Action, ale nie kopiują bieżących wartości action i controller do wartości trasy.These methods are similar to Url.Action, but they don't copy the current values of action and controller to the route values. Najczęstsze użycie Url.RouteUrl :The most common usage of Url.RouteUrl:

  • Określa nazwę trasy do wygenerowania adresu URL.Specifies a route name to generate the URL.
  • Zwykle nie określa kontrolera ani nazwy akcji.Generally doesn't specify a controller or action name.
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();
    }

Następujący Razor plik generuje link HTML do Destination_Route :The following Razor file generates an HTML link to the Destination_Route:

<h1>Test Links</h1>

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

Generuj adresy URL w kodzie HTML i RazorGenerate URLs in HTML and Razor

IHtmlHelper udostępnia HtmlHelper metody HTML. BeginForm oraz HTML. ActionLink do wygenerowania <form> i <a> elementów.IHtmlHelper provides the HtmlHelper methods Html.BeginForm and Html.ActionLink to generate <form> and <a> elements respectively. Metody te używają metody URL. Action do generowania adresu URL i akceptują podobne argumenty.These methods use the Url.Action method to generate a URL and they accept similar arguments. Url.RouteUrlPomocników dla programu HtmlHelper mają Html.BeginRouteForm Html.RouteLink podobną funkcjonalność.The Url.RouteUrl companions for HtmlHelper are Html.BeginRouteForm and Html.RouteLink which have similar functionality.

TagHelpers Generuj adresy URL za pomocą form TagHelper i <a> TagHelper.TagHelpers generate URLs through the form TagHelper and the <a> TagHelper. Oba te zastosowania IUrlHelper dla ich implementacji.Both of these use IUrlHelper for their implementation. Aby uzyskać więcej informacji, zobacz pomocników tagów w formularzach .See Tag Helpers in forms for more information.

W widokach IUrlHelper można korzystać z Url właściwości dla dowolnej generacji adresów URL ad hoc, która nie jest objęta powyższym.Inside views, the IUrlHelper is available through the Url property for any ad-hoc URL generation not covered by the above.

Generowanie adresów URL w wynikach akcjiURL generation in Action Results

Poprzednie przykłady pokazano przy użyciu IUrlHelper w kontrolerze.The preceding examples showed using IUrlHelper in a controller. Najczęstszym sposobem użycia na kontrolerze jest wygenerowanie adresu URL jako części wyniku akcji.The most common usage in a controller is to generate a URL as part of an action result.

ControllerBase Controller Klasy bazowe i zapewniają wygodne metody dla wyników akcji, które odwołują się do innej akcji.The ControllerBase and Controller base classes provide convenience methods for action results that reference another action. Jednym z typowych zastosowań jest przekierowanie po zaakceptowaniu danych wejściowych użytkownika:One typical usage is to redirect after accepting user input:

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

Wynikiem akcji są metody fabryki, takie jak RedirectToAction i, CreatedAtAction postępuj zgodnie z podobnym wzorcem do metod w IUrlHelper .The action results factory methods such as RedirectToAction and CreatedAtAction follow a similar pattern to the methods on IUrlHelper.

Specjalny przypadek dla dedykowanych tras konwencjonalnychSpecial case for dedicated conventional routes

Funkcja routingu konwencjonalnego może używać specjalnego rodzaju definicji trasy o nazwie dedykowanej, konwencjonalnej trasy.Conventional routing can use a special kind of route definition called a dedicated conventional route. W poniższym przykładzie trasa o nazwie blog jest dedykowaną konwencjonalną trasą:In the following example, the route named blog is a dedicated conventional route:

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

Przy użyciu powyższych definicji trasy program Url.Action("Index", "Home") generuje ścieżkę URL / przy użyciu default trasy, ale dlaczego?Using the preceding route definitions, Url.Action("Index", "Home") generates the URL path / using the default route, but why? Możliwe jest odpuszczenie, że wartości trasy { controller = Home, action = Index } byłyby wystarczające do wygenerowania adresu URL przy użyciu blog , a wynikiem będzie /blog?action=Index&controller=Home .You might guess the route values { controller = Home, action = Index } would be enough to generate a URL using blog, and the result would be /blog?action=Index&controller=Home.

Dedykowane konwencjonalne trasy polegają na specjalnym zachowaniu wartości domyślnych, które nie mają odpowiadającego parametru trasy, który uniemożliwia zbyt zachłanne trasy z generowaniem adresów URL.Dedicated conventional routes rely on a special behavior of default values that don't have a corresponding route parameter that prevents the route from being too greedy with URL generation. W takim przypadku wartości domyślne to { controller = Blog, action = Article } , a ani nie controller action pojawiają się jako parametr trasy.In this case the default values are { controller = Blog, action = Article }, and neither controller nor action appears as a route parameter. Gdy Routing wykonuje generowanie adresów URL, podane wartości muszą być zgodne z wartościami domyślnymi.When routing performs URL generation, the values provided must match the default values. Generowanie adresu URL blog nie powiodło się, ponieważ wartości { controller = Home, action = Index } nie są zgodne { controller = Blog, action = Article } .URL generation using blog fails because the values { controller = Home, action = Index } don't match { controller = Blog, action = Article }. Następnie usługa routingu wraca do wypróbowania default , która się powiedzie.Routing then falls back to try default, which succeeds.

ObszaryAreas

Obszary są funkcją MVC służącą do organizowania powiązanych funkcji w grupie jako oddzielnej:Areas are an MVC feature used to organize related functionality into a group as a separate:

  • Przestrzeń nazw routingu dla akcji kontrolera.Routing namespace for controller actions.
  • Struktura folderów dla widoków.Folder structure for views.

Użycie obszarów umożliwia aplikacji posiadanie wielu kontrolerów o tej samej nazwie, o ile mają one różne obszary.Using areas allows an app to have multiple controllers with the same name, as long as they have different areas. Za pomocą obszarów tworzy hierarchię na potrzeby routingu przez dodanie kolejnego parametru trasy area do controller i action .Using areas creates a hierarchy for the purpose of routing by adding another route parameter, area to controller and action. W tej sekcji omówiono sposób, w jaki Routing współdziała z obszarami.This section discusses how routing interacts with areas. Zobacz obszary , aby uzyskać szczegółowe informacje na temat sposobu używania obszarów w widokach.See Areas for details about how areas are used with views.

Poniższy przykład konfiguruje MVC do używania domyślnej trasy konwencjonalnej i area trasy dla area nazwanego Blog :The following example configures MVC to use the default conventional route and an area route for an area named Blog:

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

W poprzednim kodzie MapAreaControllerRoute jest wywoływana w celu utworzenia "blog_route" .In the preceding code, MapAreaControllerRoute is called to create the "blog_route". Drugi parametr, "Blog" , jest nazwą obszaru.The second parameter, "Blog", is the area name.

W przypadku dopasowania ścieżki URL podobnej /Manage/Users/AddUser do "blog_route" trasy generuje wartości trasy { area = Blog, controller = Users, action = AddUser } .When matching a URL path like /Manage/Users/AddUser, the "blog_route" route generates the route values { area = Blog, controller = Users, action = AddUser }. areaWartość trasy jest generowana przez wartość domyślną dla area .The area route value is produced by a default value for area. Trasa utworzona przez MapAreaControllerRoute jest równoważna następującym:The route created by MapAreaControllerRoute is equivalent to the following:

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 tworzy trasę przy użyciu wartości domyślnej i ograniczenia dotyczącej area użycia podanej nazwy obszaru, w tym przypadku Blog .MapAreaControllerRoute creates a route using both a default value and constraint for area using the provided area name, in this case Blog. Wartość domyślna zapewnia, że trasa zawsze produkuje { area = Blog, ... } , ograniczenie wymaga wartości { area = Blog, ... } dla generowania adresów URL.The default value ensures that the route always produces { area = Blog, ... }, the constraint requires the value { area = Blog, ... } for URL generation.

Routowanie konwencjonalne jest zależne od kolejności.Conventional routing is order-dependent. Ogólnie rzecz biorąc, trasy z obszarami powinny być umieszczone wcześniej, ponieważ są bardziej specyficzne niż trasy bez obszaru.In general, routes with areas should be placed earlier as they're more specific than routes without an area.

Korzystając z powyższego przykładu, wartości trasy { area = Blog, controller = Users, action = AddUser } są zgodne z następującą akcją:Using the preceding example, the route values { area = Blog, controller = Users, action = AddUser } match the following action:

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

Atrybut [Area] wskazuje, co oznacza kontroler w ramach obszaru.The [Area] attribute is what denotes a controller as part of an area. Ten kontroler znajduje się w Blog obszarze.This controller is in the Blog area. Kontrolery bez [Area] atrybutu nie są członkami żadnego obszaru i nie są zgodne, gdy area wartość trasy jest dostarczana przez Routing.Controllers without an [Area] attribute are not members of any area, and do not match when the area route value is provided by routing. W poniższym przykładzie tylko pierwszy kontroler może być zgodny z wartościami trasy { area = Blog, controller = Users, action = AddUser } .In the following example, only the first controller listed can match the route values { area = Blog, controller = Users, action = AddUser }.

using Microsoft.AspNetCore.Mvc;

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

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

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

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

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

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

Przestrzeń nazw każdego kontrolera jest pokazana w tym miejscu na potrzeby kompletności.The namespace of each controller is shown here for completeness. Jeśli powyższe kontrolery używają tego samego obszaru nazw, wygenerowany zostanie błąd kompilatora.If the preceding controllers uses the same namespace, a compiler error would be generated. Przestrzenie nazw klas nie mają wpływu na Routing MVC.Class namespaces have no effect on MVC's routing.

Pierwsze dwa kontrolery są członkami obszarów i są zgodne tylko wtedy, gdy ich nazwa obszaru jest podana przez area wartość trasy.The first two controllers are members of areas, and only match when their respective area name is provided by the area route value. Trzeci kontroler nie jest członkiem żadnego obszaru i można go dopasować tylko wtedy, gdy nie ma żadnej wartości parametru area Routing.The third controller isn't a member of any area, and can only match when no value for area is provided by routing.

W warunkach pasujących do nie ma żadnej wartości, brak area wartości jest taka sama jak wartość area null lub pusty ciąg.In terms of matching no value , the absence of the area value is the same as if the value for area were null or the empty string.

Podczas wykonywania akcji wewnątrz obszaru wartość trasy dla area jest dostępna jako wartość otoczenia dla routingu do użycia na potrzeby generowania adresów URL.When executing an action inside an area, the route value for area is available as an ambient value for routing to use for URL generation. Oznacza to, że domyślnie obszary programu Sticky Notes mają być używane do generowania adresów URL, jak pokazano w poniższym przykładzie.This means that by default areas act sticky for URL generation as demonstrated by the following sample.

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

Poniższy kod generuje adres URL /Zebra/Users/AddUser :The following code generates a URL to /Zebra/Users/AddUser:

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

Definicja akcjiAction definition

Metody publiczne na kontrolerze, z wyjątkiem tych z atrybutem nie będącym akcją , są akcjami.Public methods on a controller, except those with the NonAction attribute, are actions.

Przykładowy kodSample code

Diagnostyka debugowaniaDebug diagnostics

W celu uzyskania szczegółowych danych wyjściowych diagnostycznych routingu ustaw wartość Logging:LogLevel:Microsoft Debug .For detailed routing diagnostic output, set Logging:LogLevel:Microsoft to Debug. W środowisku programistycznym Ustaw poziom rejestrowania w appsettings.Development.jsna:In the development environment, set the log level in appsettings.Development.json:

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

ASP.NET Core MVC używa oprogramowania pośredniczącego routingu, aby dopasować adresy URL żądań przychodzących i zmapować je na akcje.ASP.NET Core MVC uses the Routing middleware to match the URLs of incoming requests and map them to actions. Trasy są zdefiniowane w kodzie startowym lub atrybutów.Routes are defined in startup code or attributes. Trasy opisują sposób dopasowywania ścieżek adresów URL do akcji.Routes describe how URL paths should be matched to actions. Trasy są również używane do generowania adresów URL (dla linków) wysyłanych w odpowiedziach.Routes are also used to generate URLs (for links) sent out in responses.

Akcje są albo podkierowane do Konwencji lub kierowane przez atrybut.Actions are either conventionally routed or attribute routed. Umieszczenie trasy na kontrolerze lub akcja powoduje, że atrybut jest kierowany.Placing a route on the controller or the action makes it attribute routed. Aby uzyskać więcej informacji, zobacz Routing mieszany .See Mixed routing for more information.

Ten dokument wyjaśnia interakcje między MVC i routingiem oraz sposób, w jaki typowe aplikacje MVC używają funkcji routingu.This document will explain the interactions between MVC and routing, and how typical MVC apps make use of routing features. Zobacz Routing , aby uzyskać szczegółowe informacje na temat routingu zaawansowanego.See Routing for details on advanced routing.

Konfigurowanie oprogramowania pośredniczącego routinguSetting up Routing Middleware

W metodzie konfigurowania może zostać wyświetlony kod podobny do:In your Configure method you may see code similar to:

app.UseMvc(routes =>
{
   routes.MapRoute("default", "{controller=Home}/{action=Index}/{id?}");
});

Wewnątrz wywołania do UseMvc , służy MapRoute do tworzenia pojedynczej trasy, którą będziemy odnosić jako default trasy.Inside the call to UseMvc, MapRoute is used to create a single route, which we'll refer to as the default route. Większość aplikacji MVC będzie używać trasy z szablonem podobnym do default trasy.Most MVC apps will use a route with a template similar to the default route.

Szablon trasy "{controller=Home}/{action=Index}/{id?}" może być zgodny z ścieżką URL /Products/Details/5 , tak jak i będzie wyodrębniał wartości trasy { controller = Products, action = Details, id = 5 } przez tokenizowanie ścieżki.The route template "{controller=Home}/{action=Index}/{id?}" can match a URL path like /Products/Details/5 and will extract the route values { controller = Products, action = Details, id = 5 } by tokenizing the path. MVC spróbuje zlokalizować kontroler o nazwie ProductsController i uruchomić akcję Details :MVC will attempt to locate a controller named ProductsController and run the action Details:

public class ProductsController : Controller
{
   public IActionResult Details(int id) { ... }
}

Należy zauważyć, że w tym przykładzie powiązanie modelu będzie używać wartości, id = 5 Aby ustawić id parametr 5 podczas wywoływania tej akcji.Note that in this example, model binding would use the value of id = 5 to set the id parameter to 5 when invoking this action. Aby uzyskać więcej informacji, zobacz powiązanie modelu .See the Model Binding for more details.

Przy użyciu default trasy:Using the default route:

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

Szablon trasy:The route template:

  • {controller=Home} definiuje Home jako domyślne controller{controller=Home} defines Home as the default controller

  • {action=Index} definiuje Index jako domyślne action{action=Index} defines Index as the default action

  • {id?} definiuje id jako opcjonalne{id?} defines id as optional

Domyślne i opcjonalne parametry trasy nie muszą być obecne w ścieżce URL dla dopasowania.Default and optional route parameters don't need to be present in the URL path for a match. Aby uzyskać szczegółowy opis składni szablonu trasy, zobacz odwołanie do szablonu trasy .See Route Template Reference for a detailed description of route template syntax.

"{controller=Home}/{action=Index}/{id?}" może być zgodna ze ścieżką URL / i będzie generować wartości trasy { controller = Home, action = Index } ."{controller=Home}/{action=Index}/{id?}" can match the URL path / and will produce the route values { controller = Home, action = Index }. Wartości dla controller i action używają wartości domyślnych, id nie tworzy wartości, ponieważ w ścieżce URL nie ma odpowiedniego segmentu.The values for controller and action make use of the default values, id doesn't produce a value since there's no corresponding segment in the URL path. Aby można było wybrać akcję i, MVC będzie używać tych wartości tras HomeController Index :MVC would use these route values to select the HomeController and Index action:

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

Przy użyciu tej definicji kontrolera i szablonu trasy HomeController.Index Akcja będzie wykonywana dla dowolnej z następujących ścieżek URL:Using this controller definition and route template, the HomeController.Index action would be executed for any of the following URL paths:

  • /Home/Index/17

  • /Home/Index

  • /Home

  • /

Wygodna metoda UseMvcWithDefaultRoute :The convenience method UseMvcWithDefaultRoute:

app.UseMvcWithDefaultRoute();

Może służyć do zastępowania:Can be used to replace:

app.UseMvc(routes =>
{
   routes.MapRoute("default", "{controller=Home}/{action=Index}/{id?}");
});

UseMvc i UseMvcWithDefaultRoute Dodaj wystąpienie RouterMiddleware do potoku programu pośredniczącego.UseMvc and UseMvcWithDefaultRoute add an instance of RouterMiddleware to the middleware pipeline. MVC nie działa bezpośrednio w oprogramowaniu pośredniczącym i używa routingu do obsługi żądań.MVC doesn't interact directly with middleware, and uses routing to handle requests. MVC jest połączony z trasami za pomocą wystąpienia MvcRouteHandler .MVC is connected to the routes through an instance of MvcRouteHandler. Kod w programie UseMvc jest podobny do następującego:The code inside of UseMvc is similar to the following:

var routes = new RouteBuilder(app);

// Add connection to MVC, will be hooked up by calls to MapRoute.
routes.DefaultHandler = new MvcRouteHandler(...);

// Execute callback to register routes.
// routes.MapRoute("default", "{controller=Home}/{action=Index}/{id?}");

// Create route collection and add the middleware.
app.UseRouter(routes.Build());

UseMvc nie definiuje bezpośrednio żadnych tras, dodaje symbol zastępczy do kolekcji tras dla attribute trasy.UseMvc doesn't directly define any routes, it adds a placeholder to the route collection for the attribute route. Przeciążenie UseMvc(Action<IRouteBuilder>) umożliwia dodanie własnych tras, a także obsługuje routing atrybutów.The overload UseMvc(Action<IRouteBuilder>) lets you add your own routes and also supports attribute routing. UseMvc i wszystkie jego odmiany dodają symbol zastępczy dla atrybutu trasy — atrybut jest zawsze dostępny niezależnie od sposobu konfigurowania UseMvc .UseMvc and all of its variations add a placeholder for the attribute route - attribute routing is always available regardless of how you configure UseMvc. UseMvcWithDefaultRoute Definiuje domyślną trasę i obsługuje routing atrybutów.UseMvcWithDefaultRoute defines a default route and supports attribute routing. Sekcja Routing atrybutów zawiera więcej szczegółów dotyczących routingu atrybutów.The Attribute Routing section includes more details on attribute routing.

Routing konwencjonalnyConventional routing

defaultTrasa:The default route:

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

Poprzedni kod jest przykładem konwencjonalnego routingu.The preceding code is an example of a conventional routing. Ten styl jest nazywany routingiem konwencjonalnym, ponieważ ustanawia Konwencję dla ścieżek adresów URL:This style is called conventional routing because it establishes a convention for URL paths:

  • Pierwszy segment ścieżki jest mapowany na nazwę kontrolera.The first path segment maps to the controller name.
  • Druga mapowanie na nazwę akcji.The second maps to the action name.
  • Trzeci segment jest używany opcjonalnie id .The third segment is used for an optional id. id mapuje do jednostki modelu.id maps to a model entity.

Przy użyciu tej default trasy ścieżka URL jest /Products/List mapowana na ProductsController.List akcję i jest /Blog/Article/17 mapowana na BlogController.Article .Using this default route, the URL path /Products/List maps to the ProductsController.List action, and /Blog/Article/17 maps to BlogController.Article. To mapowanie jest oparte tylko na nazwach kontrolera i akcji, a nie na podstawie przestrzeni nazw, lokalizacji plików źródłowych ani parametrów metody.This mapping is based on the controller and action names only and isn't based on namespaces, source file locations, or method parameters.

Porada

Użycie konwencjonalnego routingu z domyślną trasą umożliwia szybkie Kompilowanie aplikacji bez konieczności podawania nowego wzorca adresu URL dla każdej zdefiniowanej akcji.Using conventional routing with the default route allows you to build the application quickly without having to come up with a new URL pattern for each action you define. W przypadku aplikacji z akcjami w stylu CRUD zachowanie spójności adresów URL na kontrolerach może pomóc uprościć kod i uczynić interfejs użytkownika bardziej przewidywalny.For an application with CRUD style actions, having consistency for the URLs across your controllers can help simplify your code and make your UI more predictable.

Ostrzeżenie

idJest zdefiniowany jako opcjonalny przez szablon trasy, co oznacza, że akcje mogą być wykonywane bez identyfikatora dostarczonego jako część adresu URL.The id is defined as optional by the route template, meaning that your actions can execute without the ID provided as part of the URL. Typowo, co się stanie, jeśli zostanie id pominięty z adresu URL, to zostanie ono ustawione na 0 podstawie powiązania modelu, a w rezultacie nie zostanie znaleziona żadna jednostka w dopasowaniu do bazy danych id == 0 .Usually what will happen if id is omitted from the URL is that it will be set to 0 by model binding, and as a result no entity will be found in the database matching id == 0. Routing atrybutu może dać szczegółowy formant, który ma być wymagany dla niektórych akcji, a nie dla innych.Attribute routing can give you fine-grained control to make the ID required for some actions and not for others. Zgodnie z Konwencją dokumentacja będzie zawierać opcjonalne parametry, takie jak, id gdy prawdopodobnie będą widoczne w prawidłowym użyciu.By convention the documentation will include optional parameters like id when they're likely to appear in correct usage.

Wiele trasMultiple routes

Można dodać wiele tras wewnątrz UseMvc , dodając więcej wywołań do MapRoute .You can add multiple routes inside UseMvc by adding more calls to MapRoute. Dzięki temu można zdefiniować wiele Konwencji lub dodać trasy konwencjonalne, które są przeznaczone dla konkretnej akcji, na przykład:Doing so allows you to define multiple conventions, or to add conventional routes that are dedicated to a specific action, such as:

app.UseMvc(routes =>
{
   routes.MapRoute("blog", "blog/{*article}",
            defaults: new { controller = "Blog", action = "Article" });
   routes.MapRoute("default", "{controller=Home}/{action=Index}/{id?}");
});

blogTrasa w tym miejscu jest dedykowaną tradycyjną trasą , co oznacza, że używa systemu routingu konwencjonalnego, ale jest przeznaczona dla konkretnej akcji.The blog route here is a dedicated conventional route , meaning that it uses the conventional routing system, but is dedicated to a specific action. Ponieważ controller i action nie pojawiają się w szablonie trasy jako parametry, mogą mieć tylko wartości domyślne i w związku z tym trasa będzie zawsze mapowana na akcję BlogController.Article .Since controller and action don't appear in the route template as parameters, they can only have the default values, and thus this route will always map to the action BlogController.Article.

Trasy w kolekcji tras są uporządkowane i będą przetwarzane w kolejności, w jakiej zostały dodane.Routes in the route collection are ordered, and will be processed in the order they're added. W tym przykładzie blog zostanie podjęta próba trasy przed default trasą.So in this example, the blog route will be tried before the default route.

Uwaga

Dedykowane konwencjonalne trasy często korzystają z parametrów trasy catch-all , takich jak {*article} przechwytywanie pozostałej części ścieżki URL.Dedicated conventional routes often use catch-all route parameters like {*article} to capture the remaining portion of the URL path. Może to spowodować, że trasa "zbyt zachłanne" oznacza, że pasuje do adresów URL, które mają być dopasowane przez inne trasy.This can make a route 'too greedy' meaning that it matches URLs that you intended to be matched by other routes. Umieść trasy "zachłanne" później w tabeli tras, aby rozwiązać ten problem.Put the 'greedy' routes later in the route table to solve this.

Opcja rezerwowaFallback

W ramach przetwarzania żądań MVC sprawdzi, czy wartości trasy mogą być używane do znajdowania kontrolera i akcji w aplikacji.As part of request processing, MVC will verify that the route values can be used to find a controller and action in your application. Jeśli wartości trasy nie są zgodne z akcją, trasa nie jest uważana za dopasowanie i zostanie podjęta kolejna trasa.If the route values don't match an action then the route isn't considered a match, and the next route will be tried. Jest to nazywane Fallback i ma na celu uproszczenie przypadków, w których trasy konwencjonalne nakładają się na siebie.This is called fallback , and it's intended to simplify cases where conventional routes overlap.

Niejednoznaczne akcjeDisambiguating actions

Gdy dwie akcje są zgodne z routingiem, MVC musi odróżnić się, aby wybrać najlepszy kandydat lub w przeciwnym razie zgłosić wyjątek.When two actions match through routing, MVC must disambiguate to choose the 'best' candidate or else throw an exception. Na przykład:For example:

public class ProductsController : Controller
{
   public IActionResult Edit(int id) { ... }

   [HttpPost]
   public IActionResult Edit(int id, Product product) { ... }
}

Ten kontroler definiuje dwie akcje, które byłyby zgodne ze ścieżką URL /Products/Edit/17 i danymi tras { controller = Products, action = Edit, id = 17 } .This controller defines two actions that would match the URL path /Products/Edit/17 and route data { controller = Products, action = Edit, id = 17 }. Jest to typowy wzorzec dla kontrolerów MVC, gdzie Edit(int) pokazuje formularz służący do edytowania produktu i Edit(int, Product) przetwarza opublikowany formularz.This is a typical pattern for MVC controllers where Edit(int) shows a form to edit a product, and Edit(int, Product) processes the posted form. Aby ten możliwy składnik MVC musiał wybrać, Edit(int, Product) gdy żądanie jest http POST i Edit(int) gdy zlecenie http jest inne.To make this possible MVC would need to choose Edit(int, Product) when the request is an HTTP POST and Edit(int) when the HTTP verb is anything else.

HttpPostAttribute( [HttpPost] ) Jest implementacją programu IActionConstraint , która będzie zezwalać na wybór akcji tylko wtedy, gdy czasownik http to POST .The HttpPostAttribute ( [HttpPost] ) is an implementation of IActionConstraint that will only allow the action to be selected when the HTTP verb is POST. Obecność elementu sprawia, że IActionConstraint Edit(int, Product) lepszym rozwiązaniem jest dopasowanie Edit(int) , więc Edit(int, Product) zostanie ono najpierw ponowione.The presence of an IActionConstraint makes the Edit(int, Product) a 'better' match than Edit(int), so Edit(int, Product) will be tried first.

Musisz tylko pisać IActionConstraint implementacje niestandardowe w wyspecjalizowanych scenariuszach, ale ważne jest, aby zrozumieć rolę atrybutów, takich jak HttpPostAttribute atrybuty podobne do innych czasowników HTTP.You will only need to write custom IActionConstraint implementations in specialized scenarios, but it's important to understand the role of attributes like HttpPostAttribute - similar attributes are defined for other HTTP verbs. W przypadku routingu konwencjonalnego typowe dla akcji używanie tej samej nazwy akcji, gdy są one częścią show form -> submit form przepływu pracy.In conventional routing it's common for actions to use the same action name when they're part of a show form -> submit form workflow. Wygoda tego wzorca stanie się bardziej oczywista po przejrzeniu sekcji zrozumienie IActionConstraint .The convenience of this pattern will become more apparent after reviewing the Understanding IActionConstraint section.

Jeśli wiele pasujących tras i MVC nie mogą znaleźć "najlepszej" trasy, spowoduje to zgłoszenie AmbiguousActionException .If multiple routes match, and MVC can't find a 'best' route, it will throw an AmbiguousActionException.

Nazwy trasRoute names

Ciągi "blog" i "default" w poniższych przykładach są nazwami tras:The strings "blog" and "default" in the following examples are route names:

app.UseMvc(routes =>
{
   routes.MapRoute("blog", "blog/{*article}",
               defaults: new { controller = "Blog", action = "Article" });
   routes.MapRoute("default", "{controller=Home}/{action=Index}/{id?}");
});

Nazwy tras nadaj logicznej nazwie trasy, aby nazwana trasa mogła być używana do generowania adresów URL.The route names give the route a logical name so that the named route can be used for URL generation. Znacznie upraszcza to tworzenie adresów URL, gdy porządkowanie tras może spowodować skomplikowane generowanie adresów URL.This greatly simplifies URL creation when the ordering of routes could make URL generation complicated. Nazwy tras muszą być unikatowe w całej aplikacji.Route names must be unique application-wide.

Nazwy tras nie mają wpływu na Dopasowywanie adresów URL ani obsługę żądań; są one używane tylko do generowania adresów URL.Route names have no impact on URL matching or handling of requests; they're used only for URL generation. Routing zawiera bardziej szczegółowe informacje na temat generowania adresów URL, w tym generowanie adresów URL w pomocnikach specyficznych dla MVC.Routing has more detailed information on URL generation including URL generation in MVC-specific helpers.

Routing atrybutówAttribute routing

Funkcja routingu atrybutów używa zestawu atrybutów do mapowania akcji bezpośrednio do szablonów tras.Attribute routing uses a set of attributes to map actions directly to route templates. W poniższym przykładzie app.UseMvc(); jest używany w Configure metodzie i nie jest przesyłana żadna trasa.In the following example, app.UseMvc(); is used in the Configure method and no route is passed. HomeControllerBędzie zgodna z zestawem adresów URL podobnym do trasy domyślnej, która {controller=Home}/{action=Index}/{id?} byłaby zgodna:The HomeController will match a set of URLs similar to what the default route {controller=Home}/{action=Index}/{id?} would match:

public class HomeController : Controller
{
   [Route("")]
   [Route("Home")]
   [Route("Home/Index")]
   public IActionResult Index()
   {
      return View();
   }
   [Route("Home/About")]
   public IActionResult About()
   {
      return View();
   }
   [Route("Home/Contact")]
   public IActionResult Contact()
   {
      return View();
   }
}

HomeController.Index()Akcja będzie wykonywana dla dowolnej ścieżki URL / , /Home lub /Home/Index .The HomeController.Index() action will be executed for any of the URL paths /, /Home, or /Home/Index.

Uwaga

W tym przykładzie przedstawiono najważniejsze różnice programistyczne między routingiem atrybutów i routingiem konwencjonalnym.This example highlights a key programming difference between attribute routing and conventional routing. Routing atrybutów wymaga więcej danych wejściowych w celu określenia trasy; konwencjonalne trasy domyślne obsługuje trasy bardziej zwięzłie.Attribute routing requires more input to specify a route; the conventional default route handles routes more succinctly. Jednak Routing atrybutu zezwala na (i wymaga) precyzyjnej kontroli, które szablony tras mają zastosowanie do poszczególnych akcji.However, attribute routing allows (and requires) precise control of which route templates apply to each action.

W przypadku routingu atrybutów nazwa kontrolera i nazwy akcji nie odgrywają żadnej roli, w której akcja jest zaznaczona.With attribute routing the controller name and action names play no role in which action is selected. Ten przykład będzie pasował do tych samych adresów URL, co w poprzednim przykładzie.This example will match the same URLs as the previous example.

public class MyDemoController : Controller
{
   [Route("")]
   [Route("Home")]
   [Route("Home/Index")]
   public IActionResult MyIndex()
   {
      return View("Index");
   }
   [Route("Home/About")]
   public IActionResult MyAbout()
   {
      return View("About");
   }
   [Route("Home/Contact")]
   public IActionResult MyContact()
   {
      return View("Contact");
   }
}

Uwaga

Powyższe szablony tras nie definiują parametrów trasy dla action , area i controller .The route templates above don't define route parameters for action, area, and controller. W rzeczywistości te parametry tras są niedozwolone w trasach atrybutów.In fact, these route parameters are not allowed in attribute routes. Ponieważ szablon trasy jest już skojarzony z akcją, nie ma sensu analizy nazwy akcji na podstawie adresu URL.Since the route template is already associated with an action, it wouldn't make sense to parse the action name from the URL.

Routing atrybutów z atrybutami http [Verb]Attribute routing with Http[Verb] attributes

Routing atrybutu może również używać Http[Verb] atrybutów, takich jak HttpPostAttribute .Attribute routing can also make use of the Http[Verb] attributes such as HttpPostAttribute. Wszystkie te atrybuty mogą akceptować szablon trasy.All of these attributes can accept a route template. Ten przykład przedstawia dwie akcje, które pasują do tego samego szablonu trasy:This example shows two actions that match the same route template:

[HttpGet("/products")]
public IActionResult ListProducts()
{
   // ...
}

[HttpPost("/products")]
public IActionResult CreateProduct(...)
{
   // ...
}

W przypadku ścieżki URL podobnej do /products ProductsApi.ListProducts akcji zostanie wykonane, gdy zlecenie http jest GET i ProductsApi.CreateProduct zostanie wykonane, gdy zlecenie http ma wartość POST .For a URL path like /products the ProductsApi.ListProducts action will be executed when the HTTP verb is GET and ProductsApi.CreateProduct will be executed when the HTTP verb is POST. Routing atrybutu najpierw jest zgodny z adresem URL względem zestawu szablonów tras zdefiniowanych przez atrybuty trasy.Attribute routing first matches the URL against the set of route templates defined by route attributes. Po dopasowaniu szablonu trasy IActionConstraint ograniczenia są stosowane w celu określenia, które akcje mogą być wykonywane.Once a route template matches, IActionConstraint constraints are applied to determine which actions can be executed.

Porada

Podczas kompilowania interfejsu API REST jest to rzadki, że będzie on używany [Route(...)] na potrzeby metody akcji, ponieważ akcja akceptuje wszystkie metody http.When building a REST API, it's rare that you will want to use [Route(...)] on an action method as the action will accept all HTTP methods. Lepiej jest użyć bardziej szczegółowych Http*Verb*Attributes informacji na temat tego, co obsługuje interfejs API.It's better to use the more specific Http*Verb*Attributes to be precise about what your API supports. Klienci interfejsów API REST powinni wiedzieć, jakie ścieżki i czasowniki HTTP mapują na określone operacje logiczne.Clients of REST APIs are expected to know what paths and HTTP verbs map to specific logical operations.

Ponieważ atrybut Route ma zastosowanie do określonej akcji, można łatwo wprowadzić parametry wymagane jako część definicji szablonu trasy.Since an attribute route applies to a specific action, it's easy to make parameters required as part of the route template definition. W tym przykładzie id jest wymagane jako część ścieżki URL.In this example, id is required as part of the URL path.

public class ProductsApiController : Controller
{
   [HttpGet("/products/{id}", Name = "Products_List")]
   public IActionResult GetProduct(int id) { ... }
}

ProductsApi.GetProduct(int)Akcja zostanie wykonana dla ścieżki URL, na przykład, /products/3 ale nie dla ścieżki adresu URL /products .The ProductsApi.GetProduct(int) action will be executed for a URL path like /products/3 but not for a URL path like /products. Aby uzyskać pełny opis szablonów tras i powiązanych opcji, zobacz Routing .See Routing for a full description of route templates and related options.

Nazwa trasyRoute Name

Następujący kod definiuje nazwę trasy Products_List :The following code defines a route name of Products_List:

public class ProductsApiController : Controller
{
   [HttpGet("/products/{id}", Name = "Products_List")]
   public IActionResult GetProduct(int id) { ... }
}

Nazwy tras mogą służyć do generowania adresów URL na podstawie określonej trasy.Route names can be used to generate a URL based on a specific route. Nazwy tras nie mają wpływu na zachowanie routingu w adresie URL i są używane tylko na potrzeby generowania adresów URL.Route names have no impact on the URL matching behavior of routing and are only used for URL generation. Nazwy tras muszą być unikatowe w całej aplikacji.Route names must be unique application-wide.

Uwaga

Jest to zróżnicowane dla konwencjonalnej trasy domyślnej , która definiuje id parametr jako opcjonalny ( {id?} ).Contrast this with the conventional default route , which defines the id parameter as optional ({id?}). Ta możliwość precyzyjnego określania interfejsów API ma zalety, takich jak umożliwienie /products i /products/5 wysyłanie ich do różnych akcji.This ability to precisely specify APIs has advantages, such as allowing /products and /products/5 to be dispatched to different actions.

Łączenie trasCombining routes

Aby mniej powtarzać Routing atrybutów, atrybuty trasy na kontrolerze są łączone z atrybutami trasy dla poszczególnych akcji.To make attribute routing less repetitive, route attributes on the controller are combined with route attributes on the individual actions. Wszystkie szablony tras zdefiniowane na kontrolerze są poprzedzone w celu rozesłania szablonów w akcjach.Any route templates defined on the controller are prepended to route templates on the actions. Umieszczenie atrybutu trasy na kontrolerze powoduje, że wszystkie akcje w kontrolerze używają routingu atrybutów.Placing a route attribute on the controller makes all actions in the controller use attribute routing.

[Route("products")]
public class ProductsApiController : Controller
{
   [HttpGet]
   public IActionResult ListProducts() { ... }

   [HttpGet("{id}")]
   public ActionResult GetProduct(int id) { ... }
}

W tym przykładzie ścieżka adresu URL /products może być taka sama ProductsApi.ListProducts , a Ścieżka adresu URL /products/5 może być taka sama ProductsApi.GetProduct(int) .In this example the URL path /products can match ProductsApi.ListProducts, and the URL path /products/5 can match ProductsApi.GetProduct(int). Obie te akcje pasują tylko do protokołu HTTP GET , ponieważ są oznaczone za pomocą HttpGetAttribute .Both of these actions only match HTTP GET because they're marked with the HttpGetAttribute.

Szablony tras zastosowane do akcji rozpoczynającej się od / lub ~/ nie są połączone z szablonami tras zastosowanymi do kontrolera.Route templates applied to an action that begin with / or ~/ don't get combined with route templates applied to the controller. Ten przykład dopasowuje zestaw ścieżek URL podobny do trasy domyślnej.This example matches a set of URL paths similar to the default route.

[Route("Home")]
public class HomeController : Controller
{
    [Route("")]      // Combines to define the route template "Home"
    [Route("Index")] // Combines to define the route template "Home/Index"
    [Route("/")]     // Doesn't combine, defines the route template ""
    public IActionResult Index()
    {
        ViewData["Message"] = "Home index";
        var url = Url.Action("Index", "Home");
        ViewData["Message"] = "Home index" + "var url = Url.Action; =  " + url;
        return View();
    }

    [Route("About")] // Combines to define the route template "Home/About"
    public IActionResult About()
    {
        return View();
    }   
}

Określanie kolejności tras atrybutówOrdering attribute routes

W przeciwieństwie do konwencjonalnych tras, które są wykonywane w określonej kolejności, routing atrybutu kompiluje drzewo i dopasowuje wszystkie trasy jednocześnie.In contrast to conventional routes, which execute in a defined order, attribute routing builds a tree and matches all routes simultaneously. Zachowuje się tak, jakby wpisy trasy zostały umieszczone w idealnym porządku; najbardziej konkretne trasy mają możliwość wykonania przed bardziej ogólnymi trasami.This behaves as-if the route entries were placed in an ideal ordering; the most specific routes have a chance to execute before the more general routes.

Na przykład taka trasa blog/search/{topic} jest bardziej szczegółowa niż trasa, taka jak blog/{*article} .For example, a route like blog/search/{topic} is more specific than a route like blog/{*article}. Logicznie mówiąc, blog/search/{topic} że trasy "uruchomienia" są najpierw domyślnie, ponieważ to jest jedyną rozsądną kolejnością.Logically speaking the blog/search/{topic} route 'runs' first, by default, because that's the only sensible ordering. Przy użyciu konwencjonalnego routingu deweloper jest odpowiedzialny za umieszczanie tras w odpowiedniej kolejności.Using conventional routing, the developer is responsible for placing routes in the desired order.

Trasy atrybutów mogą konfigurować kolejność przy użyciu Order właściwości wszystkich atrybutów tras dostarczonych przez platformę.Attribute routes can configure an order, using the Order property of all of the framework provided route attributes. Trasy są przetwarzane zgodnie z rosnącą sortowaniem Order właściwości.Routes are processed according to an ascending sort of the Order property. Kolejność domyślna to 0 .The default order is 0. Ustawienie trasy przy użyciu Order = -1 zostanie uruchomione przed trasami, które nie ustawiają kolejności.Setting a route using Order = -1 will run before routes that don't set an order. Ustawienie trasy przy użyciu Order = 1 zostanie uruchomione po określeniu domyślnej kolejności tras.Setting a route using Order = 1 will run after default route ordering.

Porada

Należy unikać w zależności od Order .Avoid depending on Order. Jeśli przestrzeń adresów URL wymaga jawnych wartości kolejności, aby można było prawidłowo kierować trasy, to prawdopodobnie również jest myląca dla klientów.If your URL-space requires explicit order values to route correctly, then it's likely confusing to clients as well. W ogólnym routingu atrybutów wybierz prawidłową trasę z dopasowywaniem adresów URL.In general attribute routing will select the correct route with URL matching. Jeśli domyślna kolejność generowania adresów URL nie działa, użycie nazwy trasy jako przesłonięcia jest zwykle prostsze niż stosowanie Order właściwości.If the default order used for URL generation isn't working, using route name as an override is usually simpler than applying the Order property.

Razor Strony routingu i routingu kontrolera MVC współdzielą implementację.Razor Pages routing and MVC controller routing share an implementation. Informacje o zamówieniu trasy w Razor tematach stron są dostępne na Razor stronach trasy i konwencje aplikacji: kolejność trasy.Information on route order in the Razor Pages topics is available at Razor Pages route and app conventions: Route order.

Zastępowanie tokenu w szablonach tras ([Controller], [Action], [obszar])Token replacement in route templates ([controller], [action], [area])

Dla wygody, trasy atrybutu obsługują Zastępowanie tokenu przez ujęcie tokenu w nawiasy kwadratowe ( [ , ] ).For convenience, attribute routes support token replacement by enclosing a token in square-brackets ([, ]). Tokeny [action] , [area] i [controller] są zastępowane wartościami nazwy akcji, obszaru i nazwy kontrolera z akcji, w której jest zdefiniowana trasa.The tokens [action], [area], and [controller] are replaced with the values of the action name, area name, and controller name from the action where the route is defined. W poniższym przykładzie akcje są zgodne ze ścieżkami URL zgodnie z opisem w komentarzach:In the following example, the actions match URL paths as described in the comments:

[Route("[controller]/[action]")]
public class ProductsController : Controller
{
    [HttpGet] // Matches '/Products/List'
    public IActionResult List() {
        // ...
    }

    [HttpGet("{id}")] // Matches '/Products/Edit/{id}'
    public IActionResult Edit(int id) {
        // ...
    }
}

Zastępowanie tokenu występuje jako ostatni krok tworzenia tras atrybutów.Token replacement occurs as the last step of building the attribute routes. Powyższy przykład będzie zachowywać się tak samo jak poniższy kod:The above example will behave the same as the following code:


public class ProductsController : Controller
{
    [HttpGet("[controller]/[action]")] // Matches '/Products/List'
    public IActionResult List() {
        // ...
    }

    [HttpGet("[controller]/[action]/{id}")] // Matches '/Products/Edit/{id}'
    public IActionResult Edit(int id) {
        // ...
    }
}

Trasy atrybutu można także łączyć z dziedziczeniem.Attribute routes can also be combined with inheritance. Jest to szczególnie zaawansowane w połączeniu z zastępowaniem tokenu.This is particularly powerful combined with token replacement.

[Route("api/[controller]")]
public abstract class MyBaseController : Controller { ... }

public class ProductsController : MyBaseController
{
   [HttpGet] // Matches '/api/Products'
   public IActionResult List() { ... }

   [HttpPut("{id}")] // Matches '/api/Products/{id}'
   public IActionResult Edit(int id) { ... }
}

Zastępowanie tokenu dotyczy również nazw tras zdefiniowanych przez trasy atrybutów.Token replacement also applies to route names defined by attribute routes. [Route("[controller]/[action]", Name="[controller]_[action]")] generuje unikatową nazwę trasy dla każdej akcji.[Route("[controller]/[action]", Name="[controller]_[action]")] generates a unique route name for each action.

Aby dopasować ogranicznik zamiany tokenu literału [ lub ] , należy to zrobić, powtarzając znak ( [[ lub ]] ).To match the literal token replacement delimiter [ or ], escape it by repeating the character ([[ or ]]).

Używanie transformatora parametrów do dostosowywania zastępowania tokenuUse a parameter transformer to customize token replacement

Zastępowanie tokenu można dostosować za pomocą transformatora parametrów.Token replacement can be customized using a parameter transformer. Transformator parametrów implementuje IOutboundParameterTransformer i przekształca wartość parametrów.A parameter transformer implements IOutboundParameterTransformer and transforms the value of parameters. Na przykład niestandardowy SlugifyParameterTransformer transformator parametrów zmienia SubscriptionManagement wartość trasy na subscription-management .For example, a custom SlugifyParameterTransformer parameter transformer changes the SubscriptionManagement route value to subscription-management.

RouteTokenTransformerConventionJest konwencją modelu aplikacji, która:The RouteTokenTransformerConvention is an application model convention that:

  • Stosuje transformator parametrów do wszystkich tras atrybutów w aplikacji.Applies a parameter transformer to all attribute routes in an application.
  • Dostosowuje wartości tokenów tras w miarę ich wymiany.Customizes the attribute route token values as they are replaced.
public class SubscriptionManagementController : Controller
{
    [HttpGet("[controller]/[action]")] // Matches '/subscription-management/list-all'
    public IActionResult ListAll() { ... }
}

RouteTokenTransformerConventionJest zarejestrowany jako opcja w ConfigureServices .The RouteTokenTransformerConvention is registered as an option in ConfigureServices.

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

public class SlugifyParameterTransformer : IOutboundParameterTransformer
{
    public string TransformOutbound(object value)
    {
        if (value == null) { return null; }

        // Slugify value
        return Regex.Replace(value.ToString(), "([a-z])([A-Z])", "$1-$2").ToLower();
    }
}

Wiele trasMultiple Routes

Routing atrybutów obsługuje definiowanie wielu tras, które docierają do tej samej akcji.Attribute routing supports defining multiple routes that reach the same action. Najczęstszym sposobem użycia tej metody jest naśladowanie zachowania domyślnej trasy konwencjonalnej , jak pokazano w następującym przykładzie:The most common usage of this is to mimic the behavior of the default conventional route as shown in the following example:

[Route("[controller]")]
public class ProductsController : Controller
{
   [Route("")]     // Matches 'Products'
   [Route("Index")] // Matches 'Products/Index'
   public IActionResult Index()
}

Umieszczenie wielu atrybutów trasy na kontrolerze oznacza, że każda z nich będzie łączyć się z poszczególnymi atrybutami trasy w metodach akcji.Putting multiple route attributes on the controller means that each one will combine with each of the route attributes on the action methods.

[Route("Store")]
[Route("[controller]")]
public class ProductsController : Controller
{
   [HttpPost("Buy")]     // Matches 'Products/Buy' and 'Store/Buy'
   [HttpPost("Checkout")] // Matches 'Products/Checkout' and 'Store/Checkout'
   public IActionResult Buy()
}

Gdy wiele atrybutów trasy (które Implementuj IActionConstraint ) jest umieszczanych w akcji, każde ograniczenie akcji łączy się z szablonem trasy z atrybutu, który go zdefiniował.When multiple route attributes (that implement IActionConstraint) are placed on an action, then each action constraint combines with the route template from the attribute that defined it.

[Route("api/[controller]")]
public class ProductsController : Controller
{
   [HttpPut("Buy")]      // Matches PUT 'api/Products/Buy'
   [HttpPost("Checkout")] // Matches POST 'api/Products/Checkout'
   public IActionResult Buy()
}

Porada

Chociaż używanie wielu tras w akcjach może wydawać się zaawansowane, lepiej jest zachować prosty i dobrze zdefiniowany obszar adresów URL aplikacji.While using multiple routes on actions can seem powerful, it's better to keep your application's URL space simple and well-defined. Użyj wielu tras w przypadku akcji tylko wtedy, gdy jest to konieczne, na przykład do obsługi istniejących klientów.Use multiple routes on actions only where needed, for example to support existing clients.

Określanie opcjonalnych parametrów trasy, wartości domyślnych i ograniczeńSpecifying attribute route optional parameters, default values, and constraints

Trasy atrybutów obsługują tę samą składnię wbudowaną co konwencjonalne trasy, aby określić parametry opcjonalne, wartości domyślne i ograniczenia.Attribute routes support the same inline syntax as conventional routes to specify optional parameters, default values, and constraints.

[HttpPost("product/{id:int}")]
public IActionResult ShowProduct(int id)
{
   // ...
}

Aby uzyskać szczegółowy opis składni szablonu trasy, zobacz odwołanie do szablonu trasy .See Route Template Reference for a detailed description of route template syntax.

Niestandardowe atrybuty trasy przy użyciu IRouteTemplateProviderCustom route attributes using IRouteTemplateProvider

Wszystkie atrybuty trasy podane w strukturze ( [Route(...)] , [HttpGet(...)] itp.) implementują IRouteTemplateProvider interfejs.All of the route attributes provided in the framework ( [Route(...)], [HttpGet(...)] , etc.) implement the IRouteTemplateProvider interface. MVC wyszukuje atrybuty klas kontrolera i metod akcji, gdy aplikacja jest uruchamiana i używa tych, które implementują w IRouteTemplateProvider celu utworzenia początkowego zestawu tras.MVC looks for attributes on controller classes and action methods when the app starts and uses the ones that implement IRouteTemplateProvider to build the initial set of routes.

Można zaimplementować, IRouteTemplateProvider Aby zdefiniować własne atrybuty trasy.You can implement IRouteTemplateProvider to define your own route attributes. Każdy IRouteTemplateProvider z nich umożliwia definiowanie pojedynczej trasy z niestandardowym szablonem trasy, kolejnością i nazwą:Each IRouteTemplateProvider allows you to define a single route with a custom route template, order, and name:

public class MyApiControllerAttribute : Attribute, IRouteTemplateProvider
{
   public string Template => "api/[controller]";

   public int? Order { get; set; }

   public string Name { get; set; }
}

Atrybut z powyższego przykładu automatycznie ustawia wartość Template na "api/[controller]" gdy [MyApiController] jest stosowany.The attribute from the above example automatically sets the Template to "api/[controller]" when [MyApiController] is applied.

Dostosowywanie tras atrybutów przy użyciu modelu aplikacjiUsing Application Model to customize attribute routes

Model aplikacji jest modelem obiektów tworzonym podczas uruchamiania ze wszystkimi metadanymi używanymi przez MVC do kierowania i wykonywania akcji.The application model is an object model created at startup with all of the metadata used by MVC to route and execute your actions. Model aplikacji zawiera wszystkie dane zebrane z atrybutów trasy (do IRouteTemplateProvider ).The application model includes all of the data gathered from route attributes (through IRouteTemplateProvider). Można napisać konwencje , aby zmodyfikować model aplikacji w czasie uruchamiania, aby dostosować sposób zachowania routingu.You can write conventions to modify the application model at startup time to customize how routing behaves. W tej sekcji przedstawiono prosty przykład dostosowywania routingu przy użyciu modelu aplikacji.This section shows a simple example of customizing routing using application model.

using Microsoft.AspNetCore.Mvc.ApplicationModels;
using System.Linq;
using System.Text;
public class NamespaceRoutingConvention : 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)
        {
            // This controller manually defined some routes, so treat this 
            // as an override and not apply the convention here.
            return;
        }

        // Use the namespace and controller name to infer a route for the controller.
        //
        // Example:
        //
        //  controller.ControllerTypeInfo ->    "My.Application.Admin.UsersController"
        //  baseNamespace ->                    "My.Application"
        //
        //  template =>                         "Admin/[controller]"
        //
        // This makes your routes roughly line up with the folder structure of your project.
        //
        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]");

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

Routing mieszany: Routing atrybutów a konwencjonalny RoutingMixed routing: Attribute routing vs conventional routing

Aplikacje MVC mogą łączyć użycie konwencjonalnego routingu i routingu atrybutów.MVC applications can mix the use of conventional routing and attribute routing. Typowym zastosowaniem są trasy konwencjonalne dla kontrolerów obsługujących strony HTML dla przeglądarek i routingu atrybutów dla kontrolerów obsługujących interfejsy API REST.It's typical to use conventional routes for controllers serving HTML pages for browsers, and attribute routing for controllers serving REST APIs.

Akcje są albo podkierowane do Konwencji lub kierowane przez atrybut.Actions are either conventionally routed or attribute routed. Umieszczenie trasy na kontrolerze lub akcja powoduje, że atrybut jest kierowany.Placing a route on the controller or the action makes it attribute routed. Akcje definiujące trasy atrybutów nie mogą być osiągane za pomocą konwencjonalnych tras i vice versa.Actions that define attribute routes cannot be reached through the conventional routes and vice-versa. Każdy atrybut trasy na kontrolerze powoduje kierowanie wszystkich akcji w atrybucie kontrolera.Any route attribute on the controller makes all actions in the controller attribute routed.

Uwaga

Co odróżnia dwa typy systemów routingu, proces stosowany po adresie URL pasuje do szablonu trasy.What distinguishes the two types of routing systems is the process applied after a URL matches a route template. W przypadku routingu konwencjonalnego wartości trasy z dopasowania są używane do wybierania akcji i kontrolera z tabeli odnośników wszystkich konwencjonalnych akcji kierowanych.In conventional routing, the route values from the match are used to choose the action and controller from a lookup table of all conventional routed actions. W obszarze Routing atrybutów każdy szablon jest już skojarzony z akcją i nie jest wymagany dalsze wyszukiwanie.In attribute routing, each template is already associated with an action, and no further lookup is needed.

Złożone segmentyComplex segments

Złożone segmenty (na przykład [Route("/dog{token}cat")] ) są przetwarzane przez dopasowanie literałów z prawej strony do lewej w sposób niezachłanney.Complex segments (for example, [Route("/dog{token}cat")]), are processed by matching up literals from right to left in a non-greedy way. Sprawdź kod źródłowy opisu.See the source code for a description. Aby uzyskać więcej informacji, zobacz ten problem.For more information, see this issue.

Generowanie adresu URLURL Generation

Aplikacje MVC mogą używać funkcji generowania adresów URL routingu do generowania linków URL do akcji.MVC applications can use routing's URL generation features to generate URL links to actions. Generowanie adresów URL eliminuje adresy URL zakodowana, co sprawia, że kod jest bardziej niezawodny i konserwowany.Generating URLs eliminates hardcoding URLs, making your code more robust and maintainable. Ta sekcja koncentruje się na funkcjach generowania adresów URL dostarczonych przez MVC i obejmuje tylko podstawowe informacje na temat sposobu działania generowania adresów URL.This section focuses on the URL generation features provided by MVC and will only cover basics of how URL generation works. Aby uzyskać szczegółowy opis generowania adresów URL, zobacz temat Routing .See Routing for a detailed description of URL generation.

IUrlHelperInterfejs jest podstawową częścią infrastruktury między MVC i routingiem na potrzeby generowania adresów URL.The IUrlHelper interface is the underlying piece of infrastructure between MVC and routing for URL generation. Wystąpienie IUrlHelper dostępne za pomocą właściwości można znaleźć Url w obszarze Kontrolery, widoki i składniki widoku.You'll find an instance of IUrlHelper available through the Url property in controllers, views, and view components.

W tym przykładzie IUrlHelper interfejs jest używany przez Controller.Url Właściwość w celu WYGENEROWANIA adresu URL dla innej akcji.In this example, the IUrlHelper interface is used through the Controller.Url property to generate a URL to another action.

using Microsoft.AspNetCore.Mvc;

public class UrlGenerationController : Controller
{
    public IActionResult Source()
    {
        // Generates /UrlGeneration/Destination
        var url = Url.Action("Destination");
        return Content($"Go check out {url}, it's really great.");
    }

    public IActionResult Destination()
    {
        return View();
    }
}

Jeśli aplikacja używa domyślnej trasy konwencjonalnej, wartość url zmiennej będzie ciąg ścieżki URL /UrlGeneration/Destination .If the application is using the default conventional route, the value of the url variable will be the URL path string /UrlGeneration/Destination. Ta ścieżka URL jest tworzona przez Routing przez połączenie wartości trasy z bieżącego żądania (wartości otoczenia), z wartościami przekazanymi do Url.Action i podstawianie tych wartości do szablonu trasy:This URL path is created by routing by combining the route values from the current request (ambient values), with the values passed to Url.Action and substituting those values into the route template:

ambient values: { controller = "UrlGeneration", action = "Source" }
values passed to Url.Action: { controller = "UrlGeneration", action = "Destination" }
route template: {controller}/{action}/{id?}

result: /UrlGeneration/Destination

Każdy parametr trasy w szablonie trasy ma swoją wartość zastępowaną przez pasujące nazwy wartościami i wartościami otoczenia.Each route parameter in the route template has its value substituted by matching names with the values and ambient values. Parametr trasy, który nie ma wartości, może korzystać z wartości domyślnej, jeśli ma taką wartość, lub być pominięty, jeśli jest opcjonalny (tak jak w przypadku id w przypadku w tym przykładzie).A route parameter that doesn't have a value can use a default value if it has one, or be skipped if it's optional (as in the case of id in this example). Generowanie adresu URL zakończy się niepowodzeniem, jeśli którykolwiek z wymaganych parametrów trasy nie ma odpowiadającej wartości.URL generation will fail if any required route parameter doesn't have a corresponding value. Jeśli generowanie adresów URL kończy się niepowodzeniem dla trasy, kolejna trasa zostanie ponowiona do momentu przetworzenia wszystkich tras lub znalezienia dopasowania.If URL generation fails for a route, the next route is tried until all routes have been tried or a match is found.

W Url.Action powyższym przykładzie przyjęto założenie konwencjonalnego routingu, ale generowanie adresów URL działa podobnie jak w przypadku routingu atrybutów, chociaż koncepcje różnią się.The example of Url.Action above assumes conventional routing, but URL generation works similarly with attribute routing, though the concepts are different. W przypadku routingu konwencjonalnego wartości trasy służą do rozszerzania szablonu, a wartości trasy dla controller i action zwykle pojawiają się w tym szablonie — działa to, ponieważ adresy URL dopasowane przez Routing są zgodne z Konwencją.With conventional routing, the route values are used to expand a template, and the route values for controller and action usually appear in that template - this works because the URLs matched by routing adhere to a convention. W obszarze Routing atrybutów wartości trasy dla controller i action nie mogą występować w szablonie — zamiast tego są używane do wyszukiwania szablonu do użycia.In attribute routing, the route values for controller and action are not allowed to appear in the template - they're instead used to look up which template to use.

W tym przykładzie zastosowano Routing atrybutów:This example uses attribute routing:

// In Startup class
public void Configure(IApplicationBuilder app)
{
    app.UseMvc();
}
using Microsoft.AspNetCore.Mvc;

public class UrlGenerationController : Controller
{
    [HttpGet("")]
    public IActionResult Source()
    {
        var url = Url.Action("Destination"); // Generates /custom/url/to/destination
        return Content($"Go check out {url}, it's really great.");
    }

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

MVC kompiluje tabelę odnośników wszystkich akcji przypisanych do atrybutu i odpowiada controller wartości i, action Aby wybrać szablon trasy do użycia na potrzeby generowania adresów URL.MVC builds a lookup table of all attribute routed actions and will match the controller and action values to select the route template to use for URL generation. W powyższym przykładzie custom/url/to/destination jest generowany.In the sample above, custom/url/to/destination is generated.

Generowanie adresów URL według nazwy akcjiGenerating URLs by action name

Url.Action (IUrlHelper .Url.Action (IUrlHelper . Action) i wszystkie powiązane przeciążenia są oparte na tym pomysłie, że chcesz określić, do czego łączysz, określając nazwę kontrolera i nazwę akcji.Action) and all related overloads all are based on that idea that you want to specify what you're linking to by specifying a controller name and action name.

Uwaga

W przypadku używania Url.Action , bieżąca wartość trasy dla controller i action jest określona dla Ciebie — wartości controller i action są częścią obu wartości otoczenia i wartości.When using Url.Action, the current route values for controller and action are specified for you - the value of controller and action are part of both ambient values and values. Metoda Url.Action zawsze używa bieżących wartości action i controller i wygeneruje ścieżkę URL, która jest przesyłana do bieżącej akcji.The method Url.Action, always uses the current values of action and controller and will generate a URL path that routes to the current action.

Funkcja routingu próbuje użyć wartości w otoczeniu wartości, aby podać informacje, które nie zostały wprowadzone podczas generowania adresu URL.Routing attempts to use the values in ambient values to fill in information that you didn't provide when generating a URL. Przy użyciu trasy podobnej do {a}/{b}/{c}/{d} i otoczenia { a = Alice, b = Bob, c = Carol, d = David } Routing ma wystarczającą ilość informacji do WYGENEROWANIA adresu URL bez żadnych dodatkowych wartości — ponieważ wszystkie parametry trasy mają wartość.Using a route like {a}/{b}/{c}/{d} and ambient values { a = Alice, b = Bob, c = Carol, d = David }, routing has enough information to generate a URL without any additional values - since all route parameters have a value. Po dodaniu wartości wartość zostanie { d = Donovan } { d = David } zignorowana, a wygenerowana Ścieżka adresu URL Alice/Bob/Carol/Donovan .If you added the value { d = Donovan }, the value { d = David } would be ignored, and the generated URL path would be Alice/Bob/Carol/Donovan.

Ostrzeżenie

Ścieżki URL są hierarchiczne.URL paths are hierarchical. W powyższym przykładzie, jeśli dodano wartość { c = Cheryl } , obie wartości { c = Carol, d = David } byłyby ignorowane.In the example above, if you added the value { c = Cheryl }, both of the values { c = Carol, d = David } would be ignored. W takim przypadku nie jest już dostępna wartość d i generowanie adresu URL zakończy się niepowodzeniem.In this case we no longer have a value for d and URL generation will fail. Należy określić pożądaną wartość c i d .You would need to specify the desired value of c and d. Można oczekiwać, że ten problem zostanie osiągnięty przy użyciu trasy domyślnej ( {controller}/{action}/{id?} ) — ale w takiej sytuacji rzadko napotkasz to zachowanie, ponieważ Url.Action zawsze jawnie określimy controller action wartość i.You might expect to hit this problem with the default route ({controller}/{action}/{id?}) - but you will rarely encounter this behavior in practice as Url.Action will always explicitly specify a controller and action value.

Dłuższe przeciążenia Url.Action również pobierają dodatkowy obiekt wartości trasy , aby zapewnić wartości parametrów trasy innych niż controller i action .Longer overloads of Url.Action also take an additional route values object to provide values for route parameters other than controller and action. Najczęściej zobaczysz, że będzie on używany z usługą id Url.Action("Buy", "Products", new { id = 17 }) .You will most commonly see this used with id like Url.Action("Buy", "Products", new { id = 17 }). Według Konwencji obiekt wartości trasy jest zwykle obiektem typu anonimowego, ale może również być IDictionary<> lub zwykłym starym obiektem platformy .NET.By convention the route values object is usually an object of anonymous type, but it can also be an IDictionary<> or a plain old .NET object. Wszystkie dodatkowe wartości trasy, które nie pasują do parametrów trasy, są umieszczane w ciągu zapytania.Any additional route values that don't match route parameters are put in the query string.

using Microsoft.AspNetCore.Mvc;

public class TestController : Controller
{
    public IActionResult Index()
    {
        // Generates /Products/Buy/17?color=red
        var url = Url.Action("Buy", "Products", new { id = 17, color = "red" });
        return Content(url);
    }
}

Porada

Aby utworzyć bezwzględny adres URL, Użyj przeciążenia, które akceptuje protocol : Url.Action("Buy", "Products", new { id = 17 }, protocol: Request.Scheme)To create an absolute URL, use an overload that accepts a protocol: Url.Action("Buy", "Products", new { id = 17 }, protocol: Request.Scheme)

Generowanie adresów URL według trasyGenerating URLs by route

Powyższy kod wygeneruje adres URL przez przekazanie go do kontrolera i nazwy akcji.The code above demonstrated generating a URL by passing in the controller and action name. IUrlHelper zapewnia także Url.RouteUrl rodzinę metod.IUrlHelper also provides the Url.RouteUrl family of methods. Te metody są podobne do Url.Action , ale nie kopiują bieżących wartości action i controller do wartości trasy.These methods are similar to Url.Action, but they don't copy the current values of action and controller to the route values. Najbardziej typowym zastosowaniem jest określenie nazwy trasy do użycia określonej trasy do wygenerowania adresu URL, na ogół bez określania kontrolera lub nazwy akcji.The most common usage is to specify a route name to use a specific route to generate the URL, generally without specifying a controller or action name.

using Microsoft.AspNetCore.Mvc;

public class UrlGenerationController : Controller
{
    [HttpGet("")]
    public IActionResult Source()
    {
        var url = Url.RouteUrl("Destination_Route"); // Generates /custom/url/to/destination
        return Content($"See {url}, it's really great.");
    }

    [HttpGet("custom/url/to/destination", Name = "Destination_Route")]
    public IActionResult Destination() {
        return View();
    }
}

Generowanie adresów URL w kodzie HTMLGenerating URLs in HTML

IHtmlHelper zapewnia HtmlHelper metody Html.BeginForm i Html.ActionLink wygenerowanie <form> <a> odpowiednio elementów i.IHtmlHelper provides the HtmlHelper methods Html.BeginForm and Html.ActionLink to generate <form> and <a> elements respectively. Metody te używają Url.Action metody do generowania adresu URL i akceptują podobne argumenty.These methods use the Url.Action method to generate a URL and they accept similar arguments. Url.RouteUrlPomocników dla programu HtmlHelper mają Html.BeginRouteForm Html.RouteLink podobną funkcjonalność.The Url.RouteUrl companions for HtmlHelper are Html.BeginRouteForm and Html.RouteLink which have similar functionality.

TagHelpers Generuj adresy URL za pomocą form TagHelper i <a> TagHelper.TagHelpers generate URLs through the form TagHelper and the <a> TagHelper. Oba te zastosowania IUrlHelper dla ich implementacji.Both of these use IUrlHelper for their implementation. Aby uzyskać więcej informacji, zobacz Praca z formularzami .See Working with Forms for more information.

W widokach IUrlHelper można korzystać z Url właściwości dla dowolnej generacji adresów URL ad hoc, która nie jest objęta powyższym.Inside views, the IUrlHelper is available through the Url property for any ad-hoc URL generation not covered by the above.

Generowanie adresów URL w wynikach akcjiGenerating URLS in Action Results

Powyższe przykłady przedstawiono przy użyciu IUrlHelper w kontrolerze, podczas gdy najbardziej typowym użyciem na kontrolerze jest wygenerowanie adresu URL jako części wyniku akcji.The examples above have shown using IUrlHelper in a controller, while the most common usage in a controller is to generate a URL as part of an action result.

ControllerBase Controller Klasy bazowe i zapewniają wygodne metody dla wyników akcji, które odwołują się do innej akcji.The ControllerBase and Controller base classes provide convenience methods for action results that reference another action. Jednym z typowych zastosowań jest przekierowanie po zaakceptowaniu danych wejściowych użytkownika.One typical usage is to redirect after accepting user input.

public IActionResult Edit(int id, Customer customer)
{
    if (ModelState.IsValid)
    {
        // Update DB with new details.
        return RedirectToAction("Index");
    }
    return View(customer);
}

Metody fabryki wyników akcji postępują zgodnie z podobnym wzorcem do metod w IUrlHelper .The action results factory methods follow a similar pattern to the methods on IUrlHelper.

Specjalny przypadek dla dedykowanych tras konwencjonalnychSpecial case for dedicated conventional routes

Funkcja routingu konwencjonalnego może używać specjalnego rodzaju definicji trasy o nazwie dedykowanej, konwencjonalnej trasy.Conventional routing can use a special kind of route definition called a dedicated conventional route. W poniższym przykładzie trasa o nazwie blog jest dedykowaną umowną trasą.In the example below, the route named blog is a dedicated conventional route.

app.UseMvc(routes =>
{
    routes.MapRoute("blog", "blog/{*article}",
        defaults: new { controller = "Blog", action = "Article" });
    routes.MapRoute("default", "{controller=Home}/{action=Index}/{id?}");
});

Użycie tych definicji tras Url.Action("Index", "Home") spowoduje wygenerowanie ścieżki URL / z default trasą, ale dlaczego?Using these route definitions, Url.Action("Index", "Home") will generate the URL path / with the default route, but why? Możliwe jest odpuszczenie, że wartości trasy { controller = Home, action = Index } byłyby wystarczające do wygenerowania adresu URL przy użyciu blog , a wynikiem będzie /blog?action=Index&controller=Home .You might guess the route values { controller = Home, action = Index } would be enough to generate a URL using blog, and the result would be /blog?action=Index&controller=Home.

Dedykowane konwencjonalne trasy polegają na specjalnym zachowaniu wartości domyślnych, które nie mają odpowiadającego parametru trasy, który uniemożliwia trasie "zbyt zachłanne" z generowaniem adresów URL.Dedicated conventional routes rely on a special behavior of default values that don't have a corresponding route parameter that prevents the route from being "too greedy" with URL generation. W takim przypadku wartości domyślne to { controller = Blog, action = Article } , a ani nie controller action pojawiają się jako parametr trasy.In this case the default values are { controller = Blog, action = Article }, and neither controller nor action appears as a route parameter. Gdy Routing wykonuje generowanie adresów URL, podane wartości muszą być zgodne z wartościami domyślnymi.When routing performs URL generation, the values provided must match the default values. Generowanie adresu URL blog nie powiedzie się, ponieważ wartości { controller = Home, action = Index } nie są zgodne { controller = Blog, action = Article } .URL generation using blog will fail because the values { controller = Home, action = Index } don't match { controller = Blog, action = Article }. Następnie usługa routingu wraca do wypróbowania default , która się powiedzie.Routing then falls back to try default, which succeeds.

ObszaryAreas

Obszary są funkcją MVC służącą do organizowania powiązanych funkcji w grupie jako oddzielnej przestrzeni nazw routingu (dla akcji kontrolera) i struktury folderów (dla widoków).Areas are an MVC feature used to organize related functionality into a group as a separate routing-namespace (for controller actions) and folder structure (for views). Użycie obszarów umożliwia aplikacji posiadanie wielu kontrolerów o tej samej nazwie, o ile mają one różne obszary.Using areas allows an application to have multiple controllers with the same name - as long as they have different areas. Za pomocą obszarów tworzy hierarchię na potrzeby routingu przez dodanie kolejnego parametru trasy area do controller i action .Using areas creates a hierarchy for the purpose of routing by adding another route parameter, area to controller and action. W tej sekcji omówiono sposób, w jaki Routing współdziała z obszarami — zobacz obszary , aby uzyskać szczegółowe informacje o tym, jak obszary są używane w widokach.This section will discuss how routing interacts with areas - see Areas for details about how areas are used with views.

Poniższy przykład konfiguruje MVC do używania domyślnej trasy konwencjonalnej i trasy obszaru dla obszaru o nazwie Blog :The following example configures MVC to use the default conventional route and an area route for an area named Blog:

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

W przypadku dopasowania ścieżki adresu URL /Manage/Users/AddUser , na przykład, Pierwsza trasa spowoduje wygenerowanie wartości trasy { area = Blog, controller = Users, action = AddUser } .When matching a URL path like /Manage/Users/AddUser, the first route will produce the route values { area = Blog, controller = Users, action = AddUser }. areaWartość trasy jest generowana przez wartość domyślną dla area , w rzeczywistości trasa utworzona przez MapAreaRoute jest równoważna z następującymi:The area route value is produced by a default value for area, in fact the route created by MapAreaRoute is equivalent to the following:

MapAreaRoute tworzy trasę przy użyciu wartości domyślnej i ograniczenia dotyczącej area użycia podanej nazwy obszaru, w tym przypadku Blog .MapAreaRoute creates a route using both a default value and constraint for area using the provided area name, in this case Blog. Wartość domyślna zapewnia, że trasa zawsze produkuje { area = Blog, ... } , ograniczenie wymaga wartości { area = Blog, ... } dla generowania adresów URL.The default value ensures that the route always produces { area = Blog, ... }, the constraint requires the value { area = Blog, ... } for URL generation.

Porada

Routowanie konwencjonalne jest zależne od kolejności.Conventional routing is order-dependent. Ogólnie rzecz biorąc, trasy z obszarami należy umieścić wcześniej w tabeli tras, ponieważ są one bardziej specyficzne niż trasy bez obszaru.In general, routes with areas should be placed earlier in the route table as they're more specific than routes without an area.

Korzystając z powyższego przykładu, wartości trasy będą zgodne z następującą akcją:Using the above example, the route values would match the following action:

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

AreaAttributeWskazuje to, co oznacza kontroler w ramach obszaru. Załóżmy, że ten kontroler znajduje się w Blog obszarze.The AreaAttribute is what denotes a controller as part of an area, we say that this controller is in the Blog area. Kontrolery bez [Area] atrybutu nie są członkami żadnego obszaru i nie będą zgodne, gdy area wartość trasy zostanie podana przez Routing.Controllers without an [Area] attribute are not members of any area, and will not match when the area route value is provided by routing. W poniższym przykładzie tylko pierwszy kontroler może być zgodny z wartościami trasy { area = Blog, controller = Users, action = AddUser } .In the following example, only the first controller listed can match the route values { area = Blog, controller = Users, action = AddUser }.

using Microsoft.AspNetCore.Mvc;

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

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

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

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

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

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

Uwaga

Przestrzeń nazw każdego kontrolera jest pokazana w tym miejscu w celu zapewnienia kompletności — w przeciwnym razie kontrolery będą mieć konflikt nazw i generują błąd kompilatora.The namespace of each controller is shown here for completeness - otherwise the controllers would have a naming conflict and generate a compiler error. Przestrzenie nazw klas nie mają wpływu na Routing MVC.Class namespaces have no effect on MVC's routing.

Pierwsze dwa kontrolery są członkami obszarów i są zgodne tylko wtedy, gdy ich nazwa obszaru jest podana przez area wartość trasy.The first two controllers are members of areas, and only match when their respective area name is provided by the area route value. Trzeci kontroler nie jest członkiem żadnego obszaru i można go dopasować tylko wtedy, gdy nie ma żadnej wartości parametru area Routing.The third controller isn't a member of any area, and can only match when no value for area is provided by routing.

Uwaga

W warunkach pasujących do nie ma żadnej wartości, brak area wartości jest taka sama jak wartość area null lub pusty ciąg.In terms of matching no value , the absence of the area value is the same as if the value for area were null or the empty string.

Podczas wykonywania akcji wewnątrz obszaru wartość trasy dla area będzie dostępna jako wartość otoczenia dla routingu do użycia na potrzeby generowania adresów URL.When executing an action inside an area, the route value for area will be available as an ambient value for routing to use for URL generation. Oznacza to, że domyślnie obszary programu Sticky Notes mają być używane do generowania adresów URL, jak pokazano w poniższym przykładzie.This means that by default areas act sticky for URL generation as demonstrated by the following sample.

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

Zrozumienie IActionConstraintUnderstanding IActionConstraint

Uwaga

Ta sekcja jest głęboką szczegółoweą wewnętrznych struktur oraz jak MVC wybiera akcję do wykonania.This section is a deep-dive on framework internals and how MVC chooses an action to execute. Typowa aplikacja nie będzie potrzebować niestandardowego IActionConstraintA typical application won't need a custom IActionConstraint

Prawdopodobnie już było używane, IActionConstraint nawet jeśli nie masz doświadczenia z interfejsem.You have likely already used IActionConstraint even if you're not familiar with the interface. [HttpGet]Atrybut i podobne [Http-VERB] atrybuty implementują IActionConstraint w celu ograniczenia wykonywania metody akcji.The [HttpGet] Attribute and similar [Http-VERB] attributes implement IActionConstraint in order to limit the execution of an action method.

public class ProductsController : Controller
{
    [HttpGet]
    public IActionResult Edit() { }

    public IActionResult Edit(...) { }
}

Przy założeniu domyślnej trasy konwencjonalnej, ścieżka URL /Products/Edit będzie generować wartości { controller = Products, action = Edit } , które byłyby zgodne z obiema akcjami przedstawionymi w tym miejscu.Assuming the default conventional route, the URL path /Products/Edit would produce the values { controller = Products, action = Edit }, which would match both of the actions shown here. W IActionConstraint terminologii mamy, że obie te akcje są uważane za kandydatów, ponieważ oba te są zgodne z danymi trasy.In IActionConstraint terminology we would say that both of these actions are considered candidates - as they both match the route data.

Gdy HttpGetAttribute zostanie wykonane, zobaczy, że Edit () jest dopasowaniem do Get i nie jest dopasowaniem dla żadnego innego zlecenia http.When the HttpGetAttribute executes, it will say that Edit() is a match for GET and isn't a match for any other HTTP verb. Edit(...)Akcja nie ma zdefiniowanych żadnych ograniczeń i dlatego będzie pasować do dowolnego czasownika http.The Edit(...) action doesn't have any constraints defined, and so will match any HTTP verb. Dlatego przy założeniu, że POST Edit(...) dopasowań są tylko.So assuming a POST - only Edit(...) matches. Jednak w przypadku GET obu akcji można nadal dopasować się, jednak akcja z funkcją IActionConstraint jest zawsze uznawana za lepszą od akcji bez.But, for a GET both actions can still match - however, an action with an IActionConstraint is always considered better than an action without. Dlatego, że jest Edit() [HttpGet] traktowany jako bardziej szczegółowy i zostanie wybrany, jeśli obie akcje mogą być zgodne.So because Edit() has [HttpGet] it's considered more specific, and will be selected if both actions can match.

Koncepcyjnie, IActionConstraint jest formą przeciążenia , ale zamiast przeciążać metody o tej samej nazwie, przeciążanie między akcjami, które pasują do tego samego adresu URL.Conceptually, IActionConstraint is a form of overloading , but instead of overloading methods with the same name, it's overloading between actions that match the same URL. Funkcja routingu atrybutów używa także IActionConstraint i może powodować, że działania z różnych kontrolerów są traktowane jako kandydaci.Attribute routing also uses IActionConstraint and can result in actions from different controllers both being considered candidates.

Implementowanie IActionConstraintImplementing IActionConstraint

Najprostszym sposobem implementacji IActionConstraint jest utworzenie klasy pochodnej od System.Attribute i umieszczenie jej w akcjach i kontrolerach.The simplest way to implement an IActionConstraint is to create a class derived from System.Attribute and place it on your actions and controllers. MVC automatycznie odnajdzie wszystkie IActionConstraint , które są stosowane jako atrybuty.MVC will automatically discover any IActionConstraint that are applied as attributes. Możesz użyć modelu aplikacji, aby zastosować ograniczenia i prawdopodobnie jest to najbardziej elastyczne podejście, ponieważ pozwala to na to, w jaki sposób są stosowane.You can use the application model to apply constraints, and this is probably the most flexible approach as it allows you to metaprogram how they're applied.

W poniższym przykładzie ograniczenie wybiera akcję na podstawie kodu kraju z danych trasy.In the following example, a constraint chooses an action based on a country code from the route data. Pełny przykład w witrynie GitHub.The full sample on GitHub.

public class CountrySpecificAttribute : Attribute, IActionConstraint
{
    private readonly string _countryCode;

    public CountrySpecificAttribute(string countryCode)
    {
        _countryCode = countryCode;
    }

    public int Order
    {
        get
        {
            return 0;
        }
    }

    public bool Accept(ActionConstraintContext context)
    {
        return string.Equals(
            context.RouteContext.RouteData.Values["country"].ToString(),
            _countryCode,
            StringComparison.OrdinalIgnoreCase);
    }
}

Użytkownik jest odpowiedzialny za implementację Accept metody i wybranie "Order" dla ograniczenia, które ma zostać wykonane.You are responsible for implementing the Accept method and choosing an 'Order' for the constraint to execute. W tym przypadku Accept Metoda zwraca wartość, true aby zauważyć, że akcja jest dopasowanie, gdy country wartość trasy jest zgodna.In this case, the Accept method returns true to denote the action is a match when the country route value matches. Różni się to od elementu RouteValueAttribute , który umożliwia powrót do akcji, która nie ma atrybutu.This is different from a RouteValueAttribute in that it allows fallback to a non-attributed action. Przykład pokazuje, że w przypadku zdefiniowania en-US akcji, kod kraju, taki jak, powróci fr-FR do bardziej ogólnego kontrolera, który nie został [CountrySpecific(...)] zastosowany.The sample shows that if you define an en-US action then a country code like fr-FR will fall back to a more generic controller that doesn't have [CountrySpecific(...)] applied.

OrderWłaściwość decyduje, który etap jest częścią tego ograniczenia.The Order property decides which stage the constraint is part of. Ograniczenia akcji są uruchamiane w grupach na podstawie Order .Action constraints run in groups based on the Order. Na przykład wszystkie atrybuty metody HTTP podane przez platformę używają tej samej Order wartości, aby były uruchamiane na tym samym etapie.For example, all of the framework provided HTTP method attributes use the same Order value so that they run in the same stage. Możesz mieć tyle etapów, ile potrzebujesz, aby zaimplementować odpowiednie zasady.You can have as many stages as you need to implement your desired policies.

Porada

Aby zdecydować, Order czy należy zastosować ograniczenie, przed metodami http.To decide on a value for Order think about whether or not your constraint should be applied before HTTP methods. Najpierw należy uruchomić mniejsze numery.Lower numbers run first.