Remote Data Binding with Custom Web Methods in Syncfusion React Gantt
18 Nov 201821 minutes to read
The WebMethodAdaptor enables the Syncfusion® React Gantt to communicate with server web methods and legacy endpoints by packaging task data requests and task modification payloads into a structured request envelope the server can deserialize. This adaptor is suitable for backend that expose web methods where task requests and updates are handled via HTTP POST operations.
For backend configuration and expected request/response shapes, consult the WebMethod adaptor backend setup documentation for your platform. After the backend is prepared, configure the DataManager in the React application to use the WebMethod adaptor as the Gantt data source.
For complete server‑side configuration and additional implementation details, refer to the DataManager Webmethod Adaptor documentation, which covers endpoint setup, query processing, and best practices for integrating WebMethod‑based services.
Project structure (conceptual):
- Frontend: a React project hosting the Gantt and a DataManager configured for WebMethod endpoints.
- Backend: a web methods service that receives the adaptor’s request envelope, processes task queries and mutation payloads, and returns JSON task records and related metadata.
WebMethodAdaptor/
├── WebMethodAdaptor.client/ # React frontend (Vite/React project).
│ ├── src/
│ │ ├── App.css
│ │ └── App.jsx # Add WebMethodAdaptor here.
│ └── package.json
└── WebMethodAdaptor.Server/ # ASP.NET Core backend (API).
├── Controllers/ # API controllers (will be created here).
├── Models/ # Data models (will be created here).
└── Program.cs # Server configuration.
React Gantt frontend setup using WebMethod adaptor
This section describes, at a conceptual level, how the Gantt consumes task data from web methods and submits task changes. Implementation and package installation steps are covered in platform‑specific setup guides and are intentionally omitted here.
Step 1: Packages and dependencies
- Ensure the React project includes the Syncfusion Gantt and data packages required to render the Gantt and to use the DataManager and WebMethod adaptor.
- Right‑click the WebMethodAdaptor.client folder in Solution Explorer and select Open in Terminal (available in newer Visual Studio versions), or open a Developer Command prompt/PowerShell from the Start menu and navigate manually to the WebMethodAdaptor.client. Once inside the folder, confirm that package.json is present, then run the following commands to install the required Syncfusion® packages:
npm install @syncfusion/ej2-react-gantt --save
npm install @syncfusion/ej2-data --saveStep 2: CSS and component styling
- Include the required Syncfusion theme and component styles so the Gantt and its input controls render correctly. Add these imports to index.css or App.css:
/* Basic Gantt Chart styles */
@import "../node_modules/@syncfusion/ej2-base/styles/tailwind3.css";
@import "../node_modules/@syncfusion/ej2-gantt/styles/tailwind3.css";
@import "../node_modules/@syncfusion/ej2-grids/styles/tailwind3.css";
@import "../node_modules/@syncfusion/ej2-treegrid/styles/tailwind3.css";
@import "../node_modules/@syncfusion/ej2-layouts/styles/tailwind3.css";
@import "../node_modules/@syncfusion/ej2-popups/styles/tailwind3.css";
/* For editing, toolbar, and dialog features */
@import "../node_modules/@syncfusion/ej2-calendars/styles/tailwind3.css";
@import "../node_modules/@syncfusion/ej2-dropdowns/styles/tailwind3.css";
@import "../node_modules/@syncfusion/ej2-inputs/styles/tailwind3.css";
@import "../node_modules/@syncfusion/ej2-buttons/styles/tailwind3.css";
@import "../node_modules/@syncfusion/ej2-navigations/styles/tailwind3.css";
@import "../node_modules/@syncfusion/ej2-notifications/styles/tailwind3.css";
/* For rich text editor in dialog notes tab */
@import "../node_modules/@syncfusion/ej2-richtexteditor/styles/tailwind3.css";Import the App.css in the application entry point(App.jsx).
import "./App.css";
...
...Step 3: Configure DataManager with WebMethod adaptor
- Configure a DataManager instance that targets your web method endpoints and specifies the WebMethod adaptor. The Gantt uses that DataManager to fetch tasks, request related datasets, and submit task create/update/delete payloads wrapped in the expected envelope.
Conceptually, the adaptor sends a request object that contains request metadata (for example, whether the client requires counts or which timeline range to return) together with task update payloads when the user performs create, update, or delete actions in the Gantt.
import React from "react";
import { DataManager, WebMethodAdaptor } from "@syncfusion/ej2-data";
import { GanttComponent, Inject, Selection, ColumnsDirective, ColumnDirective } from '@syncfusion/ej2-react-gantt';
function App() {
// Configure DataManager with WebMethodAdaptor
const data = new DataManager({
url: "https://localhost:xxxx/api/Gantt", // Here xxxx represents the port number.
adaptor: new WebMethodAdaptor(),
crossDomain: true
});
const taskFields = {
id: 'TaskID',
name: 'TaskName',
startDate: 'StartDate',
endDate: 'EndDate',
duration: 'Duration',
progress: 'Progress',
dependency: 'Dependency',
parentID: 'ParentID',
};
return (
<GanttComponent dataSource={data} taskFields={taskFields} height='400px' >
<ColumnsDirective>
<ColumnDirective field="TaskID" headerText="Task ID" textAlign="Right" width="90" type="number" />
<ColumnDirective field="TaskName" headerText="Task Name" textAlign="Left" width="270" type="string" />
<ColumnDirective field="StartDate" headerText="Start Date" textAlign="Right" width="150" format="yMd" type="dateTime" />
<ColumnDirective field="EndDate" headerText="End Date" textAlign="Right" width="150" format="dd/MM/yyyy hh:mm" type="dateTime" />
<ColumnDirective field="Duration" headerText="Duration" textAlign="Right" width="90" type="string" />
<ColumnDirective field="Progress" headerText="Progress" textAlign="Right" width="120" type="number" />
</ColumnsDirective>
<Inject services={[Selection]} />
</GanttComponent>
);
}
export default App;Server-side data operations
When task sets are large or when scheduling rules must be applied consistently, the server receives responsibility for processing task queries and task modifications. Using web methods, the server applies scheduling rules, dependency validation, and any project‑specific business logic before returning task records or acknowledging changes.The Syncfusion.EJ2.AspNet.Core package supports this approach by providing built‑in methods that efficiently handle these operations on the server, ensuring smooth performance even with heavy data loads.
CRUD operations
The DataManager with WebMethodAdaptor supports Create, Read, Update, and Delete workflows for task entities. In Gantt usage, these operations cover task creation, task edits (including taskbar edits and resulting scheduling recalculations), dependency creation or modification, and task deletion.
Mapping CRUD operations to service endpoints
CRUD operations are conveyed to the service using standard WebMethod conventions. The WebMethodAdaptor works with a single task endpoint and standard HTTP methods:
| Operation | HTTP Method | URL Example | Description |
|---|---|---|---|
| Read | POST | /api/Gantt |
Get all records. |
| Create | POST | /api/Gantt |
Add a new record. |
| Update | POST | /api/Gantt |
Update record. |
| Delete | POST | /api/Gantt |
Delete record. |
Step 1: Complete server-side controller
Add all CRUD methods to the GanttController.cs. Replace the entire controller with this complete version:
using Microsoft.AspNetCore.Mvc;
using Syncfusion.EJ2.Base;
using WebMethodAdaptorDemo.Server.Models;
namespace WebMethodAdaptorDemo.Server.Controllers
{
[Route("api/[controller]")]
[ApiController]
public class GanttController : ControllerBase
{
[HttpGet]
public List<GanttTask> GetOrderData()
{
return GanttDataAdaptor.GetGanttTasks().ToList();
}
[HttpPost]
public object Post([FromBody] CRUDModel<GanttTask> data)
{
if (data == null)
return BadRequest();
// Work against the single backing list once
var tasks = GanttDataAdaptor.GetGanttTasks(); // assume List<GanttTask>
if (data.action == "batch")
{
// Added: assign TaskID if missing and add to backing list
if (data.added != null)
{
int nextId = tasks.Any() ? tasks.Max(t => t.TaskID) + 1 : 1;
foreach (var task in data.added)
{
if (task.TaskID == 0)
task.TaskID = nextId++;
tasks.Add(task);
}
}
// Changed: update existing items safely (check for null)
if (data.changed != null)
{
foreach (var task in data.changed)
{
var existing = tasks.FirstOrDefault(t => t.TaskID == task.TaskID);
if (existing == null) continue;
existing.TaskName = task.TaskName;
existing.StartDate = task.StartDate;
existing.EndDate = task.EndDate;
existing.Duration = task.Duration;
existing.Progress = task.Progress;
existing.Dependency = task.Dependency;
existing.ParentID = task.ParentID;
}
}
// Deleted: remove by TaskID
if (data.deleted != null)
{
foreach (var task in data.deleted)
{
var existing = tasks.FirstOrDefault(t => t.TaskID == task.TaskID);
if (existing != null)
tasks.Remove(existing);
}
}
}
// Return the updated data and count
var dataSource = tasks.AsQueryable();
int totalRecordsCount = tasks.Count;
return Ok(new { result = dataSource, count = totalRecordsCount });
}
}
/// <summary>
/// Wrapper class for WebMethodAdaptor requests.
/// WebMethodAdaptor wraps DataManagerRequest inside a 'value' property.
/// </summary>
public class DataManager
{
public required DataManagerRequest Value { get; set; }
}
public class CRUDModel<T>
where T : class
{
public string? action { get; set; }
public string? keyColumn { get; set; }
public object? key { get; set; }
public T? value { get; set; }
public List<T>? added { get; set; }
public List<T>? changed { get; set; }
public List<T>? deleted { get; set; }
public IDictionary<string, object>? @params { get; set; }
}
}Step 2: Client-side gantt configuration
React Gantt enables full CRUD functionality by configuring the required toolbar buttons (Add, Edit, Update, Delete, and Cancel) and enabling adding, editing, updating, and deleting through the editSettings property. This setup allows the Gantt to handle all basic data operations directly from the UI.
import React from "react";
import { DataManager, WebMethodAdaptor } from "@syncfusion/ej2-data";
import { GanttComponent, Inject, Edit, Selection, Toolbar, ColumnsDirective, ColumnDirective } from '@syncfusion/ej2-react-gantt';
function App() {
// Configure DataManager with WebMethodAdaptor
const data = new DataManager({
url: "https://localhost:xxxx/api/Gantt", // Here xxxx represents the port number.
adaptor: new WebMethodAdaptor(),
crossDomain: true
});
const taskFields = {
id: 'TaskID',
name: 'TaskName',
startDate: 'StartDate',
endDate: 'EndDate',
duration: 'Duration',
progress: 'Progress',
dependency: 'Dependency',
parentID: 'ParentID',
};
const editSettings = {
allowEditing: true,
allowAdding: true,
allowDeleting: true,
allowTaskbarEditing: true
};
const toolbar = ['Add', 'Edit', 'Update', 'Delete', 'Cancel', 'ExpandAll', 'CollapseAll', 'Indent', 'Outdent'];
return (
<GanttComponent dataSource={data} taskFields={taskFields} editSettings={editSettings} height='400px' toolbar={toolbar} >
<ColumnsDirective>
<ColumnDirective field="TaskID" headerText="Task ID" textAlign="Right" width="90" type="number" />
<ColumnDirective field="TaskName" headerText="Task Name" textAlign="Left" width="270" type="string" />
<ColumnDirective field="StartDate" headerText="Start Date" textAlign="Right" width="150" format="yMd" type="dateTime" />
<ColumnDirective field="EndDate" headerText="End Date" textAlign="Right" width="150" format="dd/MM/yyyy hh:mm" type="dateTime" />
<ColumnDirective field="Duration" headerText="Duration" textAlign="Right" width="90" type="string" />
<ColumnDirective field="Progress" headerText="Progress" textAlign="Right" width="120" type="number" />
</ColumnsDirective>
<Inject services={[Edit, Selection, Toolbar]} />
</GanttComponent>
);
}
export default App;Run the application (conceptual)
Run the application in Visual Studio, accessible on a URL like https://localhost:xxxx. Verify the API returns data at https://localhost:xxxx/api/Gantt, where xxxx is the port. Gantt displays data fetched from the backend API.
Troubleshooting
| Issue | Cause | Solution |
|---|---|---|
| Empty response | Web method not returning task records or required metadata | Verify method returns records with parent ids, resource assignments, and start/end dates for the timeline range |
| 404 responses | Incorrect web method route or endpoint configuration | Confirm DataManager URLs and routes are correctly configured and accessible |
| 500 or server errors | Server-side exceptions or improper request parameter handling | Check server logs, validate parameter parsing, and ensure scheduling/dependency logic is error-free |
| CORS errors | Cross-origin requests blocked or not configured | Ensure CORS is enabled when frontend and backend are hosted on different origins |
| Related data mismatches | Remote datasets not returning expected values for relationships and dependencies | Confirm related endpoints return correct data required for display and dependency resolution |
Complete sample repository
For the complete working implementation of this example, refer to the GitHub repository.