/// <summary>
        /// Returns a ViewResult to display an "Index" view from which the user may select a row to edit (or view details that may be hidden)
        /// </summary>
        /// <returns></returns>
        public virtual ActionResult Index()
        {
            SetupIndex();
            string[] propertyNames     = GetPropertyNames();
            string[] customColumnNames = GetPropertyColumnNames();

            ExpressFormsIndexHeader indexHeader = new ExpressFormsIndexHeader();

            indexHeader.Initialize(customColumnNames, IndexButtons, ControllerContext);

            IEnumerable <ExpressFormsIndexRecord> indexRecords = Exchange.Get().ToList()
                                                                 .Select(r =>
            {
                ExpressFormsIndexRecord indexRecord = new ExpressFormsIndexRecord();
                indexRecord.Initialize <T, TId>(r, GetIdFromRecord(r), propertyNames, IndexButtons, CustomPropertyDisplay, ControllerContext);
                return(indexRecord);
            });

            ExpressFormsIndexViewModel model = new ExpressFormsIndexViewModel()
            {
                Title            = IndexTitle == null ? typeof(T).Name : IndexTitle,
                ShowAddNewButton = ShowIndexAddNewButton,
                GetAjaxUrl       = Url.Action("GetAjax", QueryStringUtility.CurrentQueryStringAsRouteValues), // pass the query string values in the URL in case they are needed to retrieve data.
                GetIndexFilterAutocompleteDataUrl = Url.Action("GetIndexFilterAutocompleteData", QueryStringUtility.CurrentQueryStringAsRouteValues),
                IndexHeader     = indexHeader,
                IndexRecords    = indexRecords,
                Filters         = GetIndexFilters(),
                FilterPlacement = IndexFilterPlacement,
                RecordType      = typeof(T)
            };

            return(View(IndexViewName, model));
        }
        public virtual ActionResult GetAjax()
        {
            SetupIndex();

            HtmlHelper helper = new HtmlHelper(new ViewContext(ControllerContext, new WebFormView(ControllerContext, "omg"), new ViewDataDictionary(), new TempDataDictionary(), new System.IO.StringWriter()), new ViewPage());

            // Here, we need to use the property names from the class definition, not the column names that we display.
            string[] propertyNames = typeof(T).GetProperties()
                                     .Where(p => !IgnoredPropertyNames.Contains(p.Name))
                                     .Select(p => p.Name)
                                     .ToArray();

            // This is expected to set up the filter and pagination (and the sorting, once that is set up)
            IndexAjaxExtension.Initialize(ControllerContext, propertyNames);

            int totalRecordCount = Exchange.Get().Count();

            string AdvancedSearchJson       = Request["ef_Filter"];
            JavaScriptSerializer serializer = new JavaScriptSerializer();
            Dictionary <string, Dictionary <string, string> > filterEntries = serializer.Deserialize <Dictionary <string, Dictionary <string, string> > >(AdvancedSearchJson);
            Dictionary <string, ExpressFormsFilter>           indexFilters  = GetIndexFilters();

            IEnumerable <T> filteredRecords     = IndexAjaxExtension.RecordFilter.GetFilteredRecords <T>(Exchange.Get(), indexFilters, filterEntries);
            int             filteredRecordCount = IndexAjaxExtension.RecordFilter.GetFilteredRecords <T>(Exchange.Get(), indexFilters, filterEntries).Count();
            IEnumerable <T> sortedRecords       = IndexAjaxExtension.RecordSorting.GetSortedRecords <T>(filteredRecords);
            IEnumerable <T> pageOfRecords       = IndexAjaxExtension.RecordPagination.GetPageOfRecords <T>(sortedRecords);

            IEnumerable <ExpressFormsIndexRecord> indexRecords =
                pageOfRecords.Select(r =>
            {
                ExpressFormsIndexRecord indexRecord = new ExpressFormsIndexRecord();
                indexRecord.Initialize <T, TId>(r, GetIdFromRecord(r), propertyNames, IndexButtons, CustomPropertyDisplay, ControllerContext);
                return(indexRecord);
            });

            var retval = new
            {
                iTotalRecords        = totalRecordCount,    // number of records in database before filtering
                iTotalDisplayRecords = filteredRecordCount, // number of records that match filter, not just on this page.
                aaData = indexRecords.Select(x => x.FieldHtml)
            };

            return(Json(retval, JsonRequestBehavior.AllowGet));
        }  // end function GetAjax