Customize SharePoint Search Results Paging…!!!


Recently I had a requirement to customize the OOB SharePoint search results paging control (SearchPagingWebPart). So below is the problem definition and the solutions I came across. (the link to the downloadable source code for the solution is attached at the end of the post)

OOB paging control gives you several options to specify and define the paging behavior.

image

Most important properties for me are the first two ones.

1) Maximum page links before current
2) Maximum page links after current

So with the above configuration paging will look like this:

image

Its fare enough so the current page is 1 and there are no pages to be displayed as previous links. so it will display only 3 after links.

When you navigate to a page in the middle it will look like this:

image

So its now displaying 4 before links with page numbers and 3 after links.

When you navigate to the last page it will look like below:

image

Will display 4 before links as expected.

So my client requirement was to display consistent number of pages regardless what is the current page getting displayed. Obvious if there are no much results to display, it should display the actual result count and pages, but when there are enough results, the displayed page count should be consistent.

So the possible options were:
1) Extend the OOB paging control do some calculations to fix the issue:
[But the SearchPagingWebPart is a sealed class and cannot be extended]
2) Create a fully custom control or a web part with custom coding
[There will be problems getting the accurate result set when any of the search
filters applied in the core result web part]

Main problem I was facing is to get the correct result count returned from SharePoint Core Results web part. If I can get that value I can do a calculation and set the next and previous page count in the OOB paging web part. So was digging through the implementation of the SearchPagingWebPart using ILSpy and found there is a shared object  named SharedQueryManager to pass the result and query data in between all those search web parts. (Core result, paging, best bet, refinement panel etc..)

Retrieve SharedQueryManager related to current search results:

QueryManager queryManager = 
SharedQueryManager.GetInstance(this.Page).QueryManager;

SharedQueryManager GetInstance contains two method overrides. If your search result page contains multiple query sources you can specify the unique query id to get the correct query manager. Default is set to QueryId.Query1

public static SharedQueryManager GetInstance(Page CurrentPage); 
public static SharedQueryManager GetInstance(Page CurrentPage, QueryId queryId);

Inside the QueryManager object it contains a collection of LocationList items.

For a single query there will be only one location list, so you can get that location list iterating through the collection. This location list will contain all the relevant properties and values related to search results.

LocationList completeResultList = null;

if (queryManager != null)
{
    foreach (LocationList locationList in queryManager)
    {
        if (locationList != null)
        {
            // Get a reference to the LocationList 
            // associated with current search.
            completeResultList = locationList;
            break;
        }
    }
}

Few useful properties that you can retrieve from the LocationList:

ItemsPerPage – Gets or sets the number of search results to display per page.

ReturnedResults – Gets the number of search results returned for the query.

StartItem – Gets or sets the number of the first item returned in the search results.

TotalResults – Gets the total number of search results returned for the query.

TotalResultsIncludingDuplicates – Gets the total number of search results returned for the query, including duplicate results.
(source from msdn)

Now the biggest issue is resolved, and we have a reference to the actual result count returned and also the page size. Then what I did was did a small calculation to recalculate the previous and next links count that should get displayed and then embedded a OOB SearchPagingWebPart inside my custom control with setting the above calculated next and previous page numbers.

It works as a charm Smile

below I have added few screen caps that how our custom paging will work for the previously listed three scenarios.

When user in the first page:

image

When user in a middle page number:

image

When user in the last page:

image

So this was enough to satisfy my client. But if you want more customized paging like the below one we did for another client, you have to do the paging calculation and rendering by your self. It’s a bit complex because you have to do more calculations but still possible.

image

You can get the complete source code (SharePoint project with the custom web part) here.

Happy Coding! Smile

Advertisements

8 thoughts on “Customize SharePoint Search Results Paging…!!!

  1. Great post! Just one question- How did you “embed a web part” inside a custom control? Could you share some of your code? 😉

    Jeannie- probably you aren’t reading this, but this is a hard coded limit inside the search core results web part. You need to extend the search core results web part (if you need more than 50 results on People Search, you need to use web services since you cannot extend the People Search web part). For instance:

    [ToolboxItemAttribute(false)]
    public class CovCustomSearchResults : CoreResultsWebPart
    {
    private int myResultsPerPage = 50;

    [Personalizable(PersonalizationScope.Shared)]
    [WebBrowsable(true)]
    [WebDescription(“Number of Results Per Page”)]
    [Category(“Results Per Page Override. This property overrides the Results Per Page above.”)]
    public int resultsPerPage
    {
    get { return myResultsPerPage; }
    set { myResultsPerPage = value; }
    }

    protected override void ConfigureDataSourceProperties()
    {
    base.ConfigureDataSourceProperties();
    try
    {
    CoreResultsDatasource ds = this.DataSource as CoreResultsDatasource;
    ds.ResultsPerPage = 500;
    ds.ResultsPerPage = myResultsPerPage;
    }
    catch (Exception ex)
    {
    throw ex;
    }
    }

    • Hi, Thanks a lot for the comment and answering the question as well 🙂

      Web Part is also a control in a way. So we can use it as a regular “Web part” in a web part zone or we can just reference it as a custom control. So what I have done is even though the search paging is an OOB web part i have embedded it inside my control referencing as a regular ASP.net control. (How we add a text box into out custom control) I have attached my complete code sample in the blog post it self. So if you are interested you can have a look. 🙂

  2. Great Post indeed!
    In SharePoint 2013, to make this work the webpart class should be inherited from :coreresultswebpart rather than :webpart. Also the functionality works only on postback since whole usercontrol implementation is on page_load() event. If the query term is changed, there is no post back and the functionality is not working as expected.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s