views:

35

answers:

1

I'd like to be able to map a domain model to a view model by newing up a view model and passing in the contributing domain model as a parameter (like the code below). My motivation is to keep from re-using mapping code AND to provide a simple way to map (not using automapper yet). A friend says the view model should not know anything about the "payment" domain model that's being passed into the optional constructor. What do you think?

public class LineItemsViewModel
{
    public LineItemsViewModel()
    {
    }

    public LineItemsViewModel(IPayment payment)
    {
        LineItemColumnHeaders = payment.MerchantContext.Profile.UiPreferences.LineItemColumnHeaders;
        LineItems = LineItemDomainToViewModelMapper.MapToViewModel(payment.LineItems);
        ConvenienceFeeAmount = payment.ConvenienceFee.Fee;
        SubTotal = payment.PaymentAmount;
        Total = payment.PaymentAmount + payment.ConvenienceFee.Fee;
    }

    public IEnumerable<Dictionary<int, string>> LineItems { get; set; }
    public Dictionary<int, string> LineItemColumnHeaders { get; set; }
    public decimal SubTotal { get; set; }
    public decimal ConvenienceFeeAmount { get; set; }
    public decimal Total { get; set; }
}
+2  A: 

Your friend is right. Views should be dumb and not know anything about your domain model.

Have you tried using Automapper to map your business/domain entities/models to your dto/viewmodels?

More details because of comment:

Putting mapping code in your viewmodels violates the separation of concern, the SOLID single responsibility principal, the MVC pattern, and domain driven design principals. Views have one responsibility, get data to the screen, thats it. IMHO there isn't much to argue about. Its simply a bad idea that violates a lot of core software development principals.

jfar
I appreciate the answer. I want to argue to draw out the most complete answer. I'm talking about the view model, and a constructor on the view model class at that. Can you give a reason (or more) why a view model object should not do its own mapping (via method or constructor).
Byron Sommardahl
@Byron I let my DTOs do the mapping internally as an implicit cast from a domain object. Sometimes I use the DTOs as a view model and sometimes I combine mutiple DTOs into a composite VM. (I know this probably isn't going to be popular!) I used to use Automapper but I've come across enough complex scenarios that it's just as fast to write them manually; plus it keeps the projection logic with the DTO/VM. What you choose depends on your scenario.
Ryan
While the mapping code does have to exist somewhere, placing it inside of the view model constructor couples it to the internal structure of the domain. If for some reason you needed to populate the view model from another source, you'd end up adding another constructor to do so with this method.Coupling aside, jfar is right that it simply boils down to a separation of concerns issue. While putting the mapping code there might feel like a convenient thing to do, why should the view model care where the data comes from?
Derek Greer