Single-field validation in form in Asp.Net MVC

2

I'm developing an application that manages enrollments in courses, and in my registration form I have the CPF field, and I would like to know how I can make this field unique, that is, bar the user from making another registration with the same field CPF. If the CPF already exists in the table, the system should bar this existing CPF and the user will have to inform another CPF if he wants to make a new registration.

    
asked by anonymous 02.06.2015 / 20:33

2 answers

2

Implement a CPF Attribute :

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.

    
02.06.2015 / 21:37
0

Use in the Controller a method that looks for cpf and also a method that verifies 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

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

You can add the single field definition in the model, I'm not sure if it works at all, or if that 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; }
    
30.09.2015 / 22:56