我试图将模型数据从视图(和View中的PartialView)传递回HttpPost上的Controller。 (改编自Pass SelectedValue of DropDownList in Html.BeginForm() in ASP.NEt MVC 3)
为什么呢?我想显示一个资产列表,每个资产都有一个DropDownList和多个选项。提交表格后,从DropDownList中读取所选项目。
我的2(简化)模型:
public class Booking
{
public int BookingID { get; set; }
public int StoreID { get; set; }
...
public IEnumerable<AssetShort> Assets { get; set; }
}
和
public class AssetShort
{
public int AssetID { get; set; }
....
public int SelectedAction { get; set; }
public IEnumerable<SelectListItem> ActionList { get; set; }
}
在我的预订控制器&gt;创建我构建列表:
public ActionResult Booking(int id)
{
// get myBag which contains a List<Asset>
// booking corresponds to 'id'
var myAssets = new List<AssetShort>();
foreach (var a in myBag.Assets)
{
var b = new AssetShort();
b.AssetID = a.ID;
b.SelectedAction = 0;
b.ActionList = new[]
{
new SelectListItem { Selected = true, Value = "0", Text = "Select..."},
new SelectListItem { Selected = false, Value = "1", Text = "Add"},
new SelectListItem { Selected = false, Value = "2", Text = "Remove"},
new SelectListItem { Selected = false, Value = "3", Text = "Relocate"},
new SelectListItem { Selected = false, Value = "4", Text = "Upgrade"},
new SelectListItem { Selected = false, Value = "5", Text = "Downgrade"}
};
myAssets.Add(b);
};
var model = new BookingRequirementsViewModel
{
BookingID = booking.ID,
StoreID = booking.StoreID,
Assets = myAssets.ToList(),
};
return View(model);
我的观点:
@model uatlab.ViewModels.BookingRequirementsViewModel
@{
ViewBag.Title = "Booking step 2";
}
<h4>Your booking ref. @Model.BookingID</h4>
@using (Html.BeginForm("Booking2", "Booking", FormMethod.Post))
{
<fieldset>
@Html.AntiForgeryToken()
@Html.HiddenFor(model => model.StoreID)
@Html.Partial("_Assets", Model.StoreAssets)
<input type="submit" value="Cancel" class="btn btn-default" />
<input type="submit" value="Next" class="btn btn-default" />
</fieldset>
}
部分视图包含
@foreach (var item in Model)
{
<tr>
<td>@item.Name</td>
<td>@item.Number</td>
<td>@Html.DropDownListFor(modelItem=>item.SelectedAction, item.ActionList)</td>
</tr>
}
所以,所有这些在浏览器中工作正常,我可以为列出的每个资产选择下拉菜单,但是当我提交时,回发的唯一值是StoreID,因为它位于&#34; HiddenFor&#34;。
booking2控制器具有参数模型:
public ActionResult Booking2(BookingRequirementsViewModel model)
{
//loop through model.Assets and display SelectedActions
}
让我明确一下问题是什么 - 在Booking2控制器中,当在调试模式下查看时,Model为null,我得到错误&#34;对象引用未设置为对象的实例。&#34;
有任何想法请如何从模型中将模型传回控制器?
此致 克雷格
答案 0 :(得分:1)
您需要为EditorTemplate
创建AssetShort
。我还建议将ActionList
移至BookingRequirementsViewModel
,以便您不为每个SelectList
重新生成AssetShort
您发布的模型没有意义。您的控制器有var model = new BookingRequirementsViewModel { ..., Assets = myAssets.ToList() };
但在视图中您引用了@Html.Partial("_Assets", Model.StoreAssets)
?这两个不同的属性。我将假设StoreAssets
为IEnumerable<AssetShort>
/Views/Shared/EditorTemplates/AssetShort.cshtml
@model AssetShort
<tr>
<td>@Html.DispayFor(m => m.Name)</td>
....
<td>
@Html.DropDownListFor(m => m.SelectedAction, (IEnumerable<SelectListItem>)ViewData["actionList"], "--Please select--")
@Html.ValidationMessageFor(m => m.SelectedAction)
</td>
</tr>
在主视图中
@model uatlab.ViewModels.BookingRequirementsViewModel
....
@using (Html.BeginForm()) // Not sure why you post to a method with a different name
{
....
@Html.HiddenFor(m => m.StoreID)
@Html.EditorFor(m => m.StoreAssets, new { actionList = Model.ActionList })
....
}
在控制器中
public ActionResult Booking(int id)
{
....
var model = new BookingRequirementsViewModel
{
BookingID = booking.ID,
StoreID = booking.StoreID,
Assets = myBag.Assets.Select(a => new AssetShort()
{
AssetID = a.ID,
SelectedAction = a.SelectedAction, // assign this if you want a selected option, otherwise the "--Please select--" option will be selected
....
})
};
ConfigureViewModel(model); // Assign select list
return View(model);
}
生成SelectList
的单独方法,因为它需要在GET方法中调用,如果返回视图则需要在POST方法中再次调用。注意使用DropDownListFor()
的重载来生成上面的选项标签(空值),并且没有设置Selected
属性的点(SelectedAction
的值确定选择的内容,而不是此)
private ConfigureViewModel(BookingRequirementsViewModel model)
{
model.ActionList = new[]
{
new SelectListItem { Value = "1", Text = "Add"},
....
new SelectListItem { Value = "5", Text = "Downgrade"}
};
}
和POST
public ActionResult Booking(BookingRequirementsViewModel model)
{
if (!ModelState.IsValid)
{
ConfigureViewModel(model); // Re-assign select list
return View(model);
}
// save and redirect
}
我建议您使用SelectedAction
属性[Required]
为空,以便获得客户端和服务器端验证
public class AssetShort
{
public int AssetID { get; set; }
....
[Required]
public int? SelectedAction { get; set; }
}