|
using System; |
|
using System.Linq; |
|
using System.Web.Mvc; |
|
using Kendo.Mvc; |
|
using Kendo.Mvc.UI; |
|
|
|
namespace MyProject.ModelBinders |
|
{ |
|
/// <summary> |
|
/// DateTime filtering is horribly unintuitive in Kendo Grids when a non-default (00:00:00) time is attached |
|
/// to the grid's datetime data. We use this custom model binder to transform the grid filters to return |
|
/// results that ignore the attached time, leading to intuitive results that make users happy. |
|
/// |
|
/// To use the code, substitute the [DataSourceRequest] attribute for [CustomDataSourceRequest] in your MVC controller |
|
/// |
|
/// If you will be comparing UTC datetimes, you will need to add ".ToUniversalTime()" to the end of all DateTime constructors |
|
/// inside the switch statement below. |
|
/// </summary> |
|
public class CustomDataSourceRequestModelBinder : IModelBinder |
|
{ |
|
public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext) |
|
{ |
|
// Get an instance of the original kendo model binder and call the binding method |
|
var baseBinder = new DataSourceRequestModelBinder(); |
|
var request = (DataSourceRequest)baseBinder.BindModel(controllerContext, bindingContext); |
|
|
|
if (request.Filters != null && request.Filters.Count > 0) |
|
{ |
|
var transformedFilters = request.Filters.Select(TransformFilterDescriptors).ToList(); |
|
request.Filters = transformedFilters; |
|
} |
|
|
|
return request; |
|
} |
|
|
|
private IFilterDescriptor TransformFilterDescriptors(IFilterDescriptor filter) |
|
{ |
|
if (filter is CompositeFilterDescriptor) |
|
{ |
|
var compositeFilterDescriptor = filter as CompositeFilterDescriptor; |
|
var transformedCompositeFilterDescriptor = new CompositeFilterDescriptor { LogicalOperator = compositeFilterDescriptor.LogicalOperator }; |
|
foreach (var filterDescriptor in compositeFilterDescriptor.FilterDescriptors) |
|
{ |
|
transformedCompositeFilterDescriptor.FilterDescriptors.Add(TransformFilterDescriptors(filterDescriptor)); |
|
} |
|
return transformedCompositeFilterDescriptor; |
|
} |
|
if (filter is FilterDescriptor) |
|
{ |
|
var filterDescriptor = filter as FilterDescriptor; |
|
if (filterDescriptor.Value is DateTime) |
|
{ |
|
var value = (DateTime)filterDescriptor.Value; |
|
switch (filterDescriptor.Operator) |
|
{ |
|
case FilterOperator.IsEqualTo: |
|
//convert the "is equal to <date><time>" filter to a "is greater than or equal to <date> 00:00:00" AND "is less than <date + 1day> 00:00:00" |
|
var isEqualCompositeFilterDescriptor = new CompositeFilterDescriptor { LogicalOperator = FilterCompositionLogicalOperator.And }; |
|
isEqualCompositeFilterDescriptor.FilterDescriptors.Add(new FilterDescriptor(filterDescriptor.Member, |
|
FilterOperator.IsGreaterThanOrEqualTo, new DateTime(value.Year, value.Month, value.Day, 0, 0, 0))); |
|
isEqualCompositeFilterDescriptor.FilterDescriptors.Add(new FilterDescriptor(filterDescriptor.Member, |
|
FilterOperator.IsLessThan, new DateTime(value.Year, value.Month, value.Day, 0, 0, 0).AddDays(1))); |
|
return isEqualCompositeFilterDescriptor; |
|
|
|
case FilterOperator.IsNotEqualTo: |
|
//convert the "is not equal to <date><time>" filter to a "is less than <date> 00:00:00" OR "is greater than or equal to <date + 1day> 00:00:00" |
|
var notEqualCompositeFilterDescriptor = new CompositeFilterDescriptor { LogicalOperator = FilterCompositionLogicalOperator.Or }; |
|
notEqualCompositeFilterDescriptor.FilterDescriptors.Add(new FilterDescriptor(filterDescriptor.Member, |
|
FilterOperator.IsLessThan, new DateTime(value.Year, value.Month, value.Day, 0, 0, 0))); |
|
notEqualCompositeFilterDescriptor.FilterDescriptors.Add(new FilterDescriptor(filterDescriptor.Member, |
|
FilterOperator.IsGreaterThanOrEqualTo, new DateTime(value.Year, value.Month, value.Day, 0, 0, 0).AddDays(1))); |
|
return notEqualCompositeFilterDescriptor; |
|
|
|
case FilterOperator.IsGreaterThanOrEqualTo: |
|
//convert the "is greater than or equal to <date><time>" filter to a "is greater than or equal to <date> 00:00:00" |
|
filterDescriptor.Value = new DateTime(value.Year, value.Month, value.Day, 0, 0, 0); |
|
return filterDescriptor; |
|
|
|
case FilterOperator.IsGreaterThan: |
|
//convert the "is greater than <date><time>" filter to a "is greater than or equal to <date + 1day> 00:00:00" |
|
var greaterThanFilterDescriptor = new FilterDescriptor(filterDescriptor.Member, FilterOperator.IsGreaterThanOrEqualTo, new DateTime(value.Year, value.Month, value.Day, 0, 0, 0).AddDays(1)); |
|
return greaterThanFilterDescriptor; |
|
|
|
case FilterOperator.IsLessThanOrEqualTo: |
|
//convert the "is less than or equal to <date><time>" filter to a "is less than <date + 1day> 00:00:00" |
|
var lessThanEqualToFilterDescriptor = new FilterDescriptor(filterDescriptor.Member, FilterOperator.IsLessThan, new DateTime(value.Year, value.Month, value.Day, 0, 0, 0).AddDays(1)); |
|
return lessThanEqualToFilterDescriptor; |
|
|
|
case FilterOperator.IsLessThan: |
|
//convert the "is less than <date><time>" filter to a "is less than <date> 00:00:00" |
|
filterDescriptor.Value = new DateTime(value.Year, value.Month, value.Day, 0, 0, 0); |
|
return filterDescriptor; |
|
|
|
case FilterOperator.IsNull: |
|
return filterDescriptor; |
|
|
|
case FilterOperator.IsNotNull: |
|
return filterDescriptor; |
|
|
|
default: |
|
throw new Exception(string.Format("Filter operator '{0}' is not supported for DateTime member '{1}'", filterDescriptor.Operator, filterDescriptor.Member)); |
|
} |
|
} |
|
} |
|
return filter; |
|
} |
|
} |
|
} |