Atributo para validar Horas utilizando Data Annotation em Asp.Net MVC 4 com C# (CSharp)

HoraBrasil, atributo customizado para validar Horas em Asp.Net MVC 4 com C#(CSharp) e integração em javascript para o lado do cliente.


Autor : Antonio Carlos Ferreira de Azevedo
Postado em : 23/04/2016

Data Annotation Custumizado [HoraBrasil()]

Nesta postagem você vai aprender a validar um campo string no formato hhh:mm ou hh:mm usando Data Annotation e jquery.validate onde será feita a validação tanto do lado do cliente como no servidor.
Vamos criar aqui uma classe derivada da ValidationAttribute e criar nossa classe customizada para a validação no servidor.

HoraBrasilAttribute

ErrorMessage Mensagem padrão de erro.
HoraRequerida True Se a digitação da hora é obrigatória False se a digitação da hora não é obrigatória.
Hora24 True se desejamos valiar horas no formato hh:mm (00:00 até 23:59) False se desejamos validar horas no formato hhh:mm no caso de informações de horas trabalhadas por exemplo.

Crie uma classe na pasta Models em seu projeto MVC com o nome de HoraBrasilAttribute.cs copie e cole o código abaixo.

HoraBrasilAttribute.cs

/* 
 * Atributo HoraBrasil
 * 
 * Data Annotations para Validar uma hora no formato hh:mm.
 * 
 * Visite nossa página http://www.codigoexpresso.com.br
 * 
 * by Antonio Azevedo
 *  
 * Chamada em sua Classe : 
 *   [HoraBrasil(ErrorMessage="Sua mensagem de erro", HoraRequerida=true/false, Hora24=true/false)]
 *    
 *   HoraRequerida  -  (False) - Valida horas em branco 
 *   Hora24         -  (True) Valida horas no formado hhh:mm (False) Valida Horas no Formato hh:mm (00:00 até 23:59) 
 *   
 */
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Text.RegularExpressions;
using System.Web.Mvc;

public class HoraBrasilAttribute : ValidationAttribute, IClientValidatable
{
   
    public Boolean HoraRequerida { get; set; }
    public Boolean Hora24 { get; set; }
    public HoraBrasilAttribute()
    {
        this.ErrorMessage = "Hora inválida.";
        this.HoraRequerida = false;
        this.Hora24 = true;
    }

    protected override ValidationResult IsValid(
        object value,
        ValidationContext validationContext)
    {

        // Verifica se o Valor é nulo
        if (value == null)
        {
            value = "";
        }

        // Caso o valor informado seja nulo não é requerido retorna sem validar
        if (value == "" && HoraRequerida == false)
        {
            return ValidationResult.Success; 
        }

        Regex regExpHora;
        
        // Atribui expressao Regex conforme Atribuito solicitado Hora24 solicitado
        if (Hora24 == false)
        {
            regExpHora = new Regex(@"^([0-9][0-9][0-9]|[0-9][0-9]|[0-9]):([0-5][0-9])$");
        }
        else
        {
            regExpHora = new Regex(@"^([0-1][0-9]|[2][0-3]):([0-5][0-9])$");
        }

        // Valida a expressao
        Match match = regExpHora.Match(value.ToString());

        if (match.Success)
        {
            // Se não for requerida valida com sucesso
            if (HoraRequerida == false)
            {
                return ValidationResult.Success; ;
            }
            else
            {
                if (Hora24==true)
                {
                    return ValidationResult.Success; ;
                }
            }
        }
        else
        {
            // Devolve o erro padrao se a expressao nao for valida.
            return new ValidationResult(this.FormatErrorMessage(validationContext.DisplayName));
        }

        // Converte o valor para Minutos inteiros
        int Minutos = 0;

        int pos = value.ToString().IndexOf(":");
        if (pos < 0)
        {
            Minutos = 0;
        }
        else
        {
            Minutos = (ConverteInt32(value.ToString().Substring(0, pos)) * 60) + (ConverteInt32(value.ToString().Substring(pos + 1)));
        }
       
        // Se Hora foi requerida e não digitada retorna erro padrao
        if (HoraRequerida==true && Minutos == 0)
        {
            return new ValidationResult(this.FormatErrorMessage(validationContext.DisplayName));
        }
     
        // Retorna com sucesso caso a converão tenha sido feita
        return ValidationResult.Success;
    }

    // Diretivas para validação do lado do Cliente, implementa com jquery.validate
    public IEnumerable<ModelClientValidationRule> GetClientValidationRules(
        ModelMetadata metadata,
        ControllerContext context)
    {
        var Rule = new ModelClientValidationRule
        {
            ValidationType = "horabrasil",
            ErrorMessage = this.FormatErrorMessage(metadata.PropertyName)

        };

        string[] array = new string[] { HoraRequerida.ToString(), Hora24.ToString() };

        Rule.ValidationParameters["params"] = string.Join(",", Array.ConvertAll(array, x => x.ToString()));

        yield return Rule;
    }


    // Função para converter uma string para inteiro, se a string nao puder ser convertida retorna 0
    private Int32 ConverteInt32(string valor)
    {
        Int32 newValor;
        try
        {
            newValor = Convert.ToInt32(valor);
        }
        catch (Exception)
        {
            return 0;
        }

        return newValor;
    }
}

Agora vamos cuidar da validação do lado no cliente, ou seja, no navegado do cliente.
O MVC se encarrega de transportar os parametros para nosso HTML mas mesmo assim temos que fazer toda a validação em JavaScript novamente.

Crie uma arquivo JavaScript na pasta Scripts de seu projeto MVC, de o nome de CustomValidacoes.js copie e cole o código abaixo.

CustomValidacoes.js

// Aqui adicionamos os metodos respeitando os nomes gerado em nossa classe atributo
// os nomes devem estar em caixa baixa tanto na integração como aqui no JavaScript (Nome atributo, parametro)
$.validator.unobtrusive.adapters.addSingleVal('horabrasil', 'params');

//Aqui temos a funcao que Valida do lado do cliente as horas digitadas utilizando uma expressão regular
$.validator.addMethod('horabrasil',
function (value, element, params) {


    var parametros = params.split(',');


    // Valida caso o valor não tenha sido preenchido
    if (value.length == 0) {
        if (parametros[0].toString() == "False") {
            return true;
        }
    }

    // Atribui expressão
    var expReg = "";

    if (parametros[1].toString() == "True") {
        expReg = /^([0-1][0-9]|[2][0-3]):([0-5][0-9])$/;
    }
    else
    {
        expReg = /^([0-9][0-9][0-9]|[0-9][0-9]|[0-9]):([0-5][0-9])$/;
    }

    // Valida Expressao
    var result = value.match(expReg);

    // Retorna false caso a expressao nao seja valida
    if (result == null) {
        return false;
    }

    else
    {
        if (parametros[1].toString() == "True")
        {
            return true;
        }

    }

    // Caso Hora24=false e HoraRequerida=true valida se o valor não é nulo

    expReg = /^([0][0][0]|[0][0]|[0]):([0][0])$/;

    result = value.match(expReg);

    if (result == null) {
        return true;
    }

    return false;
});

Este arquivo deve ser carregado após o carregamento do jquery.validate.

Exemplo de como utilizar o atributo em sua classe.

using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Web;
using SeuProjeto.Models;

namespace AspNetMVC_Aula.Models
{
    public class ModAluno
    {
       [HoraBrasil(ErrorMessage = "Hora inválida", HoraRequerido = false, Hora24 = true )]
       public string? Hora { get; set; }
    }
}


Comentários