How to validate CPF with DataAnnotation on Client and Server?

14

I need to validate CPF with Data Annotation , and check for duplicity.

    
asked by anonymous 02.03.2014 / 16:40

3 answers

19

First, create a class that will be the Custom Validation Attribute. The class code will be as follows:

/// <summary>
/// Validação customizada para CPF
/// </summary>
public class CustomValidationCPFAttribute : ValidationAttribute, IClientValidatable
{
    /// <summary>
    /// Construtor
    /// </summary>
    public CustomValidationCPFAttribute() { }

    /// <summary>
    /// Validação server
    /// </summary>
    /// <param name="value"></param>
    /// <returns></returns>
    public override bool IsValid(object value)
    {
        if (value == null || string.IsNullOrEmpty(value.ToString()))
        return true;

        bool valido = Util.ValidaCPF(value.ToString());
        return valido;
    }

    /// <summary>
    /// Validação client
    /// </summary>
    /// <param name="metadata"></param>
    /// <param name="context"></param>
    /// <returns></returns>
    public IEnumerable<ModelClientValidationRule> GetClientValidationRules(
        ModelMetadata metadata, ControllerContext context)
    {
        yield return new ModelClientValidationRule
        {
            ErrorMessage = this.FormatErrorMessage(null),
            ValidationType = "customvalidationcpf"
        };
    }
}

The code of the class Util, which has the method that does the validation of the CPF is as follows:

    /// <summary>
    /// Remove caracteres não numéricos
    /// </summary>
    /// <param name="text"></param>
    /// <returns></returns>
    public static string RemoveNaoNumericos(string text)
    {
        System.Text.RegularExpressions.Regex reg = new System.Text.RegularExpressions.Regex(@"[^0-9]");
        string ret = reg.Replace(text, string.Empty);
        return ret;
    }

    /// <summary>
    /// Valida se um cpf é válido
    /// </summary>
    /// <param name="cpf"></param>
    /// <returns></returns>
    public static bool ValidaCPF(string cpf)
    {
        //Remove formatação do número, ex: "123.456.789-01" vira: "12345678901"
        cpf = Util.RemoveNaoNumericos(cpf);

        if (cpf.Length > 11)
            return false;

        while (cpf.Length != 11)
            cpf = '0' + cpf;

        bool igual = true;
        for (int i = 1; i < 11 && igual; i++)
            if (cpf[i] != cpf[0])
                igual = false;

        if (igual || cpf == "12345678909")
            return false;

        int[] numeros = new int[11];

        for (int i = 0; i < 11; i++)
            numeros[i] = int.Parse(cpf[i].ToString());

        int soma = 0;
        for (int i = 0; i < 9; i++)
            soma += (10 - i) * numeros[i];

        int resultado = soma % 11;

        if (resultado == 1 || resultado == 0)
        {
            if (numeros[9] != 0)
                return false;
        }
        else if (numeros[9] != 11 - resultado)
            return false;

        soma = 0;
        for (int i = 0; i < 10; i++)
            soma += (11 - i) * numeros[i];

        resultado = soma % 11;

        if (resultado == 1 || resultado == 0)
        {
            if (numeros[10] != 0)
                return false;
        }
        else
            if (numeros[10] != 11 - resultado)
                return false;

        return true;
    }

Add in the page or layout that the page is using reference to the following Javascript files, which are used to use DataAnnotations:

    <script src="@Url.Content("~/Scripts/jquery-1.4.4.min.js")" type="text/javascript"></script>
    <script src="@Url.Content("~/Scripts/jquery.validate.min.js")" type="text/javascript"></script>
    <script src="@Url.Content("~/Scripts/jquery.validate.unobtrusive.min.js")" type="text/javascript"></script>
    <script src="@Url.Content("~/Scripts/jquery.unobtrusive-ajax.min.js")" type="text/javascript"></script>

In addition, add the reference to the Javascript file created to validate on the client:

In the class with the properties add the name attribute created.

public class Usuario
{
[Required(ErrorMessage="Nome requerido")]
public string Nome { get; set; }

[Required(ErrorMessage="CPF obrigatório")]
[CustomValidation.CustomValidationCPF(ErrorMessage="CPF inválido")]
public string CPF { get; set; }
}

And in the form the spaces to display the error messages:

@using (Html.BeginForm())
{
@Html.LabelFor(a => a.Nome, "Nome")
@Html.TextBoxFor(a => a.Nome)
@Html.ValidationMessageFor(a => a.Nome)
<br />

@Html.LabelFor(a => a.CPF, "CPF")
@Html.TextBoxFor(a => a.CPF)
@Html.ValidationMessageFor(a => a.CPF)
<br />

<input type="submit" value="Enviar" />
}
    
03.03.2014 / 01:40
8

Here is an add-on to the answer given by @ samir-braga, which will validate only on the server. Even if the apparent code is being validated on the client, since the error message is displayed, this validation is done on the server.

In order for a validation to occur in the client, before the data is submitted to the server, a javascript implementation of the ValidaCPF method will be required, in addition to the inclusion of this method in $.validator and $.validator.unobtrusive , thus: / p>

$.validator.addMethod("customvalidationcpf", function (value, element, param) {
    return validaCPF(value); //chama um método validaCPF implementado em javascript
});
$.validator.unobtrusive.adapters.addBool("customvalidationcpf");

The name customvalidationcpf should match the value of ValidationType declared in method GetClientValidationRules .

Here's an implementation of CPF validation in javascript:

function validaCPF(s) {
    var i;
    var l = '';
    for (i = 0; i < s.length; i++) if (!isNaN(s.charAt(i))) l += s.charAt(i);
    s = l;
    if (s.length != 11) return false;
    var c = s.substr(0, 9);
    var dv = s.substr(9, 2);
    var d1 = 0;
    for (i = 0; i < 9; i++) d1 += c.charAt(i) * (10 - i);
    if (d1 == 0) return false;
    d1 = 11 - (d1 % 11);
    if (d1 > 9) d1 = 0;
    if (dv.charAt(0) != d1) return false;
    d1 *= 2;
    for (i = 0; i < 9; i++) d1 += c.charAt(i) * (11 - i)
    d1 = 11 - (d1 % 11);
    if (d1 > 9) d1 = 0;
    if (dv.charAt(1) != d1) return false;
    return true;
}
    
28.04.2014 / 14:42
2
[System.Web.Mvc.Remote("MetodoValidarCPF", "SeuController", ErrorMessage = "CPF inválido.")]

And then you can create a validation-only class and call this dll in the controler and it will recognize

public JsonResult ValidarCPF(string cpf = "")
{
   bool validaCPF = SIBValidacoesBLL.ValidarCPF(strCpf);
   return Json(validaCPF, JsonRequestBehavior.AllowGet);
}

If it returns true passes in the validation, if false returns it slash, you can also return a message for each validation, then if it returns true passes if string returns the string, example

return Json("Se não passou na validação retorna uma mensagem customizada", JsonRequestBehavior.AllowGet);
    
10.09.2015 / 14:36