问题
I have an application with a Company model. The Company model has a navigation property to an Address model (one-to-one relationship):
Company.cs
public class Company
{
public int CompanyID { get; set; }
public string Name { get; set; }
// Snip...
public virtual Address Address { get; set; }
}
I've created a view model to handle the edit, detail, and create actions:
CompanyViewModel.cs
public class CompanyViewModel
{
public int CompanyID { get; set; }
[Required]
[StringLength(75, ErrorMessage = "Company Name cannot exceed 75 characters")]
public string Name { get; set; }
// Snip...
public Address Address { get; set; }
}
I'm using AutoMapper in my controller to map back and forth between the model and view model, and everything is working properly. However, I now want to use validation on the address object - I do not want a company to be created without an address being present.
My first thought was the simple route - I tried putting a '[Required]' annotation on the Address property. This didn't do anything.
I then thought it would be better to do away with the Address property and abstract that data in the view model, so I added properties to the view model for all the properties in my Address class:
public string Address1 { get; set; }
public string Address2 { get; set; }
public string City { get; set; }
public string PostalCode { get; set; }
// etc....
This seemed like good practice, but now my AutoMapper can't map these properties to the Company class' Address object, so I had to manually map in the controller:
public ActionResult Details(int id = 0)
{
// Snip code retrieving company from DB
CompanyViewModel viewModel = new CompanyViewModel();
viewModel.Name = company.Name;
viewModel.Address1 = company.Address.Address1;
// Snip...
return View(viewModel);
}
This leads to a lot of extra code in my controller instead of a nice one-line AutoMapper statement...so what's the right way to deal with this (validation of nested models in a view model)?
Is it good practice to expose the Address property directly in the view model, or better to abstract it out with separate properties like I have done?
Can AutoMapper work in a situation where source and destination are not exact matches?
回答1:
if you want automapper to be able to map your properties from model to your viewmodel without specifying the mappings explicitly, you've got to use the "flattenting convention" : means that you must concatenate the navigation property's name with its property names.
So your ViewModel should contain
public int CompanyID { get; set; }
[Required]
[StringLength(75, ErrorMessage = "Company Name cannot exceed 75 characters")]
public string Name { get; set; }
// Snip...
//Address is the navigation property in Company, Address1 is the desired property from Address
public string AddressAddress1 { get; set; }
public string AddressAddress2 { get; set; }
public string AddressCity { get; set; }
public string AddressPostalCode { get; set; }
}
by the way, you can also tell AutoMapper to map properties which don't respect the naming convention explicitly :
Mapper.CreateMap<Company, CompanyViewModel>()
.ForMember(dest => dest.Address1, opt => opt.MapFrom(src => src.Address.Address1));
来源:https://stackoverflow.com/questions/19162593/validation-of-nested-models-in-view-model-in-asp-net-mvc