Created
February 18, 2015 15:54
-
-
Save MatthewBarker/38cef4757fe77bcd2b1a to your computer and use it in GitHub Desktop.
Server side sorting, paging & filtering from DataTable to Kendo UI Grid
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System.Collections; | |
using System.Collections.Generic; | |
using System.Data; | |
using System.Linq; | |
using Newtonsoft.Json; | |
/// <summary> | |
/// Represents the data service. | |
/// </summary> | |
public class DataService | |
{ | |
/// <summary> | |
/// Gets the grid. | |
/// </summary> | |
/// <param name="take">The number of records to take</param> | |
/// <param name="skip">The number of records to skip</param> | |
/// <param name="sort">The sort to apply</param> | |
/// <param name="filter">The filter to apply</param> | |
/// <returns> | |
/// The grid. | |
/// </returns> | |
public Grid GetGrid( | |
int take, | |
int skip, | |
IEnumerable<Sort> sort, | |
Filter filter) | |
{ | |
var source = new DataTable(); // Get the data here | |
var sortExpression = sort == null ? string.Empty : string.Join(",", sort.Select(item => item.GetExpression())); | |
var filterExpression = filter == null ? string.Empty : filter.GetExpression(); | |
IEnumerable<DataRow> filtered = source.Select(filterExpression, sortExpression); | |
IEnumerable<DataRow> page = filtered.Skip(skip).Take(take); | |
DataTable destination = source.Clone(); | |
page.ToList().ForEach(row => destination.ImportRow(row)); | |
var grid = new Grid() | |
{ | |
Data = JsonConvert.SerializeObject(destination), | |
Total = filtered.Count() | |
}; | |
return grid; | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections.Generic; | |
using System.Linq; | |
using System.Runtime.Serialization; | |
/// <summary> | |
/// Represents a filter. | |
/// </summary> | |
[DataContract, Serializable] | |
public class Filter | |
{ | |
/// <summary> | |
/// The templates | |
/// </summary> | |
private static readonly IDictionary<string, string> Templates = new Dictionary<string, string> | |
{ | |
{ "eq", "{0} = '{1}'" }, | |
{ "neq", "{0} <> '{1}'" }, | |
{ "lt", "{0} < '{1}'" }, | |
{ "lte", "{0} <= '{1}'" }, | |
{ "gt", "{0} > '{1}'" }, | |
{ "gte", "{0} >= '{1}'" }, | |
{ "startswith", "{0} like '{1}*'" }, | |
{ "endswith", "{0} like '*{1}'" }, | |
{ "contains", "{0} like '*{1}*'" }, | |
{ "doesnotcontain", "{0} not like '*{1}*'" } | |
}; | |
/// <summary> | |
/// Gets or sets the field. | |
/// </summary> | |
/// <value> | |
/// The field. | |
/// </value> | |
[DataMember(Name = "field")] | |
public string Field { get; set; } | |
/// <summary> | |
/// Gets or sets the filters. | |
/// </summary> | |
/// <value> | |
/// The filters. | |
/// </value> | |
[DataMember(Name = "filters")] | |
public IEnumerable<Filter> Filters { get; set; } | |
/// <summary> | |
/// Gets or sets the logic. | |
/// </summary> | |
/// <value> | |
/// The logic. | |
/// </value> | |
[DataMember(Name = "logic")] | |
public string Logic { get; set; } | |
/// <summary> | |
/// Gets or sets the operator. | |
/// </summary> | |
/// <value> | |
/// The operator. | |
/// </value> | |
[DataMember(Name = "operator")] | |
public string Operator { get; set; } | |
/// <summary> | |
/// Gets or sets the value. | |
/// </summary> | |
/// <value> | |
/// The value. | |
/// </value> | |
[DataMember(Name = "value")] | |
public object Value { get; set; } | |
/// <summary> | |
/// Gets the expression. | |
/// </summary> | |
/// <returns> | |
/// The expression. | |
/// </returns> | |
public string GetExpression() | |
{ | |
return this.GetExpression(this.Filters, this.Logic); | |
} | |
/// <summary> | |
/// Called when deserialized. | |
/// </summary> | |
/// <param name="context">The context.</param> | |
[OnDeserialized] | |
public void OnDeserialized(StreamingContext context) | |
{ | |
if (this.Value != null) | |
{ | |
var value = this.Value.ToString(); | |
// DateTime values are sent in the format /Date(0000000000000)/ | |
if (value.Substring(0, 6) == "/Date(" && value.Length > 20) | |
{ | |
// The digits represent the milliseconds since the start of the Unix epoch | |
var milliseconds = long.Parse(value.Substring(6, 13)); | |
var unixEpoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc); | |
// This date format works with the data table select statement | |
this.Value = unixEpoch.AddMilliseconds(milliseconds).ToString("yyyy-MM-dd"); | |
} | |
} | |
} | |
/// <summary> | |
/// Gets the expression. | |
/// </summary> | |
/// <param name="filters">The filters.</param> | |
/// <param name="logic">The logic.</param> | |
/// <returns> | |
/// The expression. | |
/// </returns> | |
private string GetExpression(IEnumerable<Filter> filters, string logic) | |
{ | |
string result = string.Empty; | |
if (filters != null && filters.Any<Filter>() && !string.IsNullOrWhiteSpace(logic)) | |
{ | |
var list = new List<string>(); | |
foreach (Filter filter in filters) | |
{ | |
if (!string.IsNullOrWhiteSpace(filter.Field)) | |
{ | |
string template = Templates[filter.Operator]; | |
string value = filter.Value.ToString(); | |
list.Add(string.Format(template, filter.Field, value)); | |
} | |
if (filter.Filters != null) | |
{ | |
list.Add(this.GetExpression(filter.Filters, filter.Logic)); | |
} | |
} | |
result = "(" + string.Join(" " + logic + " ", list) + ")"; | |
} | |
return result; | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Runtime.Serialization; | |
/// <summary> | |
/// Represents the grid. | |
/// </summary> | |
[DataContract, Serializable] | |
public class Grid | |
{ | |
/// <summary> | |
/// Gets or sets the data. | |
/// </summary> | |
/// <value> | |
/// The data. | |
/// </value> | |
[DataMember(Name = "data")] | |
public string Data { get; set; } | |
/// <summary> | |
/// Gets or sets the total. | |
/// </summary> | |
/// <value> | |
/// The total. | |
/// </value> | |
[DataMember(Name = "total")] | |
public int Total { get; set; } | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Runtime.Serialization; | |
/// <summary> | |
/// Represents a sort. | |
/// </summary> | |
[DataContract, Serializable] | |
public class Sort | |
{ | |
/// <summary> | |
/// Gets or sets the direction. | |
/// </summary> | |
/// <value> | |
/// The direction. | |
/// </value> | |
[DataMember(Name = "dir")] | |
public string Direction { get; set; } | |
/// <summary> | |
/// Gets or sets the field. | |
/// </summary> | |
/// <value> | |
/// The field. | |
/// </value> | |
[DataMember(Name = "field")] | |
public string Field { get; set; } | |
/// <summary> | |
/// Gets the expression. | |
/// </summary> | |
/// <returns> | |
/// The expression. | |
/// </returns> | |
public string GetExpression() | |
{ | |
return this.Field + " " + this.Direction; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment