How to validate CPF with Dataannotation on Client and Server?

Asked

Viewed 15,338 times

15

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

  • I would use the remote in the model to look elsewhere instead of putting logic in the model, but then it goes from each one.

  • Remote makes request for a validation you could do in the View ? as per @iuristona’s reply

3 answers

19

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

/// <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 validates the CPF is the following:

    /// <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 on 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>

Also, add the reference to the Javascript file created to validate in the client:

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

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 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" />
}
  • This does not validate via client, as he quoted in the question

  • But with the complement of the answer below, it works =D, edit for your answer to be very complete, for other users to find easier

  • This link has the javascript needed to validate the client and the complete example. http://mmaspnetmvc.blogspot.com.br/2014/10/criando-uma-validacao-customizada-para.html

7

I make here an add-on to the answer given by @Amir-Raga, which will validate only on the server. Even if the apparent code is being validated on the client, since the error message will be displayed, this validation is done on the server.

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

$.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 customtioncpf must match the value of ValidationType stated in the method GetClientValidationRules.

Here a javascript CPF validation implementation:

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;
}

2

[System.Web.Mvc.Remote("MetodoValidarCPF", "SeuController", ErrorMessage = "CPF inválido.")]

And then you can create a class only validations 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 on validation, if it returns false it bar, you can also return a message for each validation, then if it returns true passes if it returns string displays the string, example

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

Browser other questions tagged

You are not signed in. Login or sign up in order to post.