如果其中只有一个 属性,ViewModel 真的有必要吗?
Is a ViewModel really necessary if there's going to be only one property in it?
我的 MVC (.NET 5) 应用程序中有一个名为 'Assets/Index' 的视图,我在其中显示资产 table 中的资产列表。该页面仿照 IList<Asset>
,即 @model IList<Asset>
。我的同事建议我为那个视图制作一个 ViewModel,但在这种情况下真的有必要使用 ViewModel 吗?我的意思是,我看到的唯一优势是,可以很容易地向页面添加另一个 属性(如果将来需要的话),因为在那种情况下我肯定需要一个 ViewModel。但是,由于该页面的唯一目的是显示资产列表(而且我很确定将来不需要向该假设的 ViewModel 添加属性),我很困惑是跟随我的直觉还是同行的建议。
观点:
@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>
建议的 ViewModel:
public class IndexViewModel
{
public IReadOnlyList<Asset> Assets { get; set; }
}
简洁是为了简单和更少的文件,而冗长是为了更容易扩展。
我见过有大量不必要的 ViewModel 的项目,这些 ViewModel 变得杂乱无章 space,但后来也出现过一些项目,由于缺少 ViewModel,添加额外的布尔标志或标题元素变得更加困难。
案例可以采用任何一种方式,最终取决于您的团队决定的偏好或编码风格,并与项目其余部分的一致性相匹配。如果人们期望模型在某个地方,当它们不在那里时可能会令人不快,但如果 ViewModels 在该代码库中是可选的,那么它会更容易接受。
您永远不知道未来的需求,也许可能需要一些相关的用户信息、功能或扩展。即使没有可扩展性,如果代码库的其余部分都为每个页面设置了视图模型,那么阅读代码库的开发人员就会期望该布局,因此对于您的一页省略 ViewModel 因为它非常简单实际上可能会结束由于不一致导致可读性降低。
我的 MVC (.NET 5) 应用程序中有一个名为 'Assets/Index' 的视图,我在其中显示资产 table 中的资产列表。该页面仿照 IList<Asset>
,即 @model IList<Asset>
。我的同事建议我为那个视图制作一个 ViewModel,但在这种情况下真的有必要使用 ViewModel 吗?我的意思是,我看到的唯一优势是,可以很容易地向页面添加另一个 属性(如果将来需要的话),因为在那种情况下我肯定需要一个 ViewModel。但是,由于该页面的唯一目的是显示资产列表(而且我很确定将来不需要向该假设的 ViewModel 添加属性),我很困惑是跟随我的直觉还是同行的建议。
观点:
@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>
建议的 ViewModel:
public class IndexViewModel
{
public IReadOnlyList<Asset> Assets { get; set; }
}
简洁是为了简单和更少的文件,而冗长是为了更容易扩展。
我见过有大量不必要的 ViewModel 的项目,这些 ViewModel 变得杂乱无章 space,但后来也出现过一些项目,由于缺少 ViewModel,添加额外的布尔标志或标题元素变得更加困难。
案例可以采用任何一种方式,最终取决于您的团队决定的偏好或编码风格,并与项目其余部分的一致性相匹配。如果人们期望模型在某个地方,当它们不在那里时可能会令人不快,但如果 ViewModels 在该代码库中是可选的,那么它会更容易接受。
您永远不知道未来的需求,也许可能需要一些相关的用户信息、功能或扩展。即使没有可扩展性,如果代码库的其余部分都为每个页面设置了视图模型,那么阅读代码库的开发人员就会期望该布局,因此对于您的一页省略 ViewModel 因为它非常简单实际上可能会结束由于不一致导致可读性降低。