Routing degli URL

di Erik Reitan

Scaricare il progetto di esempio Wingtip Toys (C#) o scaricare e-book (PDF)

Questa serie di esercitazioni illustra le nozioni di base per la creazione di un'applicazione Web Forms ASP.NET usando ASP.NET 4.5 e Microsoft Visual Studio Express 2013 per Web. Per questa serie di esercitazioni è disponibile un progetto di Visual Studio 2013 con codice sorgente C#.

In questa esercitazione si modificherà l'applicazione di esempio Wingtip Toys per supportare il routing degli URL. Il routing consente all'applicazione Web di usare URL descrittivi, più facili da ricordare e meglio supportati dai motori di ricerca. Questa esercitazione si basa sull'esercitazione precedente "Appartenenza e amministrazione" ed è parte della serie di esercitazioni wingtip Toys.

Contenuto dell'esercitazione:

  • Come registrare le route per un'applicazione Web Forms ASP.NET.
  • Come aggiungere route a una pagina Web.
  • Come selezionare i dati da un database per supportare le route.

Panoramica del routing di ASP.NET

Il routing degli URL consente di configurare un'applicazione per accettare GLI URL di richiesta che non eseguono il mapping ai file fisici. Un URL di richiesta è semplicemente l'URL immesso dall'utente nel browser per trovare una pagina nel sito Web. Si usa il routing per definire gli URL che sono semanticamente significativi per gli utenti e che possono essere utili per l'ottimizzazione del motore di ricerca (SEO).

Per impostazione predefinita, il modello di Web Forms include url descrittivi ASP.NET. Gran parte del lavoro di routing di base verrà implementata usando URL descrittivi. Tuttavia, in questa esercitazione si aggiungeranno funzionalità di routing personalizzate.

Prima di personalizzare il routing url, l'applicazione di esempio Wingtip Toys può collegarsi a un prodotto usando l'URL seguente:

https://localhost:44300/ProductDetails.aspx?productID=2

Personalizzando il routing url, l'applicazione di esempio Wingtip Toys si collecherà allo stesso prodotto usando un URL di lettura più semplice:

https://localhost:44300/Product/Convertible%20Car

Route

Una route è un modello URL di cui è stato eseguito il mapping su un gestore. Il gestore può essere un file fisico, ad esempio un file aspx in un'applicazione Web Forms. Un gestore può anche essere una classe che elabora la richiesta. Per definire una route, creare un'istanza della classe Route specificando il modello di URL, il gestore e facoltativamente un nome per la route.

Aggiungere la route all'applicazione aggiungendo l'oggetto Route alla proprietà statica Routes della RouteTable classe . La proprietà Routes è un RouteCollection oggetto che archivia tutte le route per l'applicazione.

Modelli URL

Un modello DI URL può contenere valori letterali e segnaposto variabili (detti parametri URL). I valori letterali e i segnaposto si trovano in segmenti dell'URL delimitati dal carattere barra (/).

Quando viene effettuata una richiesta all'applicazione Web, l'URL viene analizzato in segmenti e segnaposto e i valori delle variabili vengono forniti al gestore della richiesta. Questo processo è simile al modo in cui i dati in una stringa di query vengono analizzati e passati al gestore della richiesta. In entrambi i casi, le informazioni sulle variabili vengono incluse nell'URL e passate al gestore sotto forma di coppie chiave-valore. Per le stringhe di query, sia le chiavi che i valori si trovano nell'URL. Per le route, le chiavi sono i nomi segnaposto definiti nel modello di URL e solo i valori si trovano nell'URL.

In un modello di URL i segnaposto vengono definiti racchiudendoli tra parentesi graffe ( { e } ). È possibile definire più segnaposto in un segmento, ma i segnaposto devono essere separati da un valore letterale. Ad esempio, {language}-{country}/{action} è un modello di route valido. Tuttavia, {language}{country}/{action} non è un modello valido, perché non esiste alcun valore letterale o delimitatore tra i segnaposto. Pertanto, il routing non può determinare dove separare il valore per il segnaposto della lingua dal valore per il segnaposto del paese.

Mapping e registrazione delle route

Prima di poter includere route alle pagine dell'applicazione di esempio Wingtip Toys, è necessario registrare le route all'avvio dell'applicazione. Per registrare le route, si modificherà il Application_Start gestore eventi.

  1. In Esplora soluzioni of Visual Studio trovare e aprire il file Global.asax.cs.

  2. Aggiungere il codice evidenziato in giallo al file Global.asax.cs come indicato di seguito:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    using System.Web.Optimization;
    using System.Web.Routing;
    using System.Web.Security;
    using System.Web.SessionState;
    using System.Data.Entity;
    using WingtipToys.Models;
    using WingtipToys.Logic;
    
    namespace WingtipToys
    {
        public class Global : HttpApplication
        {
            void Application_Start(object sender, EventArgs e)
            {
              // Code that runs on application startup
              RouteConfig.RegisterRoutes(RouteTable.Routes);
              BundleConfig.RegisterBundles(BundleTable.Bundles);
    
              // Initialize the product database.
              Database.SetInitializer(new ProductDatabaseInitializer());
    
              // Create custom role and user.
              RoleActions roleActions = new RoleActions();
              roleActions.AddUserAndRole();
    
              // Add Routes.
              RegisterCustomRoutes(RouteTable.Routes);
            }
    
            void RegisterCustomRoutes(RouteCollection routes)
            {
              routes.MapPageRoute(
                  "ProductsByCategoryRoute",
                  "Category/{categoryName}",
                  "~/ProductList.aspx"
              );
              routes.MapPageRoute(
                  "ProductByNameRoute",
                  "Product/{productName}",
                  "~/ProductDetails.aspx"
              );
            }
        }
    }
    

All'avvio dell'applicazione di esempio Wingtip Toys, chiama il Application_Start gestore eventi. Alla fine di questo gestore eventi, viene chiamato il RegisterCustomRoutes metodo . Il RegisterCustomRoutes metodo aggiunge ogni route chiamando il MapPageRoute metodo dell'oggetto RouteCollection . Le route vengono definite usando un nome di route, un URL di route e un URL fisico.

Il primo parametro ("ProductsByCategoryRoute") è il nome della route. Viene usato per chiamare la route quando è necessaria. Il secondo parametro ("Category/{categoryName}") definisce l'URL di sostituzione descrittivo che può essere dinamico in base al codice. Questa route viene usata quando si popola un controllo dati con collegamenti generati in base ai dati. Viene visualizzata una route come segue:

routes.MapPageRoute(
      "ProductsByCategoryRoute",
      "Category/{categoryName}",
      "~/ProductList.aspx"
  );

Il secondo parametro della route include un valore dinamico specificato dalle parentesi graffe ({ }). In questo caso, è categoryName una variabile che verrà usata per determinare il percorso di routing appropriato.

Nota

Facoltativo

È possibile che sia più semplice gestire il codice spostando il RegisterCustomRoutes metodo in una classe separata. Nella cartella Logica creare una classe separata RouteActions . Spostare il metodo precedente RegisterCustomRoutes dal file Global.asax.cs alla nuova RoutesActions classe. Usare la RoleActions classe e il createAdmin metodo come esempio di come chiamare il RegisterCustomRoutes metodo dal file Global.asax.cs .

È anche possibile che sia stata notata la chiamata al RegisterRoutes metodo usando l'oggetto RouteConfig all'inizio del Application_Start gestore eventi. Questa chiamata viene effettuata per implementare il routing predefinito. È stato incluso come codice predefinito quando è stata creata l'applicazione usando il modello di Web Forms di Visual Studio.

Recupero e uso dei dati di route

Come indicato in precedenza, è possibile definire le route. Il codice aggiunto al Application_Start gestore eventi nel file Global.asax.cs carica le route definibili.

Impostazione delle route

Le route richiedono l'aggiunta di codice aggiuntivo. In questa esercitazione si userà l'associazione di modelli per recuperare un RouteValueDictionary oggetto usato durante la generazione delle route usando dati da un controllo dati. L'oggetto RouteValueDictionary conterrà un elenco di nomi di prodotto che appartengono a una categoria specifica di prodotti. Viene creato un collegamento per ogni prodotto in base ai dati e alla route.

Abilitare le route per categorie e prodotti

Si aggiornerà quindi l'applicazione in modo da usare ProductsByCategoryRoute per determinare la route corretta da includere per ogni collegamento di categoria di prodotti. Si aggiornerà anche la pagina ProductList.aspx per includere un collegamento indirizzato per ogni prodotto. I collegamenti verranno visualizzati come prima della modifica, ma i collegamenti useranno ora il routing degli URL.

  1. In Esplora soluzioni aprire la pagina Site.Master se non è già aperta.

  2. Aggiornare il controllo ListView denominato "categoryList" con le modifiche evidenziate in giallo, in modo che il markup venga visualizzato come segue:

    <asp:ListView ID="categoryList"  
        ItemType="WingtipToys.Models.Category" 
        runat="server"
        SelectMethod="GetCategories" >
        <ItemTemplate>
            <b style="font-size: large; font-style: normal">
            <a href="<%#: GetRouteUrl("ProductsByCategoryRoute", new {categoryName = Item.CategoryName}) %>">
                <%#: Item.CategoryName %>
            </a>
            </b>
        </ItemTemplate>
        <ItemSeparatorTemplate>  |  </ItemSeparatorTemplate>
    </asp:ListView>
    
  3. In Esplora soluzioni aprire la pagina ProductList.aspx.

  4. Aggiornare l'elemento ItemTemplate della pagina ProductList.aspx con gli aggiornamenti evidenziati in giallo, in modo che il markup venga visualizzato come segue:

    <ItemTemplate>
      <td runat="server">
        <table>
          <tr>
            <td>
              <a href="<%#: GetRouteUrl("ProductByNameRoute", new {productName = Item.ProductName}) %>">
                <image src='/Catalog/Images/Thumbs/<%#:Item.ImagePath%>'
                  width="100" height="75" border="1" />
              </a>
            </td>
          </tr>
          <tr>
            <td>
              <a href="<%#: GetRouteUrl("ProductByNameRoute", new {productName = Item.ProductName}) %>">
                <%#:Item.ProductName%>
              </a>
              <br />
              <span>
                <b>Price: </b><%#:String.Format("{0:c}", Item.UnitPrice)%>
              </span>
              <br />
              <a href="/AddToCart.aspx?productID=<%#:Item.ProductID %>">
                <span class="ProductListItem">
                  <b>Add To Cart<b>
                </span>
              </a>
            </td>
          </tr>
          <tr>
            <td>&nbsp;</td>
          </tr>
        </table>
        </p>
      </td>
    </ItemTemplate>
    
  5. Aprire il code-behind di ProductList.aspx.cs e aggiungere lo spazio dei nomi seguente come evidenziato in giallo:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    using System.Web.UI;
    using System.Web.UI.WebControls;
    using WingtipToys.Models;
    using System.Web.ModelBinding;
    using System.Web.Routing;
    
  6. Sostituire il GetProducts metodo del code-behind (ProductList.aspx.cs) con il codice seguente:

    public IQueryable<Product> GetProducts(
        [QueryString("id")] int? categoryId,
        [RouteData] string categoryName)
    {
        var _db = new WingtipToys.Models.ProductContext();
        IQueryable<Product> query = _db.Products;
    
        if (categoryId.HasValue && categoryId > 0)
        {
            query = query.Where(p => p.CategoryID == categoryId);
        }
    
        if (!String.IsNullOrEmpty(categoryName))
        {
            query = query.Where(p =>
                String.Compare(p.Category.CategoryName,
                categoryName) == 0);
        }
        return query;
    }
    

Aggiungere il codice per i dettagli del prodotto

Aggiornare ora il code-behind (ProductDetails.aspx.cs) per la pagina ProductDetails.aspx per usare i dati di route. Si noti che il nuovo GetProduct metodo accetta anche un valore stringa di query per il caso in cui l'utente abbia un segnalibro di collegamento che usa l'URL non indirizzato meno recente.

  1. Sostituire il GetProduct metodo del code-behind (ProductDetails.aspx.cs) con il codice seguente:

    public IQueryable<Product> GetProduct(
            [QueryString("ProductID")] int? productId,
            [RouteData] string productName)
    {
        var _db = new WingtipToys.Models.ProductContext();
        IQueryable<Product> query = _db.Products;
        if (productId.HasValue && productId > 0)
        {
            query = query.Where(p => p.ProductID == productId);
        }
        else if (!String.IsNullOrEmpty(productName))
        {
            query = query.Where(p =>
                  String.Compare(p.ProductName, productName) == 0);
        }
        else
        {
            query = null;
        }
        return query;
    }
    

Esecuzione dell'applicazione

È ora possibile eseguire l'applicazione per visualizzare le route aggiornate.

  1. Premere F5 per eseguire l'applicazione di esempio Wingtip Toys.
    Il browser si apre e mostra la pagina Default.aspx .
  2. Fare clic sul collegamento Prodotti nella parte superiore della pagina.
    Tutti i prodotti vengono visualizzati nella pagina ProductList.aspx . Per il browser viene visualizzato l'URL seguente (usando il numero di porta):
    https://localhost:44300/ProductList
  3. Fare quindi clic sul collegamento Categoria Automobili nella parte superiore della pagina.
    Nella pagina ProductList.aspx vengono visualizzate solo le automobili. L'URL seguente (usando il numero di porta) viene visualizzato per il browser:
    https://localhost:44300/Category/Cars
  4. Fare clic sul collegamento contenente il nome della prima auto elencata nella pagina ("Auto convertibile") per visualizzare i dettagli del prodotto.
    L'URL seguente (usando il numero di porta) viene visualizzato per il browser:
    https://localhost:44300/Product/Convertible%20Car
  5. Immettere quindi l'URL non indirizzato seguente (usando il numero di porta) nel browser:
    https://localhost:44300/ProductDetails.aspx?productID=2
    Il codice riconosce ancora un URL che include una stringa di query, nel caso in cui un utente abbia un segnalibro di collegamento.

Riepilogo

In questa esercitazione sono state aggiunte route per categorie e prodotti. Si è appreso come le route possono essere integrate con i controlli dati che usano l'associazione di modelli. Nell'esercitazione successiva si implementerà la gestione degli errori globali.

Risorse aggiuntive

URL brevi di ASP.NET
Distribuire un'app di Web Forms ASP.NET sicura con appartenenza, OAuth e database SQL in Servizio app di Azure
Microsoft Azure - Versione di valutazione gratuita