ViewModel在action方法中获取空值

本文关键字:获取 空值 方法 action ViewModel | 更新日期: 2023-09-27 18:04:14

我使用ViewModel来检索控制器动作中输入的数据。但是ViewModel在它的属性中得到空值。我正在创建一个部分视图

在那个部分视图中,我通过绑定ViewModel创建下拉列表然后我在其他视图

中呈现那个部分视图下面是我的代码

My 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<tblCurrentLocation> tblCurrentLocations { get; set; }
 [Required]
        public virtual IEnumerable<tblStream> tblStreams {  get;  set; }

My Partial View:

@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)
<br />
@Html.Label("Stream")
@Html.DropDownListFor(M => M.tblStreams, new SelectList(Model.tblStreams, "StreamId", "Stream"), "Select Streams")
@Html.ValidationMessageFor(M => M.tblStreams)

我的视图,我在其中渲染上面的部分视图

@{
    ViewBag.Title = "Resources";
}
<script src="~/Scripts/jquery.validate.min.js"></script>
<script src="~/Scripts/jquery.validate.unobtrusive.min.js"></script>
<h2>Resources</h2>
@using (Html.BeginForm("AddResource", "Resources", FormMethod.Post))
{
    @Html.AntiForgeryToken()
    @Html.ValidationSummary(true)
    Html.RenderPartial("_LookUpDropDowns", new PITCRoster.ViewModel.LookUpViewModel());
    <br />
    <input type="submit" value="Create" />
}

这是我的控制器动作方法(HttpPost)

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

当我在控制器上放一个调试器时动作方法控件会转到那个动作方法。但是ViewModel对象里面有null。我尝试访问输入的值使用FormCollection对象,我得到所有的数据如预期的…

下面是我的代码控制器动作与FormCollection

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

谁能解释我为什么我没有得到值在ViewModel对象?谢谢你…

ViewModel在action方法中获取空值

您不能将下拉列表绑定到复杂对象的集合-在您的案例中IEnumerable<tblCurrentLocation>IEnumerable<tblStream>

一个<select>标签只返回一个值(所选选项的值),所以在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

ViewModel:

public class LookUpViewModel
    {    
        [Required]
        public virtual IEnumerable<tblCurrentLocation> tblCurrentLocations { get; set; }
        [Required]
        public virtual IEnumerable<tblStream> 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);
}