Passing DTO to my ViewModels constructor to map properties

architecture asp.net-mvc c# dapper

Question

In my solution I have two projects.

Project 1 (Core) Mapping SQL to DTO using Dapper

Project 2 (WebUI - ASP.NET MVC 4) Here I use a ViewModel per View.

Examples of a Controller

  [HttpGet]
    public ActionResult Edit(int id)
    {
        // Get my ProductDto in Core
        var product = Using<ProductService>().Single(id);
        var vm = new ProductFormModel(product);

        return View(vm);
    }

Examples of a ViewModel

public class ProductFormModel : BaseViewModel, ICreateProductCommand
    {
        public int ProductId { get; set; }
        public int ProductGroupId { get; set; }
        public string ArtNo { get; set; }
        public bool IsDefault { get; set; }
        public string Description { get; set; }
        public string Specification { get; set; }
        public string Unit { get; set; }
        public string Account { get; set; }
        public decimal NetPrice { get; set; }

        public ProductFormModel(int productGroupId)
        {
            this.ProductGroupId = productGroupId;
        }

        public ProductFormModel(ProductDto dto)
        {
            this.ProductId = dto.ProductId;
            this.ProductGroupId = dto.ProductGroupId;
            this.ArtNo = dto.ArtNo;
            this.IsDefault = dto.IsDefault;
            this.Description = dto.Description;
            this.Specification = dto.Specification;
            this.Unit = dto.Unit;
            this.Account = dto.Account;
            this.NetPrice = dto.NetPrice;
        }

        public ProductFormModel()
        {
        }
    }

Explanation: I'll get my DTOs in my controller using a service class in the project (Core). Then i create my ViewModel and pass the DTO to the constructor in ViewModel. I can also use this view to add a new Product because my ViewModel can take a empty constructor.

Does anyone have experience of this. I wonder if I am in this way will have problems in the future as the project gets bigger?

I know this has nothing to do with Dapper. But I would still like a good way to explain my solution.

Accepted Answer

I think you will be fine using your current approach. More importantly, start out like this and refactor if you start to encounter problems related to your object mapping code (instead of thinking too much about it beforehand).

Another way to organize mapping logic that I use sometimes is to employ extension methods. That way, the mapping code is kept separate from the view model itself. Something like:

public static class ProductMappingExtensions
{
    public static ProductFormModel ToViewModel(this ProductDto dto)
    {
        // Mapping code goes here
    }
}

// Usage:

var viewModel = dto.ToViewModel();

Yet another approach would be to use a mapping framework like AutoMapper - this is a good fit in particular if your mapping logic is simple (lots of 1:1 mappings between properties).

But again, start simple and refactor when you need to.


Popular Answer

I realize that this is a little bit late answer, but maybe it will help someone in the future.

This way of doing mapping between objects breaks the 'S' of the SOLID principles, because the responsibility of the ViewModel is to prepare data in its properties to be ready to use by the view and nothing else, therefore, mapping objects should not be on it's responsibilities.

Another drawback of this way is that it also breaks the 'Loose Coupling' OO principle as you ViewModel is strongly coupled with your DTO.

I think, even when we are in the very first step of the project, there are some importants OO principles that we should never break, so using mapper classes, either auto (AutoMapper, ValueInjecter ...) or manual, is definitely better.



Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Is this KB legal? Yes, learn why
Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Is this KB legal? Yes, learn why