Validação de Classes — Web C#

Fulvio Cezar Canducci Dias
7 min readMar 10, 2023

--

Um assunto muito recorrento no mundo .NET são as validações dos metadados de uma determinada classe, sendo essa preocupação determinante aos diversos casos de testes de objetos de qualquer requisição. Não devemos deixar aceitar qualquer tipo de informação, pois nossa regra de negócio é que determina o que vai ser realmente salvo em algum repositório de armazenamento ou então alguma configuração pertinente a essa regra.

No espaço reservado ( namespace ) System.ComponentModel.DataAnnotaions, existem diversos atributos que tem a finalidade de validar metadados e sua lista tem diversos atributos como demonstrada logo abaixo (referencia: Site Microsoft Learn System.ComponentModel.DataAnnotations):

  • AssociatedMetadataTypeTypeDescriptionProvider: Estende as informações de metadados de uma classe adicionando informações de propriedade e atributos definidos em uma classe associada.
  • AssociationAttribute: Especifica que um membro de entidade representa uma relação de dados, como uma relação de chave estrangeira.
  • CompareAttribute: Fornece um atributo que compara duas propriedades.
  • ConcurrencyCheckAttribute: Especifica que uma propriedade participa de verificações de simultaneidade otimista.
  • CreditCardAttribute: Especifica que o valor de um campo de dados é um número de cartão de crédito.
  • CustomValidationAttribute: Especifica um método de validação personalizado que é usado para validar uma instância de classe ou propriedade.
  • DataTypeAttribute: Especifica o nome de um tipo adicional a ser associado a um campo de dados.
  • DisplayAttribute: Fornece um atributo de uso geral que permite especificar cadeias de caracteres localizáveis para tipos e membros de classes parciais de entidade.
  • DisplayColumnAttribute: Especifica a coluna que é exibida na tabela referida como uma coluna de chave estrangeira.
  • DisplayFormatAttribute: Especifica como os campos de dados são exibidos e formatados por Dados Dinâmicos do ASP.NET.
  • EditableAttribute: Indica se um campo de dados é editável.
  • EmailAddressAttribute: Valida um endereço de email.
  • EnumDataTypeAttribute: Habilita uma enumeração do .NET a ser mapeada para uma coluna de dados.
  • FileExtensionsAttribute: Valida as extensões de nome de arquivo.
  • FilterUIHintAttribute: Representa um atributo que é usado para especificar o comportamento de filtragem de uma coluna.
  • KeyAttribute: Indica que uma ou mais propriedades que identificam exclusivamente uma entidade.
  • MaxLengthAttribute: Especifica o comprimento máximo dos dados de cadeia de caracteres ou matriz permitido em uma propriedade.
  • MetadataTypeAttribute: Especifica a classe de metadados para associar a uma classe de modelo de dados.
  • MinLengthAttribute: Especifica o comprimento mínimo dos dados de cadeia de caracteres ou matriz permitido em uma propriedade.
  • PhoneAttribute: Especifica que o valor de um campo de dados é um número de telefone bem formado.
  • RangeAttribute: Especifica as restrições de intervalo numérico para o valor de um campo de dados.
  • RegularExpressionAttribute: Especifica que o valor de um campo de dados no Dados Dinâmicos do ASP.NET deve corresponder à expressão regular especificada.
  • RequiredAttribute: Especifica que o valor de um campo de dados é obrigatório.
  • ScaffoldColumnAttribute: Especifica se uma coluna de dados ou classe usa scaffolding.
  • StringLengthAttribute: Especifica o comprimento mínimo e máximo de caracteres permitidos em um campo de dados.
  • TimestampAttribute: Especifica o tipo de dados da coluna como uma versão de linha.
  • UIHintAttribute: Especifica o modelo ou controle de usuário usado pelos Dados dinâmicos para exibir um campo de dados.
  • UrlAttribute: Fornece validação da URL.
  • ValidationAttribute: Serve como a classe base para todos os atributos de validação.
  • ValidationContext: Descreve o contexto no qual é realizada uma verificação de validação.
  • ValidationException: Representa a exceção que ocorre durante a validação de um campo de dados quando a classe ValidationAttribute é usada.
  • ValidationResult: Representa um contêiner para os resultados de uma solicitação de validação.
  • Validator: Define uma classe auxiliar que pode ser usada para validar objetos, propriedades e métodos quando ela está incluída em seus atributos ValidationAttribute associados.

Essas validações já possuem sua implementações tanto no BackEnd e no FrontEnd com jQuery.Validation e jQuery.Unobtrusive, então quando se faz algum atributo de validação tambem se deve se atentar a validação do FrontEnd, tendo como base que qualquer requisição demasiada para o BackEnd tornar o trabalho do servidor maior e com isso a validação FrontEnd é um grande auxilio para enviar ao seu BackEnd os dados praticamente validados. Contudo sempre quando se pensa em validação a que realmente deve funcionar 100% é a do servidor que garante mais estabilidade na informação.

Como implementar uma validação?

Não é um trabalho dificil, precisa criar uma classe qualquer com o nome final Attribute que herda de uma classe abstrata ValidationAttribute que é o responsável pela validação servidor e IClientModelValidator para informar os parametros para validação do frontend.

Proposta

Como criar uma validação de Data (dia, mês e ano) no formato Brasileiro (dd/MM/yyyy)?

using Microsoft.AspNetCore.Mvc.ModelBinding.Validation;
using System.ComponentModel.DataAnnotations;
namespace Web.Validations
{
public class DateAttribute : ValidationAttribute, IClientModelValidator
{
public void AddValidation(ClientModelValidationContext context)
{
context.Attributes.Add
(
"data-val-date-custom",
ErrorMessage ?? "Date invalid"
);
}

protected override ValidationResult? IsValid
(
object? value,
ValidationContext validationContext
)
{
if (!DateTime.TryParse(value?.ToString(), out DateTime _))
{
return new ValidationResult(ErrorMessage ?? "Date invalid");
}
return ValidationResult.Success;
}
}
}

A classe DateAttribute é para validar os dados de entrada do tipo data no formato Brasileiro (ou aquele que você definir também, mas, nesse caso focar no formato de datas do Brasil), no método ValidationResult é a parte do servidor e no método AddValidation é para a configurações de validação do FrontEnd. No caso da validação do servidor já está implementado e agora é só decorar o campo do tipo DateOnly ou DateTime como foi especificado na classe Car no campo CreatedAt:

using System.ComponentModel.DataAnnotations;
using Web.Validations;
namespace Web.Models
{
public class Car
{
public int Id { get; set; }

[Required(ErrorMessage = "Digite o nome completo")]
public string? Name { get; set; }

[Required(ErrorMessage = "Digite a data de criação")]
[Date(ErrorMessage = "Data inválida")]
public DateTime CreatedAt { get; set; }
}
}

Para criar a validação do FronEnd precisa informar o jQuery.Validation e jQuery.Unobtrusive uma função especifica escrita em Javascript da seguinte forma:

Instale o plugin para trabalhar com data o dayjs, com o próprio Visual Studio:

dayjs

Faça a sua referencia conforme instalação no _Layout.cshtml:

<script src="~/lib/jquery/dist/jquery.min.js"></script>
<script src="~/lib/bootstrap/dist/js/bootstrap.bundle.min.js"></script>
<script src="~/lib/dayjs/dayjs.min.js"></script>
<script src="~/lib/dayjs/locale/pt-br.min.js"></script>
<script src="~/lib/dayjs/plugin/customparseformat.min.js"></script>
<script src="~/js/site.js" asp-append-version="true"></script>
@await RenderSectionAsync("Scripts", required: false)

e no arquivo site.js coloque o seguinte código:

dayjs.locale('pt-br');
dayjs.extend(window.dayjs_plugin_customParseFormat);
const formatDate = {
dateOfBr: 'DD/MM/YYYY',
dateTimeOfBr: 'DD/MM/YYYY HH:mm:ss'
}
function isDate(value, format) {
const result = dayjs(value, format, true).isValid();
return result;
}

essa função vai validar datas no formato dia, mês e ano ( DD/MM/YYYY ) como especificado no objeto formatDate.

O outro arquivo que deve ser criado é validation-custom.js onde será colocado a parte da validação do jQuery.Validation:

(function ($) {
$.validator.setDefaults({
ignore: []
});
$.validator.addMethod('data-val-date-custom',
function (value, element, params) {
console.log(value);
if (!value) return false;
if (value.length < 10) return false;
return isDate(value, formatDate.dateOfBr);
}, function (params, element) {
let msgCompare = $(element).attr('data-val-date-custom');
if (!msgCompare) {
msgCompare = 'Date invalid';
}
return msgCompare;
});
$.validator.unobtrusive.adapters.addBool('data-val-date-custom');
})(jQuery);

nesse código tem algumas informações importantes como data-val-date-custom onde na classe de validação no método AddValidation foi especifico essa configuração e com essa configuração defini a validação logo criado para data no formato Brasileiro. Dentro também possui o isDate que foi criado no arquivo site.js como explicado anteriormente.

Esse arquivo precisa ser anexado a um outro página com o nome de _ValidationScriptsPartial.cshml que é o responsável em adicionar onde for necessário validações com os scripts de validação, exemplo final do arquivo:

<script src="~/lib/jquery-validation/dist/jquery.validate.min.js"></script>
<script src="~/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.min.js"></script>
<script src="~/js/validation-custom.js"></script> // adicionado aqui

Criar uma View da classe Car que como exemplo pode ficar assim:

@model Web.Models.Car
@{ ViewData["Title"] = "Create"; }
<h1>Create</h1>
<h4>Car</h4>
<hr />
<div class="row">
<div class="col-md-4">
<form asp-action="Create">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<div class="form-group mb-2">
<label asp-for="Id" class="control-label"></label>
<input asp-for="Id" class="form-control" />
<span asp-validation-for="Id" class="text-danger"></span>
</div>
<div class="form-group mb-2">
<label asp-for="Name" class="control-label"></label>
<input asp-for="Name" class="form-control" />
<span asp-validation-for="Name" class="text-danger"></span>
</div>
<div class="form-group mb-2">
<label asp-for="CreatedAt" class="control-label"></label>
<input asp-for="CreatedAt" type="text" class="form-control" asp-format="{0:dd/MM/yyyy}" />
<span asp-validation-for="CreatedAt" class="text-danger"></span>
</div>
<div class="form-group mb-2">
<input type="submit" value="Create" class="btn btn-primary" />
</div>
</form>
</div>
</div>
<div>
<a asp-action="Index">Back to List</a>
</div>
@section Scripts {
@{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
}

e ao executar tal página ter o seguinte efeito de validação:

Car
Página exemplo Create Car

--

--

Fulvio Cezar Canducci Dias

Bacharel em Sistemas de Informação, MTAC (Multi-Plataform Technical Audience Contributor-Microsoft), BackEnd C# e PHP e Developer Web