我正在使用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<tblCurrentLocation> tblCurrentLocations { get; set; }
[Required]
public virtual IEnumerable<tblStream> 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)
<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
}
当我将调试器放在我的控制器上时,操作方法控制转到该Action方法。 但ViewModel对象中包含null。 我尝试使用 FormCollection 对象访问输入的值,并且我按预期获得所有数据...
以下是我使用 FormCollection
进行控制器操作的代码 [HttpPost]
public void AddResource(FormCollection form)
{
var x = form["tblStreams"]; //I get value here..
}
有人可以解释一下为什么我没有在ViewModel对象中获取值吗? 谢谢......
答案 0 :(得分:4)
您无法将下拉列表绑定到复杂对象的集合 - 在您的情况下IEnumerable<tblCurrentLocation>
和IEnumerable<tblStream>
<select>
标记仅回发单个值(所选选项的值),因此在POST方法中,DefaultModelBinder
正在尝试testName.tblCurrentLocations = "1"
(假设值为{1}}选择的选项是1
)当然失败,属性设置为null
您需要一个包含要绑定到的属性的视图模型(理想情况下将包含SelectList
帮助程序使用的DropDownListFor()
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的回答所示,您的视图模型应该只包含您对视图所需的属性。您的控制器负责填充值。视图模型永远不应该调用数据库 - 它甚至不应该知道存在一个数据库。
答案 1 :(得分:2)
这个答案不会直接解决您的问题,但首先我建议您至少将ViewModel的填充外包给控制器(因为否则它会在每次构造函数时重新创建DBContext叫做)。 ViewModel应该只包含数据 - 没有逻辑。而且我会在Using
语句中使用DBContext
<强>视图模型:强>
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);
}