假设给定一个 html 表格的局部视图,每个表格行都存在一个嵌套的局部视图,如下所示:
外部局部视图
<table>
<thead>
<tr>
<th>Item Name</th>
<th>Cost</th>
<th>Category</th>
</tr>
</thead>
<tbody>
@for (int i = 0; i < Model.PurchaseItems.Count; i++)
{
@Html.Partial("_PurchaseItemsDetail", Model.PurchaseItems[i])
}
</tbody>
</table>
内部部分视图,注意:这个部分视图可以在单个请求中被外部视图多次使用,但是如果使用 AJAX 请求,它也可以只使用一次
<tr id="@Model.ID">
<td>@Html.TextBoxFor(x => x.ItemName)</td>
<td>@Html.TextBoxFor(x => x.Cost)</td>
<td>
@Html.DropDownListFor(x => x.Category, CATEGORY_COLLECTION)
</td>
</tr>
问题:鉴于这种旨在灵活的内部视图,查询数据库并临时存储IEnumerable<SelectListItem>
要与下拉列表一起使用的集合的最佳方法是什么?我能想到的方法:
方法1:这似乎是最简单的,但是感觉它违反了MVC原则。在内部局部视图中评估并存储在 ViewData 集合中,这样数据库只被命中一次:
@{
if (ViewData["Categories"] == null)
{
ViewData["Categories"] = API.GetCategories();
}
}
然后在视图中
<td>
@Html.DropDownListFor(x => x.Category, ViewData["Categories"])
</td>
这很好,因为视图会自行决定如何填充其包含的下拉列表。它不依赖于视图模型。
方法2:同上,只是在返回内部局部视图的各种控制器方法中设置ViewData。这种方式似乎更符合 MVC 最佳实践,但是鉴于每个控制器方法都需要正确设置 ViewData 以及创建必要的视图模型,维护起来似乎更加乏味和混乱。
方法3:这个看起来最辛苦,最难维护,但最符合MVC原则。避免完全使用 ViewData,而是在局部视图模型中存储对集合的引用以及其他属性。控制器负责创建集合,然后将引用存储在每个表行的视图模型中。
public class PurchaseItemModel
{
public string ItemName { get; set; }
public decimal Cost { get; set; }
public string Category { get; set; }
// add this
public IEnumberable<SelectListItem> Categories { get; set; }
}
并在每个为内部视图提供服务的控制器中
// if dealing with multiple rows (GET)
IEnumerable<SelectListItem> collection = API.GetPurchaseItemList();
foreach (PurchaseItemModel pim in OuterModel.PurchaseItemModels)
{
pim.Categories = collection;
}
或者
// if dealing with a single row (Ajax)
purchaseItem.Categories = API.GetPurchaseItemList();
然后在视图中
<td>
@Html.DropDownListFor(x => x.Category, x.Categories)
</td>
也许这只是主观问题,但似乎对于这种情况会有最佳实践。有什么想法吗?