Search code examples
c#asp.net-mvctelerik

How to delete all records from a Kendo paged and filtered grid (in the controller)


I'd like to add a button to delete all records referenced in a Kendo paged and filtered grid (all paged records) abiding by any grid filters.

Obviously Telerik MVC extensions abstracts the work it does with iqueryable at the controller by the use of the extension ToDataSourceResult and the [DataSourceRequest] DataSourceRequest request parameter

So the questions are:

  • Is it possible to somehow create a custom controller action and associated front end code to pass the current filtering regime
  • Is it then possible in the action to delete all records associated with that filtering

Ie. I might have a paged grid with 1000 records (10 per page), filtered by productId, it would be nice to be able to create a custom toolbar button called "delete all", to delete all the matched filtered records.

Please note, the toolbar button I can do, however I'm not sure if Telerik lets you have access to iqueriable and DataSourceRequest mechanism in a way that might make this feasible.

Pointing me in the right direction would be sufficient.

Update

Since I'm actually dealing with millions of records, a server side solution would be preferable.


Solution

  • Ok I don't know if there is better solution but I found this one. I don't pretend that it is perfect.

    You can use the idea with custom button and attach click event to it. In the click event handler you must extract what you need (filters, sortings etc.) from the data source. All the DataSourceRequest class properties can be extracted from JavaScript dataSourceo object:

    dataSource.sort() dataSource.filter(), dataSource.group(),
    dataSource.aggregate(), dataSource.page(), dataSource.pageSize()
    

    You must extract them with kendo specific method, format them as form-data (json didn't work in my case, I don't know why :( ), send them to the controller via ajax, in the controller write your server side logic based on DataSourceRequest request.

    Script:

    function deleteAllEventHandler(){
       var dataSource = $('#Grid').data('kendoGrid').dataSource;
    
       var dataSourceRequest = dataSource.transport.parameterMap({
            sort: dataSource.sort(),
            filter: dataSource.filter(),
            group: dataSource.group(),
            aggregate: dataSource.aggregate(),
            page: dataSource.page(),
            pageSize: dataSource.pageSize()
       });
    
       var data = "";
    
       for (var key in dataSourceRequest) {
           if (dataSourceRequest[key] !== undefined) {
               data += key + "=" + dataSourceRequest[key] + "&";
           }
       }
    
       $.ajax({
            type: "POST",
            contentType: "application/x-www-form-urlencoded; charset=UTF",
            url: "@Html.Action("DeleteAllAction", "MyController")",
            data: data,
            success: function(){
                dataSource.read();
            }
       });
    }
    

    Controller:

    public ActionResult DeleteAll([DataSourceRequest] DataSourceRequest request)
    {
        // Here you must parse the request to expression tree with custom logic
        // or use the folliwng logic:
    
        // It's very important to return IQueryable here so you can apply kendo
        // filters without fetching all data from the dataprovider (sql server)
        var items = YourDataProvider.GetQueryableItems();
    
        // Applying the kendo filters on your queryable.
        // I don't know if there is a better way but I use this one. 
        var result = items.ToDataSourceResult(); 
    
        // Delete items
        YourDataProivder.DeleteItems(result.Data);
    
        // return Success 
        return new HttpStatusCodeResult(200);
    }
    

    I still think that client side extracting Ids and sending only them to the server for deletion is a better solution but feel free to use this approach if it fit better in your case or has better performance or etc.. Good luck.