我注意到我的viewmodel属性被回发为null。经过进一步调查,发现问题是文本框的名称属性(通过TextBoxFor帮助方法生成的文本框)缺少动作的viewmodel变量参数名称。
也许示例代码会更清晰 -
视图模型
public class ViewModel {
public string ID {get;set;}
public List<ViewModelChild> ViewCustomNames{ get; set; }
}
控制器操作(ViewModel包含集合属性ViewCustomNames)
public ActionResult Create(ViewModel viewModel1) {...}
查看(使用ViewModel强力输入)
@Html.TextBoxFor(vc => vc.ID) //This will not be posted back
<input name="viewModel1.ID" type="text" /> //This will be posted back
@for(int i = 0; I < Model.ViewCustomNames.Count;i++)
@Html.TextBoxFor(m => m.ViewCustomNames[i].SomeProperty)
生成的HTML
<input name="ID"...
<input name="ViewCustomNames[0].SomeProperty" id="ViewCustomNames_0_SomeProperty" type="text" value="">
生成的HTML应该是什么
<input name="viewModel1.ID"...
<input name="viewModel1.ViewCustomNames[0].SomeProperty" id="doesn't-matter-for-this-example" type="text" value="">
问题 我通过用明确的HTML输入元素替换TextBoxFor(...)来修复它,但我想知道它是否是MVC5错误或者我是否遗漏了明显的东西。我无法想象ASP.NET附带的标准TextBoxFor方法不起作用,它必须是我做错的事情。有什么想法吗?
添加我项目中使用的实际代码以供参考 -
控制器*
public class ViewCustomViewModelsController : Controller {
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create([Bind(Include = "ViewCustomId,ViewCustomName,ReconContextId,ViewCustomFieldCollection")] ViewCustomViewModel viewCustomViewModel) { }
}
查看
@model AR.UI.MVC.ViewModels.ViewCustomViewModel
@using (Html.BeginForm())
{
@Html.AntiForgeryToken()
<div class="form-horizontal">
<h4>ViewCustomViewModel</h4>
<hr />
@Html.ValidationSummary(true, "", new { @class = "text-danger" })
@Html.HiddenFor(model => model.ViewCustomId)
<div class="form-group">
<dl class="dl-horizontal">
<dt>ViewCustomId</dt>
<dd>@*@Html.TextBoxFor(vc => vc.ViewCustomId)*@ //Posts back null
<input name="viewCustomViewModel.ViewCustomId" type="text" value="@Model.ViewCustomId" /> //Posts back the correct value
</dd>
<dt>Name</dt>
<dd>@Html.TextBoxFor(vc => vc.ViewCustomName) //Posts back null
<input name="viewCustomViewModel.ViewCustomName" type="text" value="@Model.ViewCustomName" /> //Posts back the correct value
</dd>
<dt>ReconContext</dt>
<dd>@Html.DropDownList("viewCustomViewModel.ReconContextId", ViewBag.ReconContextList as SelectList)</dd>
</dl>
<span>Field</span>
@Html.DropDownList("Field", new SelectList(ViewBag.FieldList, "FieldId", "FieldName"), new { id = "ddlField" })
<a href="javascript:void(0)" onclick="AddField($('#ddlField').val(), $('#ddlField :selected').text());return false;">Add</a>
<table id="tableSelectedFields">
<tr><th>Id</th><th>FieldId</th><th>FieldName</th><th>DisplayOrder</th><th>SortOrder</th><th></th></tr>
@for (int fieldCount = 0; fieldCount < Model.ViewCustomFieldCollection.Count; fieldCount++)
{
<tr>
<td><input name="viewCustomViewModel.ViewCustomFieldCollection.Index" type="text" value="@fieldCount" /></td>
<td><input name="viewCustomViewModel.ViewCustomFieldCollection[@fieldCount].ViewCustomFieldId" type="text" value="@Model.ViewCustomFieldCollection[@fieldCount].ViewCustomFieldId" /> </td>
<td><input name="viewCustomViewModel.ViewCustomFieldCollection[@fieldCount].FieldId" type="text" value="@Model.ViewCustomFieldCollection[@fieldCount].FieldId" /> </td>
视图模型
namespace AR.UI.MVC.ViewModels
{
public class ViewCustomViewModel
{
[Key]
public int ViewCustomId { get; set; }
public string ViewCustomName { get; set; }
public int ReconContextId { get; set; }
public int ReconContextName { get; set; }
public List<ViewCustomFieldViewModel> ViewCustomFieldCollection { get; set; }
public ViewCustomViewModel() { ViewCustomFieldCollection = new List<ViewCustomFieldViewModel>(); }
public ViewCustomViewModel(int viewCustomId, string viewCustomName)
{
ViewCustomId = viewCustomId;
ViewCustomName = viewCustomName;
ViewCustomFieldCollection = new List<ViewCustomFieldViewModel>();
}
}
public class ViewCustomFieldViewModel
{
[Key]
public int ViewCustomFieldId { get; set; }
public int ViewCustomId { get; set; }
public int FieldId { get; set; }
public string FieldName { get; set; }
public int DisplayOrder { get; set; }
public int SortOrder { get; set; }
public ViewCustomFieldViewModel() { }
public ViewCustomFieldViewModel(int viewCustomFieldId, int viewCustomId, int fieldId, string fieldName, int displayOrder, int sortOrder)
{
ViewCustomFieldId = viewCustomFieldId;
ViewCustomId = viewCustomId;
FieldId = fieldId;
FieldName = fieldName;
DisplayOrder = displayOrder;
SortOrder = sortOrder;
}
}