i want to submit a form with for loop inside of it that loops over the form controllers since i want to pass list of model into a post method action in such a way that each and every form controller ( TextBoxFor ) is populated by corresponding value of my list of model
my Model :
public class ExcelRowData
{
public string LastName { get; set; }
public string FirstName { get; set; }
public string Score { get; set; }
public string EnrollmentTime { get; set; }
public string GraduationTime { get; set; }
}
and this is my view :
@model List<NewTest.Models.ExcelRowData>
@using (Html.BeginForm("Delete", "MyTest", FormMethod.Post))
{
for (var i = 0 ; i < Model.Count ; i++)
{
<tr>
<td>@Html.TextBoxFor(p => Model[i].LastName)</td>
<td>@Html.TextBoxFor(p => Model[i].FirstName)</td>
<td>@Html.TextBoxFor(p => Model[i].Score)</td>
<td>@Html.TextBoxFor(p => Model[i].EnrollmentTime)</td>
<td>@Html.TextBoxFor(p => Model[i].GraduationTime)</td>
<td><input type="submit" formaction="@Url.Action("Delete", "MyTest", new {Ln = Model[i].LastName})" value="Delete"/></td>
</tr>
}
}
i populated my model from excel file then i show the excel data in above table in view and then there is a delete button in case of deleting a record
and in my delete action i delete the selected record by the parameter passed from submit button , after that i repopulate my model and again i pass it to the same view
this is the delete action in my controller :
[HttpPost]
public ActionResult Delete(ExcelRowData evm, string Ln)
{
var exceldata = new List<ExcelRowData>();
var del = evm.FirstOrDefault(p => p.LastName == Ln);
evm.Remove(del);
foreach (var item in evm)
{
exceldata.Add(
new ExcelRowData { LastName = item.LastName, FirstName = item.FirstName, Score = item.Score, EnrollmentTime = item.EnrollmentTime, GraduationTime = item.GraduationTime}
);
}
return View("ExcelTable", exceldata);
}
the problem is when i press delete button in any row , it delets the record from bottom of the list , it doesn't matter which row i click to delete , it deletes from bottom of the list.
You posting back the whole collection, so all the property values have been added to
ModelState
, and theHtmlHelper
methods that generate form controls (exceptPasswordFor()
) use the values fromModelState
(if they exist) rather the the property value.You can solve this by adding
before you return the view, however the correct approach is to follow the PRG (Post, Redirect Get) pattern, and redirect to your GET method.
To understand why the
HtmlHelper
methods useModelState
, refer this answer.As a side note, you can improve performance by using ajax to remove the item (and if successfully deleted, remove the corresponding row from the DOM), but that means you also need to include a hidden input for the collection indexer so that you can post back non-zero/non-consecutive indexers if your also posting back the updated collection elsewhere in your view. The input would be
<input type="hidden" name="Index" value = "@i" />