Remote Data in Blazor DataGrid

2 Jun 202521 minutes to read

In the Syncfusion Blazor DataGrid, binding remote data is a fundamental feature that enables efficient interaction with external data services. This process involves assigning a remote data service, represented by an instance of SfDataManager, to the DataSource property of the Grid. By specifying the endpoint URL and the appropriate adaptor, you can seamlessly connect the Grid to remote sources such as OData, Web API, RESTful services, or GraphQL endpoints.

To bind remote data in the Grid:

  • Create an instance of SfDataManager and configure its Url property with the endpoint of your remote data service.
  • Set the Adaptor property to match the type of service you are connecting to (e.g., ODataAdaptor, WebApiAdaptor, UrlAdaptor, etc.).
  • Assign the configured SfDataManager to the DataSource property of the Grid.
  • Explicitly specify the TValue type for the Grid to match your data model.

Example:

@using Syncfusion.Blazor.Grids
@using Syncfusion.Blazor.Data

<SfGrid TValue="Order" DataSource="@RemoteData" AllowPaging="true">
    <GridColumns>
        <GridColumn Field="OrderID" HeaderText="Order ID" Width="120" TextAlign="TextAlign.Right"></GridColumn>
        <GridColumn Field="CustomerID" HeaderText="Customer Name" Width="150"></GridColumn>
        <GridColumn Field="Freight" HeaderText="Freight" Width="120" Format="C2" TextAlign="TextAlign.Right"></GridColumn>
        <GridColumn Field="ShipCountry" HeaderText="Ship Country" Width="150"></GridColumn>
    </GridColumns>
</SfGrid>

@code {
    public SfDataManager RemoteData = new SfDataManager
    {
        Url = "https://services.odata.org/V4/Northwind/Northwind.svc/Orders",
        Adaptor = Adaptors.ODataV4Adaptor
    };

    public class Order
    {
        public int OrderID { get; set; }
        public string CustomerID { get; set; }
        public double? Freight { get; set; }
        public string ShipCountry { get; set; }
    }
}

When using SfDataManager for remote data binding, ensure the TValue type of the Grid matches your data model.
If no adaptor is specified, SfDataManager uses the ODataAdaptor by default.

This setup allows the Grid to interact with remote data sources efficiently, supporting features like paging, sorting, and filtering directly from the server.

Binding with OData services

OData (Open Data Protocol) is a standardized protocol designed to simplify data sharing across disparate systems. It enables querying and updating data via RESTful APIs. The Syncfusion Blazor SfDataManager provides built-in support for consuming OData v3 and v4 services, making it easy to bind remote OData service data to the Grid.

The SfDataManager communicates with the remote OData service using the ODataAdaptor or ODataV4Adaptor, depending on the OData protocol version.

Use ODataAdaptor for OData v3 services and ODataV4Adaptor for OData v4 services.
Ensure that the response format of the OData service aligns with the expected Grid data model.

The following example demonstrates how to bind an OData service to the Grid using SfDataManager:

@using Syncfusion.Blazor
@using Syncfusion.Blazor.Data
@using Syncfusion.Blazor.Grids

<SfGrid TValue="Order" AllowPaging="true">
        <SfDataManager Url="https://services.odata.org/Northwind/Northwind.svc/Orders" Adaptor="Adaptors.ODataAdaptor"></SfDataManager>
        <GridColumns>
                <GridColumn Field=@nameof(Order.OrderID) HeaderText="Order ID" IsPrimaryKey="true" TextAlign="TextAlign.Right" Width="120"></GridColumn>
                <GridColumn Field=@nameof(Order.CustomerID) HeaderText="Customer Name" Width="150"></GridColumn>
                <GridColumn Field=@nameof(Order.OrderDate) HeaderText="Order Date" Format="d" Type="ColumnType.Date" TextAlign="TextAlign.Right" Width="130"></GridColumn>
                <GridColumn Field=@nameof(Order.Freight) HeaderText="Freight" Format="C2" TextAlign="TextAlign.Right" Width="120"></GridColumn>
                <GridColumn Field=@nameof(Order.ShipCountry) HeaderText="Ship Country" Width="150"></GridColumn>
        </GridColumns>
</SfGrid>

@code{
        public class Order {
                public int? OrderID { get; set; }
                public string CustomerID { get; set; }
                public DateTime? OrderDate { get; set; }
                public double? Freight { get; set; }
                public string ShipCountry { get; set; }
        }
}

Enable SfDataManager after initial rendering

In Syncfusion Blazor DataGrid, remote data binding using the SfDataManager is typically configured during initialization. However, in some scenarios where data should not be loaded immediately when the page is rendered. Instead, you can load data dynamically based on specific conditions or user actions. This approach optimizes performance by reducing initial load time and avoiding unnecessary network calls.

Initially, render the Grid with an empty data source. You can then conditionally assign the SfDataManager to the Grid’s DataSource property in response to a user event. When the SfDataManager is added dynamically, the Grid will immediately initiate a request to the configured remote endpoint and display the fetched data.

The following example demonstrates how to bind the Grid to a remote Web API service only after a button is clicked by the user.

@using Syncfusion.Blazor
@using Syncfusion.Blazor.Buttons
@using Syncfusion.Blazor.Data
@using Syncfusion.Blazor.Grids

<SfButton OnClick="Enable" CssClass="e-primary" IsPrimary="true" Content="Enable data manager"></SfButton>
<SfGrid TValue="Order" AllowPaging="true">
        <GridPageSettings PageSize="10"></GridPageSettings>
        @if (IsDataManagerEnabled)
        {
                <SfDataManager Url="https://blazor.syncfusion.com/services/production/api/Orders/" Adaptor="Adaptors.WebApiAdaptor"></SfDataManager>
        }
        <GridColumns>
                <GridColumn Field=@nameof(Order.OrderID) HeaderText="Order ID" IsPrimaryKey="true" TextAlign="TextAlign.Right" Width="120"></GridColumn>
                <GridColumn Field=@nameof(Order.CustomerID) HeaderText="Customer Name" Width="150"></GridColumn>
                <GridColumn Field=@nameof(Order.OrderDate) HeaderText="Order Date" Format="d" Type="ColumnType.Date" TextAlign="TextAlign.Right" Width="130"></GridColumn>
                <GridColumn Field=@nameof(Order.Freight) HeaderText="Freight" Format="C2" TextAlign="TextAlign.Right" Width="120"></GridColumn>
        </GridColumns>
</SfGrid>

@code{
        public bool IsDataManagerEnabled = false;

        public class Order
        {
                public int? OrderID { get; set; }
                public string CustomerID { get; set; }
                public DateTime? OrderDate { get; set; }
                public double? Freight { get; set; }
        }

        public void Enable()
        {
                // Enabling condition to render the data manager.
                this.IsDataManagerEnabled = true;
        }
}

The following GIF demonstrates dynamically rendering the data manager in the Grid:

Dynamically Rendering Data Manager in Blazor DataGrid

Configuring HttpClient

The SfDataManager uses an HttpClient instance to make HTTP requests to data services. When initializing, SfDataManager checks if an HttpClient is already registered in the service container. If found, it uses the registered instance; otherwise, it creates and adds its own HttpClient to the service container for server requests.

Register your HttpClient before calling AddSyncfusionBlazor() in Program.cs. This ensures SfDataManager uses your pre-configured HttpClient (with base address, authentication, default headers, etc.) instead of creating a new one.

You can also pass an HttpClient instance directly to the SfDataManager using the HttpClientInstance property. This is useful when your application has multiple pre-configured or named HttpClient instances.

To troubleshoot HTTP requests and responses, you can use a custom HTTP message handler. For details on registering a custom handler, see the ASP.NET Core documentation.

Using Typed clients with SfDataManager is not supported. To achieve similar requirements, use the custom binding feature.

Authorization and Authentication

When accessing remote data services, it is common for the server to require authorization to prevent anonymous access. The SfDataManager can consume data from protected remote services by providing the appropriate bearer (access) token. You can provide the access token to SfDataManager in the following ways:

  • Using a pre-configured HttpClient:
    Register an HttpClient instance with the access token or an authentication message handler before calling AddSyncfusionBlazor() in your Program.cs. This ensures that SfDataManager uses the configured HttpClient instead of creating its own, allowing it to access protected services.

  • Setting the access token in the default headers:
    Inject the configured HttpClient into your page and set the access token in the default request headers. For example:

      ```csharp
      @inject HttpClient _httpClient
    
      @code {
              protected override async Task OnInitializedAsync()
              {
                      _httpClient.DefaultRequestHeaders.Add("Authorization", $"Bearer {tokenValue}");
                      await base.OnInitializedAsync();
              }
      }
      ```
    
  • Using the Headers property of SfDataManager:
    Set the access token directly in the Headers property of SfDataManager. For more details, see Setting custom headers.

The method for obtaining the bearer token depends on your authentication provider. For more information on configuring HttpClient with authentication in Blazor, refer to the official documentation here.

Setting custom headers

In scenarios where your application needs to send authentication tokens, API keys, or other metadata with each data request, you can add custom HTTP headers to the requests made by the Syncfusion Blazor DataGrid. This is especially useful when interacting with secured APIs or services that require specific headers for authorization or tracking.

To achieve this, use the Headers property of the SfDataManager. The Headers property accepts a dictionary of key-value pairs, where each key is the header name and the value is the header value.

The following example demonstrates adding custom headers to the SfDataManager request:

@using Syncfusion.Blazor
@using Syncfusion.Blazor.Data
@using Syncfusion.Blazor.Grids

<SfGrid TValue="Order" AllowPaging="true">
        <GridPageSettings PageSize="10"></GridPageSettings>
        @* Replace xxxx with your actual port number *@
        <SfDataManager Headers=@HeaderData Url="https://localhost:xxxx/api/Grid" Adaptor="Adaptors.WebApiAdaptor"></SfDataManager>
        <GridColumns>
                <GridColumn Field=@nameof(Order.OrderID) HeaderText="Order ID" IsPrimaryKey="true" TextAlign="TextAlign.Right" Width="120"></GridColumn>
                <GridColumn Field=@nameof(Order.CustomerID) HeaderText="Customer Name" Width="150"></GridColumn>
                <GridColumn Field=@nameof(Order.OrderDate) HeaderText="Order Date" Format="d" Type="ColumnType.Date" TextAlign="TextAlign.Right" Width="130"></GridColumn>
                <GridColumn Field=@nameof(Order.Freight) HeaderText="Freight" Format="C2" TextAlign="TextAlign.Right" Width="120"></GridColumn>
        </GridColumns>
</SfGrid>

@code{
        private IDictionary<string, string> HeaderData = new Dictionary<string, string>();

        public class Order
        {
                public int? OrderID { get; set; }
                public string CustomerID { get; set; }
                public DateTime? OrderDate { get; set; }
                public double? Freight { get; set; }
        }
}

Setting Custom Headers

Dynamically change query parameter values

You can dynamically update the Syncfusion Blazor DataGrid’s Query property at runtime to control the data retrieved from a remote source. This is useful for scenarios where you want to filter, sort, or otherwise modify the data displayed in the Grid based on user actions, such as button clicks or other UI events.

The following example demonstrates how to modify the query parameter dynamically using button click. Initially, the Grid displays orders where CustomerID is “VINET”. When you click the Modify Query Data button, the Grid updates to show orders where CustomerID is “HANAR”.

@using Syncfusion.Blazor
@using Syncfusion.Blazor.Buttons
@using Syncfusion.Blazor.Data
@using Syncfusion.Blazor.Grids

<SfButton Content="Modify Query Data" OnClick="BtnClick"></SfButton>
<SfGrid TValue="Order" @ref="GridObj" AllowPaging="true" Query="@QueryData">
    <GridPageSettings PageSize="10"></GridPageSettings>
    <SfDataManager Url="https://services.odata.org/V4/Northwind/Northwind.svc/Orders" Adaptor="Adaptors.ODataV4Adaptor"></SfDataManager>
    <GridColumns>
        <GridColumn Field=@nameof(Order.OrderID) HeaderText="Order ID" IsPrimaryKey="true" TextAlign="TextAlign.Right" Width="120"></GridColumn>
        <GridColumn Field=@nameof(Order.CustomerID) HeaderText="Customer Name" Width="150"></GridColumn>
        <GridColumn Field=@nameof(Order.Freight) HeaderText="Freight" Format="C2" TextAlign="TextAlign.Right" Width="120"></GridColumn>
    </GridColumns>
</SfGrid>

@code {
    public SfGrid<Order> GridObj;
    private Query QueryData = new Query().Where("CustomerID", "equal", "VINET");
    private Query UpdatedQueryData = new Query().Where("CustomerID", "equal", "HANAR");

    public class Order
    {
        public int? OrderID { get; set; }
        public string CustomerID { get; set; }
        public double? Freight { get; set; }
    }

    public void BtnClick()
    {
        QueryData = UpdatedQueryData;
    }
}

The following GIF illustrates how the Grid updates its data when the query parameter is changed dynamically:

Changing Query Dynamically in the Grid

Offline mode

On remote data binding, all Syncfusion Blazor DataGrid 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 SfDataManager.

@using Syncfusion.Blazor.Grids
@using Syncfusion.Blazor.Data
@using Syncfusion.Blazor
 
<SfGrid TValue="OrdersDetails" Height="348">
    <SfDataManager Url="https://localhost:xxxx/api/Grid" Adaptor="Adaptors.WebApiAdaptor" Offline="true"></SfDataManager>
    <GridColumns>
        <GridColumn Field="OrderID" HeaderText="Order ID" Width="120" TextAlign="TextAlign.Right"></GridColumn>
        <GridColumn Field="CustomerID" HeaderText="Customer Name" Width="160"></GridColumn>
        <GridColumn Field="ShipCity" HeaderText="Ship City" Width="150"></GridColumn>
        <GridColumn Field="ShipCountry" HeaderText="Ship Country" Width="150"></GridColumn>
    </GridColumns>
</SfGrid>
using Microsoft.AspNetCore.Mvc;
using Syncfusion.Blazor.Data;
using Syncfusion.Blazor;
using WebApiAdaptor.Models;

namespace WebApiAdaptor.Controllers
{
    [ApiController]
    public class GridController : ControllerBase
    {
        /// <summary>
        /// Retrieves order data.
        /// </summary>
        /// <returns>Returns a JSON object with the list of orders and the total count.</returns>
        [HttpGet]
        [Route("api/[controller]")]
        public object GetOrderData()
        {
            // Retrieve all order records.
            List<OrdersDetails> data = OrdersDetails.GetAllRecords().ToList();

            // Return the data and total count.
            return new { Items = data, Count = data.Count() };
        }
    }
}

Replace https://localhost:xxxx/api/Grid with the actual URL of your API endpoint that provides the data in a consumable format (e.g., JSON).

You can find the complete code in the Github location.

Fetch result from the DataManager query using external button

By default, Syncfusion Blazor DataGrid binds to a remote data source using the SfDataManager. However, you may want to fetch data dynamically from the server in response to an external button click, giving you more control over when and how data is loaded into the Grid.

To achieve this, you can use an external button to trigger an HTTP request, fetch the data, and then assign it to the Grid’s DataSource property.

The following example demonstrates how to fetch data from the server when a button is clicked and display a status message indicating the fetch status:

@page "/"
@using Syncfusion.Blazor.Grids
@using Syncfusion.Blazor.Buttons
@using Syncfusion.Blazor
@using WebApiAdaptor.Models
@using System.Net.Http.Json
@inject HttpClient Http

<SfButton OnClick="ExecuteQuery" CssClass="e-primary">Execute Query</SfButton>

<p style="@StatusStyle">@StatusMessage</p>

<SfGrid TValue="OrdersDetails" DataSource="@Orders" AllowPaging="true">
    <GridColumns>
        <GridColumn Field="OrderID" HeaderText="Order ID" Width="120" TextAlign="TextAlign.Right" />
        <GridColumn Field="CustomerID" HeaderText="Customer ID" Width="160" />
        <GridColumn Field="EmployeeID" HeaderText="Employee ID" Width="120" TextAlign="TextAlign.Right" />
        <GridColumn Field="Freight" HeaderText="Freight" Width="150" Format="C2" TextAlign="TextAlign.Right" />
        <GridColumn Field="ShipCountry" HeaderText="Ship Country" Width="150" />
    </GridColumns>
</SfGrid>

@code {
    public string StatusMessage { get; set; } = "";
    public string StatusStyle { get; set; } = "color:black;";
    public List<OrdersDetails> Orders { get; set; } = new();

    private async Task ExecuteQuery()
    {
        try
        {
            StatusMessage = "Fetching data...";
            StatusStyle = "color:blue;";

            var response = await Http.GetFromJsonAsync<GridResponse<OrdersDetails>>("https://localhost:7167/api/Grid");

            if (response != null)
            {
                Orders = response.Items;
                StatusMessage = $"Data fetched successfully! Total Records: {response.Count}";
                StatusStyle = "color:green; text-align:center;";
            }
            else
            {
                StatusMessage = "No data returned from server.";
                StatusStyle = "color:orange;text-align:center;";
            }
        }
        catch (Exception ex)
        {
            StatusMessage = $"Error fetching data: {ex.Message}";
            StatusStyle = "color:red;text-align:center;";
        }
    }

    public class GridResponse<T>
    {
        public List<T> Items { get; set; }
        public int Count { get; set; }
    }
}

Fetch result using query

You can find the complete code in the Github location.