@(Html.DevExtreme().DataGrid<DevExtreme.NETCore.Demos.Models.Northwind.Order>()
.ID("gridContainer")
.DataSource(d => d.WebApi()
.Controller("DataGridBatchUpdateWebApi")
.LoadAction("Orders")
.Key("OrderID")
)
.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) {
e.promise = sendBatchRequest('@Url.RouteUrl(new { controller = "DataGridBatchUpdateWebApi", action = "Batch" })', e.changes).done(() => {
e.component.refresh(true).done(() => {
e.component.cancelEditData();
});
});
}
}
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>
using DevExtreme.NETCore.Demos.Models;
using DevExtreme.NETCore.Demos.Models.DataGrid;
using DevExtreme.NETCore.Demos.Models.SampleData;
using Microsoft.AspNetCore.Mvc;
using System.Linq;
namespace DevExtreme.NETCore.Demos.Controllers {
public class DataGridController : Controller {
public ActionResult BatchUpdateRequest() {
return View();
}
}
}
using DevExtreme.AspNet.Data;
using DevExtreme.AspNet.Mvc;
using DevExtreme.NETCore.Demos.Models.DataGrid;
using DevExtreme.NETCore.Demos.Models.Northwind;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Caching.Memory;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
namespace DevExtreme.NETCore.Demos.Controllers.ApiControllers {
[Route("api/[controller]/[action]")]
public class DataGridBatchUpdateWebApiController : Controller {
InMemoryNorthwindContext _nwind;
public DataGridBatchUpdateWebApiController(NorthwindContext nwind, IHttpContextAccessor httpContextAccessor, IMemoryCache memoryCache) {
_nwind = new InMemoryNorthwindContext(nwind, httpContextAccessor, memoryCache);
}
[HttpGet]
public object Orders(DataSourceLoadOptions loadOptions) {
return DataSourceLoader.Load(_nwind.Orders, loadOptions);
}
[HttpPost]
public object Batch([FromBody] 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);
if(!TryValidateModel(order))
return 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 Ok(changes);
}
}
}
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
namespace DevExtreme.NETCore.Demos.Models.DataGrid {
public class DataChange {
[JsonProperty("key")]
public object Key { get; set; }
[JsonProperty("type")]
public string Type { get; set; }
[JsonProperty("data")]
public object Data { get; set; }
}
}
using Microsoft.AspNetCore.Http;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Caching.Memory;
using System;
using System.Collections.Generic;
namespace DevExtreme.NETCore.Demos.Models.Northwind {
public class InMemoryNorthwindContext : InMemoryDataContext<Order> {
NorthwindContext _nwind;
public InMemoryNorthwindContext(NorthwindContext nwind, IHttpContextAccessor contextAccessor, IMemoryCache memoryCache)
: base(contextAccessor, memoryCache) {
_nwind = nwind;
}
public ICollection<Order> Orders => ItemsInternal;
public DbSet<Customer> Customers => _nwind.Customers;
public DbSet<Order_Detail> Order_Details => _nwind.Order_Details;
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;
}
}
#gridContainer {
height: 440px;
}