Introduction
I was looking for an “autocomplete” solution that would allow the user to type any value in for a username search, and not have the web application bring back so much data that it slows down the app. So, the solution I had initially worked with was Telerik autocomplete for ASP.NET Core. It was fairly straightforward to get client or server filtering working, but the big disadvantage with that is that every single item from the search results will be returned, potentially resulting in a huge amount of data sent at once, which is never good. You could also directly code the paging mechanism into your controller, which will only bring back a page at a time, but there is an easier way! There is a virtualization option, but according to the demo on Telerik’s website, there are many other functions besides the main controller action to return all the data from a particular search. The sample code shows many functions that are not written that you would potentially have to write:
@(Html.Kendo().AutoComplete()
.Name("orders")
.DataTextField("ShipName")
.Filter("contains")
.HtmlAttributes(new { style = "width:100%" })
.Placeholder("Type a ship name")
.Template("#= OrderID | For: #= ShipName #, #= ShipCountry #")
.Height(520)
.DataSource(source => {
source.Custom()
.ServerFiltering(true)
.ServerPaging(true)
.PageSize(80)
.Type("aspnetmvc-ajax")
.Transport(transport =>
{
transport.Read("Virtualization_Read", "AutoComplete");
})
.Schema(schema =>
{
schema.Data("Data").Total("Total");
});
})
.Virtual(v => v.ItemHeight(26).ValueMapper("valueMapper"))
)
<div class="demo-hint">Hint: type "an"<
</div>
<script>
function convertValues(value) {
var data = {};
value - $.isArray(value) ? value : [value];
for (var idx = 0; idx < value.length; idx++) {
data["values[" + idx + "]"] = value[idx];
}
return data;
}
</script>
The value mapper controller action is missing from the demo, and it is not obvious what you need to write. This also may not work on ASP.NET core, as there is no obvious way to send the Request Verification Token back to the controller, (if you use a POST
request.) But, according to the documentation for virtualization, the implementation of the valueMapper
function is now optional, and is only required when the autocomplete widget contains an initial value or if the value method is used. So, now we can simply create our HTML markup as follows:
@(Html.Kendo().AutoCompleteFor(m => m.UserName)
.DataTextField("UserName")
.Events(e =>
{
e.Select("onRegistrationIdSelect");
})
.Filter("contains")
.MinLength(3)
.HtmlAttributes(@getHtmlAttributes())
.DataSource(source =>
{
source.Custom()
.ServerFiltering(true)
.ServerPaging(true)
.PageSize(80)
.Type("aspnetmvc-ajax")
.Transport(transport =>
{
transport.Read(r => r.Action("GetUsers", "Admin").Data("onAdditionalData").Type(HttpVerbs.Get));
}).Schema(schema =>
{
schema.Data("Data) //define the [data](http://doc.telerik.com/kendo-ui/api/javascript/data/datasource#configuration-schema.data) option
.Total("Total"); //define the [total](http://docs.telerik.com/kendo-ui/api/javascript/data/datasource#configuration-schema.total) option
});
})
.Virtual(v => v.ItemHeight(26))
)
The controller code is basically the same as the ASP.NET Core demo code, so, no additional changes have to be made to accommodate virtualization, as that will be handled by Telerik Ajax code. It will essentially pass the correct parameters into your controller code, to only retrieve whatever page of data (or less) that it needs at any given point in time:
public DataSourceResult GetUsers([DataSourceRequest] DataSourceRequest request, string text)
{
var users = userService.GetUsers{text);
return users.ToDataSourceResult(request);
}
Now, you have complete markup and controller code, and can begin testing the behaviour and performance of the autocomplete functionality. It is interesting to compare it with only the Server Filtering option enabled, where when the autocomplete controller action is called, the entire dataset
is returned (unless, of course, as I mentioned previously, you want to implement custom paging on the server side). So, with a potentially large user database, this won’t be a practical solution.
This is the same markup, but with only server filtering enabled, no virtualization. So, as you can see on each call, the entire dataset
is returned:
Now, let's see the big difference with virtualization enabled for autocomplete:
The first few requests are the controller returning a particular page (or less than a page), per request. So, you can see a substantial reduction in the amount of data returned, which will increase the autocomplete responsiveness, and in turn the user experience.
So, as you can see, the new simplified virtualization feature on Telerik’s Autocomplete function is fairly simple to implement (if you have the patience to take their incomplete demo code, and also read most of the documentation). You definitely need to have a good understanding on how to actually implement the functionality, so you can fine-tune it if necessary. This is also an ideal solution for applications with very large dataset
s that need to be searched on demand, and yet provide a responsive user interface.
Source code on github can be found here.
CodeProject