jqGrid and ASP.NET MVC – Batch updates

Recently I've been asked to prepare a batch update scenario for jqGrid. After playing around with few prototypes I decided use inline editing for that purpose.
First we need to put all displayed rows into editable state. The best way to do this is to call editRow for each row during gridComplete event:
<script src="@Url.Content("~/Scripts/jquery-1.4.4.min.js")" type="text/javascript"></script>
<script src="@Url.Content("~/Scripts/jquery.jqGrid.locale-en-3.8.2.js")" type="text/javascript"></script>
<script src="@Url.Content("~/Scripts/jquery.jqGrid-3.8.2.min.js")" type="text/javascript"></script>
<script src="@Url.Content("~/Scripts/jquery.json-2.2.min.js")" type="text/javascript"></script>
<script type="text/javascript">
$(document).ready(function () {
$('#grid_id').jqGrid({
//Here you set up colModel, colNames and any other options
...
//This event fires after all the data is loaded into the grid
gridComplete: function() {
//Get ids for all current rows
var dataIds = $('#grid_id').jqGrid('getDataIDs');
for (var i = 0;i < dataIds.length; i++) {
//Put row in edit state
$("#grid_id").jqGrid('editRow', dataIds[i], false);
}
}
});
});
</script>
This way we can be sure, that every row loaded by jqGrid will end up in edit state. Now we need to add a button which will trigger the batch update. In the click event of that button we want to save every row to local data array. We can achieve that by using saveRow method, we just need to put 'clientArray' in third parameter. One important thing to remember here is that saveRow may throw an exception in case of validation errors - in such a case we will restore the original row and skip sending it to the server. Actual sending will be done by jQuery.ajax() method:
$('#button_id').click(function() {
var batch = new Array();
//Get ids for all current rows
var dataIds = $('#grid_id').jqGrid('getDataIDs');
for (var i = 0; i < dataIds.length; i++) {
try {
//Save row only to the grid
$('#grid_id').jqGrid('saveRow', dataIds[i], false, 'clientArray');
//Get row data
var data = $('#grid_id').jqGrid('getRowData', dataIds[i]);
//Data doesn't contains actual id
data.Id = dataIds[i];
//Add data to the batch
batch.push(data);
}
catch (ex) {
//If you are using editRules it might end up with exception
$('#grid_id').jqGrid('restoreRow', dataIds[i]);
}
}
//Send batch to the server
$.ajax({
type: 'POST',
contentType: 'application/json; charset=utf-8',
url: '@Url.Action("BatchUpdate", "Home")',
dataType: 'json',
data: $.toJSON(batch),
success: function(result) {
...
$('#grid_id').trigger('reloadGrid');
}
});
});
Now we have to receive the data on server side. Thanks to built in JSON model binding in ASP.NET MVC 3 we can do this with very simple action method:
[AcceptVerbs(HttpVerbs.Post)]
public JsonResult BatchUpdate(List<ViewModel> viewModelsBatch)
{
//Update your data storage here
...
}
Feel free to use this solution if you need something like this.