logo-aspnetmvc2
Share on facebook
Share on twitter
Share on linkedin
Diurno

ROTAS EM ASP.NET MVC – PARTE 2 – ROTEAMENTO PERSONALIZADO

Roteamento personalizado

 

Na parte anterior vimos o que é o mecanismo de rotas do ASP.NET MVC. Vimos também como o mecanismo funciona para redirecionar as URLs amigáveis inseridas no navegador para os métodos dos seus controladores e no fim, fizemos uma pergunta que – tenho certeza – deixou você ansioso por hoje, contando os minutos para a publicação desta segunda parte: como eu faço para decidir para onde as URLs serão mapeadas? Então sem mais delongas, vamos matar a curiosidade e responder.

Você pode registrar outras rotas  a se mapear no mesmo lugar em que está a rota default. Acessamos o objeto routes, a RouteCollection recebida como parâmetro no nosso método de registro, e dele chamamos o método MapRoute, baseando-nos exatamente no que temos como modelo até então.

dan4

Para nosso exemplo criei dois controladores no projeto, um chamado CustomerController e outro chamado EditCustomerController. Os nomes foram escolhidos propositadamente de modo a serem semelhantes e correrem risco de algum conflito ao mapear uma rota. O controlador Customer possui uma ação Edit que recebe um int customerId, enquanto o controlador EditCustomer possui uma ação Edit que recebe um string customerName, e uma ação Index.

No registro de nossas rotas personalizadas passamos os argumentos para o método. Nossa primeira rota personalizada recebeu o nome CustomCustomerRoute. Este nome pode ser escolhido no momento da criação, com a única restrição de não registrar mais de uma rota com o mesmo nome.

A URL é o padrão que será mapeado. Este argumento é o que se espera ver na barra de endereços do browser ou na referência de um anchor ou link. Qualquer variável que se espera na URL é passado entre chaves, enquanto textos fixos são as partes escritas diretamente. No exemplo, customerName e customerId são parâmetros que devem atender a determinadas condições (veremos a seguir), enquanto EditCustomer deve aparecer literalmente na URL.

Defaults são os valores padrão dos elementos variáveis da URL. Lembrando que o MapRoute registra uma rota com mapeamento virtual, devem ser definidos um controlador e uma ação, portanto é obrigatório que se passem valores default para eles, ou a rota criada não mapeará para ação nenhuma.

Por fim, temos um novo elemento: as constraints. Como o nome diz, estas são condições e são aplicadas aos elementos variáveis das rotas. Elas são um template regex que deve ser obedecido pela variável a que se aplica. Caso contrário, esta rota não será utilizada e a busca por uma rota que atenda à URL inserida continua.

dan5

dan6

dan7

Certo, sei como criar uma rota personalizada, mas afinal, eu coloco antes ou depois da padrão?

A resposta é: depende de sua intenção. A busca por algo que atenda à URL ocorre da seguinte forma: antes de tentar qualquer mapeamento registrado o servidor buscará por algum arquivo físico que esteja no endereço inserido. Assim, se no projeto existir uma pasta EditCustomer e lá dentro tiver um arquivo chamado GhostCustomer.txt, a URL ~/EditCustomer/GhostCustomer.txt retornará este arquivo. Se a URL não corresponder a nenhum arquivo físico do servidor, ou seja, se não existir uma extensão de arquivo na URL, somente então a coleção de rotas começa a ser percorrida na mesma ordem em que os registros ocorreram.

As rotas são percorridas na ordem em que são registradas, ou seja, de cima para baixo. Se você colocar sua rota acima da padrão, ela será pesquisada primeiro e, mesmo que a URL inserida seja válida para ambas, a padrão será ignorada, uma vez que a primeira será utilizada e a busca para por ali. Podemos ver isto no exemplo acima. A constraint da variável da segunda rota, CustomEditCustomerRoute, permite que quaisquer caracteres, em qualquer quantidade, sejam preenchidos. Logo, números também obedecem à restrição adequadamente. No entanto, a primeira rota, CustomCustomerRoute, permite que um número com qualquer quantidade de algarismos seja passado. Como a parte fixa das duas é igual, a primeira cuja variável bater com as restrições será utilizada. Vendo as imagens, conclui-se que quando utilizados números, a primeira rota coincide com as restrições e então é respondida sua ação, enquanto com outros valores, a segunda é executada. Quando não foi passado nenhum valor, vimos ainda que a terceira rota, a padrão, foi utilizada. Isto porque nenhuma das variáveis era opcional, o que pode ser declarado com UrlParameter.Optional nos defaults, como na rota padrão. Assim, sem nenhum valor para variável, nenhuma das duas primeiras é válida, e como existe um controlador de nome EditCustomer, a terceira encontrou este controlador e chamou sua ação default, Index.

Mas e se eu tiver um arquivo customer.html e quiser que ele seja retornado por uma URL na minha aplicação? Neste caso você tem duas opções: sua URL pode ser o caminho do arquivo físico, ou seja, ~/Customer/customer.html, ou pode-se realizar um mapeamento físico. O mapeamento físico é criado de maneira similar ao que vimos até agora, mas no lugar de usarmos o método MapRoute, usamos o MapPageRoute, como na imagem.

dan8

O método MapPageRoute funciona exatamente como o método MapRoute, mas no lugar de mapear uma URL para um endereço virtual que seja um método de uma classe, ele adiciona à resposta do servidor o arquivo físico definido na variável “physicalFile”. Assim sendo, não é necessário definir valores de controller e action, porque estes conceitos não se aplicam a este tipo de mapeamento.

Há ainda mais uma possibilidade. Se você quiser que o sistema não busque por um arquivo físico antes de percorrer as rotas, se quiser que somente as rotas registradas explicitamente sejam válidas, pode-se definir o valor da propriedade RouteExistingFiles no objeto routes, um bool pertencente à classe RouteCollection que possui, por padrão, o valor false. Contraintuitivamente, ele na verdade diz se o serviço de mapeamento de rotas deve tratar requisições de arquivos físicos. Assim, o valor true diz que mesmo que um arquivo físico seja encontrado, o mecanismo de roteamento é quem deve tratar a requisição, então o arquivo não é adicionado à resposta, exceto se uma rota estiver registrada para tal.

Por fim, há a possibilidade de se ordenar que o sistema não trate determinadas requisições. Utilizando o método IgnoreRoute, pode-se definir um padrão de URL a que nenhuma rota registrada será utilizada, independentemente de o valor coincidir com um padrão válido. Isto não é bem utilizado com a funcionalidade anterior de mapear requisições a arquivos físicos, visto que normalmente ignoram-se rotas para impedir que requisições a exatamente esses tipos de arquivos sejam mapeadas.

O ASP.NET MVC tem uma rota ignorada por default. Esta rota é ignorada para impedir que se mapeiem requisições a arquivos de recursos, requisições que serão feitas automaticamente dentro de determinadas condições. No IgnoreRoute padrão há o uso de uma ferramenta utilizável na url de qualquer rota, o wildcard “{*}”, que significa literalmente qualquer coisa. Assim sendo, em um padrão de rota que possua uma variável iniciada por *, aquela variável pode assumir qualquer valor, podendo incluir até mesmo o caractere “/”. Esta wildcard deve sempre ser o último elemento presente em um padrão.

Agora vamos supor um novo cenário: tem outra equipe desenvolvendo o Front-End de uma aplicação paralelamente ao seu desenvolvimento do Back-End. Este Front-End será um cliente do serviço que você está desenvolvendo e eles esperam fazer requisições a URLs específicas para cada método chamado. Então o que você faz? Registra uma rota para cada método, gerando um arquivo de configuração gigante com um método de 50 linhas? Mais uma vez encerraremos com uma pergunta. Para descobrir a resposta, basta continuar acompanhando o blog e dar uma olhada na terceira parte. 

Por: Daniel Prata e José Vicente
Revisão: Jéssica Saliba