I have a ViewModel with several properties (VM for multi-step wizard):
public class CallViewModel
{
[Key]
[Column(Order = 0)]
[HiddenInput(DisplayValue = false)]
public System.Guid CallID { get; set; }
[Required, Display(Name = "Call Date")]
[DataType(DataType.Date)]
[DisplayFormat(ApplyFormatInEditMode = true, DataFormatString = "{0:dd MM yyyy} г.")]
public System.DateTime CallDate { get; set; }
[Required, Display(Name = "Contract Number")]
public string Number { get; set; }
[Display(Name = "Date of Sampling"), DataType(DataType.Date)]
[DisplayFormat(ApplyFormatInEditMode = true, DataFormatString = "{0:dd MM yyyy} г.")]
public System.DateTime SampleActDate { get; set; }
[Display(Name = "Date of the Contract"), DataType(DataType.Date)]
[DisplayFormat(ApplyFormatInEditMode = true, DataFormatString = "{0:dd MM yyyy} г.")]
public System.DateTime ContractDate { get; set; }
[Required, Display(Name = "Cost Efficiency, %")]
public decimal CostEfficiency { get; set; }
[Required, Display(Name = "Document Type")]
public string CallName { get; set; }
//Representative
[Required, Display(Name = "Second Name")]
public string RepFamilyName { get; set; }
[Required, Display(Name = "First Name")]
public string RepFirstName { get; set; }
[Required, Display(Name = "Middle Name")]
public string RepMidName { get; set; }
[Required, Display(Name = "Position")]
public string RepPosition { get; set; }
[Required, Display(Name = "Document")]
public string DocType { get; set; }
[Required, Display(Name = "Phone (###) ###-##-##")]
[DisplayFormat(ApplyFormatInEditMode = true, DataFormatString = "{0:(###) ###-##-##}")]
public string RepPhoneNumber { get; set; }
//Customer
[Required, Display(Name = "Judicial Status")]
public string JudicialStatus { get; set; }
[Required, Display(Name = "Customer Name")]
public string CustomerName { get; set; }
[Required, Display(Name = "Address")]
public string CustomerAddress { get; set; }
[Required, Display(Name = "TaxID")]
public string TaxID { get; set; }
[Display(Name = "BIC")]
public string BIC { get; set; }
[Required, Display(Name = "PHone Number (###) ###-##-##")]
[DisplayFormat(ApplyFormatInEditMode = true, DataFormatString = "{0:(###) ###-##-##}")]
public string CustomerPhoneNumber { get; set; }
[Required, Display(Name = "OKPO")]
public int OKPO { get; set; }
[Required, Display(Name = "Account)]
public string CustomerBankAccount { get; set; }
[Required, Display(Name = "Bank Branch")]
public string BankBranch { get; set; }
[Required, Display(Name = "Bank Address")]
public string BranchAddress { get; set; }
[Display(Name = "Bank Code")]
public Nullable<int> BankCode { get; set; }
[Display(Name = "Cell Phone Number")]
public string MPhoneNumber { get; set; }
//Person
[Required, Display(Name = "Expert")]
//public string Exp { get; set; }
public Guid ExpID { get; set; }
[Required, Display(Name = "Affidavit Number")]
public int AffidavitNum { get; set; }
[Required, Display(Name = "Affidavit Date"),
DataType(DataType.Date)]
public System.DateTime AffidavitDate { get; set; }
public List<ItemClass> ItemsList { get { return _items; } }
private List<ItemClass> _items = new List<ItemClass>();
public class ItemClass
{ //Item
public Guid ItemID { get; set; }
[Required, Display(Name = "Item SubType")]
public Guid ItemSubtype { get; set; }
[Required, Display(Name = "Item Name")]
public string ItemName { get; set; }
[Required, Display(Name = "Producer")]
public string ItemProducer { get; set; }
[Required, Display(Name = "Quantity")]
public int ItemQty { get; set; }
[Display(Name = "Additionals")]
public string Additional { get; set; }
[Required, Display(Name = "Program Name")]
public string ProgramNameShort { get; set; }
[Required, Display(Name = "Calc Date")]
public string calcDate { get; set; }
[Required, Display(Name = "Calc Number")]
public string calcNum { get; set; }
}
}
I also have several entities with 1:n relationships, like
public partial class Call
{
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")]
public Call()
{
this.CallDetails = new HashSet<CallDetail>();
}
public System.Guid CallID { get; set; }
public System.DateTime CallDate { get; set; }
public System.Guid CustomerID { get; set; }
public string DocNumber { get; set; }
public int AffidavitNum { get; set; }
public System.DateTime AffidavitDate { get; set; }
public System.DateTime ContractDate { get; set; }
public int CallStatus { get; set; }
public string DocType { get; set; }
public Nullable<decimal> Cost_Efficiency { get; set; }
public System.DateTime SampleActDate { get; set; }
public string CallName { get; set; }
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
public virtual ICollection<CallDetail> CallDetails { get; set; }
public virtual Customer Customer { get; set; }
}
and
public partial class CallDetail
{
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")]
public CallDetail()
{
this.Orders = new HashSet<Order>();
}
public System.Guid CallID { get; set; }
public System.Guid ItemID { get; set; }
public int ItemQty { get; set; }
public decimal ItemTestCost { get; set; }
public System.Guid ProgramID { get; set; }
public virtual Call Call { get; set; }
public virtual Item Item { get; set; }
public virtual Program Program { get; set; }
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
public virtual ICollection<Order> Orders { get; set; }
}
to name a few.
In [HttpPost] public ActionResult Create (CallViewModel callViewModel)
method I should map the ViewModel to those entities. I know that Automapper is among the best ways to perform it, but still I need to understand the principles of correct mapping of VM and related entities (Automapper examples are welcome as well :) ), and especially how to deal with navigation properties (I'm mostly worried about ID properties). Could you please show the best (or template) practice to perform it? Please, be as detailed as possible.
Thanks in advance.
Take this example:
public class ModelClass
{
public Guid Id { get; set; }
public ChildModel ChildModel { get; set; }
}
public class ViewModelClass
{
public Guid Id { get; set; }
public ChildModel ChildModel { get; set; } = new ChildModel();
}
public class ChildModel
{
public Guid Id { get; set; }
}
If you want to map your viewmodel to your model you can do:
[HttpPost]
public ActionResult Create (CallViewModel callViewModel) {
var model = new ModelClass;
model.Id = callViewModel.Id;
model.ChildModel = callViewModel.ChildModel;
_context.Add(model);
_context.SaveChanges();
return RedirectToAction("Index");
}
For the use of automapper I suggest you read the AutoMapper docs :)