Form single field validation in Asp.Net MVC

Asked

Viewed 971 times

2

I am developing an application that manages enrollment in courses, and in my registration form I have the field CPF, and I would like to know how I make this field unique, IE, bar the user to make another registration with the same CPF. If the CPF already exists in the table, the system must bar this existing CPF and the user will have to inform another CPF if he wants to make a new registration.

2 answers

2


Implement a Attribute cpf:

namespace MeuProjeto.Attributes
{
    [AttributeUsage(AttributeTargets.Property | AttributeTargets.Field, AllowMultiple = false)]
    sealed public class CPFAttribute : ValidationAttribute
    {
        private MeuProjetoContext context = new MeuProjetoContext();

        protected override ValidationResult IsValid(object value, ValidationContext validationContext)
        {
            if (value == null) return null;

            int soma = 0, resto = 0;
            string digito;
            int[] multiplicador1 = new int[9] { 10, 9, 8, 7, 6, 5, 4, 3, 2 };
            int[] multiplicador2 = new int[10] { 11, 10, 9, 8, 7, 6, 5, 4, 3, 2 };

            string CPF = value.ToString().Replace(".", "").Replace("-", "");

            if (CPF.Length != 11)
                return new ValidationResult("CPF Inválido.");

            if (Convert.ToUInt64(CPF) % 11111111111 == 0)
                return new ValidationResult("CPF Inválido.");

            if (validationContext.ObjectInstance.GetType() == typeof(Pessoa))
            {
                var model = (Pessoa)validationContext.ObjectInstance;

                if (context.Pessoas.Any(p => (p.Cpf == CPF) && (p.PessoaID != model.PessoaID)))
                {
                    var message = FormatErrorMessage("CPF já está cadastrado.");
                    return new ValidationResult(message);
                }
            }

            string tempCpf = CPF.Substring(0, 9);

            for (int i = 0; i < 9; i++)
                soma += int.Parse(tempCpf[i].ToString()) * multiplicador1[i];

            resto = soma % 11;
            if (resto < 2)
                resto = 0;
            else
                resto = 11 - resto;

            digito = resto.ToString();
            tempCpf = tempCpf + digito;
            soma = 0;

            for (int i = 0; i < 10; i++)
                soma += int.Parse(tempCpf[i].ToString()) * multiplicador2[i];

            resto = soma % 11;

            if (resto < 2)
                resto = 0;
            else
                resto = 11 - resto;

            digito = digito + resto.ToString();

            if (CPF.EndsWith(digito))
                return null;
            else
                return new ValidationResult("CPF Inválido.");
        }

        public override string FormatErrorMessage(string name)
        {
            return name;
        }
    }
}

Use in your Model:

[CPF] 
public String Cpf { get; set; }

Validation is done by ASP.NET MVC.

0

Use in the Controller a method that searches for Cpf and also a method that checks if the CPF is valid in the same method

 private void ValidaCpf(Aluno aluno)
    {

        if (aluno.cpf != null)
        {
            Aluno duplicatealuno = db.Alunos
            .Where(d => d.cpf == aluno.cpf)
            .FirstOrDefault();
            //verifica se o Cpf ´´e igual ao existente e verifica se o id é diferente do aluno cadastrado com o CPF
            if (duplicatealuno != null && duplicatealuno.cpf == aluno.cpf && duplicatealuno.id != aluno.id)
            {
                string errorMessage = String.Format(
                "CPF já cadastrado no sistema");
                //defina qual campo irá receber a mensagem e a mensagem
                ModelState.AddModelError("cpf", errorMessage);
            }

            if (!CpfValido(aluno.cpf))
            {
                string errorMessage = String.Format(
              "CPF inválido");
                ModelState.AddModelError("aluno.cpf", errorMessage);
            }
        }
    }

     #region Helpers
    public bool CpfValido(string cpf)
    {
        int[] multiplicador1 = new int[9] { 10, 9, 8, 7, 6, 5, 4, 3, 2 };
        int[] multiplicador2 = new int[10] { 11, 10, 9, 8, 7, 6, 5, 4, 3, 2 };
        string tempCpf;
        string digito;
        int soma;
        int resto;
        cpf = cpf.Trim();
        cpf = cpf.Replace(".", "").Replace("-", "");
        if (cpf.Length != 11)
            return false;
        tempCpf = cpf.Substring(0, 9);
        soma = 0;

        for (int i = 0; i < 9; i++)
            soma += int.Parse(tempCpf[i].ToString()) * multiplicador1[i];
        resto = soma % 11;
        if (resto < 2)
            resto = 0;
        else
            resto = 11 - resto;
        digito = resto.ToString();
        tempCpf = tempCpf + digito;
        soma = 0;
        for (int i = 0; i < 10; i++)
            soma += int.Parse(tempCpf[i].ToString()) * multiplicador2[i];
        resto = soma % 11;
        if (resto < 2)
            resto = 0;
        else
            resto = 11 - resto;
        digito = digito + resto.ToString();
        return cpf.EndsWith(digito);
    }

    #endregion

And before saving use the method

ValidaCpf(aluno);
 //Caso o cpf exista ele ira mostrar a mensagem 
        if (ModelState.IsValid)
        {}

You can add the unique field setting to the model, I’m not sure if it works at all or if this is your case.

[Display(Name = "CPF")]
    [Required(ErrorMessage = "Por favor, preencher o campo CPF.")]
    [Index("INDEX_CPF2", IsUnique = true)]
    [StringLength(14)]
    public string cpf { get; set; }
  • The problem in this way is that it runs before the normal MVC validation cycle, and can even be considered an anti-standard.

Browser other questions tagged

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