Remote Data in ASP.Net Core Grid Component
29 Oct 202424 minutes to read
To bind remote data to grid component, assign service data as an instance of DataManager
to the dataSource
property. To interact with remote data source, provide the endpoint url
.
<ejs-grid id="Grid">
<e-data-manager url="http://services.odata.org/V4/Northwind/Northwind.svc/Orders/?$top=7" adaptor="ODataV4Adaptor" crossdomain="true"></e-data-manager>
<e-grid-columns>
<e-grid-column field="OrderID" headerText="Order ID" type="number" textAlign="Right" width="120"></e-grid-column>
<e-grid-column field="CustomerID" headerText="Customer ID" type="string" width="140"></e-grid-column>
<e-grid-column field="Freight" headerText="Freight" textAlign="Right" format="C2" width="120"></e-grid-column>
<e-grid-column field="OrderDate" headerText="Order Date" format='yMd' textAlign="Right" width="140"></e-grid-column>
</e-grid-columns>
</ejs-grid>
public IActionResult Index()
{
return view();
}
NOTE
By default,
DataManager
usesODataAdaptor
for remote data-binding.
ExpandoObject with complex column binding using URL adaptor
You can achieve the ExpandoObject complex data binding in the data grid by using the dot(.) operator in the column.field. In the following examples, Customer.OrderDate, Customer.Freight, and Customer.ShipCountry are complex data.
The following code example shows how to bind ExpandoObject datasource in grid using URL adaptor.
<ejs-grid id="ExpandoObjectGrid" allowPaging="true" allowSorting="true" allowFiltering="true" toolbar="@(new List<string>() {"Add", "Edit", "Delete", "Update", "Cancel"})">
<e-grid-groupSettings showGroupedColumn="true" showDropArea="true"></e-grid-groupSettings>
<e-data-manager url="/Home/UrlDataSource" adaptor="UrlAdaptor" insertUrl="/Home/Insert" updateUrl="/Home/Update" removeUrl="/Home/Remove"></e-data-manager>
<e-grid-editSettings allowAdding="true" allowDeleting="true" allowEditing="true" mode="Normal" newRowPosition="Top"></e-grid-editSettings>
<e-grid-columns>
<e-grid-column field="OrderID" headerText="Order ID" isPrimaryKey="true" validationRules="@(new { required=true, number=true})" width="140"></e-grid-column>
<e-grid-column field="Customer.OrderDate" headerText="Order Date" editType="datetimepickeredit" customFormat="@(new {type = "datetime", format = "M/d/y hh:mm a" })" width="160"></e-grid-column>
<e-grid-column field="Customer.Freight" headerText="Freight" validationRules="@(new { required=true})" textAlign="Right" editType="numericedit" format="C2" width="140"></e-grid-column>
<e-grid-column field="Customer.ShipCountry" headerText="Ship Country" editType="dropdownedit" width="150"></e-grid-column>
</e-grid-columns>
</ejs-grid>
public static List<ExpandoObject> ExpandoOrders { get; set; } = new List<ExpandoObject>();
public IActionResult Index()
{
getExpandoDatas();
return View();
}
public IActionResult Insert([FromBody] CRUDModel<ExpandoObject> value)
{
ExpandoOrders.Insert(0, value.Value);
return Json(value.Value);
}
public IActionResult Update([FromBody] CRUDModel<ExpandoObject> value)
{
if (value != null && value.Value != null)
{
var orderIDToUpdate = Convert.ToInt32(value.Key);
var existingOrder = ExpandoOrders.FirstOrDefault(order =>
{
if (order is IDictionary<string, object> orderDictionary &&
orderDictionary.TryGetValue("OrderID", out var orderIDValue))
{
var orderID = Convert.ToInt32(orderIDValue);
return orderID == orderIDToUpdate;
}
return false;
});
if (existingOrder != null)
{
ExpandoOrders.Remove(existingOrder);
ExpandoOrders.Insert(0, value.Value);
}
}
return Json(value.Value);
}
public IActionResult Remove([FromBody] CRUDModel<ExpandoObject> value)
{
if (value != null)
{
var orderIDToDelete = Convert.ToInt32(value.Key);
var itemToRemove = ExpandoOrders.FirstOrDefault(order =>
{
if (order is IDictionary<string, object> dictionary &&
dictionary.TryGetValue("OrderID", out var orderIDValue))
{
var orderID = Convert.ToInt32(orderIDValue);
return orderID == orderIDToDelete;
}
return false;
});
if (itemToRemove != null)
{
ExpandoOrders.Remove(itemToRemove);
}
}
return Json(value);
}
public class CRUDModel
{
public List<ExpandoObject> Added { get; set; }
public List<ExpandoObject> Changed { get; set; }
public List<ExpandoObject> Deleted { get; set; }
public ExpandoObject Value { get; set; }
public int key { get; set; }
public string action { get; set; }
}
public IActionResult UrlDataSource([FromBody] DataManagerRequest dm)
{
IEnumerable DataSource = ExpandoOrders;
DataOperations operation = new DataOperations();
if (dm.Search != null && dm.Search.Count > 0)
{
DataSource = operation.PerformSearching(DataSource, dm.Search); //Search
}
if (dm.Sorted != null && dm.Sorted.Count > 0) //Sorting
{
DataSource = operation.PerformSorting(DataSource, dm.Sorted);
}
if (dm.Where != null && dm.Where.Count > 0) //Filtering
{
DataSource = operation.PerformFiltering
(DataSource, dm.Where, dm.Where[0].Operator);
}
int count = DataSource.Cast<ExpandoObject>().Count();
if (dm.Select != null)
{
DataSource = operation.PerformSelect(DataSource, dm.Select);
DataSource = DataSource.Cast<ExpandoObject>().Distinct().AsEnumerable();
}
if (dm.Skip != 0)
{
DataSource = operation.PerformSkip(DataSource, dm.Skip); //Paging
}
if (dm.Take != 0)
{
DataSource = operation.PerformTake(DataSource, dm.Take);
}
return dm.RequiresCounts ?
Json(new { result = DataSource, count = count }) : Json(DataSource);
}
protected List<ExpandoObject> getExpandoDatas()
{
string[] customerIDs = { "ALFKI", "ANANTR", "ANTON", "BLONP", "BOLID" };
string[] shipCountrys = { "USA", "UK", "Denmark", "Australia", "India" };
ExpandoOrders = Enumerable.Range(1, 5).Select((x) =>
{
dynamic d = new ExpandoObject();
d.OrderID = 1000 + x;
d.Customer = new ExpandoObject();
d.Customer.Freight = (new double[] { 2, 1, 4, 5, 3 })[new Random().Next(5)] * x;
d.Customer.OrderDate = (new DateTime[] { new DateTime(2010, 11, 5), new DateTime(2018, 10, 3), new DateTime(1995, 9, 9), new DateTime(2012, 8, 2), new DateTime(2015, 4, 11) })[new Random().Next(5)];
d.Customer.ShipCountry = (new string[] { "USA", "UK", "Denmark", "Australia", "India" })[new Random().Next(5)];
d.Freight = (new double[] { 2, 1, 4, 5, 3 })[new Random().Next(5)] * x;
d.OrderDate = (new DateTime[] { new DateTime(2010, 11, 5), new DateTime(2018, 10, 3), new DateTime(1995, 9, 9), new DateTime(2012, 8, 2), new DateTime(2015, 4, 11) })[new Random().Next(5)];
d.ShipCountry = (new string[] { "USA", "UK" })[new Random().Next(2)];
d.Verified = (new bool[] { true, false })[new Random().Next(2)];
return d;
}).Cast<ExpandoObject>().ToList<ExpandoObject>();
return ExpandoOrders;
}
Perform data and CRUD operations for complex ExpandoObject binding fields as well.
The following image represents ExpandoObject complex data binding.
DynamicObject with complex column binding using URL adaptor
You can achieve DynamicObject complex data binding in the data grid by using the dot(.) operator in the column.field. In the following examples, Customer.OrderDate, Customer.Freight, and Customer.ShipCountry are complex data.
The following code example shows how to bind DynamicObject datasource in grid using URL adaptor.
<ejs-grid id="DynamicObjectGrid" allowPaging="true" allowSorting="true" allowFiltering="true" toolbar="@(new List<string>() {"Add", "Edit", "Delete", "Update", "Cancel"})">
<e-grid-groupSettings showGroupedColumn="true" showDropArea="true"></e-grid-groupSettings>
<e-data-manager url="/Home/UrlDataSource" adaptor="UrlAdaptor" insertUrl="/Home/Insert" updateUrl="/Home/Update" removeUrl="/Home/Remove"></e-data-manager>
<e-grid-editSettings allowAdding="true" allowDeleting="true" allowEditing="true" mode="Normal" newRowPosition="Top"></e-grid-editSettings>
<e-grid-columns>
<e-grid-column field="OrderID" headerText="Order ID" isPrimaryKey="true" validationRules="@(new { required=true, number=true})" width="140"></e-grid-column>
<e-grid-column field="Customer.OrderDate" headerText="Order Date" editType="datetimepickeredit" customFormat="@(new {type = "datetime", format = "M/d/y hh:mm a" })" width="160"></e-grid-column>
<e-grid-column field="Customer.Freight" headerText="Freight" validationRules="@(new { required=true})" textAlign="Right" editType="numericedit" format="C2" width="140"></e-grid-column>
<e-grid-column field="Customer.ShipCountry" headerText="Ship Country" editType="dropdownedit" width="150"></e-grid-column>
</e-grid-columns>
</ejs-grid>
public static List<DynamicDictionary> DynamicOrders { get; set; } = new List<DynamicDictionary>();
public IActionResult Index()
{
getDynamicDatas();
return View();
}
public IActionResult Insert([FromBody] CRUDModel<DynamicDictionary> value)
{
DynamicOrders.Insert(0, value.Value);
return Json(value.Value);
}
public IActionResult Update([FromBody] CRUDModel<DynamicDictionary> value)
{
if (value != null && value.Value != null)
{
var orderIDToUpdate = Convert.ToInt32(value.Key);
var existingOrder = DynamicOrders.FirstOrDefault(order =>
{
if (order is DynamicDictionary dynamicDict &&
dynamicDict.dictionary.TryGetValue("OrderID", out var orderIDValue))
{
var orderID = Convert.ToInt32(orderIDValue);
return orderID == orderIDToUpdate;
}
return false;
});
if (existingOrder != null)
{
DynamicOrders.Remove(existingOrder);
DynamicOrders.Insert(0, value.Value);
}
}
return Json(value.Value);
}
public IActionResult Remove([FromBody] CRUDModel<DynamicDictionary> value)
{
if (value != null)
{
var orderIDToDelete = Convert.ToInt32(value.Key);
var itemToRemove = DynamicOrders.FirstOrDefault(order =>
{
if (order is DynamicDictionary dynamicDict &&
dynamicDict.dictionary.TryGetValue("OrderID", out var orderIDValue))
{
var orderID = Convert.ToInt32(orderIDValue);
return orderID == orderIDToDelete;
}
return false;
});
if (itemToRemove != null)
{
DynamicOrders.Remove(itemToRemove);
}
}
return Json(value);
}
public class CRUDModel
{
public List<DynamicDictionary> Added { get; set; }
public List<DynamicDictionary> Changed { get; set; }
public List<DynamicDictionary> Deleted { get; set; }
public DynamicDictionary Value { get; set; }
public int key { get; set; }
public string action { get; set; }
}
public IActionResult UrlDataSource([FromBody] DataManagerRequest dm)
{
IEnumerable DataSource = DynamicOrders;
DataOperations operation = new DataOperations();
if (dm.Search != null && dm.Search.Count > 0)
{
DataSource = operation.PerformSearching(DataSource, dm.Search); //Search
}
if (dm.Sorted != null && dm.Sorted.Count > 0) //Sorting
{
DataSource = operation.PerformSorting(DataSource, dm.Sorted);
}
if (dm.Where != null && dm.Where.Count > 0) //Filtering
{
DataSource = operation.PerformFiltering
(DataSource, dm.Where, dm.Where[0].Operator);
}
int count = DataSource.Cast<DynamicDictionary>().Count();
if (dm.Select != null)
{
DataSource = operation.PerformSelect(DataSource, dm.Select);
DataSource = DataSource.Cast<DynamicDictionary>().Distinct().AsEnumerable();
}
if (dm.Skip != 0)
{
DataSource = operation.PerformSkip(DataSource, dm.Skip); //Paging
}
if (dm.Take != 0)
{
DataSource = operation.PerformTake(DataSource, dm.Take);
}
return dm.RequiresCounts ?
Json(new { result = DataSource, count = count }) : Json(DataSource);
}
protected List<DynamicDictionary> getDynamicDatas()
{
string[] customerIDs = { "ALFKI", "ANANTR", "ANTON", "BLONP", "BOLID" };
string[] shipCountrys = { "USA", "UK", "Denmark", "Australia", "India" };
DynamicOrders = Enumerable.Range(1, 5).Select((x) =>
{
dynamic d = new DynamicList();
d.OrderID = 1000 + x;
d.Customer = new DynamicList();
d.Customer.Freight = (new double[] { 2, 1, 4, 5, 3 })[new Random().Next(5)] * x;
d.Customer.OrderDate = (new DateTime[] { new DateTime(2010, 11, 5), new DateTime(2018, 10, 3), new DateTime(1995, 9, 9), new DateTime(2012, 8, 2), new DateTime(2015, 4, 11) })[new Random().Next(5)];
d.Customer.ShipCountry = (new string[] { "USA", "UK", "Denmark", "Australia", "India" })[new Random().Next(5)];
d.Freight = (new double[] { 2, 1, 4, 5, 3 })[new Random().Next(5)] * x;
d.OrderDate = (new DateTime[] { new DateTime(2010, 11, 5), new DateTime(2018, 10, 3), new DateTime(1995, 9, 9), new DateTime(2012, 8, 2), new DateTime(2015, 4, 11) })[new Random().Next(5)];
d.ShipCountry = (new string[] { "USA", "UK" })[new Random().Next(2)];
d.Verified = (new bool[] { true, false })[new Random().Next(2)];
return d;
}).Cast<DynamicDictionary>().ToList<DynamicDictionary>();
return DynamicOrders;
}
public class DynamicDictionary : DynamicObject
{
public Dictionary<string, object> dictionary = new Dictionary<string, object>();
public override bool TryGetMember(GetMemberBinder binder, out object result)
{
string name = binder.Name;
return dictionary.TryGetValue(name, out result);
}
public override bool TrySetMember(SetMemberBinder binder, object value)
{
dictionary[binder.Name] = value;
return true;
}
public override System.Collections.Generic.IEnumerable<string> GetDynamicMemberNames()
{
return this.dictionary?.Keys;
}
}
Perform data and CRUD operations for complex DynamicObject binding fields as well.
The following image represents DynamicObject complex data binding.
OData adaptor - Binding OData service
OData is a standardized protocol for creating and consuming data. You can retrieve data from OData service using the DataManager. Refer to the following code example for remote Data binding using OData
service.
<ejs-grid id="Grid">
<e-data-manager url="https://services.odata.org/V3/Northwind/Northwind.svc/Orders/" adaptor="ODataAdaptor" crossdomain="true"></e-data-manager>
<e-grid-columns>
<e-grid-column field="OrderID" headerText="Order ID" type="number" textAlign="Right" width="120"></e-grid-column>
<e-grid-column field="CustomerID" headerText="Customer ID" type="string" width="140"></e-grid-column>
<e-grid-column field="Freight" headerText="Freight" textAlign="Right" format="C2" width="120"></e-grid-column>
<e-grid-column field="OrderDate" headerText="Order Date" format='yMd' textAlign="Right" width="140"></e-grid-column>
</e-grid-columns>
</ejs-grid>
public IActionResult Index()
{
return View();
}
OData v4 adaptor - Binding OData v4 service
The ODataV4 is an improved version of OData protocols, and the DataManager
can also retrieve and consume OData v4 services. For more details on OData v4 services, refer to the OData documentation. To bind OData v4 service, use the ODataV4Adaptor
.
<ejs-grid id="Grid">
<e-data-manager url="http://services.odata.org/V4/Northwind/Northwind.svc/Orders/?$top=7" adaptor="ODataV4Adaptor" crossdomain="true"></e-data-manager>
<e-grid-columns>
<e-grid-column field="OrderID" headerText="Order ID" type="number" textAlign="Right" width="120"></e-grid-column>
<e-grid-column field="CustomerID" headerText="Customer ID" type="string" width="140"></e-grid-column>
<e-grid-column field="Freight" headerText="Freight" textAlign="Right" format="C2" width="120"></e-grid-column>
<e-grid-column field="OrderDate" headerText="Order Date" format='yMd' textAlign="Right" width="140"></e-grid-column>
</e-grid-columns>
</ejs-grid>
public IActionResult Index()
{
return View();
}
Odata with custom url
The Syncfusion ODataV4 adaptor extends support for calling customized URLs to accommodate data retrieval and CRUD actions as per your application’s requirements. However, when utilizing a custom URL with the ODataV4 adaptor, it’s essential to modify the routing configurations in your application’s route configuration file to align with your custom URL. You can invoke the custom URL by the following methods in the Datamanager
Configuring Custom URLs
To work with custom URLs for CRUD operations in the Syncfusion Grid, you can use the following properties:
- insertUrl: Specifies the custom URL for inserting new records.
- removeUrl: Specifies the custom URL for deleting records.
- updateUrl: Specifies the custom URL for updating records.
- batchUrl: Specifies the custom URL for batch editing operations.
Ensure that the routing configurations on the server-side are properly updated to handle these custom URLs.
The following code example describes the above behavior.
<ejs-grid id="Grid" toolbar="@(new List<string>() { "Add", "Edit", "Delete", "Update", "Cancel" })">
<e-data-manager url="http://services.odata.org/V4/Northwind/Northwind.svc/Orders/?$top=7" adaptor="ODataV4Adaptor"
updateUrl= "https://localhost:xxxx/odata/Orders/Update"
insertUrl= "https://localhost:xxxx/odata/Orders/Insert"
removeUrl= "https://localhost:xxxx/odata/Orders/Delete"
crossdomain="true"></e-data-manager>
<e-grid-editSettings allowAdding="true" allowDeleting="true" allowEditing="true" mode="Normal"></e-grid-editSettings>
<e-grid-columns>
<e-grid-column field="OrderID" headerText="Order ID" type="number" textAlign="Right" width="120" isPrimaryKey="true" validationRules="@(new { required=true})"></e-grid-column>
<e-grid-column field="CustomerID" headerText="Customer ID" type="string" width="140" validationRules="@(new { required=true, minLength=3})"></e-grid-column>
<e-grid-column field="Freight" headerText="Freight" textAlign="Right" format="C2" width="120"></e-grid-column>
<e-grid-column field="OrderDate" headerText="Order Date" format='yMd' textAlign="Right" width="140"></e-grid-column>
</e-grid-columns>
</ejs-grid>
For batch editing, you can specify a custom batch URL as follows:
<ejs-grid id="Grid" toolbar="@(new List<string>() { "Add", "Edit", "Delete", "Update", "Cancel" })">
<e-data-manager url="http://services.odata.org/V4/Northwind/Northwind.svc/Orders/?$top=7" adaptor="ODataV4Adaptor"
BatchUrl="https://localhost:xxxx/odata/Orders/BatchUpdate"
crossdomain="true"></e-data-manager>
<e-grid-editSettings allowAdding="true" allowDeleting="true" allowEditing="true" mode="Batch"></e-grid-editSettings>
<e-grid-columns>
<e-grid-column field="OrderID" headerText="Order ID" type="number" textAlign="Right" width="120" isPrimaryKey="true" validationRules="@(new { required=true})"></e-grid-column>
<e-grid-column field="CustomerID" headerText="Customer ID" type="string" width="140" validationRules="@(new { required=true, minLength=3})"></e-grid-column>
<e-grid-column field="Freight" headerText="Freight" textAlign="Right" format="C2" width="120"></e-grid-column>
<e-grid-column field="OrderDate" headerText="Order Date" format='yMd' textAlign="Right" width="140"></e-grid-column>
</e-grid-columns>
</ejs-grid>
Web API adaptor
You can use WebApiAdaptor
to bind grid with Web API created using OData endpoint.
<ejs-grid id="Grid">
<e-data-manager url="/api/Orders" adaptor="WebApiAdaptor" crossdomain="true"></e-data-manager>
<e-grid-columns>
<e-grid-column field="OrderID" headerText="Order ID" type="number" textAlign="Right" width="120"></e-grid-column>
<e-grid-column field="CustomerID" headerText="Customer ID" type="string" width="140"></e-grid-column>
<e-grid-column field="Freight" headerText="Freight" textAlign="Right" format="C2" width="120"></e-grid-column>
<e-grid-column field="OrderDate" headerText="Order Date" format='yMd' textAlign="Right" width="140"></e-grid-column>
</e-grid-columns>
</ejs-grid>
public class OrdersDetails
{
public static List<OrdersDetails> order = new List<OrdersDetails>();
public OrdersDetails()
{
}
public OrdersDetails(int OrderID, string CustomerId, int EmployeeId, double Freight, bool Verified, DateTime OrderDate, string ShipCity, string ShipName, string ShipCountry, DateTime ShippedDate, string ShipAddress)
{
this.OrderID = OrderID;
this.CustomerID = CustomerId;
this.EmployeeID = EmployeeId;
this.Freight = Freight;
this.ShipCity = ShipCity;
this.Verified = Verified;
this.OrderDate = OrderDate;
this.ShipName = ShipName;
this.ShipCountry = ShipCountry;
this.ShippedDate = ShippedDate;
this.ShipAddress = ShipAddress;
}
public static List<OrdersDetails> GetAllRecords()
{
if (order.Count() == 0)
{
int code = 10000;
for (int i = 1; i < 5; i++)
{
order.Add(new OrdersDetails(code + 1, "ALFKI", i + 0, 2.3 * i, false, new DateTime(1991, 05, 15), "Berlin", "Simons bistro", "Denmark", new DateTime(1996, 7, 16), "Kirchgasse 6"));
order.Add(new OrdersDetails(code + 2, "ANATR", i + 2, 3.3 * i, true, new DateTime(1990, 04, 04), "Madrid", "Queen Cozinha", "Brazil", new DateTime(1996, 9, 11), "Avda. Azteca 123"));
order.Add(new OrdersDetails(code + 3, "ANTON", i + 1, 4.3 * i, true, new DateTime(1957, 11, 30), "Cholchester", "Frankenversand", "Germany", new DateTime(1996, 10, 7), "Carrera 52 con Ave. Bolívar #65-98 Llano Largo"));
order.Add(new OrdersDetails(code + 4, "BLONP", i + 3, 5.3 * i, false, new DateTime(1930, 10, 22), "Marseille", "Ernst Handel", "Austria", new DateTime(1996, 12, 30), "Magazinweg 7"));
order.Add(new OrdersDetails(code + 5, "BOLID", i + 4, 6.3 * i, true, new DateTime(1953, 02, 18), "Tsawassen", "Hanari Carnes", "Switzerland", new DateTime(1997, 12, 3), "1029 - 12th Ave. S."));
code += 5;
}
}
return order;
}
public int? OrderID { get; set; }
public string CustomerID { get; set; }
public int? EmployeeID { get; set; }
public double? Freight { get; set; }
public string ShipCity { get; set; }
public bool Verified { get; set; }
public DateTime OrderDate { get; set; }
public string ShipName { get; set; }
public string ShipCountry { get; set; }
public DateTime ShippedDate { get; set; }
public string ShipAddress { get; set; }
}
namespace ApplicationName.Controllers
{
[Produces("application/json")]
[Route("api/Orders")]
public class OrdersController : Controller
{
// GET: api/Orders
[HttpGet]
public object Get()
{
var queryString = Request.Query;
var data = OrdersDetails.GetAllRecords().ToList();
int skip = Convert.ToInt32(queryString["$skip"]);
int take = Convert.ToInt32(queryString["$top"]);
return take != 0 ? new { Items = data.Skip(skip).Take(take).ToList(), Count = data.Count() } : new { Items = data, Count = data.Count() };
}
}
}
The response object should contain properties, Items
and Count
, whose values are a collection of entities and total count of the entities, respectively.
The sample response object should look like this:
{
Items: [{..}, {..}, {..}, ...],
Count: 830
}
Remote save adaptor
You may need to perform all Grid Actions in client-side except the CRUD operations, that should be interacted with server-side to persist data. It can be achieved in Grid by using RemoteSaveAdaptor
.
Datasource must be set to json
property and set RemoteSaveAdaptor
to the adaptor
property. CRUD operations can be mapped to server-side using updateUrl
, insertUrl
, removeUrl
, batchUrl
, crudUrl
properties.
You can use the following code example to use RemoteSaveAdaptor
in Grid.
<ejs-grid id="Grid" toolbar="@(new List<string>() { "Add","Delete","Update", "Cancel" })">
<e-data-manager json ="@ViewBag.dataSource" adaptor="RemoteSaveAdaptor" insertUrl="/Home/Insert" updateUrl="/Home/Update" removeUrl="/Home/Delete" ></e-data-manager>
<e-grid-editSettings allowDeleting="true" allowEditing="true" allowAdding="true"></e-grid-editSettings>
<e-grid-columns>
<e-grid-column field="OrderID" headerText="Order ID" type="number" textAlign="Right" width="120"></e-grid-column>
<e-grid-column field="CustomerID" headerText="Customer ID" type="string" width="140"></e-grid-column>
<e-grid-column field="Freight" headerText="Freight" textAlign="Right" format="C2" width="120"></e-grid-column>
<e-grid-column field="OrderDate" headerText="Order Date" format='yMd' textAlign="Right" width="140"></e-grid-column>
</e-grid-columns>
</ejs-grid>
public ActionResult Index()
{
var data = OrderRepository.GetAllRecords();
ViewBag.dataSource = data;
return View();
}
public ActionResult Update(EditableOrder value)
{
var data = OrderRepository.Update(value);
return Json(data, JsonRequestBehavior.AllowGet);
}
public ActionResult Insert(EditableOrder value)
{
var data = OrderRepository.Add(value);
return Json(data, JsonRequestBehavior.AllowGet);
}
public ActionResult Delete(int key)
{
OrderRepository.Delete(key);
return Json(key, JsonRequestBehavior.AllowGet);
}
Custom adaptor
You can create your own adaptor by extending the built-in adaptors. The following demonstrates custom adaptor approach and how to add a serial number for the records by overriding the built-in response processing using the processResponse
method of the ODataAdaptor
.
<ejs-grid id="CustomAdaptor" created="created">
<e-grid-columns>
<e-grid-column field="Sno" headerText="SNO" textAlign="Right" width="120"></e-grid-column>
<e-grid-column field="CustomerID" headerText="Customer Name" width="150"></e-grid-column>
<e-grid-column field="Freight" headerText="Freight" format="C2" width="120"></e-grid-column>
<e-grid-column field="ShipCity" headerText="Ship City"></e-grid-column>
<e-grid-column field="ShipCountry" headerText="Ship Country" width="150"></e-grid-column>
</e-grid-columns>
</ejs-grid>
<script>
function created(args) {
class SerialNoAdaptor extends ej.data.ODataAdaptor {
processResponse() {
var i = 0;
// calling base class processResponse function
var original = super.processResponse.apply(this, arguments);
// adding serial number
original.result.forEach(function (item) { item['Sno'] = ++i });
return { result: original.result, count: original.count };
}
}
var grid = document.querySelector('#CustomAdaptor').ej2_instances[0];
grid.dataSource = new ej.data.DataManager({
url: "https://js.syncfusion.com/demos/ejServices/Wcf/Northwind.svc/Orders?$top=7",
adaptor: new SerialNoAdaptor()
});
}
</script>
public IActionResult Index()
{
return View();
}
public IActionResult Index()
{
return View();
}
Offline mode
On remote data binding, all grid actions such as paging, sorting, editing, grouping, filtering, etc, will be processed on server-side. To avoid post back for every action, set the grid to load all data on initialization and make the actions process in client-side. To enable this behavior, use the Offline
property of e-data-manager
tag helper.
<ejs-grid id="Grid" allowPaging="true" allowSorting="true" allowGrouping="true">
<e-data-manager url="http://services.odata.org/V4/Northwind/Northwind.svc/Orders" adaptor="ODataV4Adaptor" offline="true" crossdomain="true"></e-data-manager>
<e-grid-pagesettings pageSize="7"></e-grid-pagesettings>
<e-grid-columns>
<e-grid-column field="OrderID" headerText="Order ID" type="number" textAlign="Right" width="120"></e-grid-column>
<e-grid-column field="CustomerID" headerText="Customer ID" type="string" width="140"></e-grid-column>
<e-grid-column field="Freight" headerText="Freight" textAlign="Right" format="C2" width="120"></e-grid-column>
<e-grid-column field="OrderDate" headerText="Order Date" format='yMd' textAlign="Right" width="140"></e-grid-column>
</e-grid-columns>
</ejs-grid>
public IActionResult Index()
{
return View();
}
Handling on-demand grid actions
On-Demand
grid actions help you to improve the performance for large data application. To achieve On-Demand
in the grid, use UrlAdaptor
. To define UrlAdaptor
in the grid, specify the data service in url
and the AdaptorType
as UrlAdaptor
like below.
<ejs-grid id="Grid" allowPaging="true" allowSorting="true" allowFiltering="true" toolbar="@(new List<string>() {"Search" })">
<e-data-manager url="/Home/UrlDataSource" adaptor="UrlAdaptor"></e-data-manager>
<e-grid-columns>
<e-grid-column field="OrderID" headerText="Order ID" isPrimaryKey="true" textAlign="Right" width="100"></e-grid-column>
<e-grid-column field="CustomerID" headerText="Customer ID" type="string" width="120"></e-grid-column>
<e-grid-column field="Freight" headerText="Freight" textAlign="Right" format="C2" editType="numericedit" width="120"></e-grid-column>
<e-grid-column field="ShipCountry" headerText="Ship Country" width="150"></e-grid-column>
</e-grid-columns>
</ejs-grid>
After defined DataManager
, grid will request an AJAX POST for data. It will be sent to the specified data service for every grid actions with the needed parameters. This query parameters will help you to perform server-side operations for grid.
Parameters | Description |
---|---|
RequiresCounts |
If it is true then the total count of records will be included in response. |
Skip |
Holds the number of records to skip. |
Take |
Holds the number of records to take. |
Sorted |
Contains details about current sorted column and its direction. |
Table |
Defines data source table name. |
Where |
Contains details about current filter column name and its constraints. |
The parameters of DataManager bound to DataManagerRequest
in the server. You can use Dataoperations
and DataManagerRequest
to process grid actions such as Paging
, Sorting
, Searching
, and Filtering
using the following methods.
Method Names | Actions |
---|---|
PerformSkip |
Bypasses a specified Skip value and returns the remaining collections of records. |
PerformTake |
Bypasses a specified Take value and returns the remaining collections of records. |
PerformFiltering |
Filters a sequence of records based on a predicate. |
PerformSorting |
Sorts the collections of records based on its direction. |
PerformSearching |
Search the records based on a predicate. |
public IActionResult UrlDatasource([FromBody]DataManagerRequest dm)
{
IEnumerable DataSource = OrdersDetails.GetAllRecords();
DataOperations operation = new DataOperations();
if (dm.Search != null && dm.Search.Count > 0)
{
DataSource = operation.PerformSearching(DataSource, dm.Search); //Search
}
if (dm.Sorted != null && dm.Sorted.Count > 0) //Sorting
{
DataSource = operation.PerformSorting(DataSource, dm.Sorted);
}
if (dm.Where != null && dm.Where.Count > 0) //Filtering
{
DataSource = operation.PerformFiltering(DataSource, dm.Where, dm.Where[0].Operator);
}
int count = DataSource.Cast<OrdersDetails>().Count();
if (dm.Skip != 0)
{
DataSource = operation.PerformSkip(DataSource, dm.Skip); //Paging
}
if (dm.Take != 0)
{
DataSource = operation.PerformTake(DataSource, dm.Take);
}
return dm.RequiresCounts ? Json(new { result = DataSource, count = count }) : Json(DataSource);
}
NOTE
If the grid rendered rows with empty/blank values then it can be resolved with the procedure explained here.
WebMethod
The WebMethodAdaptor
is used to bind datasource from remote services and code behind methods. It can be enabled in Grid using Adaptor property of DataManager as WebMethodAdaptor
.
For every operations, an AJAX post will be send to the specified data service.
<ejs-grid id="Grid">
<e-data-manager url="Default.aspx/DataSource" adaptor="WebMethodAdaptor" crossdomain="true"></e-data-manager>
<e-grid-columns>
<e-grid-column field="OrderID" headerText="Order ID" type="number" textAlign="Right" width="120"></e-grid-column>
<e-grid-column field="CustomerID" headerText="Customer ID" type="string" width="140"></e-grid-column>
<e-grid-column field="Freight" headerText="Freight" textAlign="Right" format="C2" width="120"></e-grid-column>
<e-grid-column field="OrderDate" headerText="Order Date" format='yMd' textAlign="Right" width="140"></e-grid-column>
</e-grid-columns>
</ejs-grid>
public IActionResult Index()
{
return View();
}
WebMethodAdaptor
expects JSON response from the server and the response object should contain properties result
and count
whose values are collection of entities and total count of the entities respectively.
The sample response object should look like below.
{
result: [{..}, {..}, {..}, ...],
count: 830
}
NOTE
The controller method’s data parameter name must be
value
.