TL;DR: Learn how to integrate Syncfusion ASP.NET Core DataGrid into an ASP.NET Boilerplate project. This blog walks you through setting up the project, configuring CRUD operations, and adding powerful data functionalities like filtering, sorting, and searching.
ABP (ASP.NET Boilerplate) is an application framework designed to simplify the development of modern web applications. It features a modular architecture and built-in dependency injection, and it supports patterns like Unit of Work and Repository. It includes automatic API generation, multi-tenancy, robust authorization and authentication, and localization support. It also provides auditing, logging, and code generation tools and integrates with popular UI frameworks like Angular, React, and Blazor, offering a foundation for building scalable and maintainable apps.
As the web development landscape evolves, developers constantly seek efficient and feature-rich solutions to enhance their apps. In ASP.NET development, ASP.NET Boilerplate has emerged as a popular framework for building robust and scalable web apps.
In this blog, we’ll learn how to integrate Syncfusion ASP.NET Core DataGrid with ASP.NET Boilerplate framework.
Create an ASP.NET Boilerplate project
Step 1: Install Abp CLI
Ensure the Abp CLI is installed globally on your machine. If not, install it using the following command.
dotnet tool install -g Volo.Abp.Cli
Step 2: Create a new project
In your preferred folder, create a new project with your preferred name using the following command.
abp new SyncfusionGrid -csf
Step 3: Ensure version compatibility
After successfully creating the project, open the solution file. To prevent errors, ensure that the Abp CLI version and all source project versions are the same or lower than the CLI version. If your project Abp package version is higher, update the CLI version by running the following command.
abp cli update --version x.x.x
Step 4: Configure connection strings
Configure the appropriate connection strings in the appsettings.json file for both [projectname].Web and [projectname].DbMigration projects. Afterward, right-click on the DbMigration project and select the option, Set as Start-up Project.
[projectname].DbMigration/appsettings.json &[projectname].Web/appsettings.json
{
. . .
"ConnectionStrings": {
"Default": "Server=XXXXX;Database=SyncfusionGrid;Trusted_Connection=True;TrustServerCertificate=True"
},
. . .
}
Step 5: Run the project
Run the project. It may take some time to migrate the ABP database to your database.
Step 6: Configure XSRF-TOKEN
Since the POST request is used to call the URL method in the index.cs page, we need to configure XSRF-TOKEN and add the following code on the [projectname]WebModule.cs file of the [projectname].Web project.
For more details, refer to the How to Render Grid in ASP.NET Core Razor Page?.
[projectname]WebModule.cs
public override void ConfigureServices(ServiceConfigurationContext context)
{
. . . . . .
// Need to add the codes below.
context.Services.AddAntiforgery(o => o.HeaderName = "XSRF-TOKEN");
}
Additionally, in the Index.cshtml file, add the AntiForgeryToken in the razor page as follows.
@Html.AntiForgeryToken()
Step 7: Set the web project as Start-up
Right-click on the [projectname].Web project and select Set as Start-up Project.
Install the Syncfusion ASP.NET Core package
Let’s start by installing the Syncfusion package. Right-click on the [projectname].Web.csproj file, open Manage NuGet Packages, and search for Syncfusion.EJ2.AspNet.Core and then install it.
Alternatively, you can use the Package Manager Console. Ensure that the default project is set to src/[projectname].Web of the ASP.NET Boilerplate framework, and run the following command to install the EJ2 core package:
Install-Package Syncfusion.EJ2.AspNet.Core -Version x.x.x
[projectname].Web.csproj
Add Syncfusion ASP.NET Core Tag Helper
Open the ~/Pages/_ViewImports.cshtml file and add the Syncfusion.EJ2 TagHelper.
~/Pages/_ViewImports.cshtml
@* add Syncfusion.EJ2 TagHelper. *@
@addTagHelper *, Syncfusion.EJ2
Include stylesheet and script resources
In the ~/Pages/Index.cshtml file, add a link for the EJ2 stylesheet and scripts.
~/Pages/Index.cshtml
<!-- Syncfusion ASP.NET Core controls styles -->
<link rel="stylesheet" href="https://cdn.syncfusion.com/ej2/26.1.40/fluent.css" />
<!-- Syncfusion ASP.NET Core controls scripts -->
<script src="https://cdn.syncfusion.com/ej2/26.1.40/dist/ej2.min.js"></script>
Register Syncfusion Script Manager
Register the script manager <ejs-scripts> at the @section scripts of the Razor page.
~/Pages/Index.cshtml
@section scripts {
<!-- Syncfusion ASP.NET Core Script Manager -->
<ejs-scripts></ejs-scripts>
}
Troubleshoot: Render Grid rows without data
By default, ASP.NET Core returns JSON results in camelCase format, which can also alter grid field names. To resolve this issue, we need to add DefaultContractResolver in the Program.cs file.
For this, we need to install the Microsoft.AspNetCore.Mvc.NewtonsoftJson package using the Package Manager Console or NuGet Package Manager.
Program.cs
builder.Services.AddMvc().AddNewtonsoftJson(options =>
{
options.SerializerSettings.ContractResolver = new DefaultContractResolver();
});
For more details, refer to the Troubleshooting grid rows without data.
Adding Syncfusion DataGrid
Now, insert the following grid code in the ~/Pages/Index.cshtml file. This example links the data using the customAdaptor concept by extending UrlAdaptor. This approach involves sending a post request to retrieve data from the server and execute additional grid actions.
The Syncfusion ASP.NET Core Grid component supports various server-side data operations, such as searching, sorting, filtering, aggregation, and paging. These operations can be managed using the PerformSearching, PerformFiltering, PerformSorting, PerformTake, and PerformSkip methods from the Syncfusion.EJ2.AspNet.Core package. Let’s explore how to manage these data operations using the UrlAdaptor.
In your API service project, add the Syncfusion.EJ2.AspNet.Core package through the NuGet Package Manager in Visual Studio ( Tools → NuGet Package Manager → Manage NuGet Packages for Solution ).
To access DataManagerRequest and QueryableOperation, import the Syncfusion.EJ2.Base in your controller page.
~/Pages/Index.cshtml
<ejs-grid id="grid"
load="onLoad"
allowFiltering="true"
allowGrouping="true"
allowSorting="true"
allowPaging="true"
toolbar="@(new List() { 'Add', 'Edit', 'Delete', 'Cancel', 'Update' })">
<e-grid-editsettings allowEditing="true"
allowAdding="true"
allowDeleting="true">
</e-grid-editsettings>
<e-grid-columns>
<e-grid-column field="OrderID"
headerText="Order ID"
isPrimaryKey="true"
textAlign="Right"
width="120">
</e-grid-column>
<e-grid-column field="CustomerID"
headerText="Customer ID"
width="150"
validationRules="@(new { required= true })">
</e-grid-column>
<e-grid-column field="OrderDate"
headerText="Order Date"
width="130"
textAlign="Right"
format="yMd">
</e-grid-column>
<e-grid-column field="Freight"
headerText="Freight"
width="130"
textAlign="Right"
format="C2"
editType="numericedit"
validationRules="@(new { required= true })">
</e-grid-column>
<e-grid-column field="ShipCountry"
headerText="Ship Country"
width="120">
</e-grid-column>
</e-grid-columns>
</ejs-grid>
<abp-script src="/Pages/Index.js"></abp-script>
In the ~/Pages/Index.js file, add the following JavaScript code:
window.customAdaptor = new ej.data.UrlAdaptor();
customAdaptor = ej.base.extend(customAdaptor, {
processResponse: function (data, ds, query, xhr, request, changes) {
request.data = JSON.stringify(data);
return ej.data.UrlAdaptor.prototype.processResponse.call(this, data, ds, query, xhr, request, changes);
}
});
function onLoad() {
this.dataSource = new ej.data.DataManager({
url: '/Index?handler=GridDataOperationHandler',
insertUrl: "/Index?handler=GridInsertPostHandler",
updateUrl: "/Index?handler=GridUpdatePostHandler",
removeUrl: "/Index?handler=GridRemovePostHandler",
adaptor: customAdaptor
});
this.dataSource.dataSource.headers = [
{ 'XSRF-TOKEN': $("input:hidden[name='__RequestVerificationToken']").val() }
];
}
Handling search operations
To implement search functionality, ensure your API endpoint supports custom search criteria. Implement the searching logic on the server side using the PerformSearching method from the QueryableOperation class. This allows the custom data source to undergo searching based on the criteria specified in the incoming DataManagerRequest object.
In Pages/Index.cshtml.cs file, you can manage grid data operations like in the following code example.
// All data operations except crud post.
public JsonResult OnPostGridDataOperationHandler([FromBody] DataManagerRequest dm)
{
IEnumerable DataSource = orddata.ToList();
DataOperations operation = new DataOperations();
if (dm.Search != null && dm.Search.Count > 0)
{
DataSource = operation.PerformSearching(DataSource, dm.Search); // Search
}
return dm.RequiresCounts
? new JsonResult(new { result = DataSource, count = count })
: new JsonResult(DataSource);
}
Handling filtering operations
To handle filtering operations, ensure that your API endpoint supports custom filtering criteria. Implement the filtering logic on the server side using the PerformFiltering method from the QueryableOperation class. This allows the custom data source to undergo filtering based on the criteria specified in the incoming DataManagerRequest object.
Pages/Index.cshtml.cs
// All data operations except crud post.
public JsonResult OnPostGridDataOperationHandler([FromBody] DataManagerRequest dm)
{
IEnumerable DataSource = orddata.ToList();
DataOperations operation = new DataOperations();
if (dm.Where != null && dm.Where.Count > 0) // Filtering
{
DataSource = operation.PerformFiltering(DataSource, dm.Where, dm.Where[0].Operator);
}
return dm.RequiresCounts
? new JsonResult(new { result = DataSource, count = count })
: new JsonResult(DataSource);
}
Handling sorting operations
For sorting operations, ensure that your API endpoint supports custom sorting criteria. Implement the sorting logic on the server side using the PerformSorting method from the QueryableOperation class. This allows the custom data source to undergo sorting based on the criteria specified in the incoming DataManagerRequest object.
Pages/Index.cshtml.cs
// All data operations except crud post.
public JsonResult OnPostGridDataOperationHandler([FromBody] DataManagerRequest dm)
{
IEnumerable DataSource = orddata.ToList();
DataOperations operation = new DataOperations();
if (dm.Sorted != null && dm.Sorted.Count > 0) // Sorting
{
DataSource = operation.PerformSorting(DataSource, dm.Sorted);
}
int count = DataSource.Cast().Count();
if (dm.Skip != 0)
{
DataSource = operation.PerformSkip(DataSource, dm.Skip); // Paging
}
if (dm.Take != 0)
{
DataSource = operation.PerformTake(DataSource, dm.Take); // Paging
}
return dm.RequiresCounts
? new JsonResult(new { result = DataSource, count = count })
: new JsonResult(DataSource);
}
Handling paging operations
For paging, ensure that your API endpoint supports custom paging criteria. Implement the paging logic on the server side using the PerformTake and PerformSkip methods from the QueryableOperation class. This allows the custom data source to undergo paging based on the criteria specified in the incoming DataManagerRequest object.
Pages/Index.cshtml.cs
// All data operations except crud post.
public JsonResult OnPostGridDataOperationHandler([FromBody] DataManagerRequest dm)
{
IEnumerable DataSource = orddata.ToList();
DataOperations operation = new DataOperations();
int count = DataSource.Cast().Count();
if (dm.Skip != 0)
{
DataSource = operation.PerformSkip(DataSource, dm.Skip); // Paging
}
if (dm.Take != 0)
{
DataSource = operation.PerformTake(DataSource, dm.Take); // Paging
}
return dm.RequiresCounts
? new JsonResult(new { result = DataSource, count = count })
: new JsonResult(DataSource);
}
Handling CRUD Operations
The ASP.NET Core DataGrid Component seamlessly integrates CRUD (Create, Read, Update, Delete) operations with server-side controller actions through specific properties: insertUrl, removeUrl, updateUrl, crudUrl, and batchUrl. These properties enable the grid to communicate with the data service for every grid action, facilitating server-side operations.
CRUD operations mapping
CRUD operations within the grid can be mapped to server-side controller actions using the following specific properties:
- insertUrl: Specifies the URL for inserting new data.
- removeUrl: Specifies the URL for removing existing data.
- updateUrl: Specifies the URL for updating existing data.
- crudUrl: Specifies a single URL for all CRUD operations.
- batchUrl: Specifies the URL for batch editing.
Insert operation
To insert a new record, utilize the insertUrl property to specify the controller action mapping URL for the insert operation.
// normal insert post.
public JsonResult OnPostGridInsertPostHandler([FromBody] CRUDModel value)
{
orddata.Insert(0, value.Value);
return new JsonResult(value);
}
function onLoad() {
this.dataSource = new ej.data.DataManager({
url: '/Index?handler=GridDataOperationHandler',
insertUrl: "/Index?handler=GridInsertPostHandler",
// ... other properties
adaptor: customAdaptor
});
// ... additional code
}
Update operation
To update existing records, utilize the updateUrl property to specify the controller action mapping URL for the update operation.
// normal update post.
public JsonResult OnPostGridUpdatePostHandler([FromBody] CRUDModel value)
{
var data = orddata.Where(or => or.OrderID == value.Value.OrderID).FirstOrDefault();
if (data != null)
{
data.OrderID = value.Value.OrderID;
data.CustomerID = value.Value.CustomerID;
data.Freight = value.Value.Freight;
data.EmployeeID = value.Value.EmployeeID;
data.ShipCity = value.Value.ShipCity;
data.Verified = value.Value.Verified;
data.OrderDate = value.Value.OrderDate;
data.ShipName = value.Value.ShipName;
data.ShipCountry = value.Value.ShipCountry;
data.ShippedDate = value.Value.ShippedDate;
data.ShipAddress = value.Value.ShipAddress;
}
return new JsonResult(value);
}
function onLoad() {
this.dataSource = new ej.data.DataManager({
// ... other properties
updateUrl: "/Index?handler=GridUpdatePostHandler",
// ... additional code
adaptor: customAdaptor
});
// ... more code
}
Delete operation
To delete existing records, use the removeUrl property to specify the controller action mapping URL for the delete operation
In Pages/Index.cshtml.cs, you can perform grid data operations as follows:
// normal delete post.
public JsonResult OnPostGridRemovePostHandler([FromBody] CRUDModel value)
{
orddata.Remove(orddata.Where(or => or.OrderID == (Int64)value.Key).FirstOrDefault());
return new JsonResult(value);
}
function onLoad() {
this.dataSource = new ej.data.DataManager({
// ... other properties
removeUrl: "/Index?handler=GridRemovePostHandler",
adaptor: customAdaptor
});
// ... additional code
}
A single method for performing all CRUD operations
Using the crudUrl property, the controller action mapping URL can be specified to perform all the CRUD operations on the server side using a single method instead of defining separate controller action methods for CRUD (insert, update, and delete) operations.
Refer to the following code example.
~/Pages/Index.js
window.customAdaptor = new ej.data.UrlAdaptor();
customAdaptor = ej.base.extend(customAdaptor, {
processResponse: function (data, ds, query, xhr, request, changes) {
request.data = JSON.stringify(data);
return ej.data.UrlAdaptor.prototype.processResponse.call(this, data, ds, query, xhr, request, changes);
}
});
function onLoad() {
this.dataSource = new ej.data.DataManager({
url: '/Index?handler=GridDataOperationHandler',
crudUrl: "/Index?handler=GridCrudPostHandler", // add only crud url here.
adaptor: customAdaptor
});
this.dataSource.dataSource.headers = [{ 'XSRF-TOKEN': $("input:hidden[name='__RequestVerificationToken']").val() }];
}
~/Pages/Index.cshtml.cs
// normal edit crud url post.
public JsonResult OnPostGridCrudPostHandler([FromBody] CRUDModel<OrdersDetails> value)
{
// normal update post.
if (value.Action == "update")
{
var data = orddata.Where(or => or.OrderID == value.Value.OrderID).FirstOrDefault();
if (data != null)
{
data.OrderID = value.Value.OrderID;
data.CustomerID = value.Value.CustomerID;
data.Freight = value.Value.Freight;
data.EmployeeID = value.Value.EmployeeID;
data.ShipCity = value.Value.ShipCity;
data.Verified = value.Value.Verified;
data.OrderDate = value.Value.OrderDate;
data.ShipName = value.Value.ShipName;
data.ShipCountry = value.Value.ShipCountry;
data.ShippedDate = value.Value.ShippedDate;
data.ShipAddress = value.Value.ShipAddress;
}
}
// normal insert post.
else if (value.Action == "insert")
{
orddata.Insert(0, value.Value);
}
// normal delete post.
else if (value.Action == "remove")
{
orddata.Remove(orddata.Where(or => or.OrderID == (Int64)value.Key).FirstOrDefault());
}
return new JsonResult(value);
}
Handling batch/bulk CRUD operations
To perform batch operation, define the edit mode as Batch and specify the batchUrl property in the DataManager. Use the add toolbar button to insert a new row in batch editing mode. To edit a cell, double-click the desired cell and update the value as required. To delete a record, select the record and press the delete toolbar button. Now, all CRUD operations will be executed in a single request.
~/Pages/Index.cshtml
<ejs-grid id="grid" load="onLoad" allowFiltering="true" allowGrouping="true" allowSorting="true" allowPaging="true" toolbar="@(new List<string>() { "Add", "Edit", "Delete", "Cancel", "Update" })">
// need to add batch mode.
<e-grid-editsettings allowEditing="true" allowAdding="true" allowDeleting="true" mode="Batch"></e-grid-editsettings>
. . . . . .
</ejs-grid>
<abp-script src="/Pages/Index.js" />
~/Pages/Index.js
// . . . . . . .
function onLoad() {
this.dataSource = new ej.data.DataManager({
url: '/Index?handler=GridDataOperationHandler',
batchUrl: "/Index?handler=GridBatchCrudPostHandler", // add only batch crud url here.
adaptor: customAdaptor
});
this.dataSource.dataSource.headers = [{ 'XSRF-TOKEN': $("input:hidden[name='__RequestVerificationToken']").val() }];
}
~/Pages/Index.cshtml.cs
// Batch edit bulk crud url post.
public JsonResult OnPostGridBatchCrudPostHandler([FromBody] CRUDModel<OrdersDetails> value)
{
if (value.Changed.Count > 0)
{
for (int i = 0; i < value.Changed.Count; i++)
{
var data = orddata.Where(or => or.OrderID == value.Changed[i].OrderID).FirstOrDefault();
if (data != null)
{
data.OrderID = value.Changed[i].OrderID;
data.CustomerID = value.Changed[i].CustomerID;
data.Freight = value.Changed[i].Freight;
data.EmployeeID = value.Changed[i].EmployeeID;
data.ShipCity = value.Changed[i].ShipCity;
data.Verified = value.Changed[i].Verified;
data.OrderDate = value.Changed[i].OrderDate;
data.ShipName = value.Changed[i].ShipName;
data.ShipCountry = value.Changed[i].ShipCountry;
data.ShippedDate = value.Changed[i].ShippedDate;
data.ShipAddress = value.Changed[i].ShipAddress;
}
}
}
if (value.Added.Count > 0)
{
for (var i = 0; i < value.Added.Count; i++)
{
orddata.Insert(i, value.Added[i]);
}
}
if (value.Deleted.Count > 0)
{
for (var i = 0; i < value.Deleted.Count; i++)
{
orddata.Remove(orddata.Where(or => or.OrderID == value.Deleted[i].OrderID).FirstOrDefault());
}
}
return new JsonResult(value);
}
Refer to the following image.
GitHub reference
For more details, refer to the integrating ASP.NET Core DataGrid in ASP.NET Boilerplate GitHub demo.
Conclusion
Thanks for reading! In conclusion, integrating Syncfusion ASP.NET Core DataGrid with ASP.NET Boilerplate provides developers with a potent combination for building robust and scalable web apps. By harnessing the capabilities of the DataGrid, developers can streamline their development workflows and deliver compelling user experiences.
Throughout this exploration, we’ve witnessed how our DataGrid serves as a cornerstone for displaying and managing tabular data effectively within ASP.NET Boilerplate apps.
For existing customers, the new version of Essential Studio® is available for download from the License and Downloads page. If you are not a Syncfusion customer, try our 30-day free trial to check out our available features.
You can contact us through our support forum, support portal, or feedback portal. We are here to help you succeed!
Top comments (0)