Roteamento de URL

por Erik Reitan

Baixar o Projeto de Exemplo de Brinquedos wingtip (C#) ou baixar e-book (PDF)

Esta série de tutoriais ensinará os conceitos básicos da criação de um aplicativo ASP.NET Web Forms usando ASP.NET 4.5 e Microsoft Visual Studio Express 2013 para Web. Um projeto Visual Studio 2013 com código-fonte C# está disponível para acompanhar esta série de tutoriais.

Neste tutorial, você modificará o aplicativo de exemplo Wingtip Toys para dar suporte ao roteamento de URL. O roteamento permite que seu aplicativo Web use URLs amigáveis, mais fáceis de lembrar e com melhor suporte por mecanismos de pesquisa. Este tutorial se baseia no tutorial anterior "Associação e Administração" e faz parte da série de tutoriais Wingtip Toys.

O que você aprenderá:

  • Como registrar rotas para um aplicativo ASP.NET Web Forms.
  • Como adicionar rotas a uma página da Web.
  • Como selecionar dados de um banco de dados para dar suporte a rotas.

Visão geral do roteamento de ASP.NET

O roteamento de URL permite configurar um aplicativo para aceitar URLs de solicitação que não são mapeadas para arquivos físicos. Uma URL de solicitação é simplesmente a URL que um usuário insere no navegador para encontrar uma página em seu site. Você usa o roteamento para definir URLs semanticamente significativas para os usuários e que podem ajudar com a SEO (otimização do mecanismo de pesquisa).

Por padrão, o modelo de Web Forms inclui urls ASP.NET amigáveis. Grande parte do trabalho básico de roteamento será implementada usando URLs amigáveis. No entanto, neste tutorial, você adicionará recursos de roteamento personalizados.

Antes de personalizar o roteamento de URL, o aplicativo de exemplo Wingtip Toys pode vincular a um produto usando a seguinte URL:

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

Ao personalizar o roteamento de URL, o aplicativo de exemplo Wingtip Toys será vinculado ao mesmo produto usando uma URL mais fácil de ler:

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

Rotas

Um rota é um padrão de URL mapeado para um manipulador. O manipulador pode ser um arquivo físico, como um arquivo .aspx em um aplicativo Web Forms. Um manipulador também pode ser uma classe que processa a solicitação. Para definir uma rota, crie uma instância da classe Route especificando o padrão de URL, o manipulador e, opcionalmente, um nome para a rota.

Adicione a rota ao aplicativo adicionando o Route objeto à propriedade estática Routes da RouteTable classe . A propriedade Routes é um RouteCollection objeto que armazena todas as rotas para o aplicativo.

Padrões de URL

Um padrão de URL pode conter valores literais e espaços reservados variáveis (conhecidos como parâmetros de URL). Os literais e espaços reservados estão localizados em segmentos da URL delimitados pelo caractere de barra (/).

Quando uma solicitação para seu aplicativo Web é feita, a URL é analisada em segmentos e espaços reservados e os valores de variável são fornecidos ao manipulador de solicitação. Esse processo é semelhante à maneira como os dados em uma cadeia de caracteres de consulta são analisados e passados para o manipulador de solicitação. Em ambos os casos, as informações de variável são incluídas na URL e passadas para o manipulador na forma de pares chave-valor. Para cadeias de caracteres de consulta, as chaves e os valores estão na URL. Para rotas, as chaves são os nomes de espaço reservado definidos no padrão de URL e apenas os valores estão na URL.

Em um padrão de URL, você define espaços reservados colocando-os entre chaves ( { e } ). Você pode definir mais de um espaço reservado em um segmento, mas os espaços reservados devem ser separados por um valor literal. Por exemplo, {language}-{country}/{action} é um padrão de rota válido. No entanto, {language}{country}/{action} não é um padrão válido, pois não há nenhum valor literal ou delimitador entre os espaços reservados. Portanto, o roteamento não pode determinar onde separar o valor do espaço reservado do idioma do valor para o espaço reservado do país.

Mapeando e registrando rotas

Antes de incluir rotas para páginas do aplicativo de exemplo Wingtip Toys, você deve registrar as rotas quando o aplicativo for iniciado. Para registrar as rotas, você modificará o Application_Start manipulador de eventos.

  1. No Gerenciador de Soluções do Visual Studio, localize e abra o arquivo Global.asax.cs.

  2. Adicione o código realçado em amarelo ao arquivo Global.asax.cs da seguinte maneira:

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

Quando o aplicativo de exemplo Wingtip Toys é iniciado, ele chama o Application_Start manipulador de eventos. No final desse manipulador de eventos, o RegisterCustomRoutes método é chamado. O RegisterCustomRoutes método adiciona cada rota chamando o MapPageRoute método do RouteCollection objeto . As rotas são definidas usando um nome de rota, uma URL de rota e uma URL física.

O primeiro parâmetro ("ProductsByCategoryRoute") é o nome da rota. Ele é usado para chamar a rota quando ela é necessária. O segundo parâmetro ("Category/{categoryName}") define a URL de substituição amigável que pode ser dinâmica com base no código. Você usa essa rota quando está preenchendo um controle de dados com links gerados com base em dados. Uma rota é mostrada da seguinte maneira:

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

O segundo parâmetro da rota inclui um valor dinâmico especificado por chaves ({ }). Nesse caso, o categoryName é uma variável que será usada para determinar o caminho de roteamento adequado.

Observação

Opcional

Talvez seja mais fácil gerenciar seu código movendo o RegisterCustomRoutes método para uma classe separada. Na pasta Lógica , crie uma classe separada RouteActions . Mova o método acima RegisterCustomRoutes do arquivo Global.asax.cs para a nova RoutesActions classe. Use a RoleActions classe e o createAdmin método como um exemplo de como chamar o RegisterCustomRoutes método do arquivo Global.asax.cs .

Talvez você também tenha notado a chamada de RegisterRoutes método usando o RouteConfig objeto no início do Application_Start manipulador de eventos. Essa chamada é feita para implementar o roteamento padrão. Ele foi incluído como código padrão quando você criou o aplicativo usando o modelo de Web Forms do Visual Studio.

Recuperando e usando dados de rota

Conforme mencionado acima, as rotas podem ser definidas. O código que você adicionou ao Application_Start manipulador de eventos no arquivo Global.asax.cs carrega as rotas definíveis.

Definindo rotas

As rotas exigem que você adicione código adicional. Neste tutorial, você usará a associação de modelo para recuperar um RouteValueDictionary objeto usado ao gerar as rotas usando dados de um controle de dados. O RouteValueDictionary objeto conterá uma lista de nomes de produtos que pertencem a uma categoria específica de produtos. Um link é criado para cada produto com base nos dados e na rota.

Habilitar rotas para categorias e produtos

Em seguida, você atualizará o aplicativo para usar o ProductsByCategoryRoute para determinar a rota correta a ser incluída para cada link de categoria de produto. Você também atualizará a página ProductList.aspx para incluir um link roteado para cada produto. Os links serão exibidos como eram antes da alteração, no entanto, os links agora usarão o roteamento de URL.

  1. Em Gerenciador de Soluções, abra a página Site.Master se ela ainda não estiver aberta.

  2. Atualize o controle ListView chamado "categoryList" com as alterações realçadas em amarelo, para que a marcação apareça da seguinte maneira:

    <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. Em Gerenciador de Soluções, abra a página ProductList.aspx.

  4. Atualize o ItemTemplate elemento da página ProductList.aspx com as atualizações realçadas em amarelo, para que a marcação apareça da seguinte maneira:

    <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. Abra o code-behind de ProductList.aspx.cs e adicione o seguinte namespace, conforme realçado em amarelo:

    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. Substitua o GetProducts método do code-behind (ProductList.aspx.cs) pelo seguinte código:

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

Adicionar código para detalhes do produto

Agora, atualize o code-behind (ProductDetails.aspx.cs) para a página ProductDetails.aspx para usar dados de rota. Observe que o novo GetProduct método também aceita um valor de cadeia de caracteres de consulta para o caso em que o usuário tem um link marcado que usa a URL não amigável e não roteada mais antiga.

  1. Substitua o GetProduct método do code-behind (ProductDetails.aspx.cs) pelo seguinte código:

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

Executando o aplicativo

Agora você pode executar o aplicativo para ver as rotas atualizadas.

  1. Pressione F5 para executar o aplicativo de exemplo Wingtip Toys.
    O navegador é aberto e mostra a página Default.aspx .
  2. Clique no link Produtos na parte superior da página.
    Todos os produtos são exibidos na página ProductList.aspx . A SEGUINTE URL (usando o número da porta) é exibida para o navegador:
    https://localhost:44300/ProductList
  3. Em seguida, clique no link categoria Carros próximo à parte superior da página.
    Somente os carros são exibidos na página ProductList.aspx . A SEGUINTE URL (usando o número da porta) é exibida para o navegador:
    https://localhost:44300/Category/Cars
  4. Clique no link que contém o nome do primeiro carro listado na página ("Carro Conversível") para exibir os detalhes do produto.
    A SEGUINTE URL (usando o número da porta) é exibida para o navegador:
    https://localhost:44300/Product/Convertible%20Car
  5. Em seguida, insira a seguinte URL não roteada (usando o número da porta) no navegador:
    https://localhost:44300/ProductDetails.aspx?productID=2
    O código ainda reconhece uma URL que inclui uma cadeia de caracteres de consulta, para o caso em que um usuário tem um link marcado.

Resumo

Neste tutorial, você adicionou rotas para categorias e produtos. Você aprendeu como as rotas podem ser integradas aos controles de dados que usam a associação de modelo. No próximo tutorial, você implementará o tratamento de erros global.

Recursos adicionais

URLs amigáveis do ASP.NET
Implantar um aplicativo de ASP.NET Web Forms seguro com associação, OAuth e Banco de Dados SQL para Serviço de Aplicativo do Azure
Microsoft Azure – Avaliação gratuita