I have a textbox that when the user enters a string and presses a button this is then compared to find which matching fields are in database. I also have another button that launches the display of a bootstrap modal which then views the results.
The issue I'm having is I only want one button but when I try to combine the two i get the modal and the string search never happens.
Can anyone tell me how I combine the two ?
Button 1 (search string button)
#using (Html.BeginForm("Index", "Home", FormMethod.Get))
{
<p>
<label for="platform" class="control-label">Enter Code:</label><br />
#Html.TextBox("filtername")
<input type="submit" value="Filter" "/>
</p>
}
Button 2 (Activates modal but no data comparision)
<div class="form-group">
<div class="col-xs-offset-2 col-xs-10">
<div class="span7 text-center">
<input type="text" class="form-control" id="theCode" placeholder="Please Enter Code">
<input type="submit" value="Go!" class="btn btn-success" id="sendcoderequest" data-toggle="modal"
data-target="#basicModal2" />
</div>
</div>
</div>
Home/Index Method:
public ActionResult Index(string filtername)
{
var filterresults = from m in db.UserInfoes
select m;
filterresults = filterresults.Where(x => x.UserCode.ToString().Contains(filtername)).OrderBy(x => x.UserCode);
return View(filterresults);
}
Modal :
<div class="modal fade" id="basicModal2" tabindex="-1" role="dialog" aria-labelledby="basicModal" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
<h4 class="modal-title" id="myModalLabel">Summary</h4>
</div>
<div class="modal-body">
<h2>Results</h2>
<span id="printCode"></span><br />
<div class="pull-right"><button type="submit" class="btn btn-success" id="toggle">Toggle</button> </div>
<table class="table">
<thead>
<tr>
<th></th>
<th>Date</th>
<th>Test Type</th>
</tr>
</thead>
<tbody>
#foreach (var item in Model)
{
<tr>
<td>
<input type="checkbox" class="checks">
</td>
<td>
#Html.DisplayFor(modelItem => item.CreationDateTime)
</td>
<td>
#Html.DisplayFor(modelItem => item.AppModeId)
</td>
</tr>
}
</tbody>
</table>
Code currently working with:
Form:
<form id="formid">
<label for="platform" class="control-label">Enter Code:</label>
<input type="text" name="filtername" />
<input type="submit" class="btn btn-success" value="Filter" />
</form>
JQuery:
$("#formid").submit(function () {
$.ajax({
url: "Home",
data: $(this).serialize()
}).done(function (response) {
$('#modal_content').html(response);
$('#basicModal2').modal('show');
});
return false; // prevent the form submission
});
Modal is unchanged.
You could use an AJAX call instead of the form submission. Then you could open the modal via Javascript once you receive the AJAX response. According to the tags, you're probably using JQuery, so it would look like this :
$("form").submit(function(){
$.ajax({
url: "Home",
data: $(this).serialize()
}).done(function(response){
// Fill your modal window with the response here
$('#basicModal2').modal('show');
});
return false; // prevent the form submission
});
Edit
You can find here an example that uses AJAX to send the filter name to the server, fill the modal with the server response and finally show the modal:
http://jsfiddle.net/yohanrobert/e3p4yv55/
Related
I started to learn some basic c# and im trying to find my way into ASP.net
I am running the following code with some help from this video: https://www.youtube.com/watch?v=C5cnZ-gZy2I (time stamp: 1 hour and 50min)
public class BestellenModel : PageModel
{
private ApplicationDbContext _db;
public BestellenModel(ApplicationDbContext db)
{
_db = db;
}
[BindProperty]
public Bedrijven Bedrijven { get; set; }
public async Task OnGet(int id)
{
Bedrijven = await _db.Bedrijven.FindAsync(id);
}
}
}
In the video whenever the edit button is pressed the right data from the data base appears on screen. For me nothing appears but whenever i click on my url and hit enter again the data appears.
I tried the debug option within VS and i saw that the line FindAsync doesn't run when hitting the button. But when i click enter on the url then it runs the code. My url looks like this: https://localhost:7005/Bedrijfslijst/Bestellen?id=32
Can anyone tell me what i am missing here? because i am a bit stuck.
Edit:
Now whenever the client Clicks on the "kopen" button it needs to render the data from the db to the fields.
This is a screenshot from the yt video, its supposed to show the data when the page is loaded. For me its not loading but whenever i click on the url and hit enter then the db data will load in.
cshtml script:
#page
#model test1v1.Pages.Bedrijfslijst.BestellenModel
<br />
<h2 class="text-primary">Rapport bestellen</h2>
<br />
<div class="border container" style="padding:120px;">
<form method="post">
<div class="text-danger" asp-validation-summary="ModelOnly"></div>
<div class="form-group row" style="padding:10px;">
<div class="col-4">
<label asp-for="Bedrijven.Kvk"></label>
</div>
<div class="col-4">
<input asp-for="Bedrijven.Kvk" class="form-control" />
</div>
<span asp-validation-for="Bedrijven.Kvk" class="text-danger"></span>
</div>
<div class="form-group row" style="padding:10px;">
<div class="col-4">
<label asp-for="Bedrijven.Bedrijfsnaam"></label>
</div>
<div class="col-4">
<input asp-for="Bedrijven.Bedrijfsnaam" class="form-control" />
</div>
<span asp-validation-for="Bedrijven.Bedrijfsnaam" class="text-danger"></span>
</div>
<div class="form-group row" style="padding:10px;">
<div class="col-4">
<label asp-for="Bedrijven.Adres"></label>
</div>
<div class="col-4">
<input asp-for="Bedrijven.Adres" class="form-control" />
</div>
<span asp-validation-for="Bedrijven.Adres" class="text-danger"></span>
</div>
<div class="form-group row" style="padding:10px;">
<div class="col-3 offset-4">
<input type ="submit" value="Bestellen" class="btn btn-success form-control" />
</div>
<div class="col-3">
<a asp-page="index" class="btn btn-primary form-control">Terug</a>
</div>
</div>
</form>
</div>
#section Scripts{
<partial name ="_ValidationScriptsPartial"/>
}
Edit2:
#page
#model test1v1.Pages.Bedrijfslijst.IndexModel
<br />
<div class="container row p-0 m-0">
<div class="col-9">
<h2 class="text-primary">Bedrijf Lijst</h2>
</div>
<div class="col-3">
<a asp-page="Zoeken" class="btn btn-primary form-control text-white">Bedrijf Zoeken</a>
</div>
<div class= "col-10 border p-4 mt-4">
<form method="post">
#if (Model.Bedrijven.Count() > 0)
{
<table class="table table-striped border">
<tr class="table-secondary">
<th>
<label asp-for="Bedrijven.FirstOrDefault().Kvk"></label>
</th>
<th>
#*#Html.DisplayNameFor(m=>m.Books.FirstOrDefault().Author)*#
<label asp-for="Bedrijven.FirstOrDefault().Bedrijfsnaam"></label>
</th>
<th>
<label asp-for="Bedrijven.FirstOrDefault().Adres"></label>
</th>
<th>
</th>
</tr>
#foreach (var item in Model.Bedrijven)
{
<tr>
<td>
#Html.DisplayFor(m=>item.Bedrijfsnaam)
</td>
<td>
#Html.DisplayFor(m=>item.Kvk)
</td>
<td>
#Html.DisplayFor(m=>item.Adres)
</td>
<td>
<button asp-page="Bestellen" asp-route-id="#item.Id" class="btn btn-primary btn-sm">Kopen</button>
</td>
</tr>
}
</table>
}
else
{
<p>Geen Bedrijven Gevonden.</p>
}
</form>
</div>
</div>
I have a form that displays a persons title and name.It shows a lot more than that, but this is the bit I am asking about.
I have a person table.
If the user wants to change the person details, is it possible to open up a pop up modal form that lists all the persons in the person table, so that the user can either select an existing person, or insert a new person and when the user closes the pop up, the main form is populated with the selected/new persons details?
I am using ASP.NET Core MVC 5 and EF Core 5.
Any help or pointing to a tutorial would be a great help, thanks.
UPDATE -
I have tried the following -
I have created a modal partial view -
#model Person
<div class="modal fade" id="personModal" >
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h4 class="modal-title" id="personModalLabel">Persons</h4>
<button type="button" class="close" data-dismiss="modal">
<span>x</span>
</button>
</div>
<div class="modal-body">
<form action="Create">
<table class="table table-bordered table-striped table-hover">
<tbody>
#foreach (var pers in ViewBag.PersonList)
{
<tr>
<td style="display:none">#pers.Id</td>
<td class="text-left">
<a asp-action="details" asp-controller="admin" asp-route-id="#pers.Id" title="Click to select vaccination centre">#pers.Title.Description</a><br />
</td>
<td class="text-left ">
#pers.Forename
</td>
<td class="text-left ">
#pers.Surname
</td>
</tr>
}
</tbody>
</table>
<br />
<div class="form-row">
<label asp-for="TitleId" class="control-label col-md-2">Title</label>
<div class="col-md-4 mb-2">
<select asp-for="TitleId" asp-items="#(new SelectList(ViewBag.TitleList, "Id", "Description"))" style=" width: 363px; height: 37px"></select>
<span asp-validation-for="TitleId" class="text-danger"></span>
</div>
</div>
<div class="form-row">
<label asp-for="Forename" class="control-label col-md-2">Forename</label>
<div class="col-md-4 mb-2">
<input asp-for="Forename" class="form-control" maxlength="100" />
<span asp-validation-for="Forename" class="text-danger"></span>
</div>
</div>
<div class="form-row">
<label asp-for="Surname" class="control-label col-md-2">Surname</label>
<div class="col-md-4 mb-2">
<input asp-for="Surname" class="form-control" maxlength="100" />
<span asp-validation-for="Forename" class="text-danger"></span>
</div>
</div>
</form>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-primary" data-dismiss="modal">Close</button>
<button type="button" class="btn btn-primary" data-save="modal">Save</button>
</div>
</div>
</div>
</div>
I have added the following script to site.js -
$(function () {
var placeHolderElement = $('#PlaceHolderHere');
$('button[data-toggle="ajax-modal"]').click(function (event) {
var url = $(this).data('url');
$.get(url).done(function(data) {
placeHolderElement.html(data);
placeHolderElement.find('.modal').modal('show');
})
})
placeHolderElement.on('Click', '[data-save="modal"]', function (event) {
var form = $(this).parents('.modal').find('form');
var actionUrl = form.attr('action');
var sendData = form.serialize();
$.post(actionUrl, sendData).done(function (data) {
placeHolderElement.find('.modal').modal('hide');
})
})
})
And the controller -
[HttpGet]
public IActionResult Create()
{
List<Person> personList = _personRepository.Persons.ToList();
ViewBag.PersonList = personList;
List<Title> titleList = _titleRepository.Titles.ToList();
ViewBag.TitleList = titleList;
Person pers = new Person();
return PartialView("_PersonModalPartial", pers);
}
[HttpPost]
public IActionResult Create(Person pers)
{
_personRepository.CreatePerson(pers);
List<Person> personList = _personRepository.Persons.ToList();
ViewBag.PersonList = personList;
List<Title> titleList = _titleRepository.Titles.ToList();
ViewBag.TitleList = titleList;
return PartialView("_PersonModalPartial", pers);
}
I call the modal with the the following in my main form -
<button type="button" class="btn btn-primary" data-toggle="ajax-modal" data-target="#personModal"
data-url="#Url.Action("Create")" >Insert</button>
The above code shows the modal and populates the table.
However nothing happens when you press save!?
UPDATE 2 -
I changed the button in the modal for to
input type="submit" value="Submit" name="Submit" class="btn btn-success float-right" id="SubmitForm" />
And then changed the form tag in my modal form to -
<form method="post" asp-controller="Admin" asp-action="Create">
That worked.
Now I am wondering how you can pass the id value of the model into the Modal form using the data-url part of the calling button?
<button type="button" class="btn btn-primary" data-toggle="ajax-modal" data-target="#personModal"
data-url="#Url.Action("Create")" >Insert</button>
You can use #Url.Action("Create",new { id=xxx}),here is a demo:
Html(I use "sss" as a sample data of id):
<button type="button" class="btn btn-primary" data-toggle="ajax-modal" data-target="#personModal"
data-url="#Url.Action("Create1",new { id="sss"})">
Insert
</button>
js:
$('button[data-toggle="ajax-modal"]').click(function (event) {
var url = $(this).data('url');
$.get(url).done(function (data) {
placeHolderElement.html(data);
placeHolderElement.find('.modal').modal('show');
})
})
Controller:
public IActionResult Create1(string id) {
return Ok();
}
result:
Update:
If you want to use #Model.Id:
<button type="button" class="btn btn-primary" data-toggle="ajax-modal" data-target="#personModal"
data-url="#Url.Action("Create1",new { id=Model.Id})">
Insert
</button>
i am trying to populate modals with different data, i create the modals buttons using a foreach loop and then i want to apply the relevant data to the right modal.
The problem i have is that the modal is showing the same data for each modal button. How can i make this unique? When its doing its loop its actually placing the correct info but when the page loads its only showing one type of data for every modal.
#foreach (DataRow row in Model.Tables[0].Rows)
{
<tr>
<td>#row["SerialNumber"]</td>
<td>#row["DtTmGenerated"]</td>
<td>
<button type="button" class="btn btn-danger btn-sm" data-toggle="modal" data-target="#myModal">View Error</button>
</td>
</tr>
}
</thead>
<tbody></tbody>
</table>
#if (Model.Tables[0].Rows.Count != 0)
{
<script type='text/javascript'>
window.onload = function() {
document.getElementById("cssClass").style.display = 'none';
}
</script>
}
<!-- Modal -->
<div id="myModal" class="modal fade" role="dialog">
<div class="modal-dialog">
<!-- Modal content-->
<div class="modal-content">
<div class="modal-header">
<h4 class="modal-title justify-content-center">Panda Error information</h4>
</div>
<div class="modal-body">
#foreach (DataRow row in Model.Tables[0].Rows)
{
var test = Convert.ToString(row["FriendlyError"]);
if (test != "No Error" )
{
<p>#row["FriendlyError"]</p>
}
}
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
</div>
</div>
</div>
</div>
</body>
</html>
I'm a bit late but I had the same problem today and I managed to fix it :D
The problem is the ID of the modal. In each new loop pass your modal is created with the same ID.
In other words: Your values, which come into the modal always change, but because the ID is static, all further modals get the same values as in the first one, because all have the same ID. Try this:
Add this code right after your model (#model ...)
#{
int ModalId = 0;
}
Then change the ID in the button that opens your modal:
data-target="##ModalId"
In the line before you close your foreach, add this
#(ModalId++)
Change your modal to this and put it into your foreach so that it looks like this:
#foreach (DataRow row in Model.Tables[0].Rows)
{
<tr>
<td>#row["SerialNumber"]</td>
<td>#row["DtTmGenerated"]</td>
<td>
<button type="button" class="btn btn-danger btn-sm" data-toggle="modal" data-target="##ModalId">View Error</button>
<!-- Modal -->
<div id="#ModalId" aria-labelledby="#ModalId" class="modal fade" role="dialog">
<div class="modal-dialog">
<!-- Modal content-->
<div class="modal-content">
<div class="modal-header">
<h4 class="modal-title justify-content-center">Panda Error information</h4>
</div>
<div class="modal-body">
#foreach (DataRow row in Model.Tables[0].Rows)
{
var test = Convert.ToString(row["FriendlyError"]);
if (test != "No Error")
{
<p>#row["FriendlyError"]</p>
}
}
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
</div>
</div>
</div>
</div>
</td>
</tr>
#(ModalId++)
}
</thead>
<tbody>
</tbody></table>
#if (Model.Tables[0].Rows.Count != 0)
{
<script type='text/javascript'>
window.onload = function() {
document.getElementById("cssClass").style.display = 'none';
}
</script>
}
</body>
</html>
In summary: Wherever you had "myModal" as ID, you must replace it with #ModalId
I have a table that has dynamic buttons which bring up a modal with info. Within the modal i want to add a new row to a table when i click a button.
I display the modal from within my main view, then call a partial to show the info inside the table in the modal.
From within the partial I've tried using append but doesn't seem to work, I thought jQuery could add to the table and I wouldn't have to invoke any kind of refresh.
My question is: how can I refresh my table from inside the partial?
I believe that jQuery is adding to the td but its just not being updated
EditApplication.cshmtl main view
<form method="POST">
<div class="modal fade" id="editAppModal" tabindex="-1" role="dialog" aria-labelledby="editAppModal" aria-hidden="true">
<div class="modal-dialog modal-lg">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="editAppModal">Edit Application</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
<input type="text" id="appName">
<input type="text" id="appShortName" style="width:15%">
<hr>
<table id="modalServerTB" style="border-collapse: separate; border-spacing: 5px 15px;">
</table>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
<button type="submit" class="btn btn-primary" asp-page-handler="UpdateApplication">Update Application</button>
</div>
</div>
</div>
</div>
</form>
jQuery in main view
<script>
$(document).ready(function(){
$(".selectRow").click(function(e)
{
e.preventDefault();
var row = $(this).closest("tr"),
tds = row.find("td:nth-child(1)").first(); //get row closest to click then grab first column info
var textval = $.trim(tds.text()); //tons of whitespace around the text, needs to be removed
$.ajax({
url: "EditApplication?handler=GetRowInfo",
type: "POST",
dataType: "json",
data: { textval },
beforeSend: function (xhr) {
xhr.setRequestHeader("XSRF-TOKEN",
$('input:hidden[name="__RequestVerificationToken"]').val());
},
complete: function (result) {
$("#appName").val(textval);
$("#appShortName").val(result.responseJSON);
$('#modalServerTB').load('/EditApplication?handler=ServerPartial');
$('#editAppModal').modal('show');
}
})
});
});
</script>
partial view
<tbody id="tableBody">
#foreach(var s in Model.serverUrl)
{
<tr style="border-bottom: 0.3px outset whitesmoke" >
<td style="width:40%">
<input type="text" value="#s.Key">
</td>
<td>
#foreach(var u in s.Value)
{
#Html.DropDownListFor(a=>u.Urlid, Model.urls, new{style = "width:50%", #class = "selectedURL"})
<br>
}
</td>
<td class="newURLS" style="border:solid 1px">
</td>
<button class="AddURLBtn"> + </button>
<br>
</tr>
}
</tbody>
<div>
<button type="button" class="btn btn-dark btn-sm" id="AddServerBtn">Add Server </button>
</div>
#Html.DropDownList("selectedURL",Model.urls, "Select URL" , new {style = "width:50%; display:none;", #class = "selectedURL", id="urlDDL"})
<script>
$(document).ready(function(){
$(".AddURLBtn").click(function(e)
{
e.preventDefault();
console.log("inaddurl");
$(".newURLS").append('sgagfsafsafsf');
});
});
</script>
As of right now i was just testing to see if i can add just text to the td but it doesn't seem to work
I am also passing a view model to my partial
Turns out you need a table tag for this to all work. With just TBody the div was not being created therefore my jquery function had no target
<table>
<tbody id="tableBody">
#foreach(var s in Model.serverUrl)
{
<tr style="border-bottom: 0.3px outset whitesmoke" >
<td style="width:40%">
<input type="text" value="#s.Key">
</td>
<td class="urlsTD">
#foreach(var u in s.Value)
{
#Html.DropDownListFor(a=>u.Urlid, Model.urls, new{style = "width:50%", #class = "selectedURL"})
<br>
}
</td>
<td>
<button class="AddURLBtn"> + </button>
</td>
</tr>
}
</tbody>
<div>
<button type="button" class="btn btn-dark btn-sm" id="AddServerBtn">Add Server </button>
</div>
</table>
I have a cshtml page that will be sending a list of items over to my controller. However when i click on the submit button, nothing is being passed over to my controller.
The codes below is my cshtml codes which will pass the model over to my controller.
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
<div class="form-group">
#if (Model.Count() != 0)
{
<input type='button' value='Save and Update' class="btn btn-primary" data-toggle="modal" data-target="#myModal" />
}
</div>
<table class="table cell-border" id="TempTable5">
<tbody>
#if (Model.Count() != 0)
{
int j = 0;
foreach (var item in Model)
{
#Html.HiddenFor(model => item.ExerciseInstruction.ExerciseInstructionID)
<tr>
<td align="center">
<div class="form-group">
#Html.DisplayFor(model => item.ExerciseInstruction.ExerciseInstructionID)
</div>
</td>
<td>
<div class="form-group">
#Html.DisplayFor(model => item.Exercise.Name)
</div>
</td>
<td>
<div class="form-group">
<iframe width="300" height="175" src=#item.ExerciseVideo.VideoURL frameborder="0" allowfullscreen></iframe>
</div>
</td>
<td align="center">
#Html.DisplayFor(model => item.Therapist.Name)
</td>
<td>
#Html.DisplayFor(model => item.ExerciseInstruction.Prescribed_Date)
</td>
<td>
No. of Reps: #item.ExerciseInstruction.Number_Of_Reps<br />
No. of Secs to hold: #item.ExerciseInstruction.Number_Of_Secs_PositionHold<br />
No. of Sets: #item.ExerciseInstruction.Number_Of_Sets_Per_Day<br />
No. of Times: #item.ExerciseInstruction.Frequency_Per_Week<br />
Remarks: #if (item.ExerciseInstruction.Remark == null || item.ExerciseInstruction.Remark.Trim() == "")
{
#:NIL
}
else
{
#item.ExerciseInstruction.Remark
}
</td>
<td align="center">
#Html.EditorFor(model => item.ExerciseInstruction.ToPerform, new { htmlAttributes = new { style = "width:23px; height:23px;" } })
</td>
<td>
#Html.ActionLink("View", "Details", new { id = Model[j].ExerciseInstruction.ExerciseInstructionID, pageFrom = "performExercises" }, new { target = "_blank" })
</td>
</tr>
j++;
}
}
</tbody>
</table>
#if (Model.Count() != 0)
{
<input type='submit' value='Save and Update' class="btn btn-primary" data-toggle="modal" data-target="#myModal" />
}
}
The controller that is working on this is as below.
[HttpPost]
[ValidateAntiForgeryToken]
[Authorize(Roles = "Therapist")]
public ActionResult ToPerformExercises(int? pid, List<AssignmentViewModel> avmLIst)
{
if (ModelState.IsValid)
{
foreach (var item in avmLIst)
{
ExerciseInstruction eI = db.ExerciseInstructions.SingleOrDefault(a => a.ExerciseInstructionID == item.ExerciseInstruction.ExerciseInstructionID);
eI.ToPerform = item.ExerciseInstruction.ToPerform;
db.Entry(eI).State = EntityState.Modified;
db.SaveChanges();
}
}
return RedirectToAction("ViewToPerform", "AssignExercisesViewModel", new { pid = pid });
}
This is the submit pop up box
<div id="myModal" class="modal fade" role="dialog">
<div class="modal-dialog">
<!— Modal content-->
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal">×</button>
<h4 class="modal-title">Confirmation</h4>
</div>
<div class="modal-body">
<p>Are you sure you want to add/remove the Ongoing Exercise(s) for the patient?</p>
</div>
<div class="modal-footer">
<input type="button" class="btn btn-primary" value="Confirm" onclick="DisableButton(this)" />
<button type="button" class="btn btn-default" data-dismiss="modal" id="cancel">Cancel</button>
</div>
</div>
</div>
</div>
My problem is very similar to this link Jquery tool DataTable unable to post/submit in an MVC3 Html.BeginForm
However i am unsure of how he actually solve it as the explanation on his answer was really brief.
Can anyone assist?
There's a lot going on here, but I'll take a shot at it based on a common pitfall in model binding... You should change the foreach to a for loop, then alter your HtmlEditorFor calls to use the index.
So to greatly simplify what you have above...
for(int i = 0; i < model.Count; i++)
{
// other things
#Html.EditorFor(model => model[i]. //rest of stuff
// more other things
MVC serializes a name into the element for you, then attempts to re-map this server-side when posting the form. If you use a foreach loop in this way, it will lose the index and fail to bind.
You can see this effect happening if you watch your requests in Fiddler (or Chrome or whatever).
Check out this answer. They experienced a similar problem when using foreach instead of for. The model binding does not work in the former case.
Model.List is null on POST using Razor