public ActionResult Index(UserIndexOptions options, PagerParameters pagerParameters) { if (!service.Authorizer.Authorize(Permissions.ManageUsers, T("Not authorized to list users"))) { return(new HttpUnauthorizedResult()); } var userType = contentDefinitionManager.GetTypeDefinition("User"); var hasBasicUserProfilePart = userType.Parts.Any(p => p.PartDefinition.Name == nameof(BasicUserProfilePart)); // Create criteria var session = transactionManager.GetSession(); var query = session.CreateCriteria <ContentItemVersionRecord>("version") .CreateAlias("version.ContentItemRecord", "item", JoinType.InnerJoin) // content item is aggregation of part records .CreateAlias("item.ContentType", "type", JoinType.InnerJoin) .CreateAlias("item.UserPartRecord", "user", JoinType.InnerJoin) .Add(Restrictions.Eq("type.Name", "User")) .Add(Restrictions.Eq("version.Published", true)); if (hasBasicUserProfilePart) { query.CreateAlias( "item.BasicUserProfilePartRecord", "profile", JoinType.LeftOuterJoin ); // Not all user have profiles, e.g Admin } SetFilter(options, query, hasBasicUserProfilePart); var totalItemCount = query.SetProjection(Projections.RowCount()).UniqueResult <int>(); var pager = new Pager(siteService.GetSiteSettings(), pagerParameters); var pagerShape = Shape.Pager(pager).TotalItemCount(totalItemCount); SetProjectionList(hasBasicUserProfilePart, query); // FirstResult is row index start from 0 // pager.GetStartIndex() is calculated row index that we use // If we want page number, use pager.Page. query.SetFirstResult(pager.GetStartIndex()).SetMaxResults(pager.PageSize); SetSortOrder(options, query, hasBasicUserProfilePart); var results = query.List <BasicUserProfileDto>(); var model = new UserIndexViewModel { Users = results.Select(u => new ViewModels.UserEntry() { User = u }).ToList(), Options = options, Pager = pagerShape }; // maintain previous route data when generating page links var routeData = new RouteData(); routeData.Values.Add("Options.Filter", options.Filter); routeData.Values.Add("Options.Search", options.Search); routeData.Values.Add("Options.Order", options.Order); pagerShape.RouteData(routeData); // https://stackoverflow.com/questions/43565738/name-valuetuple-properties-when-creating-with-new/43566072#43566072 // can't cast with "is (Url: string, Email: string>) activationEmail" if (TempData[activationEmailKey] is ValueTuple <string, string> activationEmail) { var(url, email) = activationEmail; model.ActivationEmailSent = Shape.ActivationEmailSent(Url: url, Email: email); } ; return(View(model)); }