Suppose we want to display how many Purchases a fabric has. If the View needs to know all this information, including the number of Purchases, then the model that we build for the View should include the number of Purchases with it. We need to do a Projection, a transformation, pass a new object that includes all the information we need for the view.
Step 1: In the Index action of the Home Controller, create an anonymous object.
var model =
from f in _db.Fabrics
orderby f.ItemsSold
select new
{
f.FabricId,
f.Name,
f.MainCategory,
f.SubCategory1,
f.SubCategory2,
f.ImagePath,
f.Location,
f.Type,
f.Weight,
f.Content,
f.Design,
f.CurrentAmount,
f.Source,
f.Notes,
f.Tags,
f.ItemsSold,
NumberOfPurchases = f.Purchases.Count()
};
return View(model);
There is a problem. Since it is an anonymous object, we don't know its name. What would we use a strongly typed model to reference in the View? What we need to do instead is create a new model.
Step 2: In the models folder, create a class called FabricListViewModel.cs. And give it the properties that we need, the ones we created in the anonymous object.
public class FabricListViewModel
{
public int FabricId { get; set; }
public string MainCategory { get; set; }
public string SubCategory1 { get; set; }
public string SubCategory2 { get; set; }
public string Name { get; set; }
public string ImagePath { get; set; }
public string Location { get; set; }
public string Type { get; set; }
public string Weight { get; set; }
public string Content { get; set; }
public string Design { get; set; }
public int CurrentAmount { get; set; }
public string Source { get; set; }
public string Notes { get; set; }
public List<string> Tags { get; set; }
public int ItemsSold { get; set; }
public int PurchaseCount { get; set; }
}
Step 3: Now use this class, FabricListViewModel, when building your model in the Index action of the HomeController and change the properties to variables as follows:
var model =
from f in _db.Fabrics
orderby f.ItemsSold
select new FabricListViewModel
{
FabricId = f.FabricId,
Name = f.Name,
MainCategory = f.MainCategory,
SubCategory1 = f.SubCategory1,
SubCategory2 = f.SubCategory2,
ImagePath = f.ImagePath,
Location = f.Location,
Type = f.Type,
Weight = f.Weight,
Content = f.Content,
Design = f.Design,
CurrentAmount = f.CurrentAmount,
Source = f.Source,
Notes = f.Notes,
ItemsSold = f.ItemsSold,
PurchaseCount = f.Purchases.Count()
};
return View(model);
Step 4: Copy class name, FabricListViewModel, and open up the View for the Index action on Home. (Views folder > Home > Index.cshtml). Add PurchaseCount to the View to display number of Purchases for each fabric in the List. Don't forget to change the model directive to point to FabricListViewModel!
@model IEnumerable<MyFabricStashApp.Models.FabricListViewModel>
@foreach (var item in Model)
{
<div class="media">
<div class="media-left">
<a href="#">
<img class="media-object"
src="@item.ImagePath" alt="" />
</a>
</div>
<div class="media-body">
<h4 class="media-heading">@item.MainCategory / @item.SubCategory1 / @item.SubCategory2</h4>
Name: @item.Name<br />
Amount Remaining: @item.CurrentAmount inches<br />
Item Location: @item.Location<br />
Items Sold to Date: <span style="color: red; font-weight: bold">@item.ItemsSold</span><br />
Purchases: @item.PurchaseCount
</div>
<hr />
</div>
}
Automapper.org - copies data from one object to another.
Step 4b (Optional): Use Extension method syntax for query instead of Comprehension query syntax:
var model = _db.Fabrics
.OrderByDescending(f => f.ItemsSold)
.Select(f => new FabricListViewModel
{
FabricId = f.FabricId,
Name = f.Name,
MainCategory = f.MainCategory,
SubCategory1 = f.SubCategory1,
SubCategory2 = f.SubCategory2,
ImagePath = f.ImagePath,
Location = f.Location,
Type = f.Type,
Weight = f.Weight,
Content = f.Content,
Design = f.Design,
CurrentAmount = f.CurrentAmount,
Source = f.Source,
Notes = f.Notes,
ItemsSold = f.ItemsSold,
PurchaseCount = f.Purchases.Count()
});
Some operators like Take() and Skip() can only be used in the Extension Method syntax.