How to use Viewmodel in MVC 5 C# with Entity Framework?

Asked

Viewed 699 times

3

I’m trying to learn how to use the concept of Viewmodel, so I did a basic project, but I’m having difficulties.

I have the following models:

  • Person

    • id
    • guy
    • document
  • Physique

    • id
    • name
    • surname
    • document
  • Juridical

    • id
    • razao_social
    • fantasy name
    • document

The idea of the example is to inform in the type field of the Person Model if it is F (Physical Person) or J (Juridical Person) and the document field, would receive the CNPJ or CPF of the Physical/Juridical Person.

Then, the Juridical or Physical Models would be filled by the specific data of each type, but the document field would receive the ID of its respective CPF or CNPJ.

I made this relationship in the database and imported it to my project using ADO.Net Entity Data Model via the Code First from database option.

My models look like this:

(Table of the Physical Person)

[Table("Fisica")]
public partial class Fisica
{
    [Key]
    public int id { get; set; }

    [Required]
    [StringLength(50)]
    public string nome { get; set; }

    [Required]
    [StringLength(50)]
    public string sobrenome { get; set; }

    public int documento { get; set; }

    public virtual Pessoa Pessoa { get; set; }
}

(Table of the Legal Person)

[Table("Juridica")]
public partial class Juridica
{
    [Key]
    public int id { get; set; }

    [Required]
    [StringLength(50)]
    public string razao_social { get; set; }

    [Required]
    [StringLength(50)]
    public string nome_fantasia { get; set; }

    public int documento { get; set; }

    public virtual Pessoa Pessoa { get; set; }
}

(Table of CPF or CNPJ Documents)

[Table("Pessoa")]
public partial class Pessoa
{
    [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")]
    public Pessoa()
    {
        Fisica = new HashSet<Fisica>();
        Juridica = new HashSet<Juridica>();
    }

    [Key]
    public int id { get; set; }

    [Required]
    [StringLength(1)]
    public string tipo { get; set; }

    [Required]
    [StringLength(14)]
    public string documento { get; set; }

    [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
    public virtual ICollection<Fisica> Fisica { get; set; }

    [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
    public virtual ICollection<Juridica> Juridica { get; set; }
}

Then I created my Viewmodel as follows:

(Viewmodel that contemplates the 3 tables)

public class ViewModelPessoas
{
    public Pessoa Pessoa { get; set; }
    public Fisica Fisica { get; set; }
    public Juridica Juridica { get; set; }
}

I don’t know if that’s correct or if you’ve already made a mistake, in case you have, please point out to me.

My idea is to create a view only where, through Javascript, if the user selects that will register an Individual, will only appear the fields related to this type, the opposite happens when he selects that will register a Legal Entity. That I know how to do, but my difficulty is now being two bigger:

  1. In this template, can I still use Modelstate.Isvalid to validate the Form Post? Because if it only sends data from the Physical Person, the Legal Person fields will be null, returned that the Modelstate.Isvalide is false. What is the best way to do this validation?

  2. How do I, within a single action, in the case of Actionresult Create(Viewmodelppeople model), I first register in the Person table, get the auto-increment id generated for this document registration and be able to useor when saving the specific data of the Natural or Legal person (field document)?

Thank you!

~Added on 04/09/2017:

I was able to solve checking if the registration that is being sent is type PF or PJ, if it is PF then I clean the errors of the PJ field and vice versa.

Do you think this is a good solution? Thank you.

//Validar modelo
switch (modelo.Pessoa.tipo)
{
 case "F":
     ModelState["Juridica.razao_social"].Errors.Clear();
     ModelState["Juridica.nome_fantasia"].Errors.Clear();
     break;

 case "J":
     ModelState["Fisica.nome"].Errors.Clear();
     ModelState["Fisica.sobrenome"].Errors.Clear();
     break;

 default:
     ModelState.AddModelError("Pessoa.tipo", "Informe se o cadastro é Pessoa Física ou Pessoa Jurídica.");
     break;
}

1 answer

3


In this model, I can still use Modelstate.Isvalid for validate the Form Post? Because if it only sends Person data Physical, the Legal Person fields will be null, returned than the Modelstate.Isvalide is false. What’s the best way to do this validation?

It can. And validate [Required] or natural person or legal person DataAnnotations for this, you will need to make a proper implementation and inherit from Validationattribute for this, or do this validation elsewhere.

How do I, within a single action, in the case of Actionresult Create(Viewmodelppeople model), I register first in the table Person, get the auto-increment id generated for that registration document and can use it afterwards when saving the specific data of the Natural or Legal person (document field)?

Is this a Joined mapping (Person primary key is Physical/Legal primary and foreign key)? If it is and you have correctly configured the database an insertion will only suffice, it is not necessary to return the id.

Even so, if you want to return the id and you use Entity would look like this:

Contexto.Pessoa.Add(entidade);
Contexto.SaveChanges();
//após o SaveChanges, a propriedade Id do seu objeto vai possuir o valor da chave.
var idGerado = entidade.Id;
return idGerado; 
  • this line Context.Peop.Addobject(entity); Did you mean this: Context.Peop.Add(entity); Correct? Because I couldn’t find this Addobject method

  • Exactly, I will correct

  • 1

    Regarding saving the id automatically on the tables without me having to worry about capturing it, it really worked, thanks!

  • About using Validationattribute for validation, I’m still in doubt. I know I can with it add personalized validations to my model, but I would have to, in addition, ignore the validation of the Individual or the Legal Person dynamically, this is the biggest doubt. But you’ve helped me enough so far, thank you.

  • The only validation that will get in the way of [Required] and anything that limits a minimum value, all this has to be done within a Validationattribute. Usually, in these cases one or the other does not use the [Required]

Browser other questions tagged

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