ASP.NET Core  -  Restrições de Rotas


Neste artigo veremos como  usar as restrições de rotas na ASP .NET Core.

O roteamento na ASP.NET Core é o processo de mapeamento de requisições recebidas para a lógica do aplicativo que reside nos controladores e métodos Actions.

A ASP.NET Core mapeia a requisição recebida com base nas rotas configuradas no seu aplicativo e, para cada rota, você pode definir configurações específicas, como valores padrão, manipuladores de mensagens, restrições e assim por diante.

Existem algumas maneiras de controlar o roteamento em um aplicativo ASP.NET Core, e, as mais comuns são:

  1. Roteamento baseado em atributos: A rota é determinada com base nos atributos que você define em seus controladores e métodos. As definições nos atributos irão realizar o mapeamento para as Actions do controlador.

As restrições de rota nos ajudam a filtrar ou impedir que os valores indesejados atinjam os métodos Action de um controlador. Isso é feito através da verificação da restrição com relação ao valor do parâmetro de URL. Como exemplo de restrição de rota podemos querer rotear os requests para corresponder a uma rota específica somente se o valor int for fornecido para um parâmetro de URL.

Como funciona a restrição de rotamento ?

Existem duas maneiras pelas quais você pode adicionar uma restrição a um parâmetro de URL.

  1. De forma Inline com o parâmetro URL
  2. Usando o argumento de restrição do método MapRoute

As restrições Inline ou embutidas são adicionadas ao parâmetro URL após o sinal de dois pontos :


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

Depois que o mecanismo de roteamento localiza uma correspondência para a URL de entrada, ele chama a restrição de rota para cada segmento da URL para ver se ela passa na verificação. As restrições atuam fazendo uma simples decisão sim/não sobre se o valor é aceitável ou não.

Vamos então criar uma aplicação ASP .NET Core MVC para analizar as restrições de rotas.

Criando o projeto ASP .NET Core MVC no VS 2019 Community

Vamos criar uma aplicação ASP .NET Core Web Application usando o template Web Application no Visual Studio 2019 Community chamada Mvc_RestricaoRotas;

Abra o VS 2019 Community e selecione : Create a new Project

Selecionando em Language : C#, Platform: All Platforms e em Project Type: web podemos selecionar o template ASP .NET Core Web Application:

A seguir vamos informar o nome do projeto: Mvc_RestricaoRota , sua localização e nome da solução, que é  o mesmo nome do projeto;

Finalmente selecione a plataforma .NET Core e ASP .NET Core 2.2 e o template Web Application.

Marque a opção para configurar HTTP e não vamos usar Autenticação nem o Docker:

Ao final teremos um projeto ASP .NET MVC com um controlador chamado HomeController definido na pasta Controllers.

Restrições de Rotas

No projeto criado vamos abrir o arquivo Startup.cs e analizar o método Configure listado abaixo:

Observe que em app.UseMvc() temos a definição de uma roteamento padrão que divide todas as requisições de entrada em três segmentos:"{controller}/{action}/{id?}";   

Vamos agora alterar o código do controlador HomeController conforme abaixo:

Executando a aplicação, ao fazer uma requisição o usando a URL  /Home/Index/10  teremos uma correspondência com a rota padrão definida da seguinte forma:

  1. Home irá acionar o controlador Home;
  2. Index irá acionar o método Action Index;
  3. 10 será passado como parâmetro para o método Action Index e você verá como resultado :
    "Id informado -> 10" 'no navegador;

Uma requisição para  /Home/Index/Teste também corresponderá à rota. O roteador analisa o parâmetro 'Teste'  para o valor 0 e o injeta como parâmetro para indexar a ação e você verá  a mensagem :
"Id informado -> 0" no navegador.

Você pode impedir que isso aconteça usando uma restrição de rota no parâmetro de URL id.

Usando Restrições embutidas (Inline)

Como já vimos as restrições Inline ou embutidas são adicionadas ao parâmetro URL após o sinal de dois pontos :


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

A restrição int verifica se o valor do Id pode ser analisado para um valor inteiro. (O segmento de id é opcional) Portanto, a rota corresponderá se o Id não estiver presente, mas se o Id estiver presente, ele deverá ser um valor inteiro.

Definindo restrições usando via atributo Route

Podemos obter o mesmo resultado usando o atributo Route definindo-o no método Action Index:

Observe que no atributo Route definimos :  [Route("Home/Index/{id:int}")]

Onde usar as restrições

As restrições podem ser usadas para validação de entrada, mas essa não é a razão pela qual elas existem.

As validações de entrada não devem ser tratadas pelas restrições de rota. Em vez disso, o Controlador deve validar a entrada e enviar a mensagem de erro apropriada ao usuário final. Se você usar restrições de rota para validações de entrada, o cliente receberá uma mensagem de erro 404 (não encontrado).

As restrições de rota devem ser usadas para ajudar o mecanismo de roteamento a distinguir entre duas rotas semelhantes.

Por exemplo, considere a seguinte rota :

   app.UseMvc (routes =>
    {
        routes.MapRoute ("default",
                        "post / {id: int}",
                         new {controller = "Post", action = "PostsByID"});

        routes.MapRoute ("outraRota",
                        "post / {id: alpha}",
                         new {controller = "Post", action = "PostsByPostName"});

    });

Temos duas rotas semelhantes:

  1. post/{id: int}
  2. post/{id: alpha}.

Com as restrições int(aceita somente inteiros) e alpha (aceita somente alfabetos), podemos dizer ao mecanismo de roteamento para escolher o método de ação PostsByID para números inteiros e PostByPostName para valores strings.

O namespace Microsoft.AspNetCore.Routing.Constraints define um conjunto de classes que podem ser usadas para definir restrições individuais.

Abaixo uma tabela das restrições que verificam o tipo de dados:

constraint Inline Classe Descrição
int {id:int} IntRouteConstraint Restringe um parâmetro de rota para representar apenas valores inteiros de 32 bits
alpha {id:alpha} AlphaRouteConstraint Restringe um parâmetro de rota para conter apenas letras minúsculas ou maiúsculas de A a Z no alfabeto inglês.
bool {id:bool} BoolRouteConstraint Restringe um parâmetro de rota para representar apenas valores booleanos.
datetime {id:datetime} DateTimeRouteConstraint Restringe um parâmetro de rota para representar apenas valores de DateTime.
decimal {id:decimal} DecimalRouteConstraint Restringe um parâmetro de rota para representar apenas valores decimais.
double {id:double} DoubleRouteConstraint Restringe um parâmetro de rota para representar apenas valores de ponto flutuante de 64 bits
float {id:float} FloatRouteConstraint Corresponde a um valor flutuante válido (na invariant culture)
guid {id:guid} GuidRouteConstraint Corresponde a um valor válido de Guid

A seguir temos uma tabela de restrições para verificação de valor/intervalo/comprimento :

constraint Inline Classe Descrição
length(length) {id:length(12)} LengthRouteConstraint Restringe um parâmetro de rota para ser uma string de um determinado comprimento ou dentro de um determinado intervalo de comprimentos.
maxlength(value) {id:maxlength(8)} MaxLengthRouteConstraint Restringe um parâmetro de rota para ser uma string com comprimento máximo.
minlength(value) {id:minlength(4)} MinLengthRouteConstraint Restringe um parâmetro de rota para ser uma string com comprimento mínimo.
range(min,max) {id:range(18,120)} RangeRouteConstraint Restringe um parâmetro de rota para ser um número inteiro dentro de um determinado intervalo de valores.
min(value) {id:min(18)} MinRouteConstraint Restringe um parâmetro de rota para um longo com um valor mínimo.
max(value) {id:max(120)} MaxRouteConstraint Restringe um parâmetro de rota para ser um inteiro com um valor máximo.

Restrições usando uma Expressão Regular

Usar expressão regular ou regex como restrição oferece mais flexibilidade para limitar qualquer entrada:

constraint Inline Classe descrição
regex(expression) {ssn:regex(^\\d{{3}}-\\d{{2}}-\\d{{4}}$)} RegexRouteConstraint Restringe um parâmetro de rota para corresponder a uma expressão regular.

No exemplo a seguir, usamos a expressão regular para restringir o valor do ano a 4 dígitos:

app.UseMvc(routes =>
   {
   routes.MapRoute("default",
        "{controller}/{action}/{year:regex(^\\d{{4}}$)}",
          new { controller = "Home", action = "Index" });
});
 

Além disso podemos combinar múltiplas restrições usando o separdor dois pontos : conforme exemplo a seguir:

  "/{id:alpha:minlength(6)?}" 

ou usando o método Constraints do MapRoute:

 
Using Microsoft.AspNetCore.Routing.CompositeRouteConstraint;
 
constraints: new {
    id = new CompositeRouteConstraint(
       new IRouteConstraint[] {
       new AlphaRouteConstraint(),
        new MinLengthRouteConstraint(6)
})
3
 
 

Dessa forma as restrições de roteamento são uma opção útil que permitir mapear rotas semelhantes e nos ajuda a restringir os valores indesejados nos métodos Action do controlador.

"Louvai ao SENHOR, porque ele é bom; porque a sua benignidade dura para sempre.
Louvai ao Deus dos deuses; porque a sua benignidade dura para sempre.
Louvai ao Senhor dos senhores; porque a sua benignidade dura para sempre."
Salmos 136:1-3

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 ?

Quer aprender a criar aplicações Web Dinâmicas usando a ASP .NET MVC 5 ?

Referências:


José Carlos Macoratti