Reputation: 36800
Is there in Razor a way to print some HTML on the page while the value later known in the view?
For example: I would like to print the sum of an expensive calculation, and that sum should be before the items in the HTML. But with the example below, it will always print 0. I would like to calculate the sum only once.
I would like to solve this in the view, not in a csharp helper or on the client side (css, javascript etc)
@{
var sum = 0;
}
<table>
@* I would like to print here the sum which is known after the foreach loop*@
<tr><td>total: @sum</td></tr>
@foreach (var item in items)
{
<tr>
@{
var x= item.expensiveCalculation();
sum+= x;
}
//print item with x
<td>@x</td>
</tr>
}
</table>
edit: It is very important that the expensiveCalculation() is only calculated once for each item!
Upvotes: 0
Views: 1184
Reputation: 1039328
Your model is not adapted to the requirements of the view. Full stop.
So when your model is not adapted to the requirements of your view you go ahead and define a view model so that all the expensive operations are done inside the controller.
So:
public class ItemViewModel
{
public decimal Price { get; set; }
public string Name { get; set; }
}
Now your view becomes strongly typed to the view model and there are no longer expensive operations there:
@model IEnumerable<ItemViewModel>
<table>
<tr>
<td>
total: @Model.Sum(item => item.Price)
</td>
</tr>
@foreach (var item in Model)
{
<tr>
<td>@item.Name - @item.Price<td>
</tr>
}
</table>
and now inside your controller action prepare this view model and pass it to the view:
public class SomeAction()
{
IEnumerable<Item> items = ... go and fetch your domain models from wherever you are fetching them
// now let's build the view model
var model = new MyViewModel
{
Items = items.Select(x => new ItemViewModel
{
Name = x.Name,
Price = x.expensiveCalculation()
})
};
// and we are obviously passing the view model to the view, not the domain model
return View(model);
}
As you can see we are doing the expensive operations for each element inside the controller in order to bind it to the corresponding property of the view model (Price
) but we are no longer paying this expensive operations price inside the view as we are simply summing over the view model pre-calculated properties.
And next time when you encounter a problem in ASP.NET MVC don't forget that view models are the solution to your problem.
Upvotes: 4