Ajax Binding

You can configure the Grid HtmlHelper extension for Ajax binding.

When configured for Ajax binding, the Grid for ASP.NET MVC makes Ajax requests when doing paging, sorting, filtering, grouping, or when saving data. For runnable examples, refer to the demo page on binding of the Grid.

The Ajax-bound mode has the following features:

  • The Grid retrieves only the data (in JSON format) representing the current page. As a result, only the Grid is updated.
  • All Grid templates (column, detail) are executed client-side. They follow the Kendo UI for jQuery template definition rules and may contain embedded JavaScript code.

Setting Up the Project

To configure the Grid for ASP.NET MVC to do Ajax binding to the Products table of the Northwind database:

  1. Create a new ASP.NET MVC 4 application. If you have installed the Telerik UI for ASP.NET MVC Visual Studio Extensions, create a Telerik UI for ASP.NET MVC application. Name the application KendoGridAjaxBinding. If you decided not to use the Telerik UI for ASP.NET MVC Visual Studio Extensions, follow the steps from the introductory article to add Telerik UI for ASP.NET MVC to the application.
  2. Add a new Entity Framework Data Model. Right-click the ~/Models folder in the solution explorer and pick Add new item. Choose Data > ADO.NET Entity Data Model in the Add New Item dialog. Name the model Northwind.edmx and click Next. This starts the Entity Data Model Wizard.

    A new entity data model

  3. Pick the Generate from database option and click Next. Configure a connection to the Northwind database. Click Next.

    Choosing the connection

  4. Choose the Products table from the Which database objects do you want to include in your model?. Leave all other options as they are set by default. Click Finish.

    Choosing the Products table

  5. Open the HomeController.cs and add a new action method which will return the Products as JSON. The Grid makes Ajax requests to this action.

    public ActionResult Products_Read()
    {
    }
    
  6. Add a new parameter of type Kendo.Mvc.UI.DataSourceRequest to the action. It will contain the current Grid request information—page, sort, group, and filter. Decorate that parameter with the Kendo.Mvc.UI.DataSourceRequestAttribute. This attribute will populate the DataSourceRequest object from the posted data. Now import the Kendo.Mvc.UI namespace.

    public ActionResult Products_Read([DataSourceRequest]DataSourceRequest request)
    {
    }
    
  7. Use the ToDataSourceResult extension method to convert the Products to a Kendo.Mvc.UI.DataSourceResult object. This extension method will page, filter, sort, or group your data using the information provided by the DataSourceRequest object. To use the ToDataSourceResult extension method, import the Kendo.Mvc.Extensions namespace.

    public ActionResult Products_Read([DataSourceRequest]DataSourceRequest request)
    {
        using (var northwind = new NorthwindEntities())
        {
            IQueryable<Product> products = northwind.Products;
            DataSourceResult result = products.ToDataSourceResult(request);
        }
    }
    
  8. Return the DataSourceResult as JSON. Configure the Grid for Ajax binding.

    public ActionResult Products_Read([DataSourceRequest]DataSourceRequest request)
    {
        using (var northwind = new NorthwindEntities())
        {
            IQueryable<Product> products = northwind.Products;
            DataSourceResult result = products.ToDataSourceResult(request);
            return Json(result);
        }
    }
    

    The same thing applies when you use the asynchronous ToDataSourceResultAsync counterpart.

    public async Task<ActionResult> Products_Read([DataSourceRequest]DataSourceRequest request)
    {
        using (var northwind = new NorthwindEntities())
        {
            IQueryable<Product> products = northwind.Products;
            DataSourceResult result = await products.ToDataSourceResultAsync(request);
            return Json(result);
        }
    }
    
  9. In the view, configure the Grid to use the action method created in the previous steps.

        <%: Html.Kendo().Grid<KendoGridAjaxBinding.Models.Product>()
            .Name("grid")
            .DataSource(dataSource => dataSource // Configure the Grid data source.
                .Ajax() // Specify that Ajax binding is used.
                .Read(read => read.Action("Products_Read", "Home")) // Set the action method which will return the data in JSON format
            )
            .Columns(columns =>
            {
                // Create a column bound to the ProductID property.
                columns.Bound(product => product.ProductID);
                // Create a column bound to the ProductName property.
                columns.Bound(product => product.ProductName);
                // Create a column bound to the UnitsInStock property.
                columns.Bound(product => product.UnitsInStock);
            })
            .Pageable() // Enable paging
            .Sortable() // Enable sorting
        %>
    
        @(Html.Kendo().Grid<KendoGridAjaxBinding.Models.Product>()
            .Name("grid")
            .DataSource(dataSource => dataSource // Configure the Grid data source.
                .Ajax() // Specify that Ajax binding is used.
                .Read(read => read.Action("Products_Read", "Home")) // Set the action method which will return the data in JSON format.
            )
            .Columns(columns =>
            {
                // Create a column bound to the ProductID property.
                columns.Bound(product => product.ProductID);
                // Create a column bound to the ProductName property.
                columns.Bound(product => product.ProductName);
                // Create a column bound to the UnitsInStock property.
                columns.Bound(product => product.UnitsInStock);
            })
            .Pageable() // Enable paging
            .Sortable() // Enable sorting
        )
    
  10. Build and run the application.

    The final result

To download the Visual Studio Project, refer to this GitHub repository.

The ToDataSourceResult method uses the DataSourceRequest parameter and LINQ expressions to page, sort, filter, and group your data. The JSON response of the action method will contain only a single page of data and the Grid will be bound to that data.

  • If your data is IQueryable<T> returned by a LINQ-enabled provider—Entity Framework, LINQ to SQL, Telerik OpenAccess, NHibernate or other—the LINQ expressions, created by the ToDataSourceResult method, are converted to SQL and executed by the database server.
  • The ToDataSourceResult() method will page, sort, filter, and group the collection that is passed to it. If this collection is already paged, the method returns an empty result.
  • As of the R1 2017 SP1 release, you can use the ToDataSourceResultAsync extension method to provide the asynchronous functionality of ToDataSourceResult by leveraging the async and await features of the .NET Framework.
  • If you impersonation is enabled, use the ToDataSourceResultAsync extension method with only one thread in your ASP.NET application. If you create a new thread, the impersonation in the newly created child thread decreases because, by default, all newly created child threads in ASP.NET run under the ASP.NET identity of the worker process. To change this behavior, explicitly impersonate the current identity within the code of the child thread.

The following example demonstrates how to implement the ToDataSourceResultAsync extension method in your project.

public async Task<ActionResult> Products_Read([DataSourceRequest]DataSourceRequest request)
{
    using (var northwind = new NorthwindEntities())
    {
        IQueryable<Product> products = northwind.Products;
        DataSourceResult result = await products.ToDataSourceResultAsync(request);
    }
}

Using the View Models

Sometimes it is convenient to use view model objects instead of entities returned by Entity Framework. For example, you may want to avoid serializing all Entity Framework properties as JSON or prevent serialization exceptions caused by circular references.

To use the view models and the Telerik UI Grid for ASP.NET MVC:

  1. Perform all steps from the previous Setting Up the Project section.
  2. Add a new class to the ~/Models folder. Name it ProductViewModel.

    public class ProductViewModel
    {
        public int ProductID { get; set; }
        public string ProductName { get; set; }
        public short? UnitsInStock { get; set; }
    }
    
  3. Modify the Grid declaration and make it use ProductViewModel instead of Product.

        <%: Html.Kendo().Grid<KendoGridAjaxBinding.Models.ProductViewModel>()
            .Name("grid")
            .DataSource(dataSource => dataSource
                .Ajax()
                .Read(read => read.Action("Products_Read", "Home"))
            )
            .Columns(columns =>
            {
                columns.Bound(product => product.ProductID);
                columns.Bound(product => product.ProductName);
                columns.Bound(product => product.UnitsInStock);
            })
            .Pageable()
            .Sortable()
        %>
    
        @(Html.Kendo().Grid<KendoGridAjaxBinding.Models.ProductViewModel>()
            .Name("grid")
            .DataSource(dataSource => dataSource
                .Ajax()
                .Read(read => read.Action("Products_Read", "Home"))
            )
            .Columns(columns =>
            {
                columns.Bound(product => product.ProductID);
                columns.Bound(product => product.ProductName);
                columns.Bound(product => product.UnitsInStock);
            })
            .Pageable()
            .Sortable()
        )
    
  4. Modify the Products_Read action method and use the ToDataSourceResult method overload which accepts a mapping lambda.

    public ActionResult Products_Read([DataSourceRequest]DataSourceRequest request)
    {
        using (var northwind = new NorthwindEntities())
        {
            IQueryable<Product> products = northwind.Products;
            // Convert the Product entities to ProductViewModel instances.
            DataSourceResult result = products.ToDataSourceResult(request, product => new ProductViewModel
                    {
                    ProductID = product.ProductID,
                    ProductName = product.ProductName,
                    UnitsInStock = product.UnitsInStock
                    });
            return Json(result);
        }
    }
    

To download the Visual Studio Project, refer to this GitHub repository.

Passing Additional Data to Action Methods

To pass additional parameters to the action, use the Data method. Provide the name of a JavaScript function which will return a JavaScript object with the additional data.

The custom parameter names must not match reserved words, which are used by the Kendo UI DataSource for jQuery for sorting, filtering, paging, and grouping.

The following example demonstrates how to add the additional parameters to the action method.

public ActionResult Products_Read([DataSourceRequest]DataSourceRequest request, string firstName, string lastName)
{
    // The implementation is omitted.
}

The following example demonstrates how to specify the JavaScript function which returns additional data.

    <%: Html.Kendo().Grid<KendoGridAjaxBinding.Models.Product>()
        .Name("grid")
        .DataSource(dataSource => dataSource
            .Ajax()
            .Read(read => read
                .Action("Products_Read", "Home") // Set the action method which will return the data in JSON format.
                .Data("productsReadData") // Specify the JavaScript function which will return the data.
            )
        )
        .Columns(columns =>
        {
            columns.Bound(product => product.ProductID);
            columns.Bound(product => product.ProductName);
            columns.Bound(product => product.UnitsInStock);
        })
        .Pageable()
        .Sortable()
    %>
    <script>
        function productsReadData() {
            return {
                firstName: "John",
                lastName: "Doe"
            };
        }
    </script>
    @(Html.Kendo().Grid<KendoGridAjaxBinding.Models.Product>()
        .Name("grid")
        .DataSource(dataSource => dataSource
            .Ajax()
            .Read(read => read
                .Action("Products_Read", "Home") // Set the action method which will return the data in JSON format.
                .Data("productsReadData") // Specify the JavaScript function which will return the data.
            )
        )
        .Columns(columns =>
        {
            columns.Bound(product => product.ProductID);
            columns.Bound(product => product.ProductName);
            columns.Bound(product => product.UnitsInStock);
        })
        .Pageable()
        .Sortable()
    )
    <script>
        function productsReadData() {
            return {
                firstName: "John",
                lastName: "Doe"
            };
        }
    </script>

Enabling Client Data Processing

By default, the Telerik UI Grid for ASP.NET MVC makes an Ajax request to the action method every time the user changes the page, sorts, filters, or groups. Change this behavior by disabling the ServerOperation.

    <%: Html.Kendo().Grid<KendoGridAjaxBinding.Models.Product>()
        .Name("grid")
        .DataSource(dataSource => dataSource
            .Ajax()
            .ServerOperation(false) //Paging, sorting, filtering, and grouping will be done client-side.
            .Read(read => read
                .Action("Products_Read", "Home") // Set the action method which will return the data in JSON format.
                .Data("productsReadData")
            )
        )
        .Columns(columns =>
        {
            columns.Bound(product => product.ProductID);
            columns.Bound(product => product.ProductName);
            columns.Bound(product => product.UnitsInStock);
        })
        .Pageable()
        .Sortable()
    %>
    @(Html.Kendo().Grid<KendoGridAjaxBinding.Models.Product>()
        .Name("grid")
        .DataSource(dataSource => dataSource
            .Ajax()
            .ServerOperation(false) // Paging, sorting, filtering, and grouping will be done client-side.
            .Read(read => read
                .Action("Products_Read", "Home") // Set the action method which will return the data in JSON format.
                .Data("productsReadData")
            )
        )
        .Columns(columns =>
        {
            columns.Bound(product => product.ProductID);
            columns.Bound(product => product.ProductName);
            columns.Bound(product => product.UnitsInStock);
        })
        .Pageable()
        .Sortable()
    )

Customizing Content and Attaching Event Handlers on the Fly

In addition to using server and client column templates, you may need to customize the appearance or content of the Grid data rows by using JavaScript—hide, show, or modify content, or attach custom event handlers.

When you use client-side data binding for the Grid, perform all these customizations in the dataBound event of the Grid. If the custom code is executed earlier—for example, in document.ready—it is very likely it has no effect, because the table rows are still not rendered at that time.

The following exception exists: delegated event handlers will work because they are attached to an ancestor element of the data rows—for example, the Grid table, tbody, or wrapper, and the event handler code has to check what the event target is.

Preventing Ajax Response Caching

To prevent Ajax response caching, refer to this section from the Frequently Asked Questions article

See Also

In this article
Not finding the help you need? Improve this article