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