Telerik blogs

In the past few months we've seen a few questions about using Kendo UI with Microsoft's ASP.NET WebAPI which is now a built-in part of MVC 4. The gorilla in the room is "Does Kendo UI Work With WebAPI?".

The answer is of course a resounding "YES!".

Kendo UI itself is engineered towards open web standards and does not cater to a specific technology stack. It is agnostic of what your server is doing and in the end, really just wants you to provide it with a healthy diet of JSON data. How you choose to deliver that data is up to you.

You have a cornucopia of options when it comes to using ASP.NET to return JSON data in a RESTful fashion. It’s all one ASP.NET as Scott Hanselman is fond of saying, but that doesn’t change the fact that all the choices, acronyms and technologies can get really confusing. Essentially, you can get your data as JSON using any of the following:

  • ASP.NET WebForms (Page Methods)
  • ASP.NET MVC
  • ASP.NET WebAPI
  • ASP.NET WCF

All of those are capable of returning JSON data via a URL, which is precisely what you want when building HTML5 applications. The most commonly used of these for creating RESTful services is probably ASP.NET MVC. Just when we were all becoming comfortable with MVC, WebAPI showed up. WebAPI allows you to more easily adhere to a RESTful schema with your URL’s and is very closely related to ASP.NET MVC.

Let’s take a closer look at both ASP.NET MVC, and WebAPI to identify some of the differences between the two. You have several options comes to using it with each of these with Kendo UI.

ASP.NET MVC And Kendo UI

When you are working with ASP.NET MVC, you have two choices. One is to use straight Kendo UI JavaScript, and the other is of course to use the MVC Server Wrappers.

Using Kendo UI JavaScript With MVC

If you decide to use the Kendo UI JavaScript libraries directly, returning JSON is simple. You just need to defined a controller method and call this.Json on your return result. Provided .NET can serialize your response, this is all there is to it. Usually, you have a view model that you return in a collection since .NET cannot serialize LinqToSQL or EF objects.

Returning JSON From an MVC Controller

[HttpGet]
public JsonResult Get()
{
    var albums = _entities.Albums.Select(a => new Models.Album {
        AlbumId = a.AlbumId,
        ArtistId = a.ArtistId,
        GenreId = a.GenreId,
        Title = a.Title,
        Price = a.Price,
        AlbumArtUrl = a.AlbumArtUrl
    });

    return this.Json(albums, JsonRequestBehavior.AllowGet);
}

 

Now you could create a simple grid with a small bit of JavaScript.

Simple Kendo UI Grid

<div id="grid"></div>

$(function() {
    $("#grid").kendoGrid({
        transport: {
            read: "Albums/Get"
        }
    });
});

 

That's all well and good, but of course this starts to get a bit more complicated when we talk about sending parameters over to the controller method to do things like paging, sorting, aggregating and the like. You can parse the parameters out of the Request object, or you can create your own custom DataSourceRequest class and let MVC ParameterBinding take over. Assume you decide to turn on paging for the server to handle.

Turn On Paging In The Grid

<div id="grid"></div>

$(function() {
    $("#grid").kendoGrid({
        dataSource: {
            transport: {
                read: "Albums/Get"
            },
            pageSize: 10
            serverPaging: true
        },
        pageable: true
    });
});

 

When the grid loads, the DataSource will automatically make a request to the server (unless you have autoBind: false) and send along some parameters for paging. Let’s have a look into what a request with paging looks like.

http_request

In that capture, I have outlined the request URL and you can see that the query string has some parameters in it that I’ve highlighted as well. These are the parameters that we need to apply to the query on the server before returning the data.

Let's parse out these parameters. We're doing a GET so we can pluck them right off the query string without any trouble. Then we can apply them to the LINQ query after adding an OrderBy as EF requires this before doing a Skip.

Get Parameters Out Of The Request

[HttpGet]
public JsonResult Get()
{
    var take = string.IsNullOrEmpty(Request.QueryString["take"]) ? 1000 : Convert.ToInt32(Request.QueryString["take"]);
    var skip = string.IsNullOrEmpty(Request.QueryString["skip"]) ? 1000 : Convert.ToInt32(Request.QueryString["skip"]);

    var albums = _entities.Albums.Select(a => new Models.Album {
        AlbumId = a.AlbumId,
        ArtistId = a.ArtistId,
        GenreId = a.GenreId,
        Title = a.Title,
        Price = a.Price,
        AlbumArtUrl = a.AlbumArtUrl
    }).OrderBy(a => a.AlbumId).Skip(skip).Take(take);

    return this.Json(albums, JsonRequestBehavior.AllowGet);
}

 

That's already a bit messy. We have to check for the existence of the parameters on the Request, handle them if they are null, cast to the appropriate type and set default values.

The other option is to create a custom class which MVC will use to map the parameters that the grid just tossed over the fence.

Custom DataSourceRequest Class

public class DataSourceRequest
{
    public int Take { get; set; }
    public int Skip { get; set; }

    public DataSourceRequest()
    {
        // default values
        Take = 1000;
    }
}

 

This is much nicer as now we can just map the request coming in. All the type conversion and nulls will be handled by ASP.NET. You can see that I set a default value for the Take in the constructor. Now we just need to specify that our request coming in will be of type DataSourceRequest (this class that we just created).

Use DataSourceRequest With Get

[HttpGet]
public JsonResult Get(Models.DataSourceRequest request)
{
   var albums = _entities.Albums.Select(a => new Models.Album {
        AlbumId = a.AlbumId,
        ArtistId = a.ArtistId,
        GenreId = a.GenreId,
        Title = a.Title,
        Price = a.Price,
        AlbumArtUrl = a.AlbumArtUrl
    }).OrderBy(a => a.AlbumId).Skip(request.Skip).Take(request.Take);

    return this.Json(albums, JsonRequestBehavior.AllowGet);
}

 

This is cleaner. But the problem still isn't completely solved. You also need a class which will return a result that includes the total count of records for the grid. You can create this class as well, but you are watching your plumbing code grow on the server. Additionally, doing sorting and filtering in LINQ queries gets TOUGH (to put it mildly) when you are dealing with dynamic values. LINQ is no good at this. While there is the Dynamic LINQ library, you are going to have to extend it further to get everything to work.

Lucky for you, our own head of engineering has already put this together for you in a complete downloadable package with samples. This contains everything that you need for mapping in requests and applying them to your queries. I highly suggest you download this project and have a look at the QueryableExtension.cs class, as well as the Sort.cs and Filter.cs classes. This is an excellent resource where you will find everything you need to implement the appropriate structure for communicating seamlessly with Kendo UI.

However, the cleanest option when using MVC is of course the ASP.NET MVC Server Wrappers.

The Server Wrappers. Way More Than Just HTML Helpers.

The ASP.NET MVC Server Wrappers are engineered with the sole mission of tailoring Kendo UI to ASP.NET MVC and providing you with all the necessary server parsing and querying wrapped up in a nice DLL. The first time that I saw Carl Bergenhem demo the MVC Wrappers I was completely blown away that anything could be that easy. Let's take the example from above. First we use the Html Helpers to construct the grid. I can go ahead and make it pageable, sortable and filterable.

Use Kendo UI Html Helpers To Create The Grid

@(Html.Kendo().Grid<kendouimvcapplication1.models.albummodel>()
    .Name("grid")
    .DataSource(dataSource => dataSource
        .Ajax()
        .Read(read => read.Action("Get", "Albums"))
    )
    .Pageable()
    .Sortable()
    .Filterable()
)
</kendouimvcapplication1.models.albummodel>

 

Now what do we have to implement in the controller to handle all the filtering, sorting and paging? Here is the complete code.

Handle Request From Kendo UI

public ActionResult Get([DataSourceRequest]DataSourceRequest request)
{
    var albums = _context.Albums.Select(a => new Models.AlbumModel
    {
        AlbumId = a.AlbumId,
        ArtistId = a.ArtistId,
        GenreId = a.GenreId,
        Title = a.Title,
        Price = a.Price,
        AlbumArtUrl = a.AlbumArtUrl
    });

    return this.Json(albums.ToDataSourceResult(request));
}

 

That's IT. No parsing parameters. No dynamic linq queries. No pain.

The DataSourceRequest object maps the parameters for you and then the uber convenient ToDataSourceResult applies these parameters to your query. There is an underlying LINQ engine that Kendo UI uses to do this and it abstracts away all of the manual burden in communicating constraints to your database from Kendo UI. There is no faster way to get up and running with Kendo UI on ASP.NET MVC then with the server wrappers.

What About WebAPI?

WebAPI hit production status this year and showed up in MVC 4. It's an elegant way to expose your data very RESTfully while letting MVC handle the actual returning of your views. It seems like the Kendo UI extensions should "just work"® in a WebAPI controller, but due to some core differences in between ASP.NET MVC and WebAPI, they require a bit of tweaking.

MVC vs WebAPI Parameter Binding

WebAPI controllers are different than MVC controllers in many ways, not the least of which is the way that they do Parameter Binding. If you want to know the nuts and bolts of it, read this article. For the purposes of this post, just know that WebAPI does NOT do model binding against the request body by default whereas MVC does. This is what Kendo UI is expecting to happen on the server. This means that the DataSourceRequest is not going to be fully operational out of the box with WebAPI. For instance, should you turn on paging and sorting, the Take and Skip parameters will be populated in the DataSourceRequest, but the Sorts collection will not.

To work around this, we have provided a custom ModelBinder for the DataSourceRequest. All you need to do is add it to your application and you will get support for WebAPI the same way that you would in an MVC Controller. You can find this ModelBinder in a full project showing how to use it with WebAPI in the Kendo UI Code Library.

Now you might wonder why this isn't included in the default Kendo UI For MVC Distribution. This was something that was discussed internally and it was determined that at least for now, the best choice is for us to offer this class separately as including it automatically would cause a fracture in the DLL's required for MVC 3 vs MVC 4, further complicating the install and use of the extensions.

OData And WebAPI: The Plot Thickens

Adding more complexity to this discussion is OData and how it factors into the WebAPI topic. ASP.NET MVC does not support OData out of the box and and Kendo UI MVC Wrappers negate it's necessity since they have the DataSourceRequest and ToDataSourceResult, which provide the same functionality. When discussing OData, we do it in the context of WebAPI.

First off, lets define exactly what OData is. OData is the "Open Data Protocol". A standard proposed by Microsoft that specifies how parameters should be formatted to work across API's. In other words, if everyone implemented OData support, you wouldn't have to trapse through API documentation to figure out how to do pagination. You would just send the $take and $skip parameters in the query string.

This is really a very good idea. While you may only be concerned about your own API or application, it would be really nice if we were all implementing these things the same way. Kendo UI fully supports OData.

WebAPI on the other hand, does not. It's getting better and is currently implemented via this NuGet Package. The point of OData support in WebAPI is that you shouldn't have to manually parse the parameters off the HTTP request body or query string. WebAPI should apply them to your query automatically. This means that you could use the Kendo UI JavaScript and send some OData over for paging where WebAPI should handle everything for you.

Simple Grid

$("#myGrid").kendoGrid({
    dataSource: {
        transport: {
            read: "api/albums",
            type: "odata"
        }
    }
})

 

Adding the "Queryable" declaration to your method should magically apply the parameters to your query.

Queryable Method Applies Parameters

[Queryable]
public IQueryable Get()
{
    db.Configuration.ProxyCreationEnabled = false;

    var albums = _context.Albums.Select(a => new Models.AlbumModel
    {
        AlbumId = a.AlbumId,
        ArtistId = a.ArtistId,
        GenreId = a.GenreId,
        Title = a.Title,
        Price = a.Price,
        AlbumArtUrl = a.AlbumArtUrl
    });

    return albums;
}

 

The partial support in WebAPI for OData makes this quite a bit more complicated. Jeff Valore wrote an excellent article on how to make Kendo UI work with the partial OData support that I highly suggest reading. For the sake of centralizing all the information on this subject, I'll go over it again here.

$inlinecount And $format - Wherefore Art Thou?

The crux of this issue is that the $inlinecount and $format parameters are not supported yet in WebAPI. Instead of ignoring these parameters, WebAPI will error on them. To further complicate things, WebAPI does not support JSONP in the context of OData which is what Kendo UI sends by default as per the OData 2.0 standard. Jeff shows how to make your request plain JSON and remove the unsupported parameters using parameterMap method on the DataSource, but then add their values back dynamically so that everything keeps on working smoothly like butter.

Remove $inlinecout and $format

// select my grid and turn it into a kendo ui grid
$("#myGrid").kendoGrid({
    dataSource: {
        serverFiltering: true, // <-- Do filtering server-side
        serverPaging: true, // <-- Do paging server-side
        type: 'odata', // <-- Include OData style params on query string.
        transport: {
            read: {
                url: "/api/albums", // <-- Get data from here
                dataType: "json" // <-- The default was "jsonp"
            },
            parameterMap: function (options, type) {
                var paramMap = kendo.data.transports.odata.parameterMap(options);

                delete paramMap.$inlinecount; // <-- remove inlinecount parameter.
                delete paramMap.$format; // <-- remove format parameter.

                return paramMap;
            }
        },
        schema: {
            data: function (data) {
                return data; // <-- The result is just the data, it doesn't need to be unpacked.
            },
            total: function (data) {
                return data.length; // <-- The total items count is the data length, there is no .Count to unpack.
            }
        }
    });

});

 

Now you may think to yourself at this point "That's a lot of manual intervention for something that should just work.". We completely agree! Are there other options? Yes.

There are ways for you to add missing OData support to WebAPI should you be so inclined.

The other option that you have that might better suit your situation is to use the new WCF Data Services which do fully support OData.

WCF Data Services 5.1

Jeff posted a really good walkthrough on this one over on his own blog.

What Jeff points out is that you can use WCF services in your MVC/WebAPI project. Why not? It's all the same ASP.NET in the end right? In fact, the new Awesome Sauce Music Store Example uses a combination of ASP.NET MVC AND WCF. The WCF Data Services have remarkably better support for OData and Jeff's article will show you in detail how to implement it with Kendo UI.

Plain JSON And Kendo UI

Of course, should you choose to, you can always just use plain JSON with MVC/WebAPI and Kendo UI. WebAPI is really good when it comes to sending and receiving plain JSON and so is Kendo UI!

In the case of passing parameters from Kendo UI To WebAPI using plain JSON, you are in pretty much the exact same boat as you are with MVC Controllers. You can pop them off manually, or you can create a custom class which maps for you. You are still faced with manually applying them to your query either with giant switch statements or hopefully with a more flexible solution like the Dynamic LINQ Library.

If you like to roll this way, then we have you covered with tutorials and screencasts on exposing your data as JSON, consuming it with the grid, and then implementing sorting on the server.

Have It Your Way

What all these choices really give you is a TON of flexibility and the chance to do it the way that you want to. This is nice, but sometimes it's nicer to know exactly what you should do instead of having to try and make a decision based on a number of factors. Let's sum it up like this:

Your Choices When Using Kendo UI With ASP.NET

 

Use Kendo UI With ASP.NET MVC / WebAPI And Plain JSON

Pros

  • MVC, WebAPI and Kendo UI all understand and serialize JSON just fine
  • No additional dependencies are required

Cons

  • Parameters must be manually parsed and casted to the appropriate type in the controller method
  • Dynamic parameters in LINQ queries can be a pain to implement

 

Use Kendo UI MVC Wrappers With ASP.NET MVC Or WebAPI

Pros

  • Helpers construct UI elements giving you strong typing and Intellisense
  • Parameters are mapped automatically and applied to your query all by Kendo UI

Cons

  • You lose granular control over your controller methods and LINQ queries
  • When using WebAPI, a nominal amount of work is required from you to implement additional code

 

 

Use Kendo UI With ASP.NET WebAPI And OData

Pros

  • WebAPI allows you to create clean and beautiful RESTful URL's
  • You can separate API logic and view logic between MVC controllers and WebAPI controllers
  • OData replaces the need for the MVC Server Wrappers in the sense that it maps and applies parameters for you

Cons

  • The OData support in WebAPI is subpar right now and requires this NuGet package coupled with some creative hacks to make it work
  • The lack of support in OData requires more configuration on your part

 

Use Kendo UI With ASP.NET WCF And OData

Pros

  • WCF has really great support for OData
  • Jeff has a post that explains how to make it work
  • You don't have to do any hacking or coersing to make it function

Cons

  • WCF is not as "hip" as WebAPI or ASP.NET MVC (note: this is might be the worst reason not to choose something)
  • WCF can be more verbose than WebAPI
  • Some configuration is required

 

It’s All JSON In The End

It’s easy to forget in all of this that at the end of the day, all you are really doing is sending parameters to the server, and then sending some JSON data back based on the constraints given to you by Kendo UI and applied to your data.

Also remember that we have the following samples and tutorials to help you out:

Getting Started With The MVC Wrappers

Sample Project For Using Kendo UI ASP.NET MVC Wrappers With WebAPI

Using Kendo UI With WebAPI (Plain JSON)

Using Kendo UI With WebAPI (OData)

Sample Project For Using Kendo UI With MVC, WCF, ASMX and Page Methods Using Kendo UI With WCF (OData)

Clearly what you choose will depend on your particular situation and needs. I realize this article really expanded beyond the scope of just "Kendo UI With WebAPI", but it's really important to at least know what all the options are. There is no one "right" way to do things, and you are free to mix and match these as you see fit. Use MVC with WebAPI, WCF with MVC, or MVC With WebForms. It's all one big happy ASP.NET!


Burke Holland is the Director of Developer Relations at Telerik
About the Author

Burke Holland

Burke Holland is a web developer living in Nashville, TN and was the Director of Developer Relations at Progress. He enjoys working with and meeting developers who are building mobile apps with jQuery / HTML5 and loves to hack on social API's. Burke worked for Progress as a Developer Advocate focusing on Kendo UI.

Related Posts

Comments

Comments are disabled in preview mode.