Logo

Atributos de Validação

Somente um post rápido com todos os atributos de validação disponíveis no framework. Muito usados para decorar modelos no ASP.NET MVC, mas podendo ser utilizados com qualquer tecnologia .NET.

[CreditCard]

Verifica se a string é um cartão de crédito válido, a string pode ter traços ou espaços que funciona

[EmailAddress]

Verifica se a string é um email válido. É a mesma coisa se usasse o atributo [RegularExpression] com a expressão regular: @"^((([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+(\.([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+)*)|((\x22)((((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(([\x01-\x08\x0b\x0c\x0e-\x1f\x7f]|\x21|[\x23-\x5b]|[\x5d-\x7e]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(\\([\x01-\x09\x0b\x0c\x0d-\x7f]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]))))*(((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(\x22)))@((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?$"


[MaxLength]

Verifica o tamanho máximo de um array ou string, o tamanho mínimo não importa.


[MinLength]

Verifica o tamanho mínimo de um array ou string, o tamanho máximo não importa.


[Phone]

Verifica se a string é um telefone válido. Infelizmente não é adequado ao padrão brasileiro, basicamente permite o preenchimento de números e caracteres de formatação comuns usados na hora de informar um telefone e restringe os demais caracteres. É o mesmo que usar o atributo [RegularExpression] com a expressão regular @"^(\+\s?)?((?<!\+.*)\(\+?\d+([\s\-\.]?\d+)?\)|\d+)([\s\-\.]?(\(\d+([\s\-\.]?\d+)?\)|\d+))*(\s?(x|ext\.?)\s?\d+)?$"


[Range]

Verifica números ou qualquer objeto que implemente a interface IComparable se estão dentro de uma faixa de mínimo ou máximo.


[RegularExpression]

Compara uma string para checar se é válida através de uma expressão regular.


[Required]

Verifica se uma string contém valor.


[StringLength]

Verifica o comprimento de uma string, podendo ser definido o seu mínimo e/ou máximo.


[Url]

Verifica se a string é uma URL válida. É a mesma coisa se usasse o atributo [RegularExpression] com a expressão regular @"^(https?|ftp):\/\/(((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:)*@)?(((\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5]))|((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?)(:\d*)?)(\/((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)+(\/(([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)*)*)?)?(\?((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|[\uE000-\uF8FF]|\/|\?)*)?(\#((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|\/|\?)*)?$"


Versões do .NET Framework

As vezes existem dúvidas por parte do pessoal de suporte ou de implantação, a respeito de qual versão do .NET Framework instalar. Até mesmo desenvolvedores, por não ter passado ainda por uma situação de dificuldade, ou simplesmente não se preocupar com isso.

Em primeiro lugar, é necessário explicar sobre a "retrocompatibilidade suportada" pela Microsoft. Se você tem um projeto (assembly) feito para o .NET 2.0, o ideal é que você tenha instalado no seu sistema operacional a versão topo da linhagem de retrocompatibilidade, que no caso é a 3.5.

Não veja essa retrocompatibilidade como algo que foi "adaptado" para se compatível sem a mesma qualidade da versão original. Diversas correções de bugs, otimizações, e novos recursos foram disponibilizados desde a versão inicial, a versão topo é realmente a melhor indicada para rodar a sua aplicação.

O que acontece quando você vai instalando as versões na sequência, uma após a outra?

Fazer dessa maneira era um mito de alguns técnicos no passado, achando que você precisava instalar a primeira versão, depois ir "atualizando" com as próximas. Infelizmente a grande responsável por essa confusão foi a própria Microsoft, por não deixar claro como era o ciclo de vida da plataforma .NET. Fazer dessa maneira (ir instalando as versões na sequência) não tem problema nenhum, tudo vai funcionar da maneira como se espera, entretanto é totalmente desnecessário, basta instalar a versão topo da linha de retrocompatibiliade de acordo com a aplicação que você vai querer rodar.

Segue abaixo uma tabela com as versões do .NET Framework versus os sistemas operacionais suportados.

Compatibilidade
Versão Download Windows 2000 Windows XP Windows Vista Windows 7 Windows 8 Windows 8.1 Windows 10 Linux OS X
Não compatível
1.0 Link





Não compatível
1.1 Link




Retrocompatível 2.0 Link



3.0 Link


3.5 Link


Retrocompatível 4.0 Link


4.5 Link



4.5.1 Link



4.5.2 Link



4.6 Link



4.6.1 Link



4.6.2 Link



Não compatível
Core 1.0 Link


Legenda:

Já vem junto com o sistema operacional
Funciona, basta instalar

Algumas observações fazem-se necessárias:
  • A partir do Windows 8, o .NET 3.5 passou a ser instalado via a função de "Adicionar ou Remover Recursos" do Windows.
  • O .NET Core 1.0 agora também funciona para Linux e o OS X, o processo de instalação nesses sistemas operacionais não é o mesmo que estamos acostumados no Windows.

Números literais escritos no tipo desejado

Já teve algum problema onde o seu cálculo estava saindo sem as casas decimais? (o resultado ficava um inteiro), ou teve que fazer uma conversão explicita para float ou decimal após realizar um cálculo para então poder passar o resultado em uma função qualquer?

Provavelmente você utilizou um literal sem definir o seu tipo!

Para compreender melhor, vamos supor um cenário onde você precisa fazer uma regra de 3 para descobrir um percentual. Tenho uma janela e quero saber o quanto em percentual de largura ela está ocupando da minha tela.

1024 pixels é a largura total da tela, portanto é 100% do espaço. 567 pixels é a largura da janela, quanto em percentual isso significa? Vamos para a "regra de 3":

static void Main(string[] args)

{

    int larguraTela = 1024;

    int larguraJanela = 567;

 

    var percentualJanela = larguraJanela * 100 / larguraTela;

 

    Console.WriteLine("A janela está ocupando {0}% da largura da tela!", percentualJanela);

    Console.ReadKey();

 

    // Imprime no console:

    // A janela está ocupando 55% da largura da tela!

}

Fazendo na calculadora, podemos ver que o nosso resultado (percentual da janela) é "55,37109375%", o que aconteceu?

Quando o seu cálculo só utiliza elementos do tipo "inteiro", o resultado será do mesmo tipo, isso é uma convenção em linguagens de programação, não é aplicado somente ao C#, já me deparei com várias linguagens que se comportam da mesma maneira.

Como fazer para ter precisão de casas decimais nesse cálculo?

Basta que um elemento qualquer envolvido no cálculo tenha essa precisão, como já é conhecido pela maioria, no C# temos o double, float e o decimal, cada um com a sua precisão, sendo a escolha baseada na sua necessidade. Então converto uma variável qualquer para um desses tipos? Nesse exemplo da regra de 3 não é necessário, como temos o literal "100", basta dizer para o compilador que você, programador, escreveu alí um número decimal, não um inteiro, como fazer isso?

Finalmente chegamos ao ponto alvo desse post, que é apresentar como se escreve em "hard code" números já no seu respectivo tipo:

var d = 1.0d; // double (ou sem a letra 'd', 1.0 é considerado como double também)

var f = 1.0f; // float

var m = 1.0m; // decimal

var i = 1; // int (sem nenhuma letra, é int)

var ui = 1U; // uint

var ul = 1UL; // ulong

var l = 1L; // long

E voltando ao nosso código, agora escrevendo 100m.

static void Main(string[] args)

{

    int larguraTela = 1024;

    int larguraJanela = 567;

 

    var percentualJanela = larguraJanela * 100m / larguraTela;

 

    Console.WriteLine("A janela está ocupando {0}% da largura da tela!", percentualJanela);

    Console.ReadKey();

 

    // Imprime no console:

    // A janela está ocupando 55,37109375% da largura da tela!

}

Pronto, agora o resultado é 55,37109375%, mais um problema resolvido. Até a próxima pessoal.

Problema da primeira linha em XML com Razor

Recentemente me deparei com um problema curioso ao tentar construir um XML usando o Razor (mecânica de geração de Views do ASP.NET MVC). Apesar de ser feito para gerar HTML, o Razor funciona muito bem para gerar XML também, bom... acontece que para fabricar um XML válido, o mesmo precisa iniciar com a tag <?xml version="1.0" encoding="utf-8" ?>, absolutamente nada pode vir antes (espaço, quebra de linha, ou qualquer outro caracter). Mesmo colocando essa tag no início da minha view Razor .cshtml, o arquivo gerado insistia em conter uma quebra de linha no seu início.

Não sei se isso é um BUG, mas pesquisando um pouco vi que várias pessoas já tiveram esse mesmo problema, aqui e aqui existem várias soluções, só que todas elas (as que realmente resolviam o problema) exigia que você adicionasse no seu projeto arquivos de código que não eram pertinentes ao foco do negócio da sua aplicação: classes especializadas ou procedimentos longos que deixariam o código de difícil manutenção.

Felizmente tive uma ideia diferente, já que essa quebra de linha era gerada pelo Razor, então antes da renderização da view, vou escrever a tag que é exigida estar por primeiro, bastando adicionar uma única linha de código logo antes do return. A action ficou assim:

public ActionResult Index()

{

     Response.Write("<?xml version=\"1.0\" encoding=\"utf-8\" ?>");

 

     return View();

}

Só isso, com esse Response.Write o problema foi resolvido! A quebra de linha pode continuar lá, sem ser importunada, rsrsrs

Global.asax e seus eventos em uma requisição

O arquivo Global.asax nos dá a possibilidade de escrever algum código para a “infraestrutura” da nossa aplicação web. Infraestrutura por assim dizer, mas na verdade, entendendo bem o ciclo de vida de uma aplicação ASP.NET, podemos implementar lá qualquer coisa que seja pertinente ao nosso projeto. Por padrão, o Visual Studio não coloca todos os métodos dos eventos que podemos utilizar no Global.asax, existem alguns muito interessantes que vale a pena conferir.

Listados na sequencia que ocorrem, segue abaixo os eventos que são disparados quando uma requisição é feita:

  1. Application_BeginRequest – Disparado quando uma requisição é recebida, sendo então o primeiro evento disponível. Aqui você pode colocar algum código com a certeza de que o mesmo será executado antes de tudo.
  2. Application_AuthenticateRequest – Disparado quando a identidade do usuário que fez a requisição é válida. Analisando as propriedades contidas no objeto Request, aqui você pode implementar uma lógica de autenticação para negar o acesso ao usuário caso necessário.
  3. Application_AuthorizeRequest – Disparado quando o usuário teve permissão para acessar a página ou o conteúdo. Analisando as propriedades contidas no objeto Request, aqui você pode implementar uma lógica para negar o acesso a uma página ou recurso específico.
  4. Application_ResolveRequestCache – Disparado quando (opcionalmente) é possível obter a resposta da requisição através de um cache, evitando que a mesma seja executada da maneira normal. Se já não estiver sendo feito automaticamente pelo IIS ou por alguma mecânica padrão do ASP.NET, aqui você pode implementar um retorno obtido através de um cache customizado, e terminar a requisição forçadamente chamando o método CompleteRequest.
  5. Application_AcquireRequestState – Disparado quando a sessão do usuário foi (ou não) reconhecida e está pronta para ser usada. Aqui você fazer algum ajuste qualquer nas variáveis de sessão do usuário.
  6. Application_PreRequestHandlerExecute – Disparado logo antes de iniciar os procedimentos para do processamento da requisição do usuário. Aqui você pode executar algum código tendo a certeza de que nenhuma programação responsável por devolver o que foi solicitado foi executada.
  7. Application_PreSendRequestHeaders – Disparado logo antes que qualquer coisa seja colocada no cabeçalho de resposta da requisição. Desde nenhum código anterior tenha colocado algo no cabeçalho de resposta, aqui você pode executar algum código tendo em mente que nada ainda foi colocado no cabeçalho de resposta da requisição.
  8. Application_PreSendRequestContent – Disparado logo antes que qualquer coisa seja colocada no corpo da resposta da requisição. Desde nenhum código anterior tenha colocado algo no corpo da resposta, aqui você pode executar algum código tendo em mente que nada ainda foi colocado corpo da resposta da requisição.
  9. << A execução do seu código, podendo ser MVC, WebForms, WebAPI ou qualquer outra coisa. >>
  10. Application_PostRequestHandlerExecute – Disparado logo após terminar de executar a programação da página ou recurso requisitado. Aqui você pode implementar alguma lógica que precisa ser executada toda vez que programação da página ou recurso terminar.
  11. Application_ReleaseRequestState – Disparado quando toda a programação referente ao processamento da requisição é terminado. Similar ao evento anterior, aqui você pode implementar alguma lógica que deve ser executada quando as programações terminarem (chamar o Dispose de algum recurso, etc...).
  12. Application_UpdateRequestCache – Disparado quando a requisição foi terminada e a mesma agora pode ser armazenada em um cache para tornar mais rápido as requisições subsequentes. Se já não estiver sendo feito automaticamente pelo IIS ou por alguma mecânica padrão do ASP.NET, aqui você pode implementar a gravação do conteúdo processado em um cache customizado para reutilizá-lo mais tarde no método Application_ResolveRequestCache.
  13. Application_EndRequest – Disparado quando a requisição terminou. Aqui você pode colocar algum código com a certeza de que o mesmo será executado depois de tudo.

Legal não é? Conhecer esses eventos vai nos dar a possibilidade de resolver vários problemas de forma ágil e prática.

Mas como é a assinatura desses métodos?

Todos possuem o retorno como void e dois parâmetros de entrada, o primeiro um Object e o segundo um EventArgs, como no exemplo ilustrado abaixo:

protected void Nome_do_Evento(object sender, EventArgs e)

{

 

}

Dica: O nível de acessibilidade fica por sua conta, pode ser protected, private ou public, tanto faz. E o nome do método não é case sensitive.

Entretanto, nem sempre é bom rechear esses métodos com muito código, pois muitas vezes vamos ter implementações genéricas que poderiam ser utilizadas em outros projetos (lógicas de autenticação ou segurança por exemplo) que acabam ficando muito acopladas no Global.asax, e dessa maneira vamos perder a possibilidade de fazer um reaproveitamento de código, fora que tudo ficará muito amontoado no Global.asax, dificultando o entendimento e a manutenção. O ideal é só implementar o que é específico desse projeto, e o genérico, colocar em módulos ou utilidades específicas do MVC ou WebForms.