ViewModel在action方法中获取null值

我正在使用ViewModel来检索控制器操作中输入的数据。 但ViewModel在其属性中获取空值。 我正在创建一个局部视图

在该局部视图中,我通过绑定ViewModel创建下拉列表 ,然后我在其他视图中 渲染该局部视图

以下是我的代码

我的ViewModel:

public class LookUpViewModel { RosterManagementEntities rosterManagementContext = new RosterManagementEntities(); public LookUpViewModel() { tblCurrentLocations = from o in rosterManagementContext.tblCurrentLocations select o; tblStreams = from o in rosterManagementContext.tblStreams select o; } [Required] public virtual IEnumerable tblCurrentLocations { get; set; } [Required] public virtual IEnumerable tblStreams { get; set; } 

我的部分观点:

 @model PITCRoster.ViewModel.LookUpViewModel @Html.Label("Location") @Html.DropDownListFor(M=>M.tblCurrentLocations, new SelectList(Model.tblCurrentLocations, "LocationId", "Location"), "Select Location") @Html.ValidationMessageFor(M=>M.tblCurrentLocations) 
@Html.Label("Stream") @Html.DropDownListFor(M => M.tblStreams, new SelectList(Model.tblStreams, "StreamId", "Stream"), "Select Streams") @Html.ValidationMessageFor(M => M.tblStreams)

我在其中呈现此部分视图的视图

 @{ ViewBag.Title = "Resources"; }   

Resources

@using (Html.BeginForm("AddResource", "Resources", FormMethod.Post)) { @Html.AntiForgeryToken() @Html.ValidationSummary(true) Html.RenderPartial("_LookUpDropDowns", new PITCRoster.ViewModel.LookUpViewModel());
}

这是我的控制器动作方法:[HttpPost]

 public void AddResource(LookUpViewModel testName) { //code } 

当我将调试器放在我的控制器上时,操作方法控制转到该Action方法。 但ViewModel对象中包含null。 我尝试使用FormCollection对象访问输入的值,我按预期获得所有数据…

下面是我使用FormCollection进行控制器操作的代码

  [HttpPost] public void AddResource(FormCollection form) { var x = form["tblStreams"]; //I get value here.. } 

任何人都可以解释为什么我没有在ViewModel对象中获取值? 谢谢…

您不能将下拉列表绑定到复杂对象的集合 – 在您的情况下IEnumerableIEnumerable

标签仅回发单个值(所选选项的值),因此在POST方法中, DefaultModelBinder正在尝试使testName.tblCurrentLocations = "1" (假设所选选项的值为1 )当然失败,属性设置为null

您需要一个包含要绑定的属性的视图模型(理想情况下将包含DropDownListFor()帮助程序使用的SelectList

 public class LookUpViewModel { [Display(Name = "Location")] [Required(ErrorMessage = "Please select a location")] public int SelectedLocation { get; set; } [Display(Name = "Stream")] [Required(ErrorMessage = "Please select a stream")] public int SelectedStream { get; set; } public SelectList LocationList { get; set; } public SelectList StreamList { get; set; } } 

然后在视图中

 @Html.LabelFor(m => m.SelectedLocation) @Html.DropDownListFor(m => m.SelectedLocation, Model.LocationList, "-Please select-") @Html.ValidationMessageFor(m => m.SelectedLocation) @Html.LabelFor(m => m.SelectedStream) @Html.DropDownListFor(m => m.SelectedStream, Model.StreamList, "-Please select-") @Html.ValidationMessageFor(m => m.SelectedStream) 

并在控制器中

 public ActionResult Edit() { LookUpViewModel model = new LookUpViewModel(); ConfigureViewModel(model); return View(model); } [HttpPost] public ActionResult Edit(LookUpViewModel model) { if (!ModelState.IsValid) { ConfigureViewModel(model); return View(model); } // model.SelectedLocation will contain the value of the selected location // save and redirect } private void ConfigureViewModel(LookUpViewModel model) { // populate your select lists var locations = from o in rosterManagementContext.tblCurrentLocations select o; model.LocationList = new SelectList(locations, "LocationId", "Location"); .... // ditto for streams } 

请注意,在Maximilian的答案中也指出,您的视图模型应该只包含您需要的视图属性。 您的控制器负责填充值。 视图模型永远不应该调用数据库 – 它甚至不应该知道存在一个数据库。

这个答案不会直接解决您的问题,但首先我建议您至少将ViewModel的填充外包给控制器(因为否则每次调用构造函数时它都会重新创建DBContext)。 ViewModel应该只包含数据 – 没有逻辑。 而且我会在Using语句中使用DBContext

视图模型:

 public class LookUpViewModel { [Required] public virtual IEnumerable tblCurrentLocations { get; set; } [Required] public virtual IEnumerable tblStreams { get; set; } 

控制器:

 public ActionResult Foo() { LookUpViewModel ViewModel = new LookUpViewModel(); using(RosterManagementEntities rosterManagementContext = new RosterManagementEntities()) { ViewModel.tblCurrentLocations = from o in rosterManagementContext.tblCurrentLocations select o; ViewModel.tblStreams = from o in rosterManagementContext.tblStreams select o; } return View(ViewModel); }