我有一个场景,我想向用户显示数据并允许他们修改它。为此,我有一个预设当前对象值的表单。这个表单被封装为一个局部视图,根据我的父对象有多少个子对象,这个视图依次被调用。
我还在最后提供了一个空表单,以允许用户创建这个子项的新实例,所以简而言之我有这样的事情:
编辑表格(部分视图):
@model WebPortal.Models.AddressModel
@using (Html.BeginForm("EditAddress", "MerchantDetailsEditor", FormMethod.Post))
{
@Html.ValidationSummary(true)
@Html.LabelFor(model => model.StreetNumber, new { id = Model.ID + "_streetnumber_label", Name = Model.ID + "_streetnumber_label", @for = Model.ID + "_streetnumber" })
@Html.TextBoxFor(address => address.StreetNumber, new { id = Model.ID + "_streetnumber", Name = Model.ID + "_streetnumber"})
@Html.ValidationMessageFor(address => address.StreetNumber)
创建表单(另一部分视图)
@model WebPortal.Models.AddressModel
@{
int counter = 1;
}
@using (Html.BeginForm("AddAddress", "MerchantDetailsEditor", FormMethod.Post))
{
@Html.ValidationSummary(true)
@Html.LabelFor(model => model.StreetNumber, new { id = counter + "_streetnumber_label", Name = counter + "_streetnumber_label", @for = counter + "_streetnumber" })
@Html.TextBoxFor(address => address.StreetNumber, new { id = counter + "_streetnumber", Name = counter + "_streetnumber"})
@Html.ValidationMessageFor(address => address.StreetNumber)
counter++;
反过来这样称为:
@foreach (WebPortal.Models.AddressModel address in @Model.Addresses)
{
@Html.Partial("Edit_Form", address)
}
@Html.Partial("Add_Form", new WebPortal.Models.AddressModel())
我面临的问题是,由于它们都共享相同的模型,因此验证错误正在应用并显示在我显示的所有实例旁边。所以,如果我在哪里编辑一个对象,我会得到错误,因为另一个表单(添加表单)是空的。
我已经读过,这是因为MVC在视图级别应用了组件ID
,所以由于我使用的是同一视图的多个实例,因此它们都获得了相同的ID。
为了解决这个问题,我覆盖了ID
和Name
的属性,但无济于事。
基本上,我只是希望错误消息显示在相应的表单旁边。我对这种方法相当环保,所以如果不正确请告诉我。我的目标是允许用户在特定屏幕上查看/编辑和创建数据。
谢谢!
答案 0 :(得分:0)
请勿自行生成name
和id
属性的值。如果你使用:
HtmlFieldPrefix
传入您的部分观看次数See this blog for more details 我要向您展示的解决方案是编辑模板。
AddressModel.cshtml(编辑器模板)
@model WebPortal.Models.AddressModel
@Html.LabelFor(model => model.StreetNumber)
@Html.TextBoxFor(address => address.StreetNumber)
@Html.ValidationMessageFor(address => address.StreetNumber)
视图的
@for (int i = 0; i < Model.Addresses.Count; i++)
{
using (Html.BeginForm("EditAddress", "MerchantDetailsEditor"))
{
@Html.ValidationSummary(true)
<input type="hidden" name="Addresses.Index" value="@i" /> //http://haacked.com/archive/2008/10/23/model-binding-to-a-list.aspx/
@Html.EditorFor(m => m.Addresses[i]) //uses AddressModel.cshtml
<input type="submit" value="Edit" />
}
}
@using (Html.BeginForm("AddAddress", "MerchantDetailsEditor"))
{
@Html.ValidationSummary(true)
@Html.EditorFor(m => m.AddAddress)
<input type="submit" value="Add" />
}
控制器的
[HttpPost]
public ActionResult EditAddress([Bind(Prefix="Addresses")] AddressModel[] i)
{
//learn more about BindAttribute here
http://stackoverflow.com/questions/1317523/how-to-use-bind-prefix
}
[HttpPost]
public ActionResult AddAddress([Bind(Prefix = "AddAddress")] AddressModel i)
{
}
生成的HTML
请注意,name
和id
属性具有唯一的数字索引,在此示例中为0
<form action="/Home/EditAddress" method="post">
<input type="hidden" name="Addresses.Index" value="0" />
<label for="Addresses_0__StreetNumber">Street Number</label>
<input data-val="true" data-val-required="The Street Number field is required." id="Addresses_0__StreetNumber" name="Addresses[0].StreetNumber" type="text" value="" />
<span class="field-validation-valid" data-valmsg-for="Addresses[0].StreetNumber" data-valmsg-replace="true"></span>
<input type="submit" value="Edit" />
</form>
答案 1 :(得分:0)
我最终设法让这个工作。在遇到this之前的问题后,我选择使用Actions
。所以代码现在看起来像这样:
编辑表格(仍然是部分观点)
@model WebPortal.Models.AddressModel
@using (Html.BeginForm("EditAddress", "MerchantDetailsEditor", FormMethod.Post))
{
@Html.ValidationSummary(true)
@Html.HiddenFor(model => model.ID)
@Html.LabelFor(model => model.StreetNumber, new { id = Model.ID + "_streetnumber_label" })
@Html.TextBoxFor(address => address.StreetNumber, new { id = Model.ID + "_streetnumber" })
@Html.ValidationMessageFor(address => address.StreetNumber)
...
创建表单(仍然是部分视图)
@model WebPortal.Models.AddressModel
@{
int counter = 1;
}
@using (Html.BeginForm("AddAddress", "MerchantDetailsEditor", FormMethod.Post))
{
@Html.ValidationSummary(true)
@Html.LabelFor(model => model.StreetNumber, new { id = counter + "_streetnumber_label" })
@Html.TextBoxFor(address => address.StreetNumber, new { id = counter + "_streetnumber"})
@Html.ValidationMessageFor(address => address.StreetNumber)
...
主要变化是我接下来做的事情:
<h2>Addresses</h2>
@foreach (WebPortal.Models.AddressModel address in @Model.Addresses)
{
@Html.Action("_AddressEdit", address)
}
@if (ViewBag.AddressToAdd != null)
{
@Html.Action("_AddressAdd", (WebPortal.Models.AddressModel)ViewBag.AddressToAdd)
}
else
{
@Html.Action("_AddressAddNew")
}
我基本上为部分视图的每个实例提供了一个动作。这使我能够解决我的答案中链接中暴露的问题。
我的控制器现在看起来像这样:
#region Actions
public ActionResult _AddressEdit(AddressModel addressModel)
{
return View("...", addressModel);
}
public ActionResult _AddressAdd(AddressModel addressModel)
{
return View("...", addressModel);
}
public ActionResult _AddressAddNew()
{
return View("...");
}
#endregion Actions