This is a migrated thread and some comments may be shown as answers.

DataSourceRequest server-side filtering and sorting question

7 Answers 2295 Views
Grid
This is a migrated thread and some comments may be shown as answers.
Nathan
Top achievements
Rank 1
Nathan asked on 03 Dec 2019, 10:38 PM

Hi I am trying to implement server-side filtering and sorting using the DataSourceRequest object as a parameter in a WebApi operation. 

I ran across the following article: 

https://www.telerik.com/kendo-angular-ui/components/dataquery/mvc-integration/

This seems to be using ASP.NET Core MVC controllers instead of WebApi, so my question is this the preferred method?

Our company is on .NET Core so it is not a problem but I would like to follow best practices so if anyone can provide an answer to the question above it would be greatly appreciated. 

7 Answers, 1 is accepted

Sort by
0
Nathan
Top achievements
Rank 1
answered on 03 Dec 2019, 10:56 PM

Actually I just noticed that the article above is a version of Kendo specifically for ASP.NET Core we are using Kendo for Angular 2x. 

Could anyone please point me to examples or information showing how to implement the DataSourceRequest in a WebApi and a grid example of how to pass filters and sorting to the WebApi? 

0
Svet
Telerik team
answered on 05 Dec 2019, 12:11 PM

Hi Nathan,

Thank you for checking our documentation.

I will begin with providing some general information on this case.

All Kendo UI for Angular components are simply representational once. Thus, the used server-side technology is of no relevance as long as the data is provided in a supported format. Indeed, we have no standard example demonstrating how server side data operations should be implemented as there are multiple different approaches and technologies that can be overtaken in order to meet the requirements of any project. 

Indeed, the purpose of server side data operations is to process the data remotely and to return just the resulting data to the client. In terms of the Grid, on each (dataStateChange) event, it is fired each time a paging, filtering, sorting, or grouping operation is initiated, a remote request containing the current state of the Grid should be sent to the server. There, using any custom logic the data should be processed and returned as a response to the Grid.

I understand that this may be disappointing, but I am afraid, that we have no project demonstrating the use of Kenko UI for Angular with WebApi at the moment.

We do have an example project that demonstrates how server side data and CRUD operations can be performed using the DataSourceRequest model binder and a ToDataSourceResult() method which process bulk data operations on the server (the model binder and method are a part of our UI for ASP.Net Core product). Please check the project at the following link:

https://github.com/telerik/kendo-angular/tree/master/examples-standalone/aspnetcore-data

As further steps, I can find the source code used to perform the actual server logic and provide it to you. Please let me know in case that will help. I will be looking forward to your reply. 

Unfortunately, at the moment we don't have other projects demonstrating the desired server side logic required to process the data.

Regards,
Svetlin
Progress Telerik

Get quickly onboarded and successful with your Telerik and Kendo UI products with the Virtual Classroom free technical training, available to all active customers. Learn More.
0
Nathan
Top achievements
Rank 1
answered on 09 Dec 2019, 06:28 PM

So I am attempting to try the example linked above and the DataSourceRequest to my WebApi call is null the operation is being hit and I am passing the following querystring just using the code in your example. 

This is what it is passing over:

"filter=city~contains~'erie'&page=1&sort=nextDate-asc&pageSize=10"

When it hits my web operation on the WebApi which has a signature of the following the request is null. 

[System.Web.Http.HttpGet]
        [System.Web.Http.Route("getScheduleGridData")]
        public IHttpActionResult GetScheduleGridData([DataSourceRequest]DataSourceRequest request)

Please let me know if there is anything I have wrong I have attempted to follow the example provided. 

0
Nathan
Top achievements
Rank 1
answered on 10 Dec 2019, 06:59 PM

By turning the http.get into an http.post fixed my issue. 

public getScheduleGridData(state: DataSourceRequestState): Observable<DataResult> {
    const data = `${toDataSourceRequestString(state)}`; // Serialize the state
    const hasGroups = state.group && state.group.length;
    const httpOptions = {
      headers: new HttpHeaders({
        'Content-Type': 'application/x-www-form-urlencoded'
      }),
      withCredentials: true
    };

    return this.http.post(`${environment['host']}/api/provider/schedule/getScheduleGridData`, data, httpOptions)
      .map(({ data, total /*, aggregateResults*/ }: GridDataResult) => // Process the response
        (<GridDataResult>{
          // If there are groups, convert them to a compatible format
          data: hasGroups ? translateDataSourceResultGroups(data) : data,
          total: total,
          // Convert the aggregates if such exist
          //aggregateResult: translateAggregateResults(aggregateResults)
        })
      );
  }

0
Nathan
Top achievements
Rank 1
answered on 10 Dec 2019, 07:43 PM

However there seems to still be an issue with the serialization and deserialization using the ${toDataSourceRequestString(state)} to the WebApi call that has a DataSourceRequest parameter. 

Although the object is not passing in as null the filters are not deseralizing into the DataSourceRequest properly. Is there any sample code that can be provided as reference as to what the Json string should look like? 

[filter]="filter"
[filterable]="menu"
(filterChange)="filterChange($event)"

public filterChange(filter: CompositeFilterDescriptor): void {
    this.filter = filter;
    this.state.filter = this.filter;
    console.log(this.filter);
    this.scheduleLookup.getScheduleGridData(this.state).subscribe(r => this.schedulesToDisplay = r);
  }

public getScheduleGridData(state: DataSourceRequestState): Observable<DataResult> {
    const data = `${toDataSourceRequestString(state)}`; // Serialize the state
    const hasGroups = state.group && state.group.length;
    const httpOptions = {
      headers: new HttpHeaders({
        'Content-Type': 'application/x-www-form-urlencoded'
      }),
      withCredentials: true
    };

    return this.http.post(`${environment['host']}/api/provider/schedule/getScheduleGridData`, data, httpOptions)
      .map(({ data, total /*, aggregateResults*/ }: GridDataResult) => // Process the response
        (<GridDataResult>{
          // If there are groups, convert them to a compatible format
          data: hasGroups ? translateDataSourceResultGroups(data) : data,
          total: total,
          // Convert the aggregates if such exist
          //aggregateResult: translateAggregateResults(aggregateResults)
        })
      );
  }

[System.Web.Http.HttpPost]
        [System.Web.Http.Route("getScheduleGridData")]
        public IHttpActionResult GetScheduleGridData([DataSourceRequest]DataSourceRequest request)
        {

0
Dimiter Topalov
Telerik team
answered on 11 Dec 2019, 12:04 PM

Hello Nathan,

I noticed that the Angular service performs a POST request to the server, while the DataSourceRequest model binder and the setup in our demo relies on the request for getting data being "GET" - this.http.get(...). On the server the controller action is also marked with an HttpGet attribute.

The simplest approach would be to use a GET request instead. While using POST is also possible, it needs further adjustments that seems to be applied on the client, but not on the server:

To use a POST request we will have to use the toDataSourceRequestString and pass the created string to the body parameter of the POST method. In order for the current state of the grid to be picked up by the model binder correctly, we will also have to add the following headers to the POST request:

...
[HttpPost]
public JsonResult PostProducts([DataSourceRequest]DataSourceRequest request)
{
 
    var result = Json(this.products.ToDataSourceResult(request));
    return result;
}
...
I am also attaching a sample application where this code be inspected further.

Depending on the WebAPI version and controller type used, you might also need to use a WebAPI-specific DataSourceRequest model binder on the server, explicitly designed for WebAPI, e.g.:

// GET api/Orders
        public DataSourceResult GetOrders([System.Web.Http.ModelBinding.ModelBinder(typeof(WebApiDataSourceRequestModelBinder))]DataSourceRequest request)
        {
            return db.Orders.ToDataSourceResult(request);
        }
I hope this helps.

Regards,
Dimiter Topalov
Progress Telerik

Get quickly onboarded and successful with your Telerik and Kendo UI products with the Virtual Classroom free technical training, available to all active customers. Learn More.
0
samer
Top achievements
Rank 1
answered on 28 Apr 2020, 09:55 PM

Hello Dimiter,

 

This is just to say THANK YOU! you saved my day Dimiter!

your example works great!

 

Sam

Tags
Grid
Asked by
Nathan
Top achievements
Rank 1
Answers by
Nathan
Top achievements
Rank 1
Svet
Telerik team
Dimiter Topalov
Telerik team
samer
Top achievements
Rank 1
Share this question
or