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

3

I'm trying to learn how to use the ViewModel concept, so I did a basic project, but I'm having difficulty.

I have the following Models:

  • Person

    • id
    • type
    • document
  • Physics

    • id
    • name
    • surname
    • document
  • Juridica

    • id
    • reasonsocial
    • phantasy_name
    • document

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

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

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

My Models look like this:

(Individuals Table)

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

(Legal Person's Table)

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

(CPF or CNPJ Documents Table)

[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 covers all 3 tables)

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

I do not know if this is correct or if there is an error, if you have, please point me out.

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

  • In this template, can I still use ModelState.IsValid to validate the Form Post? For if it only sends data of the Individual, the fields of Legal Person will be null, returned that the ModelState.IsValide is false. What is the best way to do this validation?

  • How do I, within a single action, in the case of ActionResult Create (ViewModelPersonas model), I first register in the Person table, get the auto-increment id generated for that document and be able to use it in when to save the specific data for the physical or legal person (document field)?

  • Thank you!

    ~ Added on 04/09/2017:

    I was able to solve it by verifying that the register that is being sent is of type PF or PJ, if it is PF then I clear the errors of the PJ field and vice versa.

    Do you consider this 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;
    }
    
        
    asked by anonymous 02.09.2017 / 01:50

    1 answer

    3
      

    In this model, I can still use ModelState.IsValid to   to validate the Form Post? For if he only send data from Person   Physics, the fields of Legal Person will be null, returned that the   ModelState.IsValide is false. What is the best way to do this?   validation?

    You can. And validate [Required] or individual or legal entity do not know DataAnnotations for this, you will need to do your own implementation and inherit ValidationAttribute for this, or do this validation in another location.

      

    How do I, within a single action, in this case ActionResult   Create (Model ViewModelPersonal), I first register in the table   Person, get the auto-increment id generated for this document register   and then use it when saving the specific data   of the physical or legal person (field document)?

    This is a Joined Mapping (Is the primary key of Person's Primary and Foreign Physics / Legal Key)? If it is and you have correctly configured the database, an insert will only suffice, it is not necessary to return the id.

    Even though, if you want to return the id and you use the 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; 
    
        
    02.09.2017 / 02:57