ASP .NET MVC Partial View is rendering unexpected html based on Model. Can someone please explain why this is happening? There seems to be something about rendering Partial Views that I don’t understand. Thank you in advance.
I have a simple MVC Partial View that binds to a list of Person objects. I make two Ajax calls one for adding and one for removing a person from the list. The Adding of a person works fine. The Removing of a person always removes the last person object from the list instead of rendering the html according to the persons that are in the list from the Model.
After adding 2 persons (click Add Person button twice and enter names): adding 2 persons
After I hit remove button for “Person B” calls the RemovePerson() JS function, which calls the PersonController RemovePerson() Action. The Controller removes the item with the specified index from the list but the HTML coming from the partial view does not reflects the new updated model. Instead of removing person B always removes last person in this case “Person C” even though I am passing the appropriate index and removing the item from the list in the controller.
I have added the Visual Studio solution as a zip file in GitHub: https://github.com/peter-base/PersonList
Index View:
//adds a new person textbox
function OnAddPerson() {
$.ajax({
cache: false,
type: "POST",
url: "/Person/AddPerson",
data: $("#person-list-form").serialize(),
success: function (partialView) {
$("#persons-container").html(partialView);
},
error: function (jqXHR, textStatus, errorThrown) {
alert("error:" + errorThrown);
},
complete: function () {
}
});
};
function RemovePerson(index) {
$("#remove_person_index").val(index);
alert("index: " + $("#remove_person_index").val());
$.ajax({
cache: false,
type: "POST",
url: "/Person/RemovePerson",
data: $("#person-list-form").serialize(),
success: function (partialView) {
$("#persons-container").html(partialView);
},
error: function (jqXHR, textStatus, errorThrown) {
alert("error:" + errorThrown);
},
complete: function () {
}
});
};
@using PersonList.Models
<script src="~/Scripts/PersonList.js"></script>
@{
ViewBag.Title = "Index";
}
<div>
<h2>Index - Persons</h2>
<button type="button" class="btn btn-default form-control" onclick="OnAddPerson();">
<span class="glyphicon glyphicon-plus" aria-hidden="true"></span> Add Person
</button>
</div>
<div id="persons-container">
@*List of Persons*@
@Html.Partial("_PersonList", new List<Person>() { new Person() { Index = 0, Name = "Person A" } }, new ViewDataDictionary())
</div>
<!-- Partial View in Different File --> @model
List<PersonList.Models.Person>
@using (Html.BeginForm("", "", FormMethod.Post, new { @id = "person-list-form", @name = "person-list-form" })) {
for (int i = 0; i < Model.Count; i++)
{
<div class="panel panel-info">
<div class="panel-body">
<div class="col-md-2">
@Html.HiddenFor(m => m[i].Index)
<label class="control-label">Name</label>
@Html.TextBoxFor(m => m[i].Name,
new
{
@class = "ccb-nodes form-control",
@placeholder = "Enter CR-CN"
})
</div>
<div class="col-md-2">
<button type="button" id="@Model[i].Index" class="btn btn- primary" onclick="RemovePerson(this.id)">Remove</button>
</div>
</div>
</div>
}
@Html.Hidden("remove_person_index", 1, new { @id = "remove_person_index" })
}
Person Object:
public class Person
{
public string Name { get; set; }
public int Index { get; set; }
}
Person Controller:
public class PersonController : Controller
{
// GET: Person
public ActionResult Index()
{
return View();
}
[HttpPost]
public ActionResult AddPerson(List<Person> personList)
{
//add new person
personList.Add(new Person());
//set indexes
for (int i = 0; i < personList.Count; i++)
{
personList[i].Index = i;
}
return PartialView("_PersonList", personList);
}
[HttpPost]
public ActionResult RemovePerson(List<Person> personList, int remove_person_index)
{
//remove person
var person = personList.FirstOrDefault(i => i.Index == remove_person_index);
if (person != null)
{
personList.Remove(person);
}
//set indexes
for (int i = 0; i < personList.Count; i++)
{
personList[i].Index = i;
}
return PartialView("_PersonList", personList);
}
}