What is a Model
- Parts of the application that implement the domain logic.
- also known as business logic.
- Domain logic handles the data that is passed between the database and the UI.
- As an example, in an inventory system, the model keeps track of the items in storage and the logic to determine whether an item is in stock.
- In addition, the model would be the part of the application that updates the database,when an item is sold and shipped out of the warehouse.
- Often, the model also stores and retrieves model state in a database.
What is a ViewModel
- Allow you to shape multiple entities from one or more data models or sources into a single object.
- Optimized for consumption and rendering by the view.
It shows below image
Why We Use ViewModel
- If you need to pass more than one thing to a strongly-typed view (which is best practice),
you will generally want to create a separate class to do so.
- This allows you to validate your ViewModel differently than your domain model for
attribute-based validation scenarios
- Can be used to help shape and format data.
e.g: need a date or money value formatted a particular way?
ViewModel is the best place to do it.
- The use of a ViewModel can make the interaction between model and view more simple
ViewModel Interaction with Model and View
Where Should We Create ViewModel (physically)
- In a folder called ViewModels that resides in the root of the project. (small applications)
- As a .dll referenced from the MVC project (any size applications)
- In a separate project(s) as a service layer, for large applications that generate
view/content specific data. (enterprise applications)
Best Practices When Using ViewModels
- Put only data that you’ll render (use in View) in the ViewModel
- The View should direct the properties of the ViewModel, this way it fits better for rendering
and maintenance
- Use a Mapper when ViewModels become Complex (i.e. How to Use ValueInjecter ?)
Let’s Try with Simple Example
- Asp.net MVC 5,C# and Visual Studio 2013 express has been used.
- Please follow an In-line Comments on Code.
- This is a simple application with product category drop down list, product name text box and Save button.
Sample Project’s Solution Tree
Domain Models
Product.cs
public class Product
{
public Product() { Id = Guid.NewGuid(); }
public Guid Id { get; set; }
public string ProductName { get; set; }
public virtual ProductCategory ProductCategory { get; set; }
}
ProductCategory.cs
public class ProductCategory
{
public int Id { get; set; }
public string CategoryName { get; set; }
public virtual ICollection<Product> Products { get; set; }
}
ViewModel
ProductViewModel.cs
public class ProductViewModel
{
public Guid Id { get; set; }
[Required(ErrorMessage = “required”)]
public string ProductName { get; set; }
public int SelectedValue { get; set; }
public virtual ProductCategory ProductCategory { get; set; }
[DisplayName(“Product Category”)]
public virtual ICollection<ProductCategory> ProductCategories { get; set; }
}
Controller Action Methods
/// <summary>
/// to generate view with categories for entering product data
/// </summary>
[HttpGet]
public ActionResult AddProduct()
{
//instantiate the product repository
var productRepository = new ProductRepository();
//for get product categories from database
var prodcutCategories = productRepository.GetAllProductCategories();
//for initialize viewmodel
var productViewModel = new ProductViewModel();
//assign values for viewmodel
productViewModel.ProductCategories = prodcutCategories;
//send viewmodel into UI (View)
return View(“AddProduct”, productViewModel);
}
/// <summary>
/// to save entered data
/// </summary>
[HttpPost]
public ActionResult AddProduct(ProductViewModel productViewModel) //save entered data
{
//instantiate the product repository
var productRepository = new ProductRepository();
//get product category for selected drop down list value
var prodcutCategory=productRepository.GetProductCategory(productViewModel.SelectedValue);
//for get all product categories
var prodcutCategories = productRepository.GetAllProductCategories();
//for fill the drop down list when validation fails
productViewModel.ProductCategories = prodcutCategories;
//for initialize Product domain model
var productObj = new Product
{
ProductName = productViewModel.ProductName,
ProductCategory = prodcutCategory,
};
if (ModelState.IsValid) //check for any validation errors
{
//code to save valid data into database
return RedirectToAction(“AddProduct”);
}
else
{
//when validation failed return viewmodel back to UI (View)
return View(productViewModel);
}
}
View
AddProduct.cshtml
@model ASPViewModel.ViewModels.ProductViewModel //set your ViewModel here
@using (Html.BeginForm())
{
Html.EnableClientValidation(true);
-
@Html.LabelFor(m => m.ProductCategories)
@Html.DropDownListFor(m => m.SelectedValue,
new SelectList(Model.ProductCategories, “Id”,”CategoryName”), “-Please select a category-“)@Html.ValidationMessageFor(m => m.ProductCategory.Id)
-
@Html.LabelFor(m => m.ProductName)
@Html.EditorFor(m => m.ProductName)
@Html.ValidationMessageFor(m => m.ProductName)
Save
}
</div>
Repository Methods by using the Entity Framework
ProductRepository.cs
public class ProductRepository
{
/// <summary>
/// to get product category
/// </summary>
public ProductCategory GetProductCategory(int categoryId)
{
var productCategoryList = GetAllProductCategoriesMockDatas();
return (from p in productCategoryList
where (p.Id == categoryId)
select p).FirstOrDefault();
}
/// <summary>
/// to get all product categories
/// </summary>
/// <returns></returns>
public List<ProductCategory> GetAllProductCategories()
{
var productCategoryList = GetAllProductCategoriesMockDatas();
return (from p in productCategoryList
select p)
.OrderBy(p => p.CategoryName)
.ToList();
}
/// <summary>
/// to Get All Product Categories mock datas
/// </summary>
private List<ProductCategory> GetAllProductCategoriesMockDatas()
{
var productCategoryList = new List<ProductCategory>();
productCategoryList.Add(new ProductCategory
{
Id = 1,
CategoryName = “Foods”,
});
productCategoryList.Add(new ProductCategory
{
Id = 2,
CategoryName = “Toys”,
});
productCategoryList.Add(new ProductCategory
{
Id = 3,
CategoryName = “Mobile Phones”,
});
return productCategoryList;
}
}
Conclusion
- ViewModels help you organize and manage data in MVC applications when you need to work with more complex data than the other objects allow.
- Using ViewModels gives you the flexibility to use data as you see fit.
- ViewModels are generally a more flexible way to access multiple data sources than domain models.
- Even for simple scenarios always try to use ViewModel approach to maintain consistency in Your coding practices.