模型绑定列表在 Asp MVC 中不起作用
List of Models binding not working in Asp MVC
我在使用 MVC 时遇到了一个问题。我想在同一个视图中使用不同的模型(创建一个大表格)。我正在使用 ViewModel 方法在内部收集我的模型。
视图模型:
public class EditByUserObjectsVM
{
public Person Person {set; get; }
public List<EmergencyContact> EmergencyContacts {set; get; }
}
我的观点是这样的(紧急联系人方面):
<div class="tab-content">
@for (var i = 0; i < Model.EmergencyContacts.Count(); i++)
{
<div class="tab-pane" id="tab@(i + 1)" name="@(i + 1)">
<form class="form-horizontal">
<fieldset>
@Html.HiddenFor(model => model.EmergencyContacts[i].ID)
<div class="form-group">
@Html.LabelFor(model => model.EmergencyContacts[i].LastName, htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.EditorFor(model => model.EmergencyContacts[i].LastName, new { htmlAttributes = new { @class = "form-control" } })
@Html.ValidationMessageFor(model => model.EmergencyContacts[i].LastName, "", new { @class = "text-danger" })
</div>
</div>
<div class="form-group">
@Html.LabelFor(model => model.EmergencyContacts[i].FirstName, htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.EditorFor(model => model.EmergencyContacts[i].FirstName, new { htmlAttributes = new { @class = "form-control" } })
@Html.ValidationMessageFor(model => model.EmergencyContacts[i].FirstName, "", new { @class = "text-danger" })
</div>
</div>
<div class="form-group">
@Html.LabelFor(model => model.EmergencyContacts[i].Phone, htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.EditorFor(model => model.EmergencyContacts[i].Phone, new { htmlAttributes = new { @class = "form-control" } })
@Html.ValidationMessageFor(model => model.EmergencyContacts[i].Phone, "", new { @class = "text-danger" })
</div>
</div>
<div class="form-group">
@Html.LabelFor(model => model.EmergencyContacts[i].PersonalMail, htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.EditorFor(model => model.EmergencyContacts[i].PersonalMail, new { htmlAttributes = new { @class = "form-control" } })
@Html.ValidationMessageFor(model => model.EmergencyContacts[i].PersonalMail, "", new { @class = "text-danger" })
</div>
</div>
<div class="form-group">
@Html.LabelFor(model => model.EmergencyContacts[i].Adress, htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.EditorFor(model => model.EmergencyContacts[i].Adress, new { htmlAttributes = new { @class = "form-control" } })
@Html.ValidationMessageFor(model => model.EmergencyContacts[i].Adress, "", new { @class = "text-danger" })
</div>
</div>
<div class="form-group">
@Html.LabelFor(model => model.EmergencyContacts[i].PostalCode, htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.EditorFor(model => model.EmergencyContacts[i].PostalCode, new { htmlAttributes = new { @class = "form-control" } })
@Html.ValidationMessageFor(model => model.EmergencyContacts[i].PostalCode, "", new { @class = "text-danger" })
</div>
</div>
<div class="form-group">
@Html.LabelFor(model => model.EmergencyContacts[i].Town, htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.EditorFor(model => model.EmergencyContacts[i].Town, new { htmlAttributes = new { @class = "form-control" } })
@Html.ValidationMessageFor(model => model.EmergencyContacts[i].Town, "", new { @class = "text-danger" })
</div>
</div>
<div class="form-group">
@Html.LabelFor(model => model.EmergencyContacts[i].Link, htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.EditorFor(model => model.EmergencyContacts[i].Link, new { htmlAttributes = new { @class = "form-control" } })
@Html.ValidationMessageFor(model => model.EmergencyContacts[i].Link, "", new { @class = "text-danger" })
</div>
</div>
</fieldset>
</form>
</div>
}
<ul class="pager wizard">
<li class="previous"><a href="javascript:void(0);">Retour</a></li>
<li class="next"><a href="javascript:void(0);">Suivant</a></li>
</ul>
</div>
我们的想法是创建一个包含 3 个步骤的向导,其中每个步骤都是要填写的紧急联系表。
最后,有 1 个全局提交按钮将所有模型数据发送到我的控制器:
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult EditByUser(EditByUserObjectsVM editByUserObjectsVM)
{
if (ModelState.IsValid)
{
try
{
db.Entry(editByUserObjectsVM.Person).State = EntityState.Modified;
db.SaveChanges();
editByUserObjectsVM.EmergencyContacts[0].PersonSerial = editByUserObjectsVM.EmergencyContacts[1].PersonSerial = editByUserObjectsVM.EmergencyContacts[2].PersonSerial = editByUserObjectsVM.Person.Serial;
db.Entry(editByUserObjectsVM.EmergencyContacts[0]).State = EntityState.Modified;
db.SaveChanges();
db.Entry(editByUserObjectsVM.EmergencyContacts[1]).State = EntityState.Modified;
db.SaveChanges();
db.Entry(editByUserObjectsVM.EmergencyContacts[2]).State = EntityState.Modified;
db.SaveChanges();
return RedirectToAction("Index");
}
catch (DbEntityValidationException e)
{
var newException = new FormattedDbEntityValidationException(e);
throw newException;
}
}
ViewBag.ResponsibleSerial = new SelectList(db.People, "Serial", "LastName", editByUserObjectsVM.Person.ResponsibleSerial);
return View(editByUserObjectsVM.Person);
}
当我点击提交按钮时,我在控制器中收到了我的 ViewModel 对象,但是我的紧急联系人列表只包含向导中填写的第一个!其他两个为空!
谁能告诉我为什么?
你的 form
应该在 forloop 之外。
<form class="form-horizontal">
<div class="tab-content">
@for (var i = 0; i < Model.EmergencyContacts.Count(); i++)
{
<div class="tab-pane" id="tab@(i + 1)" name="@(i + 1)">
<fieldset>
<!-- ... -->
</fieldset>
</div>
}
<ul class="pager wizard">
<li class="previous"><a href="javascript:void(0);">Retour</a></li>
<li class="next"><a href="javascript:void(0);">Suivant</a></li>
</ul>
</div>
</form>
现在您正在创建多个表单。如果您想创建一个大表单,则只需要创建一个表单,其中包含多个选项卡和字段集。
您可能没有携带数据。每个请求都是独立的,因此它必须 post 来自先前请求的所有数据 或 您必须以某种方式保留先前 posted 的数据,要么将其存储在数据库或会话。
很难从所提供的代码中准确判断这是如何运作的。通过第三次联系,用户是否会在屏幕上看到 3 套完整的联系方式?换句话说,第一次通过时,只有一组字段。第二次通过,有两套第一次填写,最后第三次,有两套有填充数据和一套空的准备由用户填写?
如果是这样的话,我会说这很糟糕UI。真的,最好放弃所有 post 在服务器之间来回切换,一次渲染所有三个集合,这样用户就可以一次性输入它们。
如果情况并非如此,并且每次您都只显示一组字段,那为什么会有一个循环?您还需要在请求之间以某种方式保留其他联系人。
我在使用 MVC 时遇到了一个问题。我想在同一个视图中使用不同的模型(创建一个大表格)。我正在使用 ViewModel 方法在内部收集我的模型。
视图模型:
public class EditByUserObjectsVM
{
public Person Person {set; get; }
public List<EmergencyContact> EmergencyContacts {set; get; }
}
我的观点是这样的(紧急联系人方面):
<div class="tab-content">
@for (var i = 0; i < Model.EmergencyContacts.Count(); i++)
{
<div class="tab-pane" id="tab@(i + 1)" name="@(i + 1)">
<form class="form-horizontal">
<fieldset>
@Html.HiddenFor(model => model.EmergencyContacts[i].ID)
<div class="form-group">
@Html.LabelFor(model => model.EmergencyContacts[i].LastName, htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.EditorFor(model => model.EmergencyContacts[i].LastName, new { htmlAttributes = new { @class = "form-control" } })
@Html.ValidationMessageFor(model => model.EmergencyContacts[i].LastName, "", new { @class = "text-danger" })
</div>
</div>
<div class="form-group">
@Html.LabelFor(model => model.EmergencyContacts[i].FirstName, htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.EditorFor(model => model.EmergencyContacts[i].FirstName, new { htmlAttributes = new { @class = "form-control" } })
@Html.ValidationMessageFor(model => model.EmergencyContacts[i].FirstName, "", new { @class = "text-danger" })
</div>
</div>
<div class="form-group">
@Html.LabelFor(model => model.EmergencyContacts[i].Phone, htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.EditorFor(model => model.EmergencyContacts[i].Phone, new { htmlAttributes = new { @class = "form-control" } })
@Html.ValidationMessageFor(model => model.EmergencyContacts[i].Phone, "", new { @class = "text-danger" })
</div>
</div>
<div class="form-group">
@Html.LabelFor(model => model.EmergencyContacts[i].PersonalMail, htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.EditorFor(model => model.EmergencyContacts[i].PersonalMail, new { htmlAttributes = new { @class = "form-control" } })
@Html.ValidationMessageFor(model => model.EmergencyContacts[i].PersonalMail, "", new { @class = "text-danger" })
</div>
</div>
<div class="form-group">
@Html.LabelFor(model => model.EmergencyContacts[i].Adress, htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.EditorFor(model => model.EmergencyContacts[i].Adress, new { htmlAttributes = new { @class = "form-control" } })
@Html.ValidationMessageFor(model => model.EmergencyContacts[i].Adress, "", new { @class = "text-danger" })
</div>
</div>
<div class="form-group">
@Html.LabelFor(model => model.EmergencyContacts[i].PostalCode, htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.EditorFor(model => model.EmergencyContacts[i].PostalCode, new { htmlAttributes = new { @class = "form-control" } })
@Html.ValidationMessageFor(model => model.EmergencyContacts[i].PostalCode, "", new { @class = "text-danger" })
</div>
</div>
<div class="form-group">
@Html.LabelFor(model => model.EmergencyContacts[i].Town, htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.EditorFor(model => model.EmergencyContacts[i].Town, new { htmlAttributes = new { @class = "form-control" } })
@Html.ValidationMessageFor(model => model.EmergencyContacts[i].Town, "", new { @class = "text-danger" })
</div>
</div>
<div class="form-group">
@Html.LabelFor(model => model.EmergencyContacts[i].Link, htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.EditorFor(model => model.EmergencyContacts[i].Link, new { htmlAttributes = new { @class = "form-control" } })
@Html.ValidationMessageFor(model => model.EmergencyContacts[i].Link, "", new { @class = "text-danger" })
</div>
</div>
</fieldset>
</form>
</div>
}
<ul class="pager wizard">
<li class="previous"><a href="javascript:void(0);">Retour</a></li>
<li class="next"><a href="javascript:void(0);">Suivant</a></li>
</ul>
</div>
我们的想法是创建一个包含 3 个步骤的向导,其中每个步骤都是要填写的紧急联系表。
最后,有 1 个全局提交按钮将所有模型数据发送到我的控制器:
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult EditByUser(EditByUserObjectsVM editByUserObjectsVM)
{
if (ModelState.IsValid)
{
try
{
db.Entry(editByUserObjectsVM.Person).State = EntityState.Modified;
db.SaveChanges();
editByUserObjectsVM.EmergencyContacts[0].PersonSerial = editByUserObjectsVM.EmergencyContacts[1].PersonSerial = editByUserObjectsVM.EmergencyContacts[2].PersonSerial = editByUserObjectsVM.Person.Serial;
db.Entry(editByUserObjectsVM.EmergencyContacts[0]).State = EntityState.Modified;
db.SaveChanges();
db.Entry(editByUserObjectsVM.EmergencyContacts[1]).State = EntityState.Modified;
db.SaveChanges();
db.Entry(editByUserObjectsVM.EmergencyContacts[2]).State = EntityState.Modified;
db.SaveChanges();
return RedirectToAction("Index");
}
catch (DbEntityValidationException e)
{
var newException = new FormattedDbEntityValidationException(e);
throw newException;
}
}
ViewBag.ResponsibleSerial = new SelectList(db.People, "Serial", "LastName", editByUserObjectsVM.Person.ResponsibleSerial);
return View(editByUserObjectsVM.Person);
}
当我点击提交按钮时,我在控制器中收到了我的 ViewModel 对象,但是我的紧急联系人列表只包含向导中填写的第一个!其他两个为空!
谁能告诉我为什么?
你的 form
应该在 forloop 之外。
<form class="form-horizontal">
<div class="tab-content">
@for (var i = 0; i < Model.EmergencyContacts.Count(); i++)
{
<div class="tab-pane" id="tab@(i + 1)" name="@(i + 1)">
<fieldset>
<!-- ... -->
</fieldset>
</div>
}
<ul class="pager wizard">
<li class="previous"><a href="javascript:void(0);">Retour</a></li>
<li class="next"><a href="javascript:void(0);">Suivant</a></li>
</ul>
</div>
</form>
现在您正在创建多个表单。如果您想创建一个大表单,则只需要创建一个表单,其中包含多个选项卡和字段集。
您可能没有携带数据。每个请求都是独立的,因此它必须 post 来自先前请求的所有数据 或 您必须以某种方式保留先前 posted 的数据,要么将其存储在数据库或会话。
很难从所提供的代码中准确判断这是如何运作的。通过第三次联系,用户是否会在屏幕上看到 3 套完整的联系方式?换句话说,第一次通过时,只有一组字段。第二次通过,有两套第一次填写,最后第三次,有两套有填充数据和一套空的准备由用户填写?
如果是这样的话,我会说这很糟糕UI。真的,最好放弃所有 post 在服务器之间来回切换,一次渲染所有三个集合,这样用户就可以一次性输入它们。
如果情况并非如此,并且每次您都只显示一组字段,那为什么会有一个循环?您还需要在请求之间以某种方式保留其他联系人。