Customizing the SharePoint 2010 Search User Experience
While the SharePoint 2010 Search out-of-the-box user interface is very intuitive and useful for information workers, power users can create their own search experiences. SharePoint Server 2010 includes many search-related web parts for power users to create customized search experiences, including Best Bets, refinement panel extensions, featured content, and predefined queries. Figure 6-21 shows the standard Search web parts.
IT pros or developers can configure the built-in search web parts to tailor the search experience. As a developer, you can also extend the web parts, to change the behavior of built-in web parts on search results pages. Instead of building new web parts, developers can build onto the functionality of existing ones.
In addition, query logging is now available from customized search web parts, and from any use of the Query object to query the Search Service.

Figure 6-21
Example: New Core Results Web Part
Let’s walk you through the creation of a new search web part in Visual Studio 2010. (The full code is included with Code Project 6-P-1, and is courtesy of Steve Peschka.) This web part inherits from the CoreResultsWebPart class and displays data from a custom source. The standard CoreResultsWebPart part includes a constructor and then two methods that we will modify in this example.
The first step is to create a new WebPart class. Create a new web part project that inherits from the CoreResultsWebPart class. Override CreateChildControls to add any controls necessary for your interface, and then override CreateDataSource. This is where you get access to the “guts” of the query. In the override, you will create an instance of a custom datasource class you will build.
class MSDNSample : CoreResultsWebPart
{
public MSDNSample()
{
//default constructor; }
protected override void CreateChildControls()
{
base.CreateChildControls();
//add any additional controls needed for your UI here
}
protected override void CreateDataSource()
{
//base.CreateDataSource();
this.DataSource = new MyCoreResultsDataSource(this);
}
The second step is to create a new CoreResultsDatasource class. In the override for CreateDataSource, set the DataSource property to a new class that inherits from CoreResultsDataSource. In the CoreResultsDataSource constructor, create an instance of a custom datasource view class you will build. No other overrides are necessary.
public class MyCoreResultsDataSource : CoreResultsDatasource
{
public MyCoreResultsDataSource(CoreResultsWebPart ParentWebpart)
: base(ParentWebpart)
{
//to reference the properties or methods of the web part
//use the ParentWebPart parameter
//create the View that will be used with this datasource
this.View = new MyCoreResultsDataSourceView(this,”MyCoreResults”);
}
}
The third step is to create a new CoreResultsDatasourceView class. Set the View property for your CoreResultsDatasource to a new class that inherits from CoreResultsDatasourceView. In the CoreResultsDatasourceView constructor, get a reference to the CoreResultsDatasource so that you can refer back to the web part. Then, set the QueryManager property to the shared query manager used in the page.
public class MyCoreResultsDataSourceView : CoreResultsDatasourceView
{
public MyCoreResultsDataSourceView (SearchResultsBaseDatasource DataSourceOwner, string ViewName)
: base(DataSourceOwner, ViewName)
{
//make sure we have a value for the datasource
if (DataSourceOwner == null)
{
throw new ArgumentNullException(“DataSourceOwner”);
}
//get a typed reference to our datasource
MyCoreResultsDataSource ds = this.DataSourceOwner as MyCoreResultsDataSource;
//configure the query manager for this View
this.QueryManager = SharedQueryManager.GetInstance (ds.ParentWebpart.Page).QueryManager;
}
You now have a functional custom web part displaying data from your custom source. In the next example, we take things one step further to provide some custom query processing.
Example: Adding Sorting to Your New Web Part
The CoreResultsDataSourceView class lets you modify virtually any aspect of the query. The primary way to do that is in an override of AddSortOrder. This class provides access to SharePointSearchRuntime class, which includes: KeywordQueryObject, Location, and RefinementManager.
The code example below adds sorting by overriding AddSortOrder. (The full code is included with Code Project 6-P-1, courtesy of Steve Peschka.)
public override void AddSortOrder(SharePointSearchRuntime runtime)
{
#region Ensure Runtime
//make sure our runtime has been properly instantiated
if (runtime.KeywordQueryObject == null)
{
return;
}
#endregion
//remove any other sorted fields we might have had
runtime.KeywordQueryObject.SortList.Clear();
//get the datasource so we can get to the web part
//and retrieve the sort fields the user selected
SearchResultsPart wp = this.DataSourceOwner.ParentWebpart as SearchResultsPart;
string sortField = wp.SortFields;
//check to see if any sort fields have been provided
if (!string.IsNullOrEmpty(sortField))
{
//if posting back, then use the value from the sort drop-down
if (wp.Page.IsPostBack)
{
//get the sort direction that was selected
SortDirection dir =
(wp.Page.Request.Form[SearchResultsPart .mFormSortDirection] == “ASC” ?
SortDirection.Ascending : SortDirection.Descending);
//configure the sort list with sort field and direction
runtime.KeywordQueryObject.SortList.Add (wp.Page.Request.Form[SearchResultsPart.mFormSortField],
dir);
}
else
{
//split the value out from its delimiter and
//take the first item in descending order
string[] values = sortField.Split(“;”.ToCharArray(), StringSplitOptions.RemoveEmptyEntries);
runtime.KeywordQueryObject.SortList.Add(values[0], SortDirection.Descending);
}
}
else //no sort fields provided so use the default sort order
base.AddSortOrder(runtime);
The KeywordQueryObject class is what’s used in this scenario. It provides access to key query properties like:
|
EnableFQL
|
RowLimit
|
|
EnableNicknames
|
SearchTerms
|
|
EnablePhonetic
|
SelectProperties
|
|
EnableStemming
|
SortList
|
|
Filter
|
StartRow
|
|
QueryInfo
|
SummaryLength
|
|
QueryText
|
TrimDuplicates
|
|
Refiners
|
. . . and many more
|
To change the sort order in your web part, first remove the default sort order. Get a reference to the web part, as it has a property that has the sort fields. If the page has been posted back, then get the sort field the user selected. Otherwise, use the first sort field the user selected. Finally, add the sort field to the SortList property.
To allow sorting, you also need to provide fields on which to sort. Ordering can be done with DateTime fields, Numeric fields, or Text fields where: HasMultipleValues = false, IsInDocProps = true, and MaxCharactersInPropertyStoreIndex > 0.
You can limit the user to only selected fields by creating a custom web part property editor. This uses the same process as in SharePoint 2007: inherit from EditorPart and implement IWebEditable. The custom version of EditorPart in this example web part uses a standard LINQ query against the search schema to find properties.
This article is excerpted from chapter 6 "Search" of the book Professional SharePoint 2010 Development by Tom Rizzo, Reza Alirezaei, Jeff Fried, Paul Swider, Scot Hillier, Kenneth Schaefer (ISBN: 978-0-470-52942-3, Wrox, 2010, Copyright Wiley Publishing Inc.)
