我可以使用 ModelBinder 获取对象而不向操作添加参数吗?
Can I use ModelBinder to get object without adding parameter to action?
我是 MVC 新手。我有一个包含许多下拉列表和带有许多列表的视图模型的视图。这些列表中的大多数都是静态的,因此我想缓存检索到的记录。我可以使用(自定义)模型绑定器执行此操作,但我不喜欢实际使用(自定义)模型绑定器我需要为 Action 方法中的每个对象添加参数,如下所示:
public ViewResult SubmitNewValue(MyViewModel viewMod, IEnumerable<List1> list1, IEnumerable<List2> list2, IEnumerable<List3> list3 ...)
{
viewMod._list1 = list1;
viewmod._list2 = list2;
viewMod._list3 = list3;
...
return View(viewMod);
}
我认为更好看的是这样的:
public ViewResult SubmitNewValue(MyViewModel viewMod)
{
viewMod._list1 = ModelBinders.GetInstanceFor<List1>();
viewmod._list2 = ModelBinders.GetInstanceFor<List2>();
viewMod._list3 = ModelBinders.GetInstanceFor<List3>();
//I am able to wrap above to separate function like PrepareViewModel(viewMod)
...
return View(viewMod);
}
是否有 function/way 可以做到这一点?
我也不确定我是否选择了好的方法,但我的视图模型正在丢失下拉列表列表,因此我需要以某种方式在 [HttpPost] 之后将它们重新添加到 ViewModel。
模型绑定器的唯一工作是将请求(查询字符串或 post 正文)中的数据绑定到您的操作方法 上的参数 。所以,不,如果没有参数,modelbinder 不会对数据做任何事情。
您可以直接从请求访问数据,即Request["list1"]
。但是,这是模型绑定器在实际执行任何工作之前收到的原始数据。换句话说,您需要使用该数据手动执行类型强制或更新等操作。
也就是说,这听起来像 XY problem。您实际上想要实现的是什么,因为可能有更好的方法。
您可以使用ControllerBase.ViewBag
属性 来存储资源以供视图使用。
public class MyController : Controller {
public ActionResult SubmitNewValue() {
populateDropDownLists();
MyViewModel model = GetDefaultViewModel();
return View(model);
}
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult SubmitNewValue(MyViewModel viewMod) {
processMyViewModel(viewMod);
populateDropDownLists();
return View(viewMod);
}
void populateDropDownLists() {
//These could be cached lists
ViewBag.List1 = GetList1();
ViewBag.List2 = GetList1();
ViewBag.List3 = GetList1();
}
}
然后在您的视图中,您可以访问列表来填充您的下拉列表
@Html.DropDownListFor(m => m.MyViewModelProperty, (IEnumerable<SelectListItem>)ViewBag.List1, "Select...", new { @class = "form-control select" })
视图模型不应该负责存储列表。由于列表仅用于填充视图中的下拉菜单,因此应将它们分开
我是 MVC 新手。我有一个包含许多下拉列表和带有许多列表的视图模型的视图。这些列表中的大多数都是静态的,因此我想缓存检索到的记录。我可以使用(自定义)模型绑定器执行此操作,但我不喜欢实际使用(自定义)模型绑定器我需要为 Action 方法中的每个对象添加参数,如下所示:
public ViewResult SubmitNewValue(MyViewModel viewMod, IEnumerable<List1> list1, IEnumerable<List2> list2, IEnumerable<List3> list3 ...)
{
viewMod._list1 = list1;
viewmod._list2 = list2;
viewMod._list3 = list3;
...
return View(viewMod);
}
我认为更好看的是这样的:
public ViewResult SubmitNewValue(MyViewModel viewMod)
{
viewMod._list1 = ModelBinders.GetInstanceFor<List1>();
viewmod._list2 = ModelBinders.GetInstanceFor<List2>();
viewMod._list3 = ModelBinders.GetInstanceFor<List3>();
//I am able to wrap above to separate function like PrepareViewModel(viewMod)
...
return View(viewMod);
}
是否有 function/way 可以做到这一点?
我也不确定我是否选择了好的方法,但我的视图模型正在丢失下拉列表列表,因此我需要以某种方式在 [HttpPost] 之后将它们重新添加到 ViewModel。
模型绑定器的唯一工作是将请求(查询字符串或 post 正文)中的数据绑定到您的操作方法 上的参数 。所以,不,如果没有参数,modelbinder 不会对数据做任何事情。
您可以直接从请求访问数据,即Request["list1"]
。但是,这是模型绑定器在实际执行任何工作之前收到的原始数据。换句话说,您需要使用该数据手动执行类型强制或更新等操作。
也就是说,这听起来像 XY problem。您实际上想要实现的是什么,因为可能有更好的方法。
您可以使用ControllerBase.ViewBag
属性 来存储资源以供视图使用。
public class MyController : Controller {
public ActionResult SubmitNewValue() {
populateDropDownLists();
MyViewModel model = GetDefaultViewModel();
return View(model);
}
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult SubmitNewValue(MyViewModel viewMod) {
processMyViewModel(viewMod);
populateDropDownLists();
return View(viewMod);
}
void populateDropDownLists() {
//These could be cached lists
ViewBag.List1 = GetList1();
ViewBag.List2 = GetList1();
ViewBag.List3 = GetList1();
}
}
然后在您的视图中,您可以访问列表来填充您的下拉列表
@Html.DropDownListFor(m => m.MyViewModelProperty, (IEnumerable<SelectListItem>)ViewBag.List1, "Select...", new { @class = "form-control select" })
视图模型不应该负责存储列表。由于列表仅用于填充视图中的下拉菜单,因此应将它们分开