If you have technical questions, please create a support ticket in the DevExpress Support Center.
Html.DevExtreme().DataGrid<DevExtreme.MVC.Demos.Models.Northwind.Order>() (
.ID("gridContainer")
.DataSource(d => d.WebApi()
.RouteName("DataGridBatchUpdateWebApi")
.LoadAction("Orders")
.Key("OrderID")
)
.Pager(p => p.Visible(true))
.ShowBorders(true)
.RemoteOperations(true)
.RepaintChangesOnly(true)
.Editing(e => e
.Mode(GridEditMode.Batch)
.AllowAdding(true)
.AllowDeleting(true)
.AllowUpdating(true)
)
.Columns(columns =>
{
columns.AddFor(m => m.OrderID).AllowEditing(false);
columns.AddFor(m => m.ShipName);
columns.AddFor(m => m.ShipCountry);
columns.AddFor(m => m.ShipCity);
columns.AddFor(m => m.ShipAddress);
columns.AddFor(m => m.OrderDate).DataType(GridColumnDataType.Date);
columns.AddFor(m => m.Freight);
})
.OnSaving("onSaving")
)
<script>
function onSaving(e) {
e.cancel = true;
if (e.changes.length) {
const changes = normalizeChanges(e.changes);
e.promise = sendBatchRequest('@Url.HttpRouteUrl("DataGridBatchUpdateWebApi", new { action = "Batch" })', changes).done(() => {
e.component.refresh(true).done(() => {
e.component.cancelEditData();
});
});
}
}
function normalizeChanges(changes) {
return changes.map(c => {
switch (c.type) {
case 'insert':
return {
type: c.type,
data: c.data,
};
case 'update':
return {
type: c.type,
key: c.key,
data: c.data,
};
case 'remove':
return {
type: c.type,
key: c.key,
};
}
});
}
function sendBatchRequest(url, changes) {
var d = $.Deferred();
$.ajax(url, {
method: "POST",
data: JSON.stringify(changes),
cache: false,
contentType: 'application/json',
xhrFields: { withCredentials: true }
}).done(d.resolve).fail(function (xhr) {
d.reject(xhr.responseJSON ? xhr.responseJSON.Message : xhr.statusText);
});
return d.promise();
}
</script>
xxxxxxxxxx
using DevExtreme.MVC.Demos.Models;
using DevExtreme.MVC.Demos.Models.DataGrid;
using DevExtreme.MVC.Demos.Models.SampleData;
using System;
using System.Linq;
using System.Web.Mvc;
namespace DevExtreme.MVC.Demos.Controllers {
public class DataGridController : Controller {
public ActionResult BatchUpdateRequest() {
return View();
}
}
}
xxxxxxxxxx
using DevExtreme.AspNet.Data;
using DevExtreme.AspNet.Mvc;
using Newtonsoft.Json;
using System;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Web.Http;
using DevExtreme.MVC.Demos.Models.Northwind;
using DevExtreme.MVC.Demos.Models.DataGrid;
using System.Collections.Generic;
namespace DevExtreme.MVC.Demos.Controllers {
[Route("api/DataGridBatchUpdateWebApi/{action}", Name = "DataGridBatchUpdateWebApi")]
public class DataGridBatchUpdateWebApiController : ApiController {
InMemoryNorthwindContext _nwind = new InMemoryNorthwindContext();
[HttpGet]
public HttpResponseMessage Orders(DataSourceLoadOptions loadOptions) {
return Request.CreateResponse(DataSourceLoader.Load(_nwind.Orders, loadOptions));
}
[HttpPost]
public HttpResponseMessage Batch(List<DataChange> changes) {
foreach(var change in changes) {
Order order;
if(change.Type == "update" || change.Type == "remove") {
var key = Convert.ToInt32(change.Key);
order = _nwind.Orders.First(o => o.OrderID == key);
} else {
order = new Order();
}
if(change.Type == "insert" || change.Type == "update") {
JsonConvert.PopulateObject(change.Data.ToString(), order);
Validate(order);
if(!ModelState.IsValid)
return Request.CreateErrorResponse(HttpStatusCode.BadRequest, ModelState.GetFullErrorMessage());
if(change.Type == "insert") {
_nwind.Orders.Add(order);
}
change.Data = order;
} else if(change.Type == "remove") {
_nwind.Orders.Remove(order);
}
}
_nwind.SaveChanges();
return Request.CreateResponse(HttpStatusCode.OK, changes);
}
}
}
xxxxxxxxxx
using System.Text.Json.Serialization;
namespace DevExtreme.MVC.Demos.Models.DataGrid {
public class DataChange {
[JsonPropertyName("key")]
public int Key { get; set; }
[JsonPropertyName("type")]
public string Type { get; set; }
[JsonPropertyName("data")]
public object Data { get; set; }
}
}
xxxxxxxxxx
using System;
using System.Collections.Generic;
using System.Data.Entity;
namespace DevExtreme.MVC.Demos.Models.Northwind {
public class InMemoryNorthwindContext : InMemoryDataContext<Order> {
readonly NorthwindContext _nwind = new NorthwindContext();
public DbSet<Customer> Customers => _nwind.Customers;
public DbSet<Order_Detail> Order_Details => _nwind.Order_Details;
public ICollection<Order> Orders => ItemsInternal;
public DbSet<Shipper> Shippers => _nwind.Shippers;
protected override IEnumerable<Order> Source => _nwind.Orders;
protected override int GetKey(Order item) => item.OrderID;
protected override void SetKey(Order item, int key) => item.OrderID = key;
}
}
xxxxxxxxxx
#gridContainer {
height: 440px;
}
If data is stored on a server, our DataGrid sends multiple requests to save edited objects - one request per object (this is because most servers only process one edit operation at a time). If your server supports batch update, you can configure the DataGrid to save all changes with a single request.
To incorporate this functionality into your web app, implement the DataGrid's onSaving function. This function accepts an e
object that contains fields used for batch update. The following is a summary of the steps you must follow to enable batch update:
-
Disable default save logic
Set thee.cancel
field totrue
. -
Send pending changes to the server
Pending changes are contained in thee.changes
array. Ensure it is not empty and send the changes to the server. -
Update data in the DataGrid
Once changes are saved, call the refresh(changesOnly) method. -
Reset edit state
Use the cancelEditData() method to clear pending changes.