我创建了一个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));
}
我的POST动作结果定义为
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不能也不应该调用构造函数。我将不得不返回带有模型对象的View(在这种情况下不包含SelectList值)。使用视图模型时如何处理这种情况。
我可以在actionresult中手动填充这些值,但这会违反DRY原则。但是,出于这个问题的目的,我想帮助解决更大的设计问题。
答案 0 :(得分:10)
为什么不遵循我认为大多数人使用的惯例?您已将ViewModel与您的仓库相结合,我也建议您更改。通过将repo.GetStatuses放在Controller / Action中很简单并且它可以工作。我也更喜欢将SelectList放在我的视图中,并让ViewModel包含项目列表 - 但这是我个人的偏好。然后,您可以清楚地看到/了解ViewModel处理的对象类型。 DRY是一项原则而非要求。
<强>视图模型强>
public VMPosition
{
public int StatusId { get; set; }
public IList<Status> StatusList { get; set; }
}
<强>控制器强>
public ActionResult UpdatePosition(int id)
{
var model = new VMPosition(id);
model.StatusList = _repo.getStatuses;
return View(model);
}
public ActionResult UpdatePosition(int id, VMPosition Position)
{
if(!ModelState.IsValid)
{
Position.StatusList = _repo.getStatuses;
return View(Position);
}
...
}
查看强>
<%= Html.DropDownListFor(m => m.StatusId, new SelectList(Model.StatusList)...
编辑 - 重构PopulateSelectLists
public ActionResult UpdatePosition(int id)
{
var model = new VMPosition(id);
PopulateSelectLists(model);
return View(model);
}
public ActionResult UpdatePosition(int id, VMPosition Position)
{
if(!ModelState.IsValid)
{
PopulateSelectLists(Position);
return View(Position);
}
...
}
private void PopulateSelectLists(VMPosition Position)
{
Position.StatusList = _repo.GetStatuses;
Position.OtherSelectList = ...
...
}
答案 1 :(得分:2)
在我的视图模型中处理下拉列表时,我通常会有一个与所选列表项的值相关联的属性,并且我有一个返回selectlistitems列表的属性。然后,我使用Html.DropDownListFor(m =&gt; m.ValueProperty,Model.DropDownValues)来呈现下拉列表。
我想在您的场景中,您没有与所选列表项的值相对应的值?
编辑:以下是我的某个应用中的示例...
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)%>
您可能已经注意到填充列表的LINQ查询。在这个例子中,我有一个已经由AutoMapper填充的列表(MyObjects)。如果您愿意,可以简单地返回一个静态列表。