C# 我可以使用ModelBinder获取对象而不向操作添加参数吗?

C# 我可以使用ModelBinder获取对象而不向操作添加参数吗?,c#,asp.net-mvc,asp.net-mvc-4,asp.net-mvc-viewmodel,modelbinders,C#,Asp.net Mvc,Asp.net Mvc 4,Asp.net Mvc Viewmodel,Modelbinders,我是MVC的新手。我有一个包含许多下拉列表和viewmodel的视图。这些列表中的大多数是静态的,所以我想缓存检索到的记录。我可以使用(自定义)模型绑定器来实现这一点,但我不喜欢实际使用(自定义)模型绑定器,我需要为每个动作中的对象添加参数,方法如下: public ViewResult SubmitNewValue(MyViewModel viewMod, IEnumerable<List1> list1, IEnumerable<List2> list2, IEnum

我是MVC的新手。我有一个包含许多下拉列表和viewmodel的视图。这些列表中的大多数是静态的,所以我想缓存检索到的记录。我可以使用(自定义)模型绑定器来实现这一点,但我不喜欢实际使用(自定义)模型绑定器,我需要为每个动作中的对象添加参数,方法如下:

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);
}
公共ViewResult SubmitNewValue(MyViewModel viewMod、IEnumerable列表1、IEnumerable列表2、IEnumerable列表3…) { viewMod._list1=list1; viewmod._list2=list2; viewMod._list3=list3; ... 返回视图(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);
}
public ViewResult SubmitNewValue(MyViewModel viewMod)
{
viewMod.\u list1=ModelBinders.GetInstanceFor();
viewmod.\u list2=ModelBinders.GetInstanceFor();
viewMod.\u list3=ModelBinders.GetInstanceFor();
//我可以将上面的内容包装成单独的函数,如PrepareViewModel(viewMod)
...
返回视图(viewMod);
}
有没有一种功能/方法可以做到这一点


我也不确定我是否选择了好的方法,但我的viewmodel正在丢失下拉列表,因此我需要在[HttpPost]之后以某种方式将它们读入viewmodel。modelbinder的唯一任务是将请求(querystring或post正文)中的数据绑定到动作方法上的参数。因此,不,如果没有参数,modelbinder对数据不做任何处理

您可以直接从请求访问数据,即
request[“list1”]
。然而,这是modelbinder在实际执行任何工作之前收到的原始数据。换句话说,您需要使用该数据手动执行类型强制或更新操作等


也就是说,这听起来像是一个错误。您实际上想要实现的是什么,因为可能有更好的方法。

您可以使用
ControllerBase.ViewBag
属性来存储视图要使用的资源。

然后在视图中,您可以访问列表以填充下拉列表

@Html.DropDownListFor(m => m.MyViewModelProperty, (IEnumerable<SelectListItem>)ViewBag.List1, "Select...", new { @class = "form-control select" })
@Html.DropDownListFor(m=>m.MyViewModelProperty,(IEnumerable)ViewBag.List1,“选择…”,新建{@class=“表单控件选择”})

视图模型不应负责存储列表。由于列表仅用于填充视图中的下拉列表,因此应将其分开

列表是视图模型所必需的还是仅用于填充下拉列表?不确定我是否正确理解了您的问题。我认为它们是viewmodel所必需的,因为我需要它们来填充下拉列表。我知道可以使用ViewData,但ViewModel似乎是更好的方法。这些列表仅用于下拉列表。如果您的
viewMod
集合属性未仅使用
MyViewModel viewMod
绑定,则其原因是您的视图错误。您应该显示它,以便更正错误(查看生成的html-您应该具有
name
属性,例如
name=“\u list1[0]。someProperty”
name=“\u list1[1]。someProperty”
等)我的选项标记没有此属性,只有select标记具有此属性。我找不到设置dropdownlistfor的方法,因此它也会在后期操作中发送集合。”@DropDownListFor(它=>Model.SomeProp,新的选择列表(Model.MyIEnumerable,“Id”,“Description”,Model.SomeProp))”。互联网上说,我应该在每一次行动后重新填充收集的样本:@Kostrzak。如果这些集合用于在DropDownList中生成选项,那么您就不会为它们生成表单控件(这太疯狂了)。如果由于
ModelState
无效而再次需要集合,并且需要返回视图,则可以从存储库中再次获取数据。将数据(列表)传递到视图没有问题。我可以使用viewbag、viewdata、viewmodel等。在您的解决方案中,我需要为我需要的每个列表创建并向控制器添加一个方法。我并不是说这是一种不好的做法,但如果我可以创建自定义ModelBinder,为我创建一个列表,并且我可以在每个控制器中使用它,那么应该有一种方法通过ModelBinder.GetObject()之类的东西来显式地获取这些对象…那么你要找的与模型活页夹无关。然后@ChrisPratt回答了你的问题。您可以尝试使用DI获取列表。您甚至可以使用服务定位器直接在视图中获取列表,如果这是您想要的。是的,我想我已经尝试以不同于预期的方式使用Model Binder,并且需要创建自己的类来存储所有需要的列表。谢谢。您已经说过ModelBinder绑定来自请求的数据,但是如果我创建了一个实现IModelBinder的自定义模式绑定器,那么我可以传递(创建?)请求中不存在的对象(我可以在表单上有一个简单的按钮),并且仍然会创建该对象并将其作为参数传递。我认为,当我向POST-action方法添加一个参数时,默认模型绑定器将尝试查找匹配的请求数据,如果失败,它将尝试使用自定义模型绑定器创建一个对象并将其作为参数传递。我是否正确理解了这一点?自定义ModelBinder是查找问题的解决方案。也许它们有一个用例,但我还没有遇到一个使用自定义模型绑定器的建议,这不能通过一开始就正确地操作来解决。同样,请详细说明您正试图实现的目标,然后也许有人可以告诉您如何以正确且可维护的方式实现这一目标。
@Html.DropDownListFor(m => m.MyViewModelProperty, (IEnumerable<SelectListItem>)ViewBag.List1, "Select...", new { @class = "form-control select" })