我可以使用 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" })

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