I have an Item
that contains a list of Product
's which are mapped to their respective ViewModel
objects using AutoMapper.
In my MVC project I have an Action method that displays an Item
with a selected Product
. For this i have a ViewModel
called ItemDetailsViewModel
that contains the flattened Item
object, a list of ProductViewModel
's and a flattened selected Product
.
The difficulty I am having is best showing this flattened selected Product
.
Think of it like eBay where you have an Item
and you can choose multiple variations e.g. by colour. For me, the multiple variations are the Products
. When the user selects the Product
I want to return the ItemDetails
i.e. the Item
, the list of Products
and the selected Product
.
I was wondering the best way of doing this? At the moment my method is mapping an Item
to an ItemDetailsViewModel
, selecting the desired ProductViewModel
and then specifically mapping each property of the ProductViewModel
back onto the ItemDetailsViewModel
. Also, due to the Item
and Product
having the same named properties, the last line mapping the product back overwrites the Item
s id and code.
Any suggestions on how best to configure the mapping?
I've left out the mapping I have in place as it is mostly a direct one-to-one mapping apart from mapping the selected ProductViewModel
back to the ItemDetailsViewModel
.
Mapper.CreateMap<Item, ItemViewModel>()
.ReverseMap();
Mapper.CreateMap<ProductViewModel, ItemDetailsViewModel>()
.ForMember(d => d.ProductId, o => o.MapFrom(s => s.Id))
.ForMember(d => d.ProductCode, o => o.MapFrom(s => s.Code));
Classes
public class Item
{
public int Id { get; set; }
public string Code { get; set; }
public IList<Product> Products { get; set; }
}
public class Product
{
public int Id { get; set; }
public string Code { get; set; }
}
public class ItemViewModel
{
public int Id { get; set; }
public string Code { get; set; }
public IList<ProductViewModel> Products { get; set; }
}
public class ItemDetailsViewModel : ItemViewModel
{
public int ProductId;
public string ProductCode;
}
public class ProductViewModel
{
public int Id { get; set; }
public string Code { get; set; }
}
Action
public ActionResult ItemDetails()
{
var item = new Item
{
Id = 1,
Code = "Item1",
Products = new List<Product>()
{
new Product { Id = 1, Code = "Product1" },
new Product { Id = 2, Code = "Product2" },
new Product { Id = 3, Code = "Product3" },
}
};
var productCode = "Product2";
var itemDetailsViewModel = Mapper.Map<ItemDetailsViewModel>(item);
if (itemDetailsViewModel.Products != null && itemDetailsViewModel.Products.Count > 0)
{
ProductViewModel productViewModel = null;
if (!String.IsNullOrEmpty(productCode))
productViewModel = itemViewModel.Products.FirstOrDefault(e => e.Code.Equals(productCode, StringComparison.OrdinalIgnoreCase));
if (productViewModel == null)
productViewModel = itemViewModel.Products[0];
Mapper.Map<ProductViewModel, ItemDetailsViewModel>(productViewModel, itemDetailsViewModel);
}
}
One solution would be to ignore the properties in ItemDetailsViewModel
in your mapping from ProductViewModel
to ItemDetailsViewModel
:
Mapper.CreateMap<ProductViewModel, ItemDetailsViewModel>()
.ForMember(d => d.Id, opt => opt.Ignore())
.ForMember(d => d.Code, opt => opt.Ignore())
.ForMember(d => d.ProductId, o => o.MapFrom(s => s.Id))
.ForMember(d => d.ProductCode, o => o.MapFrom(s => s.Code));