ASP .NET MVC 5 - Customizando Rotas


 No artigo de hoje vou mostrar como podemos customizar rotas em um aplicação ASP .NET MVC 5 e também como obter URLs amigáveis.

No modelo tradicional de desenvolvimento ASP .NET, usando Web Forms, as requisições do navegador são mapeadas para páginas, que devem existir fisicamente no servidor.  O desenvolvimento é centrado no conteúdo das páginas.

No modelo de desenvolvimento ASP .NET MVC as requisições do navegador são mapeadas para ações do Controlador (Controller). O desenvolvimento é centrado na lógica da aplicação. (leia-se mapeamento)

Assim, em uma aplicação MVC, uma requisição feita pelo navegador esta mapeada para uma ação de um controlador (Controller Action) através de um recurso do ASP .NET Framework chamado ASP .NET Routing (roteamento ASP .NET).

Para fazer o roteamento o ASP .NET Rounting usa uma tabela de rotas para lidar com as requisições recebidas. Esta tabela de rotas esta presente no arquivo RouteConfig na pasta App_Start:

using System.Web.Mvc;
using System.Web.Routing;
namespace Mvc_Rotas
{
    public class RouteConfig
    {
        public static void RegisterRoutes(RouteCollection routes)
        {
            routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
            routes.MapRoute(
                name: "Default",
                url: "{controller}/{action}/{id}",
                defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
            );
        }
    }
}

Quando uma aplicação ASP .NET MVC é iniciada pela primeira vez o método Application_Start() do arquivo Global.asax é chamado, e, o método RegisterRoutes(RouteTable.Routes) é invocado e assim cria a tabela de rotas padrão.

A tabela de rotas padrão possui uma rota, e, esta rota padrão divide todas as requisições de entrada em três segmentos:("{controller}/{action}/{id}",)   

Neste artigo eu vou mostrar como podemos criar novas rotas no arquivo RouteConfig de forma a tornar o acesso a nossa aplicação mais intuitivo usando URLs amigáveis.

 

Recursos usados :

Criando o projeto no VS 2013 Express for web

Abra o VS 2013 Express for web e clique em New Project;

A seguir selecione Visual C# -> ASP .NET Web Application;

Informe o nome Mvc_Rotas e clique no botão OK;

A seguir selecione o template Empty, marque MVC  e clique no botão OK;

Será criado um projeto ASP .NET MVC vazio com a estrutura básica para criarmos o nosso exemplo.

Definindo o Model : criando uma classe Produto na pasta Models

Precisamos agora definir um model para que nossa aplicação possa ter o que consumir. Neste exemplo eu vou criar uma classe Produto com uma estrutura bem simples para simular um cenário de uma loja virtual.

Selecione a pasta Models e no menu PROJECT clique em Add Class e informe o nome Produto e a seguir clique no botão Add:

A seguir digite o código abaixo definindo 3 propriedades na classe Produto:

using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
namespace Mvc_Rotas.Models
{
    public class Produto
    {
        public int ProdutoId { get; set; }
        public string Nome { get; set; }
        public string Descricao { get; set; }
        public string Categoria { get; set; }
        [DisplayFormat(DataFormatString = "{0:c}")]
        public decimal Preco { get; set; }
        [DisplayFormat(DataFormatString = "{0:dd/MM/yyyy}")]
        public DateTime Data { get; set; }
        public List<Produto> TodosProdutos()
        {
            var produtos = new List<Produto>
            {
                new Produto
                {
                    ProdutoId = 110,
                    Categoria = "Informatica",
                    Nome = "Notebook Acer",
                    Descricao = "E5-571-54MC com Intel Core i5, 4GB de RAM, Windows 8.1",
                    Preco = 1690.00M,
                    Data = new DateTime(2015,7,15)
                },
                new Produto
                {
                    ProdutoId = 120,
                    Categoria = "Informatica",
                    Nome = "Notebook Positivo Premium",
                    Descricao = "TV S6050 LCD 14’’ Processador Intel Core i3, Windows 8, HD 500GB",
                    Preco = 1290.00M,
                    Data = new DateTime(2015,7,1)
                },
                new Produto
                {
                    ProdutoId = 130,
                    Categoria = "Informatica",
                    Nome = "iPad Mini 3",
                    Descricao = "16 GB Wi Fi Dourado MGYE2BR/A Apple",
                    Preco = 1990.00M,
                    Data = new DateTime(2015,7,10)
                },
                new Produto
                {
                    ProdutoId = 210,
                    Categoria = "Eletrodomesticos",
                    Nome = "Ar Condicionado Consul",
                    Descricao = "Portátil 12.000 Btus Frio C1A12AB, 220 V, Branco",
                    Preco = 990.00M,
                    Data = new DateTime(2015,7,11)
                },
                new Produto
                {
                    ProdutoId = 220,
                    Categoria = "Eletrodomesticos",
                    Nome = "Micro-Ondas LG",
                    Descricao = "30 L, EasyClean MH7093R Prata, com Grill, Branco",
                    Preco = 430.00M,
                    Data = new DateTime(2015,7,6)
                },
                new Produto
                {
                    ProdutoId = 230,
                    Categoria = "Eletrodomesticos",
                    Nome = "Refrigerador Electrolux",
                    Descricao = "DF42 382 Litros 2 Portas Frost Free, 220 V , Branco",
                    Preco = 1250.00M,
                    Data = new DateTime(2015,7,7)
                },
                new Produto
                {
                    ProdutoId = 310,
                    Categoria = "Telefonia",
                    Nome = "Samsung Galasy S6",
                    Descricao = "SM-G920I Single Chip, Branco, Processador quad-core",
                    Preco = 2120.00M,
                    Data = new DateTime(2015,7,3)
                },
                new Produto
                {
                    ProdutoId = 320,
                    Categoria = "Telefonia",
                    Nome = "Motorola Moto G",
                    Descricao = "Preto, TV Digital, Dual Chip, Processador Quad Core 1.2GHz, Tela 5",
                    Preco = 870.00M,
                    Data = new DateTime(2015,7,16)
                },
                new Produto
                {
                    ProdutoId = 410,
                    Categoria = "Esporte",
                    Nome = "Bicicleta Colli Bike ",
                    Descricao = "Aro 26 18 Marchas Suspensão Dianteira CBX 750 Preta + Garrafa Térmica",
                    Preco = 380.00M,
                    Data = new DateTime(2015,7,9)
                },
                new Produto
                {
                    ProdutoId = 420,
                    Categoria = "Esporte",
                    Nome = "Tênis Feminino Fila",
                    Descricao = "Kenya Racer, 2.0 W Vermelho/Limão, 38, Palminha durável",
                    Preco = 125.00M,
                    Data = new DateTime(2015,7,10)
                },
                new Produto
                {
                    ProdutoId = 430,
                    Categoria = "Esporte",
                    Nome = "Tênis Diadora",
                    Descricao = "Ghost III Azul e Verde Masculino, número 44",
                    Preco = 65.00M,
                    Data = new DateTime(2015,7,11)
                },
                new Produto
                {
                    ProdutoId = 510,
                    Categoria = "Beleza",
                    Nome = "Barbeador Philips",
                    Descricao = "Aquatouch AT751 Recarregável, 110 V",
                    Preco = 219.00M,
                    Data = new DateTime(2015,7,1)
                },
                new Produto
                {
                    ProdutoId = 520,
                    Categoria = "Beleza",
                    Nome = "Secador Candence",
                    Descricao = "Secador de Cabelo - SEC400 - 1400w, Cabo, 220 V",
                    Preco = 205.00M,
                    Data = new DateTime(2015,7,3)
                },
            };
            return produtos;
        }
    }
}

Observe que definimos o namespace System.Componente.DataAnnotations para poder aplicar os atributos de formatação DysplayFormat() na data e no preço.

Também usei o recurso Collection Initializer, da plataforma .NET, para fornecer dados à nossa classe Produto.

Criando o controlador ProdutoController na pasta Controllers

Clique com o botão direito do mouse sobre a pasta Controllers e a seguir clique em Add => Controller;

A seguir selecione o Scaffold : MVC 5 Controller Empty e clique no botão Add;

Digite o nome ProdutoController na janela Add Controller e clique no botão Add:

Digite o código abaixo para o HomeController:

using System.Linq;
using System.Web;
using System.Web.Mvc;
using Mvc_Rotas.Models;
namespace Mvc_Rotas.Controllers
{
    public class ProdutoController : Controller
    {
        private readonly List<Produto> todosProdutos;
        public ProdutoController()
        {
            todosProdutos = new Produto().TodosProdutos().OrderBy(x => x.Preco).ToList();
        }
        public ActionResult Index()
        {
            ViewBag.Produtos = "Todos os Produtos";
            return View(todosProdutos);
        }
        public ActionResult Detalhes(int produtoId)
        {
            return View(todosProdutos.FirstOrDefault(x => x.ProdutoId == produtoId));
        }
        public ActionResult Categorias(string categoria)
        {
            var _categoria = todosProdutos.Where(x => x.Categoria == categoria).ToList();
            ViewBag.Categoria = categoria;
            return View(_categoria);
        }
    }
}

 

Temos definidos no controlador ProdutoController um construtor, onde estamos obtendo uma lista de produtos, e as seguintes Actions:

Criando as views Index, Detalhes e Categorias na pasta Views/Produto

1- Criando a view Index

Para criar as views o procedimento é clicar com o botão direito sobre o nome do método Action Index no controlador e a seguir clique em Add View:

Para a view Index selecione o template Empty, o Model class Produto e clique no botão Add;

Com isso estamos criando a view tipada Index.cshtml na pasta Views/Produto.

A seguir inclua o código abaixo neste arquivo:

@model IEnumerable<Mvc_Rotas.Models.Produto>
<!DOCTYPE html>
<html>
<head>
    <meta name="viewport" content="width=device-width" />
    <title>Todos os Produtos</title>
</head>
<body>
    <div>
        <h2> @ViewBag.Produtos </h2>
        <hr />
        <div>
            <ul>
                @foreach (var item in Model)
                {
                 <li>
                   @Html.ActionLink(item.Nome, "Detalhes", "Produto", new
                   {
                       @produtoId = item.ProdutoId,
                   }, null)
                   <em>@Html.DisplayFor(modelItem => item.Categoria)</em>
                   <em>@Html.DisplayFor(modelItem => item.Data)</em>
                   <b>@Html.DisplayFor(modelItem => item.Preco)</b>
                </li>
                }
            </ul>
        </div>
    </div>
</body>
</html>

Nesta view estamos usando o HTML Helper ActionLink para criar um link na página com o texto que irá exibir o nome do Produto; quando acionado o link irá executar a Action Detalhes do controlador ProdutoController.

Sintaxe do ActionLink:  @Html.ActionLink("texto do link", " Nome da Action")

2- Criando a view Detalhes

Agora clique com o botão direito sobre o nome do método Action Detalhes no controlador e a seguir clique em Add View:

A seguir defina o nome Incluir e o template Empty;

Selecione o Model class Produto contido na pasta Models e clique no botão Add;

Vamos criar uma view tipada usando o model Produto.

Para isso inclua o código abaixo no arquivo Detalhes.cshtml da pasta Views/Produto:

@model Mvc_Rotas.Models.Produto
<!DOCTYPE html>
<html>
<head>
    <meta name="viewport" content="width=device-width" />
    <title>Exibir Produto</title>
</head>
<body>
    <h2>@Model.Nome</h2>
    <hr />
    <div>
        <ul>
            <li>
                <em>Valor : <b> @Model.Preco </b> - @Html.ActionLink(Model.Categoria, "Categorias", "Produto", new 
                 { 
                      @categoria = Model.Categoria 
                  }, null)
               </em>
            </li>
        </ul>
    </div>
    <div>
        <b>@Model.Descricao</b>
    </div>
    <div>
        <hr />
        @Html.ActionLink("Retornar", "Index")
    </div>
</body>
</html>
 

Observe a diretiva @model no início do código definindo um tipo específico que esta view irá renderizar.

Nesta View estamos criando um link para exibir os produtos de uma categoria usando o Html Helper ActionLink.

3- Criando a view Categorias

Agora clique com o botão direito sobre o nome do método Action Categorias no controlador e a seguir clique em Add View:

A seguir defina o nome Incluir e o template Empty;

Selecione o Model class Produto contido na pasta Models e clique no botão Add;

Após isso inclua o código abaixo no arquivo Detalhes.cshtml da pasta Views/Produto:

@model IEnumerable<Mvc_Rotas.Models.Produto>
<!DOCTYPE html>
<html>
<head>
    <meta name="viewport" content="width=device-width" />
    <title>Exibir Categoria</title>
</head>
<body>
    <h2>Categoria : @ViewBag.Categoria</h2>
    <hr />
    <div>
        <ul>
            @foreach (var item in Model)
            {
                <li>
                    @Html.ActionLink(item.Nome, "Detalhes", "Produto", new
                    {
                        @produtoId = item.ProdutoId,
                    }, null)
                    <em>@Html.DisplayFor(modelItem => item.Categoria)</em>
                    <em>@Html.DisplayFor(modelItem => item.Data)</em>
                    <b>@Html.DisplayFor(modelItem => item.Preco)</b>
                </li>
            }
        </ul>
    </div>
</body>
</html>

Esta view exibe informações dos produtos para uma categoria selecionada. Temos também um link que permite exibir os detalhes de um produto da categoria.

Agora estamos prontos para executar o projeto mas a primeira providência que teremos que fazer para evitar um erro é alterar a rota padrão definida para :

using System.Web.Mvc;
using System.Web.Routing;
namespace Mvc_Rotas
{
    public class RouteConfig
    {
        public static void RegisterRoutes(RouteCollection routes)
        {
            routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
             routes.MapRoute(
                name: "Default",
                url: "{controller}/{action}/{id}",
                defaults: new { controller = "Produto", action = "Index", id = UrlParameter.Optional }
            );
        }
    }
}

Porque fizemos isso ?

Porque não temos um controlador chamado Home em nossa aplicação. Nosso controlador chama-se ProdutoController e possui uma Action Index.

Fazendo assim, ao rodar a aplicação, a nova rota irá acionar a Action Index no controlador Produto renderizando a view Index.cshtml conforme figura abaixo:

Note na base da página do navegador o link gerado quando passamos o mouse sobre o nome do produto.

Agora clicando em um produto teremos:

Agora quando selecionamos o link para a categoria vemos na base da página do navegador outro link.

Observe também o link no navegador : http://localhost:51074/Produto/Detalhes?produtoId=410

Clicando no link da categoria (Esporte) iremos obter:

Novamente note o link da página e o link na base da página, obtido quando passamos o mouse sobre o link do produto.

Então concluímos que esta tudo funcionando e pronto. Artigo encerrado...

É claro que não.

Podemos melhorar as URLs da nossa aplicação criando novas rotas no arquivo RouteConfig da pasta App_Start do projeto.

Abra então esse arquivo e altere o seu código conforme abaixo:

using System.Web.Mvc;
using System.Web.Routing;
namespace Mvc_Rotas
{
    public class RouteConfig
    {
        public static void RegisterRoutes(RouteCollection routes)
        {
            routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
            routes.MapRoute(
                "Produtos",
                "Produtos/",
                new { controller = "Produto", action = "Index" }
            );
            routes.MapRoute(
                "Detalhes",
                "Produtos/{produtoid}",
                new { controller = "Produto", action = "Detalhes" },
                new { produtoid = @"\d+" }
            );
            routes.MapRoute(
                "Categorias",
                "Produtos/{categoria}",
                new { controller = "Produto", action = "Categorias" }
            );
            routes.MapRoute(
                name: "Default",
                url: "{controller}/{action}/{id}",
                defaults: new { controller = "Produto", action = "Index", id = UrlParameter.Optional }
            );
        }
    }
}

Criamos 3 novas rotas no arquivo de rotas:

URL =>   Produtos/                   Ex: http://localhost:xxxx/Produtos

URL =>   Produtos/{produtoid}   Ex: http://localhost:xxxx/Produtos/110

Esta rota possui uma restrição definida por new { produtoid = @"\d+" }.

Como a Action Detalhes(int produtoid) espera um parâmetro inteiro, fazendo uma solicitação que contém algo diferente de um valor inteiro causará um erro. Por exemplo, se você digitar a URL /Produto/Esporte em seu navegador, irá obter um erro.

Queremos que a Action Detalhes seja acionada quando receber o parâmetro correto ou seja um valor inteiro. Para isso usamos uma restrição ao definir a rota de forma a restringir as URLs que correspondem a rota.

A expressão regular \d+ corresponde a um ou mais inteiros. Esta restrição faz com que o percurso do produto coincida com as seguintes URLs:

/ Produto/3
/ Produto/999


Mas não aceite :

/Produto/Esporte
/Produto

URL =>   Produtos/{categoria}   Ex: http://localhost:xxxx/Produtos/Esporte

Após essas alterações vamos executar a aplicação novamente e abaixo eu vou exibir as páginas com as novas URLs geradas:

1- A view Index.cshtml renderizando todos os produtos :

2- A view Detalhes.cshtml exibindo detalhes de um produto a partir do ID do mesmo:

3- A view Categorias.chtml exibindo os produtos para uma determinada categoria :

Observe como ficou mais intuitivo, sem contar que as novas URLs ajudam a alavancar o SEO do seu site.

O termo SEO (Search Engine Marketing Optimization) refere-se ao trabalho de entender os algoritmos de busca e otimizar sua presença online para ficar mais amigável com os buscadores permitindo que seu conteúdo posicione de maneira adequada ao seu potencial nos resultados de busca.

Pegue o projeto completo aqui :   Mvc_Rotas.zip

Disse-lhe Jesus: Estou há tanto tempo convosco, e não me tendes conhecido, Filipe ? Quem me vê a mim vê o Pai; e como dizes tu: Mostra-nos o Pai ?
Não crês tu que eu estou no Pai, e que o Pai está em mim ? As palavras que eu vos digo não as digo de mim mesmo, mas o Pai, que está em mim, é quem faz as obras.

João 14:9,10

Veja os Destaques e novidades do SUPER DVD Visual Basic (sempre atualizado) : clique e confira !

Quer migrar para o VB .NET ?

Quer aprender C# ??

Quer aprender os conceitos da Programação Orientada a objetos ?

Quer aprender o gerar relatórios com o ReportViewer no VS 2013 ?

  Gostou ?   Compartilhe no Facebook   Compartilhe no Twitter

Referências:


José Carlos Macoratti