How to post all table data to MVC controller
How to post all table data to MVC controller
I am developing a C# MVC application. I am using a View and Display template to manage the User Interface. The Users are able to edit the data presented on multiple pages. I am having an issue posting the Datatable data from all pages to the Controller. The List object in the Model returned to the Controller contains the correct number of rows, but the column values of all the rows except the rows on the last edited page are null. How do I post all of the data to the Controller?
Code from my View:
@model TreatyMilestonesViewModel
@{
ViewData["Title"] = "Treaty Milestones";
}
<link rel="stylesheet" type="text/css" href="~/lib/datatables/media/css/jquery.dataTables.min.css">
The custom data source library is required for sorting on the check box column
@Model.SelectedTreatyName - Treaty Milestones
@Html.HiddenFor(modelItem => modelItem.SelectedTreatyId)
<table class="table table-striped table-hover row-border order-column oBinder" id="TreatyMilestones">
<thead>
<tr>
<th>@Html.Label("Assigned Milestone")</th>
<th>@Html.Label("Milestone Description")</th>
<th>@Html.Label("Milestone SLA")</th>
<th>@Html.Label("Processing Period")</th>
<th>@Html.Label("Inactive")</th>
<th>@Html.HiddenFor(modelItem => modelItem.SelectedTreatyId) @Html.HiddenFor(modelItem =>
modelItem.SelectedTreatyName)</th>
</tr>
</thead>
<tbody>
@Html.DisplayFor(model => model.TreatyMilestonesList)
</tbody>
</table>
<div class="row">
<div class="col-lg-2">
<input type="submit" name="response" value="Save" formaction=@Url.Action("SaveMilestones") formmethod="post"
class="btn btn-link" />
</div>
<div class="col-lg-10">
<a asp-action="Index" class="btn btn-link">Back to Treaty Selection</a>
</div>
</div>
}
Code form my Display Template:
@model MilestoneTracking.Models.TreatyMilestonesList
<tr class="rowBinder">
<td>
@if (this.ViewContext.HttpContext.Request.Cookies["mtaUserRole"] != "IsAppUser")
{
@Html.CheckBoxFor(modelItem => modelItem.AssignedMilestone, new { onchange="enableFields(this)"})
}
else //This is an "AppUser", do not allow editing
{
@Html.CheckBoxFor(modelItem => modelItem.AssignedMilestone, new { disabled = "disabled" })
}
</td>
<td>@Html.DisplayFor(modelItem => modelItem.MilestoneDescription)</td>
<td>
@if (Model.AssignedMilestone)
{
@Html.TextBoxFor(modelItem => modelItem.TreatyMilestoneSLA, new { type = "number" })
}
else
{
@Html.TextBoxFor(modelItem => modelItem.TreatyMilestoneSLA, new { disabled = "disabled", type = "number" })
}
@Html.ValidationMessageFor(modelItem => modelItem.TreatyMilestoneSLA)
</td>
<td>
@Html.DisplayFor(modelItem => modelItem.ProcessingPeriod)
</td>
<td>
@if (Model.AssignedMilestone)
{
@Html.CheckBoxFor(modelItem => modelItem.Inactive)
}
else
{
@Html.CheckBoxFor(modelItem => modelItem.Inactive, new { disabled = "disabled" })
}
</td>
<td>
These were put here for two reasons;
1. They are within a <td> to eliminiate HTML warning 1503 "Unexpected start tag"
2. They were initially moved within the first column to eliminate the warning, but having them there broke the checkbox
sorting feature hence I moved them to their own cell.
@Html.HiddenFor(modelItem => modelItem.TreatyMilestoneId)
@Html.HiddenFor(modelItem => modelItem.TreatyId)
@Html.HiddenFor(modelItem => modelItem.MilestoneId)
@Html.HiddenFor(modelItem => modelItem.TreatyName)
</td>
</tr>
Code from Controller:
[HttpPost]
public ActionResult SaveMilestones(TreatyMilestonesViewModel _model)
{
// retrieve the as-is state of currently assigned Milestones
List<TreatyMilestone> currentlyAssignedMilestones = GetCurrentlyAssignedMilestones(_model.SelectedTreatyId);
// Let's create this now and we will assign the TreatyId and TreatyName to be passed back to the View after processing is completed
TreatyMilestonesViewModel vm = new TreatyMilestonesViewModel()
{
//SelectedTreatyId = _model.TreatyMilestonesList[0].TreatyId,
//SelectedTreatyName = _model.TreatyMilestonesList[0].TreatyName
SelectedTreatyId = _model.SelectedTreatyId,
SelectedTreatyName = _model.SelectedTreatyName
};
foreach (TreatyMilestonesList tmlrec in _model.TreatyMilestonesList)
{
...
This question has accepted answers - jump to:
Answers
I am attaching a text file with the code. I could not get the code properly formatted in the post.
You need to use the DataTables API to get the data from all pages as DataTables removes the DOM elements that aren't needed for the current display. If you are using Ajax use
rows().data()
to get the data, or if you are posting a regular http post, use something like in this example.Allan
Allan,
I have been scratching my head on how to get the data formatted in the way the MVC Controller expects it.
e.g.
'TreatyMilestonesList': [ { "TreatyMilestoneId": "1", "TreatyId": "1", "MilestoneId": "1", "TreatyName": "Treaty1", "AssignedMilestone": "true", "TreatyMilestoneSLA": "10", "Inactive": "false" }, { "TreatyMilestoneId": "2", "TreatyId": "2", "MilestoneId": "2", "TreatyName": "Treaty2", "AssignedMilestone": "true", "TreatyMilestoneSLA": "20", "Inactive": "false" } ],
Perhaps:
Allan
Funny you should suggest that, that is what I was attempting now.
var treatyMilestonesTable = $('#tableTreatyMilestones').DataTable();
var tableData = treatyMilestonesTable.rows().data().toArray();
The result is an [object (Array)] and the data looks like this:
[0] [<input name="TreatyMilestonesList[0].AssignedMilestone" id="TreatyMilestonesList_0__AssignedMilestone" onchange="enableFields(this)" type="checkbox" alue="true" data-val-required="The AssignedMilestone field is required." data-val="true">,Data Received,<input name="TreatyMilestonesList[0].TreatyMilestoneSLA" disabled="disabled" id="TreatyMilestonesList_0__TreatyMilestoneSLA" type="number" value="0" data-val-required="The TreatyMilestoneSLA field is required." data-val="true" data-val-range-min="-100" data-val-range-max="100" data-val-range="SLA must be in the range of -100 to 100"> <span class="field-validation-valid" data-valmsg-replace="true" data-valmsg-for="TreatyMilestonesList[0].TreatyMilestoneSLA"></span>,M00,<input name="TreatyMilestonesList[0].Inactive" disabled="disabled" id="TreatyMilestonesList_0__Inactive" type="checkbox" value="true" data-val-required="The Inactive field is required." data-val="true">,<input name="TreatyMilestonesList[0].TreatyMilestoneId" id="TreatyMilestonesList_0__TreatyMilestoneId" type="hidden" value=""> <input name="TreatyMilestonesList[0].TreatyId" id="TreatyMilestonesList_0__TreatyId" type="hidden" value="38" data-val-required="The TreatyId field is required." data-val="true"> <input name="TreatyMilestonesList[0].MilestoneId" id="TreatyMilestonesList_0__MilestoneId" type="hidden" value="1" data-val-required="The MilestoneId field is required." data-val="true"> <input name="TreatyMilestonesList[0].TreatyName" id="TreatyMilestonesList_0__TreatyName" type="hidden" value="Test001">]
Could it be I need a different tool to handle this scenario?
Oh I see - you want to get the data from inside the
input
elements? The link I gave above shows how that can be done.Allan
Allan,
Thank you for your input. We have resolved our issue with the following workaround:
Javascript
$('#btnSave').click(function () {
var oTable = $('#tableTreatyMilestones').DataTable();
oTable.page.len(200).draw();
});
HTML
<input type="submit" name="response" id="btnSave" value="Save" formaction=@Url.Action("SaveMilestones") formmethod="post" class="btn btn-link" />