Asp.net mvc 选择列表设计决策的视图模型

Asp.net mvc 选择列表设计决策的视图模型,asp.net-mvc,asp.net-mvc-2,viewmodel,Asp.net Mvc,Asp.net Mvc 2,Viewmodel,我已经创建了一个viewmodel public VMPosition { public VMPosition(){}//for model binder public VMPosition(int EmployeeID) { PositionStatusList = new SelectList(_repo.getStatuses); //populate other properties

我已经创建了一个viewmodel

public VMPosition
{
        public VMPosition(){}//for model binder  
        public VMPosition(int EmployeeID)
        {
            PositionStatusList = new SelectList(_repo.getStatuses);
            //populate other properties
        }
        public int CurrentPositionID { get; set; }
        public int EmployeeID { get; set; }
        public int CurrentPositionHistoryID { get; set; }
        public bool AddingNew { get; set; }
        public bool ClosingCurrent { get; set; }
        public string CurrentPosition { get; set; }
        public DateTime CurrentPositionStartDate { get; set; }
        public string ReasonForDeparture { get; set; }
        public SelectList PositionStatusList { get; set; }

}
我的GET ActionResult定义为

public ActionResult UpdatePosition(int id)
{
     return View(new VMPosition(id)); 
} 
 public ActionResult UpdatePosition(int id, VMPosition Position)
    {
        if(ModelState.IsValid){
             Position Current = new Position{Position.Title etc..}
             //save to db
             return redirectToAction("someAction");
         }
         return View(Position);//here is the problem
    }
我的POST actionresult定义为

public ActionResult UpdatePosition(int id)
{
     return View(new VMPosition(id)); 
} 
 public ActionResult UpdatePosition(int id, VMPosition Position)
    {
        if(ModelState.IsValid){
             Position Current = new Position{Position.Title etc..}
             //save to db
             return redirectToAction("someAction");
         }
         return View(Position);//here is the problem
    }
我的SelectList在接受一个参数的构造函数中填充。如果modelstate无效,Modelbinder不能也不应该调用构造函数。我必须返回带有模型对象的视图(在本例中不包含SelectList值)。如何在使用视图模型时处理此场景


我可以在actionresult中手动填充这些值,但这将违反DRY原则。但是,出于这个问题的目的,我想帮助解决更大的设计问题。

在处理viewmodels中的下拉列表时,我通常有一个与所选列表项的值关联的属性,还有一个返回selectlistitems列表的属性。然后,我使用Html.DropDownListFor(m=>m.ValueProperty,Model.DropDownValues)来呈现下拉列表

我想在您的场景中,您没有与所选listitem的值对应的值

编辑:下面是我的一个应用程序的示例

public class MyVM
{
  public int MyObjectId { get; set; }

  public List<SelectListItem> MyObjectList
  {
    get
    {
      List<SelectListItem> list = (from o in MyObjects select new SelectListItem 
        { Value = o.ObjectId.ToString(), Text = o.ObjectName }).ToList();
      list.Insert(0, new SelectListItem 
        { Value = "0", Text = "[Select an object]" });
      return list;
    }
  }
}

<%: Html.DropDownListFor(m => m.MyObjectId, Model.MyObjectList)%>
公共类MyVM
{
公共int MyObjectId{get;set;}
公共列表MyObjectList
{
得到
{
列表=(从MyObject中的o选择新的SelectListItem
{Value=o.ObjectId.ToString(),Text=o.ObjectName}).ToList();
列表。插入(0,新建SelectListItem
{Value=“0”,Text=“[选择对象]”});
退货清单;
}
}
}
m、 MyObjectId,Model.MyObjectList)%%>

您可能已经注意到填充列表的LINQ查询。在本例中,我有一个列表(MyObject),它已经由AutoMapper填充。如果愿意,您可以简单地返回一个静态列表。

为什么不遵循我认为大多数人使用的惯例呢?您已经将ViewModel与您的回购进行了耦合,我也建议您进行更改。通过将repo.getStatus放在控制器/操作中,操作简单且有效。我还喜欢将SelectList放在我的视图中,让ViewModel包含项目列表,但这是我个人的偏好。然后,您可以清楚地看到/理解ViewModel处理的对象类型。干燥是原则,不是要求

视图模型

public VMPosition
{
    public int StatusId { get; set; }
    public IList<Status> StatusList { get; set; }
}
查看

<%= Html.DropDownListFor(m => m.StatusId, new SelectList(Model.StatusList)...

谢谢你的快速回复。在get中编写列表代码是个好主意,但如果我们多次选择它,会导致两个单独的查询。我知道列表通常只会在查看时调用一次,只是出于好奇@穆罕默德:我相信你的问题的答案是这要看情况而定。在本例中,我有一个实体,其中包含已创建的子对象列表。我使用AutoMapper将实体的数据复制到视图模型。当我查询视图模型的列表时,没有数据库交互。但是,如果您依赖IQueryable,则针对列表的查询可能会导致数据库查询。如果您通过直接点击存储库来构建列表,也可以这么说——在这种情况下,您可以使用视图模型的构造函数来填充本地列表一次?假设我们的页面上有4到5个选择列表,而我的页面上也有。使用您的方法,我们将在(Get和post)actionresult中为列表编写两次填充代码。不过,我喜欢将存储库与viewmodel分离的想法。问题是我怎样才能以最好的方式做到这一点。网络是一个无状态的模型。我不认为在不同的ActionResult中检索相同的信息是一个问题,因为这是两个独立的请求。如果您担心代码的重复,那么重构ActionResult以返回状态-因此您只编写了一次代码。