0

I've been searching all over the web to find an answer for such simple question, but I can't seem to find one.

Suppose we have a Product that has an edit page where we can set name, price and category.

Following the MVC(MVVM) pattern we have:

  • 2 models ProductModel and ProductCategoryModel
  • ViewModel that holds the product and the categories list (for the dropdown)
  • View to display the edit page

Beside the above we have the ProductService which handles the CRUD operations

// Model
public class ProductModel
{
    public int ProductId { get; set; }
    public string Name { get; set; }
    public decimal Price { get; set; }
    public int CategoryId { get; set; }
}

// Model
public class ProductCategoryModel
{
        public int CategoryId { get; set; }
        public string Name { get; set; }
}

// ViewModel
public class EditProductViewModel
{
    public ProductModel Product { get; set; }
    public List<ProductCategoryModel> Categories { get; set; }
}

The question is who is responsible for populating the ViewModel? I though it could be done in the constructor of the view model, however people say it is bad practice. Populating it in the controller also doesn't seems right.

jekcom
  • 2,065
  • 2
  • 24
  • 34
  • either inside the controller directly or in your model and called by controller – Steve Feb 06 '19 at 16:10
  • 4
    Normally the controller action creates and populates the instance of the view model to return to the view. This can be done with a view model constructor, an object initializer, etc. What exactly is the issue here? Why would anyone say that using a constructor is "bad practice" for contructing an instance of an object? – David Feb 06 '19 at 16:10
  • usually the controller layer. You could manually populate the view or use some kind of automation like AutoMapper. – Kim Lage Feb 06 '19 at 16:12
  • https://stackoverflow.com/questions/35959968/best-way-to-project-viewmodel-back-into-model – Kim Lage Feb 06 '19 at 16:14
  • Agreed, normally the controller action is responsible for assembling the viewmodel object (often by fetching data from one or more sources e.g. database, webservice, user input etc). Or at least, it is responsible for calling another method which will do the assembling, and passing the relevant parameters to that method. Certainly it's the responsibility of the controller action to make the constructing of the viewmodel happen, even if the code which does it is not directly within the action method. – ADyson Feb 06 '19 at 16:57
  • @David it is not about constructing an instance of an object - bad practice, it is about using a VM's constructor to populate itself, this will tightly couple it to the data source- making it aware of the business logic. While "good practice" says that the VM should be "dumb" as much as possible. I guess some View model builder is the way to go? – jekcom Feb 07 '19 at 09:45
  • @jekcom: That’s not clear in the question. Note that the code you’re showing us has no constructors at all. Show an example of what you’re asking so this isn’t a guessing game. – David Feb 07 '19 at 11:31
  • @David no reason to be upset. There is only one question and it is conceptual question. It does not require code to answer it (The code i provided is just to illustrate the situation). You asked "Why would anyone say that using a constructor is "bad practice"" i gave you an answer. – jekcom Feb 07 '19 at 12:43
  • If provided answer has helped, etiquette is to mark this as "the answer" and probably upvote its usefulness. This prevents this question coming up under "show unanswered questions" in SOF and also gives some more reputation to the person who helped you. – Alex Leo Mar 02 '19 at 14:57

1 Answers1

0

You will map your EditProductViewModel from your ProductModel/ProductCategoryModel in the page controller. You can then call your action to render your html page and pass your viewModel object.

Something like this :

public class HomeController : Controller
{

    private EditProductViewModel viewModel;

    public HomeController()
    {
        this.viewModel = new EditProductViewModel();
        InitialiseViewModel();
    }

    public ActionResult Index()
    {

        return View("Index", viewModel);
    }

    private void InitialiseViewModel()
    {
        ProductCategoryModel productCategoryModel = new ProductCategoryModel();
        ProductModel productModel = new ProductModel();

        //do your mapping 
        productModel.Name = "Test mapping";
        this.viewModel.Product = productModel;
    }
}

Your .cshtml will look like this

@model WebApplication5.ViewModels.EditProductViewModel

<div class="jumbotron">
    <h1>ASP.NET</h1>
    <p>@Model.Product.Name</p>
    <p class="lead">ASP.NET is a free web framework for building great Web sites and Web applications using HTML, CSS and JavaScript.</p>
    <p><a href="https://asp.net" class="btn btn-primary btn-lg">Learn more &raquo;</a></p>
</div>
Alex Leo
  • 2,781
  • 2
  • 13
  • 29