public override bool OverrideExecuteResult(ControllerContext context)
        {
            if (context.HttpContext.Request.IsAjaxRequest())
            {
                var formProvider = FormProvider ?? ControlFormProvider.DefaultFormProvider();

                // Return data only
                var request = ControlGridFormRequest.Create(context.HttpContext.Request);
                if (request.PageSize <= 0)
                {
                    request.PageSize = DefaultPageSize;
                }

                var response = context.HttpContext.Response;
                response.ContentType     = "application/json";
                response.ContentEncoding = Encoding.UTF8;

                if (context.HttpContext.Request.QueryString["subGrid"] == "1")
                {
                    var id   = context.HttpContext.Request.Form["id"];
                    var data = subGridForm.GetSubGridData(id);
                    WriteJsonData(response, request, data,
                                  data.Count(),
                                  formProvider,
                                  subGridForm.Columns,
                                  subGridForm.GetRowActions(),
                                  x => subGridForm.GetModelId(x), true, false, null, null);
                }
                else
                {
                    var data = FetchAjaxSource(request);
                    WriteJsonData(response, request, data,
                                  data.TotalRecords > 0 ? data.TotalRecords : data.Count,
                                  formProvider,
                                  columns.Select(x => (ControlGridFormColumn)x).ToList(),
                                  rowActions.Count > 0 && !HideActionsColumn ? rowActions.Select(x => (IControlGridFormRowAction)x).ToList() : new List <IControlGridFormRowAction>(),
                                  GetModelId, false, enableTreeGrid, treeGridParentId, treeGridHasChildren);
                }

                return(true);
            }
            return(base.OverrideExecuteResult(context));
        }
        public override bool OverrideExecuteResult(ControllerContext context)
        {
            if (context.HttpContext.Request.IsAjaxRequest())
            {
                // Return data only
                var request = ControlGridFormRequest.Create(context.HttpContext.Request);
                if (request.PageSize <= 0)
                {
                    request.PageSize = DefaultPageSize;
                }
                var data = FetchAjaxSource(request);

                var response = context.HttpContext.Response;
                response.ContentType     = "application/json";
                response.ContentEncoding = Encoding.UTF8;

                using (var writer = new JsonTextWriter(response.Output)
                {
                    Formatting = Formatting.None
                })
                {
                    writer.WriteStartObject();

                    writer.WritePropertyName("iTotalRecords");
                    var totalRecords = data.TotalRecords > 0 ? data.TotalRecords : data.Count;
                    writer.WriteValue(totalRecords);

                    writer.WritePropertyName("aaData");
                    writer.WriteStartArray();

                    var needWriteValueDelimiter = false;
                    foreach (var item in data)
                    {
                        var jsonObject = new JObject();

                        //foreach (var column in columns)
                        //{
                        //    if (column.IsCheckbox)
                        //    {
                        //        throw new NotImplementedException();
                        //    }
                        //    else
                        //    {
                        //        jsonObject.Add(column.PropertyName, Convert.ToString(column.HtmlBuilder(item)));
                        //    }
                        //}

                        //if (rowActions.Count > 0 && !HideActionsColumn)
                        //{
                        //    var sb = new StringBuilder();
                        //    sb.Append("<table style=\"margin-left: auto; margin-right: auto; border: none; padding: 0;\">");
                        //    sb.Append("<tr>");

                        //    var rowActionIndex = -1;
                        //    foreach (var action in rowActions)
                        //    {
                        //        rowActionIndex++;

                        //        if (action.VisibleWhenFunc != null && !action.VisibleWhenFunc(item))
                        //        {
                        //            continue;
                        //        }

                        //        sb.Append("<td style=\"border: none; background-color: transparent; padding: 0 2px;\">");
                        //        if (action.IsSubmitButton)
                        //        {
                        //            var value = action.ValueSelector != null ? action.ValueSelector(item) : null;
                        //            var attributes = new RouteValueDictionary();
                        //            if (!string.IsNullOrEmpty(action.CssClass))
                        //            {
                        //                attributes.Add("class", action.CssClass);
                        //            }

                        //            if (!string.IsNullOrEmpty(action.ConfirmMessage))
                        //            {
                        //                attributes.Add("onclick", string.Format("return confirm('{0}');", action.ConfirmMessage));
                        //            }

                        //            attributes.Add("id", "btn" + Guid.NewGuid().ToString("N").ToLowerInvariant());
                        //            attributes.Add("style", "white-space: nowrap;");

                        //            var tagBuilder = new TagBuilder("button");
                        //            tagBuilder.MergeAttribute("type", "submit");
                        //            tagBuilder.MergeAttribute("name", action.Name);
                        //            tagBuilder.InnerHtml = action.Text;
                        //            tagBuilder.MergeAttribute("value", value);
                        //            tagBuilder.MergeAttributes(attributes);
                        //            sb.Append(tagBuilder.ToString(TagRenderMode.Normal));
                        //        }
                        //        else
                        //        {
                        //            var href = action.UrlBuilder != null ? action.UrlBuilder(item) : null;
                        //            var attributes = new RouteValueDictionary();
                        //            if (!string.IsNullOrEmpty(action.CssClass))
                        //            {
                        //                attributes.Add("class", action.CssClass);
                        //            }

                        //            attributes.Add("style", "white-space: nowrap;");

                        //            if (action.IsShowModalDialog)
                        //            {
                        //                attributes.Add("data-toggle", "modal");
                        //                attributes.Add("data-target", "#dlgRowAction_" + rowActionIndex);
                        //            }

                        //            var tagBuilder = new TagBuilder("a");
                        //            tagBuilder.MergeAttribute("href", href ?? "javascript:void(0)");
                        //            tagBuilder.InnerHtml = action.Text;
                        //            tagBuilder.MergeAttributes(attributes);
                        //            sb.Append(tagBuilder.ToString(TagRenderMode.Normal));
                        //        }
                        //        sb.Append("</td>");
                        //    }

                        //    sb.Append("</tr>");
                        //    sb.Append("</table>");

                        //    jsonObject.Add("_RowActions", sb.ToString());
                        //}
                        //else
                        //{
                        //    jsonObject.Add("_RowActions", null);
                        //}

                        if (needWriteValueDelimiter)
                        {
                            writer.WriteRaw(",");
                        }

                        writer.WriteRaw(jsonObject.ToString());
                        needWriteValueDelimiter = true;
                    }

                    writer.WriteEndArray();

                    writer.WriteEndObject();
                    writer.Flush();
                }

                return(true);
            }
            return(base.OverrideExecuteResult(context));
        }
        public static ControlGridFormRequest Create(HttpRequestBase request)
        {
            var result = new ControlGridFormRequest();

            var rows = request.Form["rows"];

            if (rows != null)
            {
                result.PageSize = Convert.ToInt32(rows);
            }

            var page = request.Form["page"];

            if (page != null)
            {
                result.PageIndex = Convert.ToInt32(page);
            }

            if (result.PageIndex < 1)
            {
                result.PageIndex = 1;
            }

            result.NodeId = request.Form["nodeid"];
            if (request.Form.AllKeys.Contains("n_level"))
            {
                var level = request.Form["n_level"];
                if (string.IsNullOrEmpty(level))
                {
                    result.NodeLevel = -1;
                }
                else
                {
                    result.NodeLevel = Convert.ToInt32(request.Form["n_level"]);
                }
            }
            else
            {
                result.NodeLevel = -1;
            }

            result.SortColumn    = request.Form["sidx"];
            result.SortDirection = request.Form["sord"] == "asc";

            var isSearch = request.Form["_search"];

            if (isSearch == "true")
            {
                result.Filters = new List <ControlGridFilter>();

                var filters = JObject.Parse(request.Form["filters"]);
                var rules   = (JArray)filters["rules"];
                foreach (var rule in rules)
                {
                    ControlGridFilterOperator @operator;
                    switch (rule["op"].Value <string>())
                    {
                    case "eq":
                        @operator = ControlGridFilterOperator.Equal;
                        break;

                    case "ne":
                        @operator = ControlGridFilterOperator.NotEqual;
                        break;

                    case "lt":
                        @operator = ControlGridFilterOperator.Less;
                        break;

                    case "le":
                        @operator = ControlGridFilterOperator.LessOrEqual;
                        break;

                    case "gt":
                        @operator = ControlGridFilterOperator.Greater;
                        break;

                    case "ge":
                        @operator = ControlGridFilterOperator.GreaterOrEqual;
                        break;

                    case "bw":
                        @operator = ControlGridFilterOperator.BeginsWith;
                        break;

                    case "bn":
                        @operator = ControlGridFilterOperator.NotBeginsWith;
                        break;

                    case "in":
                        @operator = ControlGridFilterOperator.IsIn;
                        break;

                    case "ni":
                        @operator = ControlGridFilterOperator.NotIsIn;
                        break;

                    case "ew":
                        @operator = ControlGridFilterOperator.EndsWith;
                        break;

                    case "en":
                        @operator = ControlGridFilterOperator.NotEndsWith;
                        break;

                    case "cn":
                        @operator = ControlGridFilterOperator.Contains;
                        break;

                    case "nc":
                        @operator = ControlGridFilterOperator.NotContains;
                        break;

                    default:
                        throw new ArgumentOutOfRangeException();
                    }
                    result.Filters.Add(new ControlGridFilter
                    {
                        Name     = rule["field"].Value <string>(),
                        Operator = @operator,
                        Value    = rule["data"].Value <string>()
                    });
                }
            }

            return(result);
        }
        private static void WriteJsonData <TModelRecord>(HttpResponseBase response, ControlGridFormRequest request, ControlGridAjaxData <TModelRecord> data, int totalRecords,
                                                         ControlFormProvider formProvider, IList <ControlGridFormColumn> columns, ICollection <IControlGridFormRowAction> rowActions, Func <TModelRecord, object> getModelId, bool isSubGrid, bool isTreeGrid, Func <TModelRecord, dynamic> getParentId, Func <TModelRecord, bool> hasChildren)
        {
            using (var writer = new JsonTextWriter(response.Output)
            {
                Formatting = Formatting.None
            })
            {
                writer.WriteStartObject();

                writer.WritePropertyName("page");
                writer.WriteValue(request.PageIndex);

                writer.WritePropertyName("records");
                writer.WriteValue(totalRecords);

                writer.WritePropertyName("total");
                writer.WriteValue((int)Math.Ceiling((totalRecords * 1d) / request.PageSize));

                if (data.Callbacks.Count > 0)
                {
                    writer.WritePropertyName("callback");
                    writer.WriteValue(string.Join("", data.Callbacks));
                }

                writer.WritePropertyName("rows");

                writer.WriteStartArray();

                var needWriteValueDelimiter = false;
                foreach (TModelRecord item in data)
                {
                    var jsonObject = new JObject {
                        { "_id", Convert.ToString(getModelId(item)) }
                    };

                    foreach (var column in columns)
                    {
                        jsonObject.Add(column.PropertyName, Convert.ToString(column.BuildHtml(item)));
                    }

                    if (isTreeGrid)
                    {
                        jsonObject.Add("_level", request.NodeLevel + 1);
                        jsonObject.Add("_parentId", getParentId(item));
                        jsonObject.Add("_isLeaf", !hasChildren(item));
                        jsonObject.Add("_isExpanded", false);
                    }

                    if (rowActions.Count > 0)
                    {
                        var sb = new StringBuilder();
                        sb.Append("<table style=\"margin-left: auto; margin-right: auto; border: none; padding: 0;\">");
                        sb.Append("<tr>");

                        foreach (var action in rowActions)
                        {
                            if (!action.IsVisible(item))
                            {
                                continue;
                            }

                            var enabled    = action.IsEnable(item);
                            var attributes = new RouteValueDictionary(action.GetAttributes(item));

                            sb.Append("<td style=\"border: none; background-color: transparent; padding: 0 2px;\">");
                            if (action.IsSubmitButton)
                            {
                                var value = action.GetValue(item);

                                var cssClass =
                                    (formProvider.GetButtonSizeCssClass(action.ButtonSize) + " " +
                                     formProvider.GetButtonStyleCssClass(action.ButtonStyle) + " " + action.CssClass).Trim();

                                if (!string.IsNullOrEmpty(cssClass))
                                {
                                    attributes.Add("class", cssClass);
                                }

                                if (!enabled)
                                {
                                    attributes.Add("disabled", "disabled");
                                }

                                if (!string.IsNullOrEmpty(action.ClientClickCode))
                                {
                                    attributes.Add("onclick", action.ClientClickCode);
                                }
                                else
                                {
                                    if (!string.IsNullOrEmpty(action.ConfirmMessage))
                                    {
                                        attributes.Add("onclick", string.Format("return confirm('{0}');", action.ConfirmMessage));
                                    }
                                }

                                attributes.Add("id", "btn" + Guid.NewGuid().ToString("N").ToLowerInvariant());
                                attributes.Add("style", "white-space: nowrap;");

                                var tagBuilder = new TagBuilder("button");
                                tagBuilder.MergeAttribute("type", "submit");
                                tagBuilder.MergeAttribute("name", action.Name);
                                tagBuilder.InnerHtml = action.Text;
                                tagBuilder.MergeAttribute("value", Convert.ToString(value));
                                tagBuilder.MergeAttributes(attributes, true);
                                sb.Append(tagBuilder.ToString(TagRenderMode.Normal));
                            }
                            else
                            {
                                var href = action.GetUrl(item);

                                var cssClass =
                                    (formProvider.GetButtonSizeCssClass(action.ButtonSize) + " " +
                                     formProvider.GetButtonStyleCssClass(action.ButtonStyle) + " " + action.CssClass).Trim();

                                if (!string.IsNullOrEmpty(cssClass))
                                {
                                    if (enabled)
                                    {
                                        attributes.Add("class", cssClass);
                                    }
                                    else
                                    {
                                        attributes.Add("class", cssClass + " disabled");
                                    }
                                }
                                else
                                {
                                    if (!enabled)
                                    {
                                        attributes.Add("class", "disabled");
                                    }
                                }

                                attributes.Add("style", "white-space: nowrap;");

                                if (action.IsShowModalDialog && enabled)
                                {
                                    attributes.Add("data-toggle", "fancybox");
                                    attributes.Add("data-fancybox-type", "iframe");
                                    attributes.Add("data-fancybox-width", action.ModalDialogWidth);
                                    attributes.Add("data-fancybox-height", action.ModalDialogHeight);
                                }

                                var tagBuilder = new TagBuilder("a");
                                if (enabled)
                                {
                                    tagBuilder.MergeAttribute("href", href ?? "javascript:void(0)");
                                }
                                else
                                {
                                    tagBuilder.MergeAttribute("href", "javascript:void(0)");
                                }
                                tagBuilder.InnerHtml = action.Text;
                                tagBuilder.MergeAttributes(attributes, true);
                                sb.Append(tagBuilder.ToString(TagRenderMode.Normal));
                            }
                            sb.Append("</td>");
                        }

                        sb.Append("</tr>");
                        sb.Append("</table>");

                        jsonObject.Add("_RowActions", sb.ToString());
                    }
                    else
                    {
                        jsonObject.Add("_RowActions", null);
                    }

                    if (needWriteValueDelimiter)
                    {
                        writer.WriteRaw(",");
                    }

                    writer.WriteRaw(jsonObject.ToString());
                    needWriteValueDelimiter = true;
                }

                if (isSubGrid && data.UserData.ContainsKey("_RowActions"))
                {
                    if (needWriteValueDelimiter)
                    {
                        writer.WriteRaw(",");
                    }

                    writer.WriteStartObject();
                    writer.WritePropertyName("_RowActions");
                    writer.WriteValue(data.UserData["_RowActions"]);
                    writer.WriteEndObject();

                    data.UserData.Remove("_RowActions");
                }

                writer.WriteEndArray();

                if (data.UserData.Count > 0)
                {
                    writer.WritePropertyName("userdata");

                    writer.WriteStartObject();

                    foreach (var item in data.UserData)
                    {
                        writer.WritePropertyName(item.Key);
                        writer.WriteValue(item.Value);
                    }

                    writer.WriteEndObject();
                }

                writer.WriteEndObject();
                writer.Flush();
            }
        }