asp mvc list product details in view using View Model

12,668

Viewmodels are indeed the way to go here. I won't elaborate on what viewmodels are as you already have some declared in your code so I'm assuming you already know their purpose and functionality. However—for the sake of completeness—viewmodels represent only the data that you want displayed in your view; assuming a view displaying the first and last name of an employee, there's no reason to send back an Employee object when you only really need two of it's properties.

As per the short viewmodel definition provided above, to return a viewmodel instead of attaching the returned object on ViewBag, you simply create a class which will only hold the data that you want presented in the view. So, based on your "expected output in view", your viewmodel would look similar to this:

public class YourViewModel 
{
    public string Title { get; set; }
    public string SmallDescription { get; set; }
    public string FullDescription { get; set; }
    public string MobileName { get; set; }
    public int ModelYear { get; set; }
    public decimal Price { get; set; }
    public string Color { get; set; }
}

Once you have your viewmodel instantiated and populated, pass it to the view:

var yourViewModel = new YourViewModel();
//populate it and pass it to the view
return View(yourViewModel);

On the top part of your view, declare your @model variable to be of type YourViewModel:

@model YourViewModel

..and you're good to go. So if you wanted to print out the mobile name in the view:

@Model.MobileName

Bear in mind that while you can only have one @model per view, you can still have multiple viewmodels. This is possible by creating a parent viewmodel to hold all the view-related viewmodels and setting that as the @model instead:

public class ParentViewModel
{
    //all the viewmodels which are relevant to your view
    public DetailsViewModel DetailsViewModel { get; set; }
    public YourViewModel YourViewModel { get; set; }
    //...etc        
}

Once you have your viewmodel instantiated and populated, pass it to the view:

var parentViewModel = new ParentViewModel();
var yourViewModel = new YourViewModel();
//populate it and attach it to the parent viewmodel
parentViewModel.YourViewModel = yourViewModel;
return View(parentViewModel);

This time, on the top part of your view, declare your @model variable to be of type ParentViewModel instead:

@model ParentViewModel

..and you're good to go. Using the same example, if you wanted to print out the mobile name in the view:

@Model.YourViewModel.MobileName

Bear in mind that I haven't really given much attention to how you have structured your viewmodels, but rather explained how to pass one (or more) viewmodels back to your view and use those instead of ViewBag (as per your question). For how your viewmodels should be actually populated and look like, Stephen Muecke's answer is the way to go.

Share:
12,668
Shaiju T
Author by

Shaiju T

Hi, :) I am a Full stack .NET Developer , I use tech stack like C#, Asp.Net Mvc , SQL Server , Mongo DB, Azure,JavaScript libraries , Twitter Bootstrap etc to deliver dynamic and speedy web apps. Always eager to learn new technologies. I am here @SO to help, ask and eventually learn. I am also in .to community. Some Cool Site's to check! 20 things i learned about browsers & the web. - Book published by Google Inc. 24ways to impress your friends using web design and development goodness.

Updated on July 04, 2022

Comments

  • Shaiju T
    Shaiju T almost 2 years

    I am trying to list single product details in a view. The product specification changes dynamically because specifications are added row-wise in table, which means we can add huge number of specifications for each product (as done in ecommerce sites). Right now I am able to meet the requirement using ViewBag, but I am deciding to use ViewModel as a better practice.

    Model class:

    // Product:
    public partial class ProductTable
    {
        public ProductTable()
        {
            this.SpecificationsTable = new HashSet<SpecificationsTable>();
        }
    
        public int ProductID { get; set; }
        public string Title { get; set; }
        public string SmallDescription { get; set; }
        public string FullDescription { get; set; }
    
        public virtual ICollection<SpecificationsTable> SpecificationsTable { get; set; }
        }
    
    //Specifications:
    public partial class SpecificationsTable
    {
        public int SpecificationsID { get; set; }
        public string SpecificationName { get; set; }
        public string SpecificationValue { get; set; }
        public Nullable<int> ProductID { get; set; }
        public virtual ProductTable ProductTable { get; set; }
    }
    

    ViewModel:

    public class DetailsViewModel
    {
        public int ProductID { get; set; }
        public string Title { get; set; }
        public string SmallDescription { get; set; }
        public string FullDescription { get; set; }
        public string SpecificationName { get; set; }
        public string SpecificationValue { get; set; }
    }
    

    ActionMethod

    public ActionResult ProductDetails(int id)
    {
        var details = (from c in dbo.ProductTable
                       join s in dbo.SpecificationsTable 
                       on c.ProductID equals s.ProductID
                       where c.ProductID == id
                       select new DetailViewModel
                       {
                           Title = c.Title,
                           SmallDescription = c.SmallDescription,
                           FullDescription = c.FullDescription
                       }).ToList();
    
         // To remove repeated product title , small and full description
         var distinctItems = details.GroupBy(x => x.ProductID).Select(y => y.First());
    
         // To show product title, small and full description for this product
    
         ViewBag.ProductDetails = distinctItems;
    
         var specifications = (from c in dbo.ProductTable
                                 join s in dbo.SpecificationsTable 
                                 on c.ProductID equals s.ProductID
                                 where c.ProductID == id
                                 select new DetailViewModel
                                 {
                                     SpecificationName = s.SpecificationName,
                                     SpecificationValue = s.SpecificationValue
                                 }).ToList();
    
        // To show list of specifications for this product
        ViewBag.Specifcations = specifications;
        return View();
    }
    

    expected output in view:

    Details:

    Title: New Samsung offer
    
    SmallDescription : Something small 
    
    FullDescription : Something full
    

    Specifcations:

    Mobile Name :Samsung
    
    Model : 2015
    
    Price : 70 $
    
    Color:  White
    

    I am using database first method and I am trying to learn how we can use view model here.