November Happy Hour will be moved to Thursday December 5th.
November Happy Hour will be moved to Thursday December 5th.
Hi,
I have created a Gist with the code I have written and using for paging (works for any IEnumerable<T>) that you can take a look at. You can find it here. To use this code you can modify your search page view model by changing the type of the Hits property to IPagedEnumerable<SearchHit>:
public IPagedEnumerable<SearchHit> Hits { get; set; }
Next, modify your action so it handles a page querystring parameter:
public ViewResult Index(SearchPage currentPage, string q, int page = 1)
And in your action where you create an instance of the view model you set the Hits property like this:
int pageSize = 10; var hits = Search(q.Trim(), ContentReference.StartPage, ControllerContext.HttpContext, currentPage.LanguageID).ToList(); model.Hits = new PagedList<SearchPageModel.SearchHit>(HttpContext, hits, page, pageSize) { QueryParamName = "page" };
Finally in the view, somewhere below or above the search results, you render the paging partial that you can find in the Gist:
@{ Html.RenderPartial("_Paging", Model.Hits); }
I would also modify the SearchService class in Alloy so it handles paging, so you only get back the results for the current page. In the implementation I have (maybe it's an old version of Alloy) it just gets the 40 first hits. This Search method should be changed from:
public virtual SearchResults Search(string searchText, PageReference rootPage, HttpContextBase context, string languageBranch, string[] fileDirectories, int maxResults) { var query = CreateQuery(searchText, rootPage, context, languageBranch, fileDirectories); return _searchHandler.GetSearchResults(query, 1, maxResults); }
To:
public virtual SearchResults Search(string searchText, PageReference rootPage, HttpContextBase context, string languageBranch, string[] fileDirectories, int page, int pageSize) { var query = CreateQuery(searchText, rootPage, context, languageBranch, fileDirectories); return _searchHandler.GetSearchResults(query, page, pageSize); }
Next you should modify the Search method in the SearchPage controller:
private IEnumerable<SearchPageModel.SearchHit> Search(string searchText, PageReference rootPage, HttpContextBase context, string languageBranch, int page, int pageSize, out int numberOfHits) { var searchResults = _searchService.Search(searchText, rootPage, context, languageBranch, _fileDirectories, page, pageSize); numberOfHits = searchResults.TotalHits; return searchResults.IndexResponseItems.SelectMany(CreateHitModel); }
And finally, use this code in the Index action:
int numberOfHits; int pageSize = 10; var hits = Search(q.Trim(), ContentReference.StartPage, ControllerContext.HttpContext, currentPage.LanguageID, page, pageSize, out numberOfHits).ToList(); model.Hits = new PagedList<SearchPageModel.SearchHit>(HttpContext, hits, numberOfHits, page, pageSize) { QueryParamName = "page" }; model.NumberOfHits = numberOfHits;
When modifying the Search Service I have a different version (IEnumerable<ContentReference> searchRoots instead of PageReference rootPage).
If I modifiy it I will also need to modify the CreateQuery method.
These are my versions.
Search
public virtual SearchResults Search(string searchText, IEnumerable<ContentReference> searchRoots, HttpContextBase context, string languageBranch, int maxResults) { var query = CreateQuery(searchText, searchRoots, context, languageBranch); return _searchHandler.GetSearchResults(query, 1, maxResults); }
CreateQuery
private IQueryExpression CreateQuery(string searchText, IEnumerable<ContentReference> searchRoots, HttpContextBase context, string languageBranch) { //Main query which groups other queries. Each query added //must match in order for a page or file to be returned. var query = new GroupQuery(LuceneOperator.AND); //Add free text query to the main query query.QueryExpressions.Add(new FieldQuery(searchText)); //Search for pages using the provided language var pageTypeQuery = new GroupQuery(LuceneOperator.AND); pageTypeQuery.QueryExpressions.Add(new ContentQuery<PageData>()); pageTypeQuery.QueryExpressions.Add(new FieldQuery(languageBranch, Field.Culture)); //Search for media without languages var contentTypeQuery = new GroupQuery(LuceneOperator.OR); contentTypeQuery.QueryExpressions.Add(new ContentQuery<MediaData>()); contentTypeQuery.QueryExpressions.Add(pageTypeQuery); query.QueryExpressions.Add(contentTypeQuery); //Create and add query which groups type conditions using OR var typeQueries = new GroupQuery(LuceneOperator.OR); query.QueryExpressions.Add(typeQueries); foreach (var root in searchRoots) { var contentRootQuery = new VirtualPathQuery(); contentRootQuery.AddContentNodes(root, _contentLoader); typeQueries.QueryExpressions.Add(contentRootQuery); } var accessRightsQuery = new AccessControlListQuery(); accessRightsQuery.AddAclForUser(PrincipalInfo.Current, context); query.QueryExpressions.Add(accessRightsQuery); return query; }
It also says that _fileDirectories doesn't exist in the SearchPageController.
Hi everyone!
I'm trying to sort the search results of the Alloy example MVC in pages but I don't know how to start doing it and I need someone who guides me a little bit in my way to do it.
I'm not using EPiServer Find, is essential to use it to make this work?
Thanks =)