Routing ad azioni del controller in ASP.NET CoreRouting to controller actions in ASP.NET Core

Di Ryan Nowak e Rick AndersonBy Ryan Nowak and Rick Anderson

ASP.NET Core MVC usa middleware di routing per verificare la corrispondenza degli URL delle richieste in ingresso ed eseguirne il mapping alle azioni.ASP.NET Core MVC uses the Routing middleware to match the URLs of incoming requests and map them to actions. Le route sono definite nel codice di avvio o negli attributi.Routes are defined in startup code or attributes. Le route descrivono il modo in cui i percorsi URL devono corrispondere alle azioni.Routes describe how URL paths should be matched to actions. Vengono usate anche per generare gli URL (per i collegamenti) inviati nelle risposte.Routes are also used to generate URLs (for links) sent out in responses.

Le azioni vengono indirizzate in modo convenzionale o con attributi.Actions are either conventionally routed or attribute routed. Se una route viene inserita nel controller o nell'azione, viene indirizzata con attributi.Placing a route on the controller or the action makes it attribute routed. Per altre informazioni, vedere Routing misto.See Mixed routing for more information.

Questo documento illustra le interazioni tra MVC e il routing e il modo in cui le tipiche app MVC usano le funzionalità di routing.This document will explain the interactions between MVC and routing, and how typical MVC apps make use of routing features. Vedere Routing per informazioni dettagliate sul routing avanzato.See Routing for details on advanced routing.

Impostazione del middleware di routingSetting up Routing Middleware

Nel metodo Configure può apparire codice simile al seguente:In your Configure method you may see code similar to:

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

Nella chiamata a UseMvc, si usa MapRoute per creare una singola route, a cui si farà riferimento come alla route predefinita (default).Inside the call to UseMvc, MapRoute is used to create a single route, which we'll refer to as the default route. La maggior parte delle app MVC userà una route con un modello simile alla route default.Most MVC apps will use a route with a template similar to the default route.

Il modello di route "{controller=Home}/{action=Index}/{id?}" può corrispondere a un percorso URL come /Products/Details/5 ed estrae i valori di route { controller = Products, action = Details, id = 5 } suddividendo il percorso in token.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 tenterà di individuare un controller denominato ProductsController e di eseguire l'azione Details:MVC will attempt to locate a controller named ProductsController and run the action Details:

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

Si noti che in questo esempio l'associazione di modelli usa il valore di id = 5 per impostare il parametro id su 5 quando si richiama l'azione.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. Per maggiori dettagli, vedere Associazione di modelli.See the Model Binding for more details.

Usando la route default:Using the default route:

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

Il modello di route:The route template:

  • {controller=Home} definisce Home come oggetto controller predefinito{controller=Home} defines Home as the default controller

  • {action=Index} definisce Index come oggetto action predefinito{action=Index} defines Index as the default action

  • {id?} definisce id come facoltativo{id?} defines id as optional

I parametri di route predefiniti e facoltativi non devono necessariamente essere presenti nel percorso URL per trovare una corrispondenza.Default and optional route parameters don't need to be present in the URL path for a match. Vedere Riferimento per i modelli di route per una descrizione dettagliata della sintassi del modello di route.See Route Template Reference for a detailed description of route template syntax.

"{controller=Home}/{action=Index}/{id?}" può corrispondere al percorso URL / e restituirà i valori di route { controller = Home, action = Index }."{controller=Home}/{action=Index}/{id?}" can match the URL path / and will produce the route values { controller = Home, action = Index }. I valori per controller e action usano i valori predefiniti, id non genera un valore perché non esiste un segmento corrispondente nel percorso URL.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. MVC usa questi valori di route per selezionare l'azione HomeController e Index:MVC would use these route values to select the HomeController and Index action:

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

Usando questa definizione del controller e il modello di route, l'azione HomeController.Index viene eseguita per tutti i percorsi URL seguenti: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

  • /

Il metodo pratico UseMvcWithDefaultRoute:The convenience method UseMvcWithDefaultRoute:

app.UseMvcWithDefaultRoute();

Può essere usato per sostituire:Can be used to replace:

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

UseMvc e UseMvcWithDefaultRoute aggiungono un'istanza di RouterMiddleware alla pipeline middleware.UseMvc and UseMvcWithDefaultRoute add an instance of RouterMiddleware to the middleware pipeline. MVC non interagisce direttamente con il middleware e usa il routing per gestire le richieste.MVC doesn't interact directly with middleware, and uses routing to handle requests. MVC è connesso alle route attraverso un'istanza di MvcRouteHandler.MVC is connected to the routes through an instance of MvcRouteHandler. Il codice all'interno di UseMvc è simile al seguente: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 non definisce direttamente le route, aggiunge un segnaposto alla raccolta di route per la route attribute.UseMvc doesn't directly define any routes, it adds a placeholder to the route collection for the attribute route. L'overload UseMvc(Action<IRouteBuilder>) consente di aggiungere le proprie route e supporta anche il routing con attributi.The overload UseMvc(Action<IRouteBuilder>) lets you add your own routes and also supports attribute routing. UseMvc e tutte le relative varianti aggiungono un segnaposto per l'attributo Route: il routing degli attributi è sempre disponibile indipendentemente dalla modalità di configurazione 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 definisce una route predefinita e supporta il routing con attributi.UseMvcWithDefaultRoute defines a default route and supports attribute routing. La sezione Routing con attributi include maggiori dettagli sul routing con attributi.The Attribute Routing section includes more details on attribute routing.

Routing convenzionaleConventional routing

La route predefinita (default):The default route:

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

è un esempio di routing convenzionale.is an example of a conventional routing. Questo stile è detto routing convenzionale poiché stabilisce una convenzione per i percorsi URL:We call this style conventional routing because it establishes a convention for URL paths:

  • il primo segmento del percorso esegue il mapping al nome del controllerthe first path segment maps to the controller name

  • il secondo esegue il mapping al nome dell'azione.the second maps to the action name.

  • il terzo segmento viene usato per un id facoltativo usato per eseguire il mapping a un'entità del modellothe third segment is used for an optional id used to map to a model entity

Usando la route default, il percorso URL /Products/List esegue il mapping all'azione ProductsController.List e /Blog/Article/17 lo esegue a 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. Questo mapping si basa solo sui nomi dell'azione e del controller e non su spazi dei nomi, percorsi dei file di origine o parametri del metodo.This mapping is based on the controller and action names only and isn't based on namespaces, source file locations, or method parameters.

Suggerimento

L'uso del routing convenzionale con la route predefinita consente di compilare rapidamente l'applicazione senza dover creare un nuovo modello di URL per ogni azione che si definisce.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. Per un'applicazione con azioni di stile CRUD, la coerenza degli URL tra i controller può semplificare il codice e rendere l'interfaccia utente più prevedibile.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.

Avviso

L'oggetto id è definito come facoltativo nel modello di route, ovvero le azioni possono essere eseguite senza l'ID specificato come parte dell'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. In genere, se si omette id dall'URL, il valore viene impostato su 0 dall'associazione del modello e di conseguenza non viene rilevata alcuna entità nel database corrispondente a 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. Il routing con attributi offre un controllo con granularità fine che consente di rendere l'ID obbligatorio per alcune azioni e non per altre.Attribute routing can give you fine-grained control to make the ID required for some actions and not for others. Per convenzione la documentazione include i parametri facoltativi come id quando è probabile che appaiano nell'uso corretto.By convention the documentation will include optional parameters like id when they're likely to appear in correct usage.

Route multipleMultiple routes

È possibile aggiungere più route all'interno di UseMvc aggiungendo altre chiamate a MapRoute.You can add multiple routes inside UseMvc by adding more calls to MapRoute. Questa operazione consente di definire più convenzioni o di aggiungere route convenzionali dedicate a un'azione specifica, ad esempio: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?}");
});

La route blog è una route convenzionale dedicata, vale a dire che usa il sistema di routing convenzionale, ma è dedicata a un'azione specifica.The blog route here is a dedicated conventional route, meaning that it uses the conventional routing system, but is dedicated to a specific action. Poiché controller e action non appaiono nel modello di route come parametri, possono avere solo i valori predefiniti e quindi questa route eseguirà sempre il mapping all'azione 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.

Le route sono ordinate nella raccolta di route e verranno elaborate nell'ordine in cui vengono aggiunte.Routes in the route collection are ordered, and will be processed in the order they're added. Quindi in questo esempio la route blog viene tentata prima della route default.So in this example, the blog route will be tried before the default route.

Nota

Le route convenzionali dedicate usano spesso parametri di route catch-all come {*article} per acquisire la parte rimanente del percorso URL.Dedicated conventional routes often use catch-all route parameters like {*article} to capture the remaining portion of the URL path. In questo modo una route può diventare troppo "greedy", ovvero corrispondere agli URL che dovrebbero corrispondere ad altre route.This can make a route 'too greedy' meaning that it matches URLs that you intended to be matched by other routes. Posizionare le route "greedy" più avanti nella tabella delle route per risolvere il problema.Put the 'greedy' routes later in the route table to solve this.

FallbackFallback

Come parte dell'elaborazione della richiesta, MVC verifica che i valori di route possano essere usati per trovare un controller e un'azione nell'applicazione.As part of request processing, MVC will verify that the route values can be used to find a controller and action in your application. Se i valori di route non corrispondano a un'azione, la route non viene considerata una corrispondenza e viene tentata la route successiva.If the route values don't match an action then the route isn't considered a match, and the next route will be tried. Questa operazione si chiama fallback e viene eseguita allo scopo di semplificare i casi in cui le route convenzionali si sovrappongono.This is called fallback, and it's intended to simplify cases where conventional routes overlap.

Rimozione dell'ambiguità delle azioniDisambiguating actions

Quando due azioni corrispondono in base al routing, MVC deve rimuovere l'ambiguità per scegliere il candidato migliore, altrimenti genera un'eccezione.When two actions match through routing, MVC must disambiguate to choose the 'best' candidate or else throw an exception. Ad esempio:For example:

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

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

Questo controller definisce due azioni corrispondenti al percorso URL /Products/Edit/17 e indirizzano i dati { 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 }. Si tratta di un modello tipico per i controller MVC in cui Edit(int) visualizza un modulo per modificare un prodotto e Edit(int, Product) elabora il modulo inviato.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. Per poter eseguire l'operazione, MVC deve scegliere Edit(int, Product) se la richiesta è un POST HTTP e Edit(int) quando il verbo HTTP è un altro elemento.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]) è un'implementazione di IActionConstraint che consente di selezionare l'azione solo quando il verbo HTTP è POST.The HttpPostAttribute ( [HttpPost] ) is an implementation of IActionConstraint that will only allow the action to be selected when the HTTP verb is POST. La presenza di un oggetto IActionConstraint fa sì che Edit(int, Product) sia una corrispondenza migliore di Edit(int), quindi Edit(int, Product) viene tentata per prima.The presence of an IActionConstraint makes the Edit(int, Product) a 'better' match than Edit(int), so Edit(int, Product) will be tried first.

È necessario scrivere implementazioni personalizzate di IActionConstraint solo in scenari specializzati, ma è importante comprendere il ruolo degli attributi, ad esempio HttpPostAttribute. Attributi simili vengono definiti per altri verbi 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. Nel routing convenzionale è normale che le azioni usino lo stesso nome di azione quando fanno parte di un flusso di lavoro show form -> submit form.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. La comodità offerta da questo modello sarà più evidente dopo aver esaminato la sezione relativa a IActionConstraint.The convenience of this pattern will become more apparent after reviewing the Understanding IActionConstraint section.

Se vi sono più route corrispondenti e MVC non è in grado di trovare la route migliore, viene generata un'eccezione AmbiguousActionException.If multiple routes match, and MVC can't find a 'best' route, it will throw an AmbiguousActionException.

Nomi di routeRoute names

Le stringhe "blog" e "default" degli esempi seguenti sono nomi di route: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?}");
});

I nomi di route consentono di assegnare a una route un nome logico, in modo che la route denominata possa essere usata per la generazione di URL.The route names give the route a logical name so that the named route can be used for URL generation. Questo semplifica notevolmente la creazione degli URL quando l'ordinamento delle route può rendere complessa la generazione di URL.This greatly simplifies URL creation when the ordering of routes could make URL generation complicated. I nomi delle route devono essere univoci a livello di applicazione.Route names must be unique application-wide.

I nomi di route non influiscono sulla corrispondenza degli URL o sulla gestione delle richieste, vengono usati solo per la generazione di URL.Route names have no impact on URL matching or handling of requests; they're used only for URL generation. L'articolo sul routing contiene informazioni dettagliate sulla generazione di URL, inclusa la generazione negli helper specifici di MVC.Routing has more detailed information on URL generation including URL generation in MVC-specific helpers.

Routing con attributiAttribute routing

Il routing con attributi usa un set di attributi per eseguire il mapping delle azioni direttamente ai modelli di route.Attribute routing uses a set of attributes to map actions directly to route templates. Nell'esempio seguente viene usato l'oggetto app.UseMvc(); nel metodo Configure e non viene passata alcuna route.In the following example, app.UseMvc(); is used in the Configure method and no route is passed. HomeController corrisponde a un set di URL simile a quello a cui corrisponderebbe la route predefinita {controller=Home}/{action=Index}/{id?}: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();
   }
}

L'azione HomeController.Index() verrà eseguita per tutti i percorsi URL, /, /Home o /Home/Index.The HomeController.Index() action will be executed for any of the URL paths /, /Home, or /Home/Index.

Nota

In questo esempio viene evidenziata un'importante differenza a livello di programmazione tra il routing con attributi e il routing convenzionale.This example highlights a key programming difference between attribute routing and conventional routing. Il routing con attributi richiede più input per specificare una route, la route convenzionale predefinita gestisce le route in modo più conciso.Attribute routing requires more input to specify a route; the conventional default route handles routes more succinctly. Tuttavia, il routing con attributi consente, e richiede, un controllo preciso dei modelli route da applicare a ogni azione.However, attribute routing allows (and requires) precise control of which route templates apply to each action.

Con il routing con attributi i nomi del controller e delle azioni non hanno alcun ruolo nella selezione dell'azione.With attribute routing the controller name and action names play no role in which action is selected. In questo esempio viene verificata la corrispondenza degli stessi URL dell'esempio precedente.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");
   }
}

Nota

I modelli di route precedenti non definiscono i parametri di route per action, area e controller.The route templates above don't define route parameters for action, area, and controller. In realtà, questi parametri di route non sono consentiti nelle route con attributi.In fact, these route parameters are not allowed in attribute routes. Poiché il modello di route è già associato a un'azione, non avrebbe senso analizzare il nome dell'azione dall'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 con attributi Http[Verb]Attribute routing with Http[Verb] attributes

Il routing con attributi può usare anche gli attributi Http[Verb], ad esempio HttpPostAttribute.Attribute routing can also make use of the Http[Verb] attributes such as HttpPostAttribute. Tutti questi attributi possono accettare un modello di route.All of these attributes can accept a route template. Questo esempio illustra due azioni che corrispondono allo stesso modello di route:This example shows two actions that match the same route template:

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

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

Per un percorso URL come /products l'azione ProductsApi.ListProducts verrà eseguita quando il verbo HTTP è GET e ProductsApi.CreateProduct verrà eseguita quando il verbo HTTP è 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. Nel routing con attributi l'URL viene prima confrontato con il set di modelli di route definiti dagli attributi della route.Attribute routing first matches the URL against the set of route templates defined by route attributes. Quando un modello di route corrisponde, vengono applicati i vincoli IActionConstraint per determinare quali azioni possono essere eseguite.Once a route template matches, IActionConstraint constraints are applied to determine which actions can be executed.

Suggerimento

Quando si compila un'API REST, è raro che si voglia usare [Route(...)] su un metodo di azione perché l'azione accetterà tutti i metodi 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. Si consiglia di usare l'oggetto Http*Verb*Attributes, più specifico, per essere precisi circa gli elementi supportati dall'API.It's better to use the more specific Http*Verb*Attributes to be precise about what your API supports. I client delle API REST devono sapere quali percorsi e verbi HTTP devono essere mappati a operazioni logiche specifiche.Clients of REST APIs are expected to know what paths and HTTP verbs map to specific logical operations.

Poiché una route con attributi si applica a un'azione specifica, è facile fare in modo che i parametri siano richiesti come parte della definizione del modello di route.Since an attribute route applies to a specific action, it's easy to make parameters required as part of the route template definition. In questo esempio id è richiesto come parte del percorso 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) { ... }
}

L'azione ProductsApi.GetProduct(int) verrà eseguita per un percorso URL come /products/3, ma non per un percorso URL come /products.The ProductsApi.GetProduct(int) action will be executed for a URL path like /products/3 but not for a URL path like /products. Vedere Routing per una descrizione completa dei modelli di route e delle opzioni correlate.See Routing for a full description of route templates and related options.

Nome di routeRoute Name

Nell’esempio di codice riportato di seguito viene definito un nome di route di 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) { ... }
}

I nomi di route possono essere usati per generare un URL in base a un percorso specifico.Route names can be used to generate a URL based on a specific route. I nomi di route non influiscono sul comportamento del routing riguardo alla corrispondenza degli URL e vengono usati solo per la generazione di URL.Route names have no impact on the URL matching behavior of routing and are only used for URL generation. I nomi delle route devono essere univoci a livello di applicazione.Route names must be unique application-wide.

Nota

Confrontare questa opzione con la route predefinita convenzionale, che definisce il parametro id come facoltativo ({id?}).Contrast this with the conventional default route, which defines the id parameter as optional ({id?}). La possibilità di specificare in modo preciso le API presenta dei vantaggi, ad esempio consente di inviare /products e /products/5 ad azioni differenti.This ability to precisely specify APIs has advantages, such as allowing /products and /products/5 to be dispatched to different actions.

Combinazione di routeCombining routes

Per rendere il routing con attributi meno ripetitivo, gli attributi di route del controller vengono combinati con gli attributi di route delle singole azioni.To make attribute routing less repetitive, route attributes on the controller are combined with route attributes on the individual actions. I modelli di route definiti per il controller vengono anteposti ai modelli di route delle azioni.Any route templates defined on the controller are prepended to route templates on the actions. Inserendo un attributo di route nel controller, tutte le azioni presenti nel controller useranno il routing con attributi.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) { ... }
}

In questo esempio il percorso URL /products può corrispondere a ProductsApi.ListProducts e il percorso URL /products/5 può corrispondere a 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). Entrambe le azioni corrispondono solo a GET HTTP perché sono contrassegnate con l'HttpGetAttribute.Both of these actions only match HTTP GET because they're marked with the HttpGetAttribute.

I modelli di route applicati a un'azione che iniziano con / o ~/ non vengono combinati con i modelli di route applicati al controller.Route templates applied to an action that begin with / or ~/ don't get combined with route templates applied to the controller. Questo esempio illustra la corrispondenza di un set di percorsi URL simile alla route predefinita.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();
    }   
}

Ordinamento delle route con attributiOrdering attribute routes

A differenza delle route convenzionali che vengono eseguite in un ordine definito, il routing con attributi crea una struttura ad albero e confronta tutte le route contemporaneamente.In contrast to conventional routes which execute in a defined order, attribute routing builds a tree and matches all routes simultaneously. Si comporta come se le voci delle route seguissero un ordine ideale in cui le route più specifiche vengono probabilmente eseguite prima delle route più generali.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.

Ad esempio, una route come blog/search/{topic} è più specifica di una route come blog/{*article}.For example, a route like blog/search/{topic} is more specific than a route like blog/{*article}. In termini logici la route blog/search/{topic} viene eseguita per prima, per impostazione predefinita, perché questo è l'ordine più plausibile.Logically speaking the blog/search/{topic} route 'runs' first, by default, because that's the only sensible ordering. Usando il routing convenzionale, lo sviluppatore ordina le route in base alle proprie esigenze.Using conventional routing, the developer is responsible for placing routes in the desired order.

Nelle route con attributi si può configurare un ordine usando la proprietà Order di tutti gli attributi di route specificati dal framework.Attribute routes can configure an order, using the Order property of all of the framework provided route attributes. Le route vengono elaborate in base a un ordinamento crescente della proprietà Order.Routes are processed according to an ascending sort of the Order property. L'ordine predefinito è 0.The default order is 0. L'impostazione di una route usando Order = -1 viene eseguita prima delle route per cui non è impostato un ordine.Setting a route using Order = -1 will run before routes that don't set an order. L'impostazione di una route usando Order = 1 viene eseguito dopo l'ordinamento predefinito delle route.Setting a route using Order = 1 will run after default route ordering.

Suggerimento

Evitare la dipendenza da Order.Avoid depending on Order. Se lo spazio URL richiede i valori in un ordine esplicito per indirizzare correttamente i dati, si può probabilmente creare confusione anche per i client.If your URL-space requires explicit order values to route correctly, then it's likely confusing to clients as well. In genere il routing con attributi seleziona la route corretta con la corrispondenza di URL.In general attribute routing will select the correct route with URL matching. Se l'ordine predefinito usato per la generazione di URL non funziona, usare il nome della route come override è in genere più semplice che applicare la proprietà Order.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.

Il routing di Razor Pages e il routing del controller MVC condividono un'implementazione.Razor Pages routing and MVC controller routing share an implementation. Per informazioni sull'ordine di routing negli argomenti di Razor Pages, vedere Convenzioni di route e app per Razor Pages in ASP.NET Core: Ordine della route.Information on route order in the Razor Pages topics is available at Razor Pages route and app conventions: Route order.

Sostituzione dei token nei modelli di route ([controller], [action], [area])Token replacement in route templates ([controller], [action], [area])

Per praticità, le route con attributi supportano la sostituzione dei token eseguita racchiudendo i token tra parentesi quadre ([, ]).For convenience, attribute routes support token replacement by enclosing a token in square-braces ([, ]). I token [action], [area] e [controller] vengono sostituiti con i valori di nome dell'azione, nome dell'area e nome del controller dall'azione in cui è definita la route.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. Nell'esempio seguente le azioni corrispondono ai percorsi URL come descritto nei commenti: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) {
        // ...
    }
}

La sostituzione dei token avviene come ultimo passaggio della creazione delle route con attributi.Token replacement occurs as the last step of building the attribute routes. L'esempio precedente si comporterà come il codice seguente: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) {
        // ...
    }
}

Le route con attributi possono anche essere combinate con l'ereditarietà.Attribute routes can also be combined with inheritance. Ciò risulta particolarmente efficace se combinato con la sostituzione dei token.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) { ... }
}

La sostituzione dei token si applica anche ai nomi di route definiti dalle route con attributi.Token replacement also applies to route names defined by attribute routes. [Route("[controller]/[action]", Name="[controller]_[action]")] genera un nome di route univoco per ogni azione.[Route("[controller]/[action]", Name="[controller]_[action]")] generates a unique route name for each action.

Per verificare la corrispondenza del delimitatore letterale della sostituzione di token [ o ], eseguirne l'escape ripetendo il carattere ([[ o ]]).To match the literal token replacement delimiter [ or ], escape it by repeating the character ([[ or ]]).

Usare un trasformatore di parametri per personalizzare la sostituzione dei tokenUse a parameter transformer to customize token replacement

La sostituzione dei token può essere personalizzata usando un trasformatore di parametri.Token replacement can be customized using a parameter transformer. Un trasformatore di parametri implementa IOutboundParameterTransformer e trasforma il valore dei parametri.A parameter transformer implements IOutboundParameterTransformer and transforms the value of parameters. Ad esempio, un trasformatore di parametri SlugifyParameterTransformer personalizzato cambia il valore di route SubscriptionManagement in subscription-management.For example, a custom SlugifyParameterTransformer parameter transformer changes the SubscriptionManagement route value to subscription-management.

RouteTokenTransformerConvention è una convenzione del modello di applicazione che:The RouteTokenTransformerConvention is an application model convention that:

  • Applica un trasformatore di parametri a tutte le route di attributi in un'applicazione.Applies a parameter transformer to all attribute routes in an application.
  • Personalizza i valori dei token delle route di attributi quando vengono sostituiti.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() { ... }
}

La convenzione RouteTokenTransformerConvention è registrata come un'opzione in 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();
    }
}

Route multipleMultiple Routes

Il routing con attributi supporta la definizione di più route che raggiungono la stessa azione.Attribute routing supports defining multiple routes that reach the same action. L'uso più comune è simulare il comportamento della route convenzionale predefinita come illustrato nell'esempio seguente: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()
}

Inserire più attributi di route nel controller significa che verranno tutti combinati con tutti gli attributi di route nei metodi dell'azione.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()
}

Quando più attributi di route (che implementano IActionConstraint) sono inseriti in un'azione, ogni vincolo dell'azione viene combinato con il modello di route dall'attributo che lo definisce.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()
}

Suggerimento

Benché l'uso di più route per le azioni possa sembrare efficace, è preferibile mantenere lo spazio URL dell'applicazione semplice e ben definito.While using multiple routes on actions can seem powerful, it's better to keep your application's URL space simple and well-defined. Usare più route per le azioni solo se necessario, ad esempio per supportare i client esistenti.Use multiple routes on actions only where needed, for example to support existing clients.

Definizione di parametri facoltativi, valori predefiniti e vincoli della route con attributiSpecifying attribute route optional parameters, default values, and constraints

Le route con attributi supportano la stessa sintassi inline delle route convenzionali per specificare i parametri facoltativi, i valori predefiniti e i vincoli.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)
{
   // ...
}

Vedere Riferimento per i modelli di route per una descrizione dettagliata della sintassi del modello di route.See Route Template Reference for a detailed description of route template syntax.

Attributi di route personalizzati che usano IRouteTemplateProviderCustom route attributes using IRouteTemplateProvider

Tutti gli attributi di route disponibili nel framework ([Route(...)], [HttpGet(...)] e così via) implementano l'interfaccia IRouteTemplateProvider.All of the route attributes provided in the framework ( [Route(...)], [HttpGet(...)] , etc.) implement the IRouteTemplateProvider interface. MVC cerca gli attributi per le classi del controller e i metodi delle azioni all'avvio dell'app e usa quelli che implementano IRouteTemplateProvider per compilare il set iniziale di route.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.

È possibile implementare IRouteTemplateProvider per definire i propri attributi di route.You can implement IRouteTemplateProvider to define your own route attributes. Ogni IRouteTemplateProvider consente di definire una singola route con un modello di route, un ordinamento e un nome personalizzati: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; }
}

L'attributo dell'esempio precedente imposta automaticamente Template su "api/[controller]" quando si applica [MyApiController].The attribute from the above example automatically sets the Template to "api/[controller]" when [MyApiController] is applied.

Uso del modello applicativo per personalizzare le route con attributiUsing Application Model to customize attribute routes

Il modello applicativo è un modello a oggetti creato all'avvio con tutti i metadati usati da MVC per indirizzare ed eseguire le azioni.The application model is an object model created at startup with all of the metadata used by MVC to route and execute your actions. Il modello applicativo include tutti i dati raccolti da attributi di route (attraverso IRouteTemplateProvider).The application model includes all of the data gathered from route attributes (through IRouteTemplateProvider). È possibile scrivere convenzioni per modificare il modello applicativo in fase di avvio per personalizzare il comportamento del routing.You can write conventions to modify the application model at startup time to customize how routing behaves. Questa sezione illustra un semplice esempio di personalizzazione del routing con il modello applicativo.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 misto: routing con attributi e routing convenzionaleMixed routing: Attribute routing vs conventional routing

Le applicazioni MVC sono in grado di usare una combinazione di routing convenzionale e routing con attributi.MVC applications can mix the use of conventional routing and attribute routing. In genere le route convenzionali vengono usate per i controller che gestiscono le pagine HTML per i browser e le route con attributi per i controller che gestiscono le API REST.It's typical to use conventional routes for controllers serving HTML pages for browsers, and attribute routing for controllers serving REST APIs.

Le azioni vengono indirizzate in modo convenzionale o con attributi.Actions are either conventionally routed or attribute routed. Se una route viene inserita nel controller o nell'azione, viene indirizzata con attributi.Placing a route on the controller or the action makes it attribute routed. Le azioni che definiscono le route con attributi non possono essere raggiunte usando le route convenzionali e viceversa.Actions that define attribute routes cannot be reached through the conventional routes and vice-versa. Qualsiasi attributo di route del controller rende tutte le azioni presenti nel controller indirizzate con attributi.Any route attribute on the controller makes all actions in the controller attribute routed.

Nota

Ciò che distingue i due tipi di sistema di routing è il processo applicato dopo che si è verificata la corrispondenza di un URL con un modello di route.What distinguishes the two types of routing systems is the process applied after a URL matches a route template. Nel routing convenzionale i valori di route della corrispondenza vengono usati per scegliere l'azione e il controller da una tabella di ricerca di tutte le azioni indirizzate in modo convenzionale.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. Nel routing con attributi ogni modello è già associato a un'azione e non è necessaria alcuna ulteriore ricerca.In attribute routing, each template is already associated with an action, and no further lookup is needed.

Segmenti complessiComplex segments

I segmenti complessi (ad esempio, [Route("/dog{token}cat")]), vengono elaborati individuando corrispondenze per i valori letterali da destra a sinistra in modalità non-greedy.Complex segments (for example, [Route("/dog{token}cat")]), are processed by matching up literals from right to left in a non-greedy way. Vedere il codice sorgente per una descrizione.See the source code for a description. Per altre informazioni, vedere questo problema.For more information, see this issue.

Generazione di URLURL Generation

Le applicazioni MVC sono in grado di usare le funzionalità di generazione di URL del routing per generare i collegamenti URL alle azioni.MVC applications can use routing's URL generation features to generate URL links to actions. La generazione di URL evita la codifica degli URL e consente di rendere il codice più affidabile e gestibile.Generating URLs eliminates hardcoding URLs, making your code more robust and maintainable. Questa sezione illustra le funzionalità di generazione di URL disponibili in MVC e tratta solo le nozioni di base sul funzionamento della generazione di URL.This section focuses on the URL generation features provided by MVC and will only cover basics of how URL generation works. Vedere Routing per una descrizione dettagliata della generazione di URL.See Routing for a detailed description of URL generation.

L'interfaccia IUrlHelper è l'elemento sottostante dell'infrastruttura tra MVC e il routing per la generazione di URL.The IUrlHelper interface is the underlying piece of infrastructure between MVC and routing for URL generation. È possibile trovare un'istanza di IUrlHelper disponibile usando la proprietà Url in controller, visualizzazioni e componenti di visualizzazione.You'll find an instance of IUrlHelper available through the Url property in controllers, views, and view components.

In questo esempio l'interfaccia IUrlHelper viene usata attraverso la proprietà Controller.Url per generare un URL a un'altra azione.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();
    }
}

Se l'applicazione usa la route convenzionale predefinita, il valore della variabile url sarà la stringa del percorso 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. Il percorso URL viene creato dal routing combinando i valori di route della richiesta corrente (valori di ambiente) con i valori passati a Url.Action e sostituendo tali valori nel modello di route: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

Il valore di ogni parametro di route del modello di route viene sostituito attraverso la corrispondenza dei nomi con i valori e i valori di ambiente.Each route parameter in the route template has its value substituted by matching names with the values and ambient values. Per un parametro di route senza un valore si può usare un valore predefinito, se ne esiste uno, oppure ignorare il parametro se è facoltativo (come nel caso di id in questo esempio).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). La generazione di URL avrà esito negativo se un parametro di route obbligatorio non ha un valore corrispondente.URL generation will fail if any required route parameter doesn't have a corresponding value. Se la generazione di URL non riesce per una route, viene tentata la route successiva finché non vengono tentate tutte le route o viene trovata una corrispondenza.If URL generation fails for a route, the next route is tried until all routes have been tried or a match is found.

Nell'esempio di Url.Action precedente si presuppone che il routing sia convenzionale, ma la generazione di URL funziona in modo analogo con il routing con attributi, sebbene i concetti siano differenti.The example of Url.Action above assumes conventional routing, but URL generation works similarly with attribute routing, though the concepts are different. Con il routing convenzionale i valori di route vengono usati per espandere un modello e i valori di route per controller e action in genere appaiono in quel modello. Questo procedimento funziona perché gli URL corrispondenti in base al routing rispettano una convenzione.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. Nel routing con attributi i valori di route per controller e action non possono essere visualizzati nel modello ma vengono usati per individuare il modello da usare.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.

Questo esempio usa il routing con attributi: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 compila una tabella di ricerca di tutte le azioni indirizzate con attributi e stabilisce la corrispondenza dei valori controller e action per selezionare il modello di route da usare per la generazione di 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. Nell'esempio precedente viene generato custom/url/to/destination.In the sample above, custom/url/to/destination is generated.

Generazione di URL in base al nome dell'azioneGenerating URLs by action name

Url.Action (IUrlHelper .Url.Action (IUrlHelper . Action) e tutti gli overload correlati sono basati sull'idea che si voglia definire l'oggetto a cui ci si sta collegando specificando un nome di controller e un nome di azione.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.

Nota

Quando si usa Url.Action, vengono specificati i valori di route correnti per controller e action: il valore di controller e action sono parte dei valori di ambiente e .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. Il metodo Url.Action, usa sempre i valori correnti di action e controller e genererà un percorso URL che indirizza all'azione corrente.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.

Il routing tenta di usare i valori nei valori di ambiente per ottenere le informazioni non specificate durante la generazione di un URL.Routing attempts to use the values in ambient values to fill in information that you didn't provide when generating a URL. Usando una route come {a}/{b}/{c}/{d} e i valori di ambiente { a = Alice, b = Bob, c = Carol, d = David }, il routing ha informazioni sufficienti per generare un URL senza valori aggiuntivi, poiché tutti i parametri di route hanno un valore.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. Se è stato aggiunto il valore { d = Donovan }, il valore { d = David } viene ignorato e il percorso URL generato è 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.

Avviso

I percorsi URL sono gerarchici.URL paths are hierarchical. Nell'esempio precedente, se è stato aggiunto il valore { c = Cheryl }, entrambi i valori { c = Carol, d = David } vengono ignorati.In the example above, if you added the value { c = Cheryl }, both of the values { c = Carol, d = David } would be ignored. In questo caso non è più disponibile un valore per d e la generazione dell'URL avrà esito negativo.In this case we no longer have a value for d and URL generation will fail. Sarà necessario specificare un valore per c e d.You would need to specify the desired value of c and d. In apparenza questo problema si può risolvere con la route predefinita ({controller}/{action}/{id?}), ma in realtà questo comportamento si verifica raramente perché Url.Action specifica sempre in modo esplicito un valore controller e action.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.

Anche gli overload di Url.Action di maggiore durata accettano anche un oggetto valori di route aggiuntivo per specificare i valori per i parametri di route diversi da controller e action.Longer overloads of Url.Action also take an additional route values object to provide values for route parameters other than controller and action. In genere viene usato con id come Url.Action("Buy", "Products", new { id = 17 }).You will most commonly see this used with id like Url.Action("Buy", "Products", new { id = 17 }). Per convenzione l'oggetto valori di route è in genere un oggetto di tipo anonimo, ma può anche essere un IDictionary<> o un normale oggetto .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. I valori di route aggiuntivi che non corrispondono a parametri di route vengono inseriti nella stringa di query.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);
    }
}

Suggerimento

Per creare un URL assoluto, usare un overload che accetta un 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)

Generazione di URL in base alla routeGenerating URLs by route

Il codice precedente illustra come generare un URL passando il nome del controller e dell'azione.The code above demonstrated generating a URL by passing in the controller and action name. IUrlHelper specifica anche la famiglia di metodi Url.RouteUrl.IUrlHelper also provides the Url.RouteUrl family of methods. Questi metodi sono simili a Url.Action, ma non copiano i valori correnti di action e controller nei valori di route.These methods are similar to Url.Action, but they don't copy the current values of action and controller to the route values. L'uso più comune consiste nello specificare un nome di route per usare un percorso specifico per generare l'URL, in genere senza specificare un nome di controller o azione.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();
    }
}

Generazione di URL in HTMLGenerating URLs in HTML

IHtmlHelper specifica i metodi HtmlHelper``Html.BeginForm e Html.ActionLink per generare rispettivamente gli elementi <form> e <a>.IHtmlHelper provides the HtmlHelper methods Html.BeginForm and Html.ActionLink to generate <form> and <a> elements respectively. Questi metodi usano il metodo Url.Action per generare un URL e accettano argomenti simili.These methods use the Url.Action method to generate a URL and they accept similar arguments. Gli oggetti Url.RouteUrl complementi di HtmlHelper sono Html.BeginRouteForm e Html.RouteLink e hanno una funzionalità simile.The Url.RouteUrl companions for HtmlHelper are Html.BeginRouteForm and Html.RouteLink which have similar functionality.

Gli helper tag generano gli URL attraverso l'helper tag form e l'helper tag <a>.TagHelpers generate URLs through the form TagHelper and the <a> TagHelper. Entrambi usano IUrlHelper per la propria implementazione.Both of these use IUrlHelper for their implementation. Per altre informazioni, vedere Uso dei moduli.See Working with Forms for more information.

All'interno delle visualizzazioni IUrlHelper è reso disponibile dalla proprietà Url per tutte le generazioni di URL ad hoc che non rientrano nelle situazioni descritte in precedenza.Inside views, the IUrlHelper is available through the Url property for any ad-hoc URL generation not covered by the above.

Generazione di URL nei risultati delle azioniGenerating URLS in Action Results

Negli esempi precedenti è stato usato IUrlHelper in un controller, ma l'uso più comune in un controller è generare un URL come parte del risultato di un'azione.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.

Le classi di base ControllerBase e Controller offrono metodi pratici per i risultati delle azioni che fanno riferimento a un'altra azione.The ControllerBase and Controller base classes provide convenience methods for action results that reference another action. Un uso tipico è eseguire il reindirizzamento dopo aver accettato l'input dell'utente.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);
}

I metodi factory dei risultati delle azioni seguono un modello simile ai metodi per IUrlHelper.The action results factory methods follow a similar pattern to the methods on IUrlHelper.

Caso speciale per le route convenzionali dedicateSpecial case for dedicated conventional routes

Nel routing convenzionale è possibile usare un tipo speciale di definizione di route denominata route convenzionale dedicata.Conventional routing can use a special kind of route definition called a dedicated conventional route. Nell'esempio seguente la route denominata blog è una route convenzionale dedicata.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?}");
});

Usando queste definizioni di route, Url.Action("Index", "Home") genera il percorso URL / con la route default per un motivo ben preciso.Using these route definitions, Url.Action("Index", "Home") will generate the URL path / with the default route, but why? Si potrebbe pensare che i valori di route { controller = Home, action = Index } siano sufficienti per generare un URL usando blog e che il risultato sia /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.

Le route convenzionali dedicate si basano su un comportamento speciale dei valori predefiniti per i quali non esiste un parametro di route corrispondente che impedisce alla route di essere troppo "greedy" con la generazione degli 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. In questo caso i valori predefiniti sono { controller = Blog, action = Article } e né controlleraction vengono visualizzati come parametri di route.In this case the default values are { controller = Blog, action = Article }, and neither controller nor action appears as a route parameter. Quando il routing esegue la generazione di URL, i valori specificati devono corrispondere ai valori predefiniti.When routing performs URL generation, the values provided must match the default values. La generazione di URL che usa blog avrà esito negativo perché i valori { controller = Home, action = Index } non corrispondono a { controller = Blog, action = Article }.URL generation using blog will fail because the values { controller = Home, action = Index } don't match { controller = Blog, action = Article }. Il routing quindi esegue il fallback per provare default, che ha esito positivo.Routing then falls back to try default, which succeeds.

AreeAreas

Le aree sono una funzionalità di MVC che consente di organizzare le funzioni correlate in un gruppo come spazio dei nomi di routing separato (per le azioni del controller) e struttura di cartelle (per le visualizzazioni).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). L'uso delle aree consente a un'applicazione di usare più controller con lo stesso nome, purché abbiano aree diverse.Using areas allows an application to have multiple controllers with the same name - as long as they have different areas. Usando le aree si crea una gerarchia per il routing aggiungendo un altro parametro di route, area a controller e action.Using areas creates a hierarchy for the purpose of routing by adding another route parameter, area to controller and action. Questa sezione illustra il modo in cui il routing interagisce con le aree. Vedere Aree per informazioni dettagliate sull'uso delle aree con le visualizzazioni.This section will discuss how routing interacts with areas - see Areas for details about how areas are used with views.

Nell'esempio seguente MVC viene configurato in modo da usare la route convenzionale predefinita e una route di area per un'area denominata Blog:The following example configures MVC to use the default conventional route and an area route for an area named Blog:

app.UseMvc(routes =>
{
    routes.MapAreaRoute("blog_route", "Blog",
        "Manage/{controller}/{action}/{id?}");
    routes.MapRoute("default_route", "{controller}/{action}/{id?}");
});

Nella corrispondenza di un percorso URL come /Manage/Users/AddUser la prima route produrrà i valori di route { 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 }. Il valore di route area è generato da un valore predefinito per area, infatti la route creata da MapAreaRoute equivale alla seguente:The area route value is produced by a default value for area, in fact the route created by MapAreaRoute is equivalent to the following:

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

MapAreaRoute crea una route che usa sia un valore predefinito che un vincolo per area usando il nome di area specificato, in questo caso Blog.MapAreaRoute creates a route using both a default value and constraint for area using the provided area name, in this case Blog. Il valore predefinito assicura che la route generi sempre { area = Blog, ... }, il vincolo richiede il valore { area = Blog, ... } per la generazione di URL.The default value ensures that the route always produces { area = Blog, ... }, the constraint requires the value { area = Blog, ... } for URL generation.

Suggerimento

Il routing convenzionale dipende dall'ordinamento.Conventional routing is order-dependent. In generale, le route con aree devono essere posizionate prima delle altre nella tabella di route poiché sono più specifiche rispetto alle route senza un'area.In general, routes with areas should be placed earlier in the route table as they're more specific than routes without an area.

Se si usa l'esempio precedente, i valori di route corrispondono all'azione seguente: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
    {
        public IActionResult AddUser()
        {
            return View();
        }        
    }
}

AreaAttribute è ciò che denota un controller come parte di un'area, questo controller in particolare si trova nell'area Blog.The AreaAttribute is what denotes a controller as part of an area, we say that this controller is in the Blog area. I controller senza un attributo [Area] non sono membri di alcuna area e non corrispondono quando il valore di route area viene specificato dal 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. Nell'esempio seguente solo il primo controller indicato può corrispondere ai valori di route { 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
    {
        public IActionResult AddUser()
        {
            return View();
        }        
    }
}
using Microsoft.AspNetCore.Mvc;

namespace MyApp.Namespace2
{
    // Matches { area = Zebra, controller = Users, action = AddUser }
    [Area("Zebra")]
    public class UsersController : Controller
    {
        public IActionResult AddUser()
        {
            return View();
        }        
    }
}
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
    {
        public IActionResult AddUser()
        {
            return View();

        }
    }
}

Nota

Lo spazio dei nomi di ogni controller viene indicato qui per motivi di completezza, per evitare conflitti di denominazione nei controller e la generazione di errori del compilatore.The namespace of each controller is shown here for completeness - otherwise the controllers would have a naming conflict and generate a compiler error. Gli spazi dei nomi delle classi non hanno effetto sul routing di MVC.Class namespaces have no effect on MVC's routing.

I primi due controller sono membri di aree e corrispondono solo quando viene specificato il relativo nome di area dal valore di route area.The first two controllers are members of areas, and only match when their respective area name is provided by the area route value. Il terzo controller non è un membro di un'area e può corrispondere solo quando non vengono specificati valori per area dal routing.The third controller isn't a member of any area, and can only match when no value for area is provided by routing.

Nota

In termini di corrispondenza con nessun valore, l'assenza del valore area è come se il valore per area fosse Null o la stringa vuota.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.

Quando si esegue un'azione all'interno di un'area, il valore di route per area sarà disponibile come valore di ambiente per il routing da usare per la generazione di 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. Ciò significa che per impostazione predefinita le aree funzionano temporaneamente per la generazione di URL, come illustrato nell'esempio seguente.This means that by default areas act sticky for URL generation as demonstrated by the following sample.

app.UseMvc(routes =>
{
    routes.MapAreaRoute("duck_route", "Duck",
        "Manage/{controller}/{action}/{id?}");
    routes.MapRoute("default", "Manage/{controller=Home}/{action=Index}/{id?}");
});
using Microsoft.AspNetCore.Mvc;

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

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

Informazioni su IActionConstraintUnderstanding IActionConstraint

Nota

Questa sezione offre un'analisi approfondita degli elementi interni del framework e del modo in cui MVC sceglie un'azione da eseguire.This section is a deep-dive on framework internals and how MVC chooses an action to execute. Un'applicazione tipica non richiede un oggetto IActionConstraint personalizzatoA typical application won't need a custom IActionConstraint

Probabilmente l'utente ha già usato IActionConstraint anche se non ha familiarità con l'interfaccia.You have likely already used IActionConstraint even if you're not familiar with the interface. L'attributo [HttpGet] e gli attributi [Http-VERB] dello stesso tipo implementano IActionConstraint per limitare l'esecuzione di un metodo di azione.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(...) { }
}

Se si usa la route convenzionale predefinita, il percorso URL /Products/Edit produce i valori { controller = Products, action = Edit }, che corrispondono a entrambe le azioni illustrate qui.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. Nella terminologia di IActionConstraint si dice che entrambe le azioni sono considerate candidati poiché corrispondono entrambe ai dati della route.In IActionConstraint terminology we would say that both of these actions are considered candidates - as they both match the route data.

Quando viene eseguito HttpGetAttribute indica che Edit() è una corrispondenza per GET e non è una corrispondenza per qualsiasi altro verbo 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. L'azione Edit(...) non ha tutti i vincoli definiti e quindi corrisponde a qualsiasi verbo HTTP.The Edit(...) action doesn't have any constraints defined, and so will match any HTTP verb. Presupponendo l'uso di un oggetto POST, corrisponde solo Edit(...).So assuming a POST - only Edit(...) matches. Per un oggetto GET possono invece corrispondere entrambe le azioni, tuttavia un'azione con IActionConstraint viene sempre considerata migliore rispetto a un'azione senza tale oggetto.But, for a GET both actions can still match - however, an action with an IActionConstraint is always considered better than an action without. Quindi, dal momento che Edit() ha [HttpGet] è considerata più specifica e verrà selezionata se entrambe le azioni possono corrispondere.So because Edit() has [HttpGet] it's considered more specific, and will be selected if both actions can match.

Concettualmente, IActionConstraint è una forma di overload, ma anziché sostituire i metodi con lo stesso nome, supporta l'overload tra le azioni che corrispondono allo stesso 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. Anche il routing con attributi usa IActionConstraint e può accadere che azioni di controller diversi vengano entrambe considerate candidati.Attribute routing also uses IActionConstraint and can result in actions from different controllers both being considered candidates.

Implementazione di IActionConstraintImplementing IActionConstraint

Il modo più semplice di implementare un oggetto IActionConstraint è creare una classe derivata da System.Attribute e inserirla nelle azioni e nel controller.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 rileverà automaticamente tutti gli oggetti IActionConstraint applicati come attributi.MVC will automatically discover any IActionConstraint that are applied as attributes. È possibile usare il modello di applicazione per applicare i vincoli e questo è probabilmente l'approccio più flessibile, poiché consente di metaprogrammare le modalità di applicazione.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.

Nell'esempio seguente un vincolo sceglie un'azione in base a un codice paese dai dati di route.In the following example a constraint chooses an action based on a country code from the route data. Vedere l'esempio completo su 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);
    }
}

L'utente è responsabile dell'implementazione del metodo Accept e della scelta di un "ordine" per il vincolo da eseguire.You are responsible for implementing the Accept method and choosing an 'Order' for the constraint to execute. In questo caso il metodo Accept restituisce true per indicare che l'azione è una corrispondenza quando il valore di route country corrisponde.In this case, the Accept method returns true to denote the action is a match when the country route value matches. Questo comportamento è diverso da quello di RouteValueAttribute poiché viene consentito il fallback a un'azione senza attributi.This is different from a RouteValueAttribute in that it allows fallback to a non-attributed action. L'esempio indica che se si definisce un'azione en-US, per il codice paese, ad esempio fr-FR, viene eseguito il fallback a un controller più generico a cui non è applicato [CountrySpecific(...)].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.

La proprietà Order decide a quale fase appartiene il vincolo.The Order property decides which stage the constraint is part of. I vincoli relativi alle azioni vengono eseguiti in gruppi basati su Order.Action constraints run in groups based on the Order. Ad esempio, tutti gli attributi del metodo HTTP specificati dal framework usano lo stesso valore Order in modo da essere eseguiti nella stessa fase.For example, all of the framework provided HTTP method attributes use the same Order value so that they run in the same stage. È possibile usare un numero illimitato di fasi per implementare i criteri necessari.You can have as many stages as you need to implement your desired policies.

Suggerimento

Quando si sceglie un valore per Order considerare se il vincolo dovrà essere applicato o meno prima dei metodi HTTP.To decide on a value for Order think about whether or not your constraint should be applied before HTTP methods. I numeri più bassi vengono eseguiti per primi.Lower numbers run first.