我目前正在开展一个项目,其中我们有许多类似的模型。我们让它们都继承自同一个基本模型,我们还制作了一个通用控制器(基本的东西,如列表、添加、编辑等)来处理基本模型。它实际上可以工作并使我们的事情变得容易,但我对下拉菜单有一个小问题。
无需详细说明,如果我可以使用操作将数据从控制器传递到视图,这对我来说真的很容易。像这样的东西:
@Html.DropDownListFor(model => model.Xtypechild, Action("GetList", "XController"))
动作GetList
返回的地方IEnumerable<SelectListItem>
这样我可以只编写一次代码并将其用于许多不同的控制器。
我知道这听起来很疯狂,但如果我尝试使用一种更传统的方法来做到这一点,我最终会再次出现冗余代码,并且会失去我们从继承控制器中获得的一些优势。
我现在能看到的唯一选择是GetList
使用所有项目返回 JSON 并使用 Ajax/JS 填充下拉列表。我还可以执行一个返回包含下拉列表的局部视图的操作,但我不确定这是否是个好主意。
非常感谢您的所有输入。最后,我采用了以下解决方案:
我们有一个服务类来处理我们模型的数据库操作。我只是添加一个生成IEnumerable<SelectListItem>
基本服务类的方法。现在我通过 ViewBag 传递下拉项目(尽管它迫使我在视图中使用之前将它们转换回 IEnumerable)。我在继承控制器的重写构造函数中将它们分配给 ViewBag。
如果这个解决方案适用于我们的项目,我最好咨询代码的原始作者,尽管他现在正在度假。现在必须这样做。从好的方面来说,这种方法产生的代码很少,所以它应该很容易替换(如果我必须这样做的话)。
代码稍微改进了一点,现在我在视图中有这样的东西(注意int?
转换是因为属性是 int 类型,否则它不会工作):
Html.DropDownListFor(
model => model.XId,
new SelectList((List<X>)ViewBag.Xs, "Id", "Name", (Model != null ? (int?)Model.XId : null)),
" -- select -- ",
null)
在控制器的重写构造函数内部是这样的:
ViewBag.Xs = db.Xs.ToList();
这绝对不是在 Razor 中实现下拉菜单的最佳方式,但它是在项目中实现它们的最佳方式。这样做的原因是:没有时间让项目使用 ViewModel 并覆盖基本控制器的所有操作来处理它们(以及为这些操作中的下拉菜单提供数据)。
代码进一步发展。如果数据仅在少数视图中使用,那么在控制器构造函数中执行查询肯定不是一个好主意。所以现在构造函数包含等价于:
ViewBag.Xs = (IQueryable<X>)db.Xs;
和观点:
Html.DropDownListFor(
model => model.XId,
new SelectList((IQueryable<X>)ViewBag.Xs, "Id", "Name", (Model != null ? (int?)Model.XId : null)),
" -- select -- ",
null)
这样查询仅在视图实际需要数据时执行。