I have a scenario in which I would like to display data to users and allow them to be able to modify it. To do this, I have a form which is preset with the current object values. This form is enclosed as a partial view which is in turn called in a loop depending on how many child objects my parent object has.
I also provide an empty form at the end to allow users to create new instances of this child item, so in short I have something like so:
Edit Form (a partial view):
@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)
Create Form (another partial view)
@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++;
Which are in turn called like so:
@foreach (WebPortal.Models.AddressModel address in @Model.Addresses)
{
@Html.Partial("Edit_Form", address)
}
@Html.Partial("Add_Form", new WebPortal.Models.AddressModel())
The problem I am facing is that since they are all sharing the same model, the validation errors are being applied and shown next to all instances I have displayed. So if I where to edit an object, I would get errors because the other form (the add form) was empty.
I have read that this is due to the fact that MVC applies the component ID
's at a view level, so since I am using multiple instances of the same view, they are all getting the same ID's.
To go round this I overrode the properties for the ID
and Name
, but to no avail.
Essentially, I just want the error messages to be shown next to the appropriate form. I am fairly green on this type of approach, so if it is incorrect please do let me know. My objective is to allow users to View/Edit and Create data on a particular screen.
Thanks!
I eventually managed to get this working. After coming across this previous SO question, I opted to use Actions
instead. So the code now looks something like so:
EDIT Form (Still a partial view)
@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)
...
Create Form (Still a partial view)
@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)
...
The major change is what I did next:
<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")
}
I essentially provided an action per instance of my partial view. This allowed me to go round the problem exposed in the link in my answer.
My controller now looks like so:
#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
Collected from the Internet
Please contact [email protected] to delete if infringement.
Comments