I have a View called 'Assets/Index' in my MVC (.NET 5) app, where I show a list of the Assets in the assets table. The page is modelled on IList<Asset>
, i.e., @model IList<Asset>
. I was suggested by my peers to make a ViewModel for that View, but is a ViewModel really necessary in this case? I mean the only advantage that I see is, it'll be easy to add another property (if ever required in the future) to the page, as I would in that case definitely need a ViewModel. But, as the sole purpose of the page is to display a list of Assets (and I am pretty sure it won't be required to add properties to that hypothetical ViewModel ever in the future), I am confused whether to follow my instinct or the suggestions of peers.
The View:
@using AdminPortal.Models;
@model IReadOnlyList<Asset>
@{
ViewData["Title"] = "List";
}
@{ await Html.RenderPartialAsync("../Partials/SearchPartial", "AssetsController"); }
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"></script>
<script type="text/javascript">
document.getElementById('list-btn').hidden = true;
</script>
<p>
<a asp-action="Create" class="btn-link">Create New</a>
</p>
<table class="table">
<thead class="thead-light">
<tr>
<th>@Html.DisplayNameFor(model => model.First().Id)</th>
<th>@Html.DisplayNameFor(model => model.First().Address)</th>
<th>@Html.DisplayNameFor(model => model.First().State)</th>
<th>@Html.DisplayNameFor(model => model.First().Temperature)</th>
<th>@Html.DisplayNameFor(model => model.First().Moisture)</th>
<th>@Html.DisplayNameFor(model => model.First().Alerts)</th>
<th>@Html.DisplayNameFor(model => model.First().LastServiced)</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
@foreach (var asset in Model)
{
<tr>
@if (asset.State != AssetState.deleted)
{
<td>
<a asp-action="Index" asp-controller="Home"
asp-route-id="@asset.Id">@Html.DisplayFor(item => asset.Id)</a>
</td>
}
else
{
<td>
<a>@Html.DisplayFor(item => asset.Id)</a>
</td>
}
<td>@Html.DisplayFor(item => asset.Address)</td>
<td>
@if (asset.State != AssetState.deleted)
{
var IdName = "assetStateDropdown" + asset.Id;
<select class="dropdown" id="@IdName">
<option class="dropdown-item dropdown-item-text"
value="@AssetState.functional">
functional
</option>
<option class="dropdown-item dropdown-item-text"
value="@AssetState.non_functional">
non-functional
</option>
<option class="dropdown-item dropdown-item-text"
value="@AssetState.under_maintenance">
under-maintenance
</option>
</select>
<script type="text/javascript">
//change the state of the asset from the dropdown
$(function () {
$("#@IdName").change(function () {
$.ajax({
type: "POST",
url: "/Assets/UpdateState",
data: {
"state": $("#@IdName").val(),
"id": '@asset.Id'
},
success: function (response) {
alert("State Changed");
},
failure: function (response) {
alert("Could not Change state");
},
error: function (response) {
alert("Some error occurred. Try again later");
}
});
});
});
</script>
<script type="text/javascript">
//set the value of the asset state drop down to the current state
document.getElementById('@IdName').value = '@asset.State';
</script>
}
else
{
<p>deleted</p>
}
</td>
<td>@Html.DisplayFor(item => asset.Temperature)</td>
<td>@Html.DisplayFor(item => asset.Moisture)</td>
<td>
<a asp-action="Index" asp-controller="Alerts"
asp-route-id="@asset.Id">@Html.DisplayFor(item => asset.Alerts.Count)</a>
</td>
<td>@Html.DisplayFor(item => asset.LastServiced)</td>
@if (asset.State != AssetState.deleted)
{
<td>
<a asp-action="Delete" asp-route-id="@asset.Id" class="btn-link" style="color: darkred">Decommission</a>
</td>
}
</tr>
}
</tbody>
</table>
The suggested ViewModel:
public class IndexViewModel
{
public IReadOnlyList<Asset> Assets { get; set; }
}
Succinctness for simplicity and fewer files, vs verbosity for easier extendability.
I've seen projects with tons of unnecessary ViewModels that cluttered up space, but then also been in projects where adding an extra boolean flag or title element was made much harder by the lack of ViewModels.
A case can be made either way, in the end it is down to the preference or coding styles decided by your team, and matching the consistency of the rest of the project. If people are expecting models to be in a certain place, it may be jarring when they are not there, but if ViewModels are optional in that codebase then it would be more acceptable.
You never know future requirements, perhaps some associated user information, functions, or extensions may be required. Even without extensibility, if the rest of the codebase is set up with view models for every page, then a dev reading the codebase will come to expect that layout, so for your one page to omit the ViewModel because it is quite simple could actually end up being less readable due to inconsistencies.