Backend API
@(Html.DevExtreme().DataGrid<DevExtreme.MVC.Demos.Models.Northwind.Order>() .ID("grid") .DataSource(d => d.WebApi() .RouteName("DataGridWebApi") .LoadAction("Orders") .InsertAction("InsertOrder") .UpdateAction("UpdateOrder") .DeleteAction("DeleteOrder") .Key("OrderID") .OnBeforeSend("beforeSend") ) .ShowBorders(true) .RepaintChangesOnly(true) .Scrolling(s => s.Mode(GridScrollingMode.Virtual)) .Editing(e => e .Mode(GridEditMode.Cell) .RefreshMode(GridEditRefreshMode.Reshape) .AllowAdding(true) .AllowDeleting(true) .AllowUpdating(true) ) .Columns(columns => { columns.AddFor(m => m.CustomerID) .Lookup(lookup => lookup .DataSource(d => d.WebApi() .RouteName("DataGridWebApi") .LoadAction("CustomersLookup") .LoadMode(DataSourceLoadMode.Raw) .Key("Value") .OnBeforeSend("beforeSend") ) .DataSourceOptions(o => o.Paginate(true)) .ValueExpr("Value") .DisplayExpr("Text") ); columns.AddFor(m => m.OrderDate); columns.AddFor(m => m.Freight); columns.AddFor(m => m.ShipCountry); columns.AddFor(m => m.ShipVia) .Lookup(lookup => lookup .DataSource(d => d.WebApi() .RouteName("DataGridWebApi") .LoadAction("ShippersLookup") .LoadMode(DataSourceLoadMode.Raw) .Key("Value") .OnBeforeSend("beforeSend") ) .ValueExpr("Value") .DisplayExpr("Text") ); }) .Summary(s => s .TotalItems(totalItems => { totalItems.AddFor(t => t.CustomerID).SummaryType(SummaryType.Count); totalItems.AddFor(t => t.Freight).ValueFormat("#0.00").SummaryType(SummaryType.Sum); }) ) ) <div class="options"> <div class="caption">Options</div> <div class="option"> <span>Refresh Mode:</span> @(Html.DevExtreme().SelectBox() .ID("refresh-mode") .InputAttr("aria-label", "Refresh Mode") .DataSource(new[] { "full", "reshape", "repaint" }) .Value("reshape") .OnValueChanged(@<text> function(e) { $("#grid").dxDataGrid("instance").option("editing.refreshMode", e.value); } </text>) ) </div> <div id="requests"> <div> <div class="caption">Network Requests</div> @(Html.DevExtreme().Button() .ID("clear") .Text("Clear") .OnClick(@<text> function() { $("#requests ul").empty(); } </text>) ) </div> <ul></ul> </div> </div> <script> function beforeSend(operation, ajaxSettings) { var data = ajaxSettings.data || {}, args = Object.keys(data).map(function (key) { return key + "=" + data[key]; }).join(" "); var logList = $("#requests ul"), time = DevExpress.localization.formatDate(new Date(), "HH:mm:ss"), newItem = $("<li>").text([time, ajaxSettings.method, ajaxSettings.url, args].join(" ")); logList.prepend(newItem); } </script>
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 RemoteCRUDOperations() { return View(); } } }
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.Net.Http.Formatting; 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/DataGridWebApi/{action}", Name = "DataGridWebApi")] public class DataGridWebApiController : ApiController { InMemoryNorthwindContext _nwind = new InMemoryNorthwindContext(); [HttpGet] public HttpResponseMessage Orders(DataSourceLoadOptions loadOptions) { return Request.CreateResponse(DataSourceLoader.Load(_nwind.Orders, loadOptions)); } [HttpPost] public HttpResponseMessage InsertOrder(FormDataCollection form) { var values = form.Get("values"); var newOrder = new Order(); JsonConvert.PopulateObject(values, newOrder); Validate(newOrder); if(!ModelState.IsValid) return Request.CreateErrorResponse(HttpStatusCode.BadRequest, ModelState.GetFullErrorMessage()); _nwind.Orders.Add(newOrder); _nwind.SaveChanges(); return Request.CreateResponse(HttpStatusCode.Created, newOrder); } [HttpPut] public HttpResponseMessage UpdateOrder(FormDataCollection form) { var key = Convert.ToInt32(form.Get("key")); var values = form.Get("values"); var order = _nwind.Orders.First(o => o.OrderID == key); JsonConvert.PopulateObject(values, order); Validate(order); if(!ModelState.IsValid) return Request.CreateErrorResponse(HttpStatusCode.BadRequest, ModelState.GetFullErrorMessage()); _nwind.SaveChanges(); return Request.CreateResponse(HttpStatusCode.OK, order); } [HttpDelete] public void DeleteOrder(FormDataCollection form) { var key = Convert.ToInt32(form.Get("key")); var order = _nwind.Orders.First(o => o.OrderID == key); _nwind.Orders.Remove(order); _nwind.SaveChanges(); } // additional actions [HttpGet] public HttpResponseMessage OrderDetails(int orderID, DataSourceLoadOptions loadOptions) { return Request.CreateResponse(DataSourceLoader.Load( from i in _nwind.Order_Details where i.OrderID == orderID select new { Product = i.Product.ProductName, Price = i.UnitPrice, i.Quantity, Sum = i.UnitPrice * i.Quantity }, loadOptions )); } [HttpGet] public HttpResponseMessage ShippersLookup(DataSourceLoadOptions loadOptions) { var lookup = from i in _nwind.Shippers orderby i.CompanyName select new { Value = i.ShipperID, Text = i.CompanyName }; return Request.CreateResponse(DataSourceLoader.Load(lookup, loadOptions)); } [HttpGet] public HttpResponseMessage CustomersLookup(DataSourceLoadOptions loadOptions) { var lookup = from i in _nwind.Customers let text = i.CompanyName + " (" + i.Country + ")" orderby i.CompanyName select new { Value = i.CustomerID, Text = text }; return Request.CreateResponse(DataSourceLoader.Load(lookup, 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); } } }
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; } }
#grid { height: 440px; } .options { padding: 20px; margin-top: 20px; background-color: rgba(191, 191, 191, 0.15); } .caption { margin-bottom: 10px; font-weight: 500; font-size: 18px; } .option { margin-bottom: 10px; } .option > span { position: relative; top: 2px; margin-right: 10px; } .option > .dx-widget { display: inline-block; vertical-align: middle; } #requests .caption { float: left; padding-top: 7px; } #requests > div { padding-bottom: 5px; } #requests > div:after { content: ""; display: table; clear: both; } #requests #clear { float: right; } #requests ul { list-style: none; max-height: 100px; overflow: auto; margin: 0; } #requests ul li { padding: 7px 0; border-bottom: 1px solid #dddddd; } #requests ul li:last-child { border-bottom: none; }