Listen Up! Autocomplete can trip you up!

Here’s a little tip that we developers all should know. This post is a little about the Kendo UI Grid, a bit about ASP.NET MVC, but more about “common sense.” So let’s get started…

Kendo UI Grid

I’m using Kendo UI’s grid for a few different ASP.NET MVC projects. If you’ve read my other Kendo UI related posts, this probably isn’t a surprise. A lot of my pages/controllers have repetition, so I have a base controller that I use for the common functionality. In the generic base controller, I have the following methods for my Index action/page:

public virtual ActionResult Index()
{
    // There is no need to query for models as we use KendoUI in Ajax
    // mode to hit the List action after the view is loaded.
    return View();
}

public virtual ActionResult List([DataSourceRequest] DataSourceRequest request)
{
    var models = GetModels<T>(_context);
    var results = models.ToDataSourceResult(request);
    return Json(results);
}

NOTE: GetModels<T>(_context) simply returns an IQueryable of the model T

This works for most of the cases, but in few nested resources, I need to filter the results on the server before calling the ToDataSourceResult. Using Visual Studio’s (or R#’s; not sure what does what anymore after using R# for so many years) override auto-completion, it generates the following:

public override ActionResult List(DataSourceRequest request)
{
    return base.List(request);
}

Not thinking much of it, I went ahead and added my revised code in the body of the method. Everything seemed fine until I tried to sort the Kendo grid. Nothing would happen. At this point, seeing the two code snippets together, you probably figured the issue. I should have caught on to it sooner, but alas, I was blinded by “it must be a Kendo UI problem.”

Heigh-ho, heigh-ho, debugging we will go

The first thing I looked at was the URL being passed to the server. I could see the sort parameter was there. Everything on the client-side seemed correct, so I looked at the server code. The request parameter coming in would show the Page and PageSize properties set, but the Sorts collection was empty.

Figure 1: Kendo UI DataSourceRequest Without Custom Model Binder (Autocomplete Fail) Figure 1: Not Binding Correctly

So let’s look at this. The query string parameter being passed is named sort but on the DataSourceRequest, the property is named Sorts (and is obviously a collection). How can the DefaultModelBinder bind the property correctly. It can’t! ::smack:: Duh!

The perils of autocomplete

As I’m sure you figured out by now, I didn’t add the [DataSourceRequest] attribute in front of the request parameter:

Wrong

public override ActionResult List(DataSourceRequest request)
public override ActionResult List([DataSourceRequest]DataSourceRequest request)

By adding the attribute on the parameter, we’re letting ASP.NET MVC know that it needs to use a custom model binder (the attribute Kendo.Mvc.UI.DataSourceRequestAttribute inherits from the CustomModelBinderAttribute class).

Now that’s better:

Figure 2: Kendo UI DataSourceRequest With Custom Model Binder Figure 2: Correctly Binding

For whatever reason, when I used Visual Studio (or was it R#?) to override the method from the base class, it didn’t stub the method correctly. You would have figured that the method would be copied exactly, but alas, that’s not what happened.

Conclusion

This is a silly error, right? That said, aren’t silly errors at least 90% of all bugs we find as software developers? Convenience (e.g. autocomplete) doesn’t always yield correct results. In this case, copy/paste coding would have been a better option, though as you know, we developers aren’t immune to copy/paste bugs.

In short, the PSA for this post is Don’t assume that autocomplete or other code conveniences are perfect. It’s something that we often take for granted, so it’s a good point to keep in mind.