Kendo Mvc CustomKendoMvcExtensions. DataSourceRequest Filters in case of Datetime comparison. Don’t take time into consideration

Usage:

return Json(requestsList.ToCustomDataSourceResult(request));

Or:

public ActionResult GetList([CustomDataSourceRequest]DataSourceRequest request)

Implementation:

using Kendo.Mvc;
using Kendo.Mvc.Extensions;
using Kendo.Mvc.UI;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System.Web.Mvc;




namespace Kendo.Mvc.Extensions
{
    public static class CustomKendoMvcExtensions
    {
        /// <summary>
        /// Changes DataSourceRequest Filters in case of Datetime comparison. Does not take time into consideration
        /// //http://www.crowbarsolutions.com/ignoring-time-when-filtering-dates-in-telerik-kendo-grids/
        /// Adapted from above link.
        /// Uses CustomDataSourceRequestModelBinder.TransformFilterDescriptors function
        /// </summary>
        /// <param name="queryable"></param>
        /// <param name="request"></param>
        /// <returns></returns>
        public static DataSourceResult ToCustomDataSourceResult(this IQueryable queryable, DataSourceRequest request)
        {
            if (request.Filters != null && request.Filters.Count > 0)
            {

                ModelBinders.CustomDataSourceRequestModelBinder customModelBinder = new ModelBinders.CustomDataSourceRequestModelBinder();

                var transformedFilters = request.Filters.Select(customModelBinder.TransformFilterDescriptors).ToList();
                request.Filters = transformedFilters;
            }

            return queryable.ToDataSourceResult(request);
        }
    }
}


namespace Kendo.Mvc.UI
{
    //http://www.crowbarsolutions.com/ignoring-time-when-filtering-dates-in-telerik-kendo-grids/
    public class CustomDataSourceRequestAttribute : DataSourceRequestAttribute
    {
        public override IModelBinder GetBinder()
        {
            return new Kendo.Mvc.ModelBinders.CustomDataSourceRequestModelBinder();
        }
    }
}

namespace Kendo.Mvc.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
    /// </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;
        }

        public 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 or equal to <date> 23:59:59"
                            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.IsLessThanOrEqualTo, new DateTime(value.Year, value.Month, value.Day, 23, 59, 59)));
                            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 <date> 23:59:59"
                            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.IsGreaterThan, new DateTime(value.Year, value.Month, value.Day, 23, 59, 59)));
                            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 <date> 23:59:59"
                            filterDescriptor.Value = new DateTime(value.Year, value.Month, value.Day, 23, 59, 59);
                            return filterDescriptor;

                        case FilterOperator.IsLessThanOrEqualTo:
                            //convert the "is less than or equal to <date><time>" filter to a "is less than or equal to <date> 23:59:59"
                            filterDescriptor.Value = new DateTime(value.Year, value.Month, value.Day, 23, 59, 59);
                            return filterDescriptor;

                        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;

                        default:
                            throw new Exception(string.Format("Filter operator '{0}' is not supported for DateTime member '{1}'", filterDescriptor.Operator, filterDescriptor.Member));
                    }
                }
            }
            return filter;
        }
    }
}

Kendo Mvc GridHelper

Code beautifier: http://hilite.me/

Usage

@(Html.CustomKendoGrid<ViewModels.UserViewModel>("grid"))

Code:

namespace Kendo.Mvc.UI
{
    //read here about Func vs Action https://stackoverflow.com/a/12687775/249895
    public static class KendoMvcGridHelper
    {

        public static readonly int AxajPageSize = 20;
        public static readonly int AxajPageSizeSmall = 10;

        public static Kendo.Mvc.UI.Fluent.GridBuilder CustomKendoGrid(this HtmlHelper helper, string name) where T : class
        {
            var returnGridBuilder = helper.Kendo().Grid();
            returnGridBuilder = returnGridBuilder.Name(name);
            returnGridBuilder = ConfigureGridBuilder(returnGridBuilder);

            return returnGridBuilder;
        }

        private static GridBuilder ConfigureGridBuilder(GridBuilder gridBuilder) where T : class
        {
            gridBuilder = gridBuilder.Pageable(p => p.PageSizes(new List<int>() { 10, 20 }));
            gridBuilder = gridBuilder.Sortable();
            gridBuilder = gridBuilder.Resizable(r => r.Columns(true));
            gridBuilder = gridBuilder.Filterable(ConfigureGridFilterableSettingsBuilder);
            gridBuilder = gridBuilder.Pageable();
            return gridBuilder;
        }


        public static void ConfigureGridFilterableSettingsBuilder(GridFilterableSettingsBuilder config)        
        {
            config = config.Mode(GridFilterMode.Row).Extra(false);
            config = config.Operators(ConfigureFilterableOperators);
        }

        public static void ConfigureFilterableOperators(FilterableOperatorsBuilder operators)
        {
            operators = operators.ForString(str => str.Clear()
                        .IsEqualTo("Is equal to")
                        .IsNotEqualTo("Is not equal to")
                        .StartsWith("Starts with")
                        .EndsWith("Ends with")                        
                        .Contains("Contains")
                        .DoesNotContain("Does not contain")
                    )
                    .ForDate(str => str.Clear()
                        .IsEqualTo("Is Equal To")
                        .IsGreaterThan("Is Greater Than")
                        .IsGreaterThanOrEqualTo("Is Greater Than Or Equal To")
                        .IsLessThan("Is Less Than")
                        .IsLessThanOrEqualTo("Is Less Than Or Equal To")
                        .IsNotEqualTo("Is Not Equal To")
                    )
                    .ForEnums(str => str.Clear()
                        .IsEqualTo("Is Equal To")
                        .IsNotEqualTo("Is Not Equal To")
                    )
                    .ForNumber(str => str.Clear()
                        .IsEqualTo("Is Equal To")
                        .IsGreaterThan("Is Greater Than")
                        .IsGreaterThanOrEqualTo("Is Greater Than Or Equal To")
                        .IsLessThan("Is Less Than")
                        .IsLessThanOrEqualTo("Is Less Than Or Equal To")
                        .IsNotEqualTo("Is Not Equal To")
                    );
        }
    }
}

MVC CustomAuthorizeAttribute using Reflection to get Controllers and Actions

Code beautifier used: http://hilite.me/ 

Usage:

    [CustomAuthorize]
    public class AdministrationController : BaseController
    {
        #region Users List

        [NavigationMenuEnumAuthorize(NavigationMenuEnum.UserAdministration)]
        public ActionResult Index()
        {
            return View();
        }
    }

CustomAuthorizeAttrbute Code:

namespace System.ComponentModel.DataAnnotations
{

    public class NavigationMenuEnumAuthorizeAttribute : System.Attribute
    {
        public List NavigationMenuEnumList { get; set; }
        public NavigationMenuEnumAuthorizeAttribute(params NavigationMenuEnum[] navigationPages)
        {
            NavigationMenuEnumList = new List();
            if (navigationPages != null && navigationPages.Count() > 0)
            {
                NavigationMenuEnumList = navigationPages.ToList();
            }
        }
    }

    public class CustomAuthorizeAttribute : System.Web.Mvc.AuthorizeAttribute
    {
        string currentAction;
        string currentController;
        string currentArea;
        public override void OnAuthorization(System.Web.Mvc.AuthorizationContext filterContext)
        {
            base.OnAuthorization(filterContext);
        }

        protected override bool AuthorizeCore(HttpContextBase httpContext)
        {
            var routeData = httpContext.Request.RequestContext.RouteData;

            currentAction = routeData.GetRequiredString("action");
            currentController = routeData.GetRequiredString("controller");
            currentArea = routeData.Values["area"] as string;

            if (Utils.CurrentUser == null)
                return false;

            Dictionary<NavigationMenuEnum, bool> menuSecurity = new Dictionary<NavigationMenuEnum, bool>();

            using (var dbContext = new Web.Models.ConnectionStringEDMX())
            {
                int userid = Utils.CurrentUser.UserId;

                menuSecurity[NavigationMenuEnum.CreateNewForm] = false;
                menuSecurity[NavigationMenuEnum.CreateNewChildForm] = false;
                menuSecurity[NavigationMenuEnum.EditNewForm] = false;
                menuSecurity[NavigationMenuEnum.FormSummary] = false;
                menuSecurity[NavigationMenuEnum.AllRequests] = false;
                menuSecurity[NavigationMenuEnum.MyRequests] = false;
                menuSecurity[NavigationMenuEnum.WaitingForApproval] = false;
                menuSecurity[NavigationMenuEnum.UserAdministration] = false;
                menuSecurity[NavigationMenuEnum.Delegate] = false;
                menuSecurity[NavigationMenuEnum.Reporting] = false;

                if (userid == 0)
                {
                    httpContext.Session[Web.Helpers.StaticStrings.MenuSecuritySessionName] = (Dictionary<NavigationMenuEnum, bool>)menuSecurity;
                    return false;
                }

                var userRoles = dbContext.admUserRoles.Where(x => x.UserId == userid || Utils.CurrentUser.CurrentUserDelegatedForUserIdList.Contains(x.UserId));

                foreach (admUserRole userRole in userRoles)
                {
                    switch ((EnRoles)userRole.RoleId)
                    {
                        case EnRoles.Admin:
                            {
                                menuSecurity[NavigationMenuEnum.CreateNewForm] = true;
                                menuSecurity[NavigationMenuEnum.CreateNewChildForm] = true;
                                menuSecurity[NavigationMenuEnum.EditNewForm] = true;
                                menuSecurity[NavigationMenuEnum.AllRequests] = true;
                                menuSecurity[NavigationMenuEnum.MyRequests] = true;
                                menuSecurity[NavigationMenuEnum.WaitingForApproval] = true;
                                menuSecurity[NavigationMenuEnum.FormSummary] = true;
                                menuSecurity[NavigationMenuEnum.UserAdministration] = true;
                                menuSecurity[NavigationMenuEnum.Delegate] = true;
                                menuSecurity[NavigationMenuEnum.Reporting] = true;
                                break;
                            }
                        case EnRoles.Originator:
                            {
                                menuSecurity[NavigationMenuEnum.CreateNewForm] = true;
                                menuSecurity[NavigationMenuEnum.CreateNewChildForm] = true;
                                menuSecurity[NavigationMenuEnum.EditNewForm] = true;
                                menuSecurity[NavigationMenuEnum.FormSummary] = true;
                                menuSecurity[NavigationMenuEnum.AllRequests] = true;
                                menuSecurity[NavigationMenuEnum.MyRequests] = true;
                                menuSecurity[NavigationMenuEnum.Delegate] = true;
                                break;
                            }
                        case EnRoles.Reviewer:
                            {
                                menuSecurity[NavigationMenuEnum.AllRequests] = true;
                                menuSecurity[NavigationMenuEnum.WaitingForApproval] = true;
                                menuSecurity[NavigationMenuEnum.FormSummary] = true;
                                menuSecurity[NavigationMenuEnum.Delegate] = true;
                                break;
                            }
                        case EnRoles.Approver:
                            {
                                menuSecurity[NavigationMenuEnum.AllRequests] = true;
                                menuSecurity[NavigationMenuEnum.WaitingForApproval] = true;
                                menuSecurity[NavigationMenuEnum.FormSummary] = true;
                                menuSecurity[NavigationMenuEnum.Delegate] = true;
                                break;
                            }
                        case EnRoles.Reporting:
                            {
                                menuSecurity[NavigationMenuEnum.AllRequests] = true;
                                menuSecurity[NavigationMenuEnum.Reporting] = true;
                                menuSecurity[NavigationMenuEnum.Delegate] = true;
                                break;
                            }
                        case EnRoles.Viewer:
                            {
                                menuSecurity[NavigationMenuEnum.AllRequests] = true;
                                menuSecurity[NavigationMenuEnum.Delegate] = true;
                                menuSecurity[NavigationMenuEnum.FormSummary] = true;
                                break;
                            }
                        case EnRoles.Supervisor:
                            {
                                menuSecurity[NavigationMenuEnum.AllRequests] = true;
                                menuSecurity[NavigationMenuEnum.WaitingForApproval] = true;
                                menuSecurity[NavigationMenuEnum.FormSummary] = true;
                                menuSecurity[NavigationMenuEnum.Delegate] = true;
                                break;
                            }
                        default:
                            {
                                break;
                            }
                    }
                }
            }

            httpContext.Session[Web.Helpers.StaticStrings.MenuSecuritySessionName] = (Dictionary<NavigationMenuEnum, bool>)menuSecurity;
            
            List pageMapping = GetGeneralPageDetailsList(); // all page mappings are generating from controllers that have the CustomAuthorizeAttribute and Actions that have the NavigationMenuEnumAuthorizeAttribute


            if (!pageMapping.Any(x => x.Action == currentAction && x.Controller == currentController))
                return true;

            NavigationMenuEnum currentPage = pageMapping.Where(x => x.Action == currentAction && x.Controller == currentController).Select(x => x.Page).FirstOrDefault();

            return menuSecurity[currentPage];
        }

        public class PageDetails
        {
            public string Action { get; set; }
            public string Controller { get; set; }
            public NavigationMenuEnum Page { get; set; }
            public PageDetails(string action, string controller, NavigationMenuEnum page)
            {
                this.Action = action;
                this.Controller = controller;
                this.Page = page;
            }
                }

        protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
        {            
            if (Utils.CurrentUser == null || Utils.CurrentUser.UserId == 0)
            {
                filterContext.Result = new RedirectToRouteResult(
                        new RouteValueDictionary 
                        {
                            { "area", "" },
                            { "controller", "Home" },
                            { "action", "SignIn" }
                        });
            }
            else
            {
                filterContext.Result = new RedirectToRouteResult(
                        new RouteValueDictionary 
                        {
                            { "area", "" },
                            { "controller", "Account" },
                            { "action", "NoAccess" }
                        });
            }
            return;
            base.HandleUnauthorizedRequest(filterContext);
        }

        /// https://stackoverflow.com/a/11305443/249895
        public List GetGeneralPageDetailsList()
        {
            try
            {
                ///https://stackoverflow.com/a/30969888/249895
                Assembly asm = Assembly.GetAssembly(typeof(MvcApplication));

                var controllerTypesList = asm.GetTypes().Where(type => typeof(System.Web.Mvc.Controller).IsAssignableFrom(type));

                var returnPagesList = new List();

                foreach (var controllerType in controllerTypesList)
                {
                    var reflectedControllerDescriptor = new ReflectedControllerDescriptor(controllerType);
                    string controllerName = reflectedControllerDescriptor.ControllerName;
                    var customAuthorizeAttributeList = reflectedControllerDescriptor.GetCustomAttributes(typeof(CustomAuthorizeAttribute), true);

                    if (customAuthorizeAttributeList != null && customAuthorizeAttributeList.Count() > 0)
                    {
                        var actionsList = reflectedControllerDescriptor.GetCanonicalActions();
                        foreach (var action in actionsList)
                        {
                            var attributesList = action.GetCustomAttributes(typeof(NavigationMenuEnumAuthorizeAttribute), true).Select(x => (NavigationMenuEnumAuthorizeAttribute)x).ToList();
                            if (attributesList != null && attributesList.Count() > 0)
                            {
                                foreach (var attribute in attributesList)
                                {
                                    foreach (var navigMenuEnum in attribute.NavigationMenuEnumList)
                                    {
                                        var page = new CustomAuthorizeAttribute.PageDetails(action.ActionName, controllerName, navigMenuEnum);
                                        returnPagesList.Add(page);
                                    }
                                }
                            }
                            else
                            {
                                var page = new CustomAuthorizeAttribute.PageDetails(action.ActionName, controllerName, NavigationMenuEnum.None);
                                returnPagesList.Add(page);
                            }
                        }
                    }
                }

                return returnPagesList;
            }
            catch (ReflectionTypeLoadException ex)
            {
                System.Text.StringBuilder sb = new System.Text.StringBuilder();
                foreach (Exception exSub in ex.LoaderExceptions)
                {
                    sb.AppendLine(exSub.Message);
                    System.IO.FileNotFoundException exFileNotFound = exSub as System.IO.FileNotFoundException;
                    if (exFileNotFound != null)
                    {
                        if (!string.IsNullOrEmpty(exFileNotFound.FusionLog))
                        {
                            sb.AppendLine("Fusion Log:");
                            sb.AppendLine(exFileNotFound.FusionLog);
                        }
                    }
                    sb.AppendLine();
                }
                string errorMessage = sb.ToString();
                Elmah.ErrorSignal.FromCurrentContext().Raise(ex);
                Exception newEx = new Exception(errorMessage);
                Elmah.ErrorSignal.FromCurrentContext().Raise(newEx);
                throw newEx;
                //Display or log the error based on your application.
            }
            catch (Exception ex)
            {
                Elmah.ErrorSignal.FromCurrentContext().Raise(ex);
                throw;
            }
        }
    }


}