Data Grids / Data Management ▸ Web API Service

This example demonstrates the DataGrid UI component communicating with a Web API service. Most of the DataGrid features are enabled, including the master-detail interface, header filter, summary, editing, and many more.

@(Html.DevExtreme().DataGrid<DevExtreme.MVC.Demos.Models.Northwind.Order>()
    .DataSource(d => d.WebApi()
        .RouteName("DataGridWebApi")
        .LoadAction("Orders")
        .InsertAction("InsertOrder")
        .UpdateAction("UpdateOrder")
        .DeleteAction("DeleteOrder")
        .Key("OrderID")
    )
    .RemoteOperations(true)
    .Columns(columns => {
        columns.AddFor(m => m.CustomerID)
            .Lookup(lookup => lookup
                .DataSource(d => d.WebApi().RouteName("DataGridWebApi").LoadAction("CustomersLookup").Key("Value"))
                .ValueExpr("Value")
                .DisplayExpr("Text")
            );

        columns.AddFor(m => m.OrderDate);

        columns.AddFor(m => m.Freight)
            .HeaderFilter(f => f.GroupInterval(100));

        columns.AddFor(m => m.ShipCountry);

        columns.AddFor(m => m.ShipVia)
            .Lookup(lookup => lookup
                .DataSource(d => d.WebApi().RouteName("DataGridWebApi").LoadAction("ShippersLookup").Key("Value"))
                .ValueExpr("Value")
                .DisplayExpr("Text")
            );

    })
    .FilterRow(f => f.Visible(true))
    .HeaderFilter(f => f.Visible(true))
    .GroupPanel(p => p.Visible(true))
    .Scrolling(s => s.Mode(GridScrollingMode.Virtual))
    .Width("100%")
    .Height(600)
    .ShowBorders(true)
    .MasterDetail(md => md
        .Enabled(true)
        .Template(@<text>

            @(Html.DevExtreme().DataGrid()
                .DataSource(d => d.WebApi()
                    .RouteName("DataGridWebApi")
                    .LoadAction("OrderDetails")
                    .LoadParams(new { orderID = new JS("data.OrderID") })
                )
                .ShowBorders(true)
            )

        </text>)
    )
    .Editing(e => e.AllowAdding(true).AllowDeleting(true).AllowUpdating(true))
    .Grouping(g => g.AutoExpandAll(false))
    .Summary(s => s
        .TotalItems(totalItems => {
            totalItems.Add().Column("Freight").SummaryType(SummaryType.Sum);
        })
        .GroupItems(groupItems => {
            groupItems.Add().Column("Freight").SummaryType(SummaryType.Sum);
            groupItems.Add().SummaryType(SummaryType.Count);
        })
    )
)
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 WebAPIService() {
            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;
    }
}