Integration with UI for ASP.NET Core

The UI for ASP.NET Core and UI for ASP.NET MVC suites provide a DataSourceRequest model binder and a ToDataSourceResult() method which process bulk data operations.

This article demonstrates how to use these features in React applications by applying the Data Query helper functions. For the full project source, refer to this GitHub repository.

Sample Integration Project

To implement the sample project:

Prerequisites

Setup

  1. Create an ASP.NET Core web application that is integrated with React.

  2. Install Telerik UI for ASP.NET Core. For more information, refer to the article on getting started.

    You can skip the UI-related steps because the sample project uses only DataSourceRequest and ToDataSourceResult() from the Kendo.Mvc.UI and Kendo.Mvc.Extensions namespaces.

  3. Create an endpoint, which will process the requests, by using the DataSourceRequest attribute and a model binder. Perform all data operations by using the ToDataSourceResult() method and return the result as JSON.

    using Microsoft.AspNetCore.Mvc;
    using reactSpa.Models;
    using Kendo.Mvc.UI;
    using Kendo.Mvc.Extensions;
    
    namespace reactSpa.Controllers
    {
       [Produces("application/json")]
       [Route("api/Products")]
       public class ProductsController : Controller
       {
           // GET: api/Products
           [HttpGet]
           public JsonResult GetProducts([DataSourceRequest]DataSourceRequest request)
           {
               // ToDataSourceResult works with IQueryable and thus Entity Framework could be used as a source
               // instead of an in-memory list.
               return Json(Products.Items.ToDataSourceResult(request));
           }
       }
    }
  4. Install the Grid package.

  5. Create a HOC which will process the requests and parse the response by using the toDataSourceRequestString and translateDataSourceResultGroups Data Query methods.

    import React from 'react';
    import { toDataSourceRequestString, translateDataSourceResultGroups } from '@progress/kendo-data-query';
    
    export function withState(WrappedGrid) {
       return class StatefullGrid extends React.Component {
           constructor(props) {
               super(props);
               this.state = { dataState: { skip: 0, take: 20 } };
           }
    
           render() {
               return (
                   <WrappedGrid
                       filterable={true}
                       sortable={true}
                       pageable={{ pageSizes: true }}
                       {...this.props}
                       total={this.state.total}
                       data={this.state.data}
                       skip={this.state.dataState.skip}
                       pageSize={this.state.dataState.take}
                       filter={this.state.dataState.filter}
                       sort={this.state.dataState.sort}
                       dataStateChange={this.dataStateChange}
                   />
               );
           }
    
           componentDidMount() {
               this.fetchData(this.state.dataState);
           }
    
           dataStateChange = (changeEvent) => {
               this.setState({ dataState: changeEvent.data });
               this.fetchData(changeEvent.data);
           }
    
           fetchData(dataState) {
               const queryStr = `${toDataSourceRequestString(dataState)}`; // Serialize the state
               const hasGroups = dataState.group && dataState.group.length;
    
               const base_url = 'api/Products';
               const init = { method: 'GET', accept: 'application/json', headers: {} };
    
               fetch(`${base_url}?${queryStr}`, init)
                   .then(response => response.json())
                   .then(({ data, total }) => {
                       this.setState({
                           data: hasGroups ? translateDataSourceResultGroups(data) : data,
                           total,
                           dataState
                       });
                   });
           }
       }
    }
  6. Wire the HOC and the Grid component.

    import * as React from 'react';
    import { RouteComponentProps } from 'react-router-dom';
    import { GridColumn, Grid } from '@progress/kendo-react-grid';
    import { withState } from './WithState.js';
    
    const StatefullGrid = withState(Grid);
    
    class GridExample extends React.Component {
    constructor(props) {
       super(props);
    }
    
    render() {
       return (
           <div>
               <StatefullGrid>
                   <GridColumn field="productId" title="Product Id" filter="numeric" />
                   <GridColumn field="productName" title="Product Name" />
                   <GridColumn field="unitsInStock" title="Units In Stock" filter="numeric" />
               </StatefullGrid>
           </div>
       );
     }
    }
    
    export default GridExample;

In this article