SharePoint 2010 : Searching Through the API - The Search API

3/8/2013 3:18:21 AM

The SharePoint 2010 Enterprise Search API has changed from using the Shared Services Provider architecture in SharePoint 2007 to using Search service applications in SharePoint 2010. A lot of the engine under the hood is still the same, however. This section focuses on how to do basic search programming in SharePoint 2010. If the purpose is to migrate search code from 2007 to 2010, this should be easy, as search has been abstracted to support code for SP 2007.

Three ways of doing search programming are covered:

  • Using the KeywordQuery
  • Using the FullTextSqlQuery
  • Using the search web service

Creating a KeywordQuery-Based Search

SharePoint 2010 now has a new way to get the object of the KeywordQuery by using the SearchServiceApplicationProxy. The name of the SearchServiceApplicationProxy is required for creating the KeywordQuery object. The name can be found by navigating to the SSA list. The proxy name is normally the same as the SSA name. Per default this is simply “Search Service Application”. If not, then go to Central Administration and open Service Applications to find it.

Having the name of the SearchServiceApplicationProxy, it is now possible to get the proper references required for creating the KeywordQuery object. This is done as follows:

SearchQueryAndSiteSettingsServiceProxy settingsProxy =Image

SearchServiceApplicationProxy searchProxy =Image
("Search Service Application");

Using(KeywordQuery keywordQuery = new KeywordQuery(searchProxy))

Having the reference to the KeywordQuery object, the search properties can now be configured. SharePoint 2010 introduces a significant number of new properties to configure. In the example below, only the basic properties, that are needed to perform a search, are configured.

keywordQuery.QueryText = "Your query text";
keywordQuery.ResultTypes = ResultType.RelevantResults;
keywordQuery.ResultsProvider = SearchProvider.Default;
ResultTableCollection keywordQueryResultsCollection = keywordQuery.Execute();

ResultTable keywordQueryResults = keywordQueryResultsCollection[ResultType.RelevantResults];
DataTable keywordQueryResultsTable = new DataTable();
keywordQueryResultsTable.TableName = "Results";
keywordQueryResultsTable.Load(keywordQueryResults, LoadOption.OverwriteChanges);

There are two properties that should receive special attention due to the new, enhanced people-finding abilities in SP 2010: EnableNicknames and EnablePhonetic.

The EnableNicknames property allows for people to be found by their, well, nicknames. This way is it possible to find Andrew by his nickname, “Andy.” This is immensely helpful if building custom people finder Web Parts.

EnablePhonetic allows users to find persons even if they do not know the exact spelling of a name. A search for Kristian will return results for “Christian” as well.

One important point of these properties is that they depend on the browser language setting. For instance, the nickname Mike for Michael applies if browser language is set to US or UK, but not if it is set to German.

Creating a FullTextSqlQuery-Based Search

Sometimes the programmer wants more control over the query. This can be achieved using the FullTextSqlQuery class. This class allows the programmer to control the query using SQL syntax, which is often a more familiar language and makes it easier to understand why a query behaves a particular way.

The FROM target object in the SQL has to be set to the SCOPE() function, as shown here. If further refinement is required, the scope can be set in a WHERE clause. If the scope is not set, no scope is applied. In the following query, the first name of all persons in the People scope are returned.

SELECT FirstName FROM SCOPE() WHERE "scope" = 'People'

The SQL select statement can be expanded to return more properties or have more property restrictions. For instance, if the query should be limited to return the author for all documents with a file type of .pdf, the following code SQL can be used to perform that search. This assumes the code is executed with the SharePoint context.

The namespace where the SharePoint search types are defined is as follows:

using Microsoft.Office.Server.Search.Query;

using(FullTextSqlQuery fullTextSqlQuery = new FullTextSqlQuery(SPContext.Current.Site))
fullTextSqlQuery.QueryText = "SELECT Author FROM SCOPE() WHERE \"scope\" = 'All Sites'
        AND CONTAINS(FileType, 'pdf')";

fullTextSqlQuery.ResultTypes = ResultType.RelevantResults;

ResultTable fullTextSqlQueryResults =

DataTable fullTextSqlQueryResultsTable = new DataTable();
fullTextSqlQueryQueryResultsTable.TableName = "Results";

This is a very basic example of how to perform a property search in SharePoint using the CONTAINS predicate.

If debugging in Visual Studio 2010, you can then use the data visualizer to see the results.  This can be a helpful way of evaluating search results.

Searching Through the Search Web Service

In SharePoint it is possible to search the SharePoint index not only using the API on a SharePoint server, but also from external locations outside SharePoint, using the search web service. Examples could be custom integrations of search into locally deployed client applications or from other non-SharePoint web sites hosted on other servers.

As opposed to using the API, which, as shown in the previous examples, is straightforward, using the search web service does introduce some new challenges, namely the binding context. Next, it is described how to contact the web service through a console application with the binding context setup from App.Config. The search web service can be called from any code, however, and the binding can be specified directly from code too, where feasible.

Consuming the Search Web Service from a Console Application

First a reference to the search service soap client is needed. The constructor can either be empty or receive a string with the name of the service binding context to use.

SearchServices.WSSearch.QueryServiceSoapClient searchService =
new SearchServices.WSSearch.QueryServiceSoapClient("SearchServiceBinding");

It is good practice to verify that the service is actually online before invoking it. This can be done by checking the status message of the soap client.

if (searchService.Status().ToLower() != "ONLINE")
        throw new Exception("The search service is not online.");

The App.Config file in this example also includes credentials to use when querying the search web service. These credentials are passed on to the search service.

Although it is possible to use anonymous access when searching, it is often a requirement in any corporation that some level of access permissions is set.

searchService.ClientCredentials.Windows.AllowNtlm = true;

searchService.ClientCredentials.Windows.AllowedImpersonationLevel =

The service is configured to use NT LAN Manager (NTLM) credentials, and the allowed impersonation level is set.

String username = ConfigurationManager.AppSettings.Get("SearchUserName").ToString();
String password = ConfigurationManager.AppSettings.Get("SearchPassword").ToString();
String domainname = ConfigurationManager.AppSettings.Get("SearchDomainName").ToString();

searchService.ClientCredentials.Windows.ClientCredential  =
        new System.Net.NetworkCredential(username, password, domainname);

At this point, the search service soap client is fully configured and ready to be queried. The web service exposes a method called QueryEx, which receives a XML-formatted query request containing the textual expression to query for. Here the query text is simply “SharePoint AND Search”.

String queryText = "SharePoint AND Search";
String queryRequestString = "<QueryPacket xmlns='urn:Microsoft.Search.Query'>" +
        "<Query>" +
                "<SupportedFormats>" +
                        "<Format revision='1'>" +
                               "urn:Microsoft.Search.Response.Document:Document" +
                         "</Format>" +
                 "</SupportedFormats>" +
                 "<Context>" +
                        "<QueryText language='en-US' type='STRING'>" +
                                queryText +
                        "</QueryText>" +
                "</Context>" +
        "</Query>" +

The request package just shown is the simplest possible request. With the search service soap client configured and the query request ready, the actual query can be executed in order to get a results data set back from the search web service. In real-life applications, there should always be an error handling code and a check on success when contacting the search web service as when calling any other web service. This is left out here for clarity.

System.Data.DataSet searchServiceQueryResults = new System.Data.DataSet();
searchServiceQueryResults = searchService.QueryEx(queryRequestString);

Finally the results can be retrieved from the search result data set by simply iterating the rows in the returned data set. Each row contains the default properties returned by the search result. Typical properties that are useful are Title, Path, Author, and a Summary of the result.

String title, author, path, summary;
foreach (DataRow row in searchServiceQueryResults.Tables[0].Rows)
title = row["Title"];
author = row["Author"];
path = row["Path"];
summary = row["HitHighlightedSummary"];
App.Config Settings

The App.Config for the application is used to define the default binding. As mentioned, this can also be defined directly in code on the search service soap client object using the API, but it is suggested to use an App.Config whenever possible. This makes it easier to maintain and reconfigure if so needed. As such, this example of the binding is sufficient for most practical uses (Listing 1).

Listing 1. Application Configuration file for console application using search web service

<?xml version="1.0"?>
<add key="SearchUserName" value="YourUserName"/>
<add key="SearchPassword" value="YourPassword"/>
<add key="SearchDomainName" value="YourDomainName"/>
<system.serviceModel> <bindings> <basicHttpBinding>
<binding name="SearchServiceBinding"
                <readerQuotas maxDepth="32"
                <security mode="TransportCredentialOnly">
                    <transport clientCredentialType="Ntlm" />
        </basicHttpBinding> </bindings>
        <endpoint address=http://[servername]:[portnumber]/_vti_bin/search.asmx

As shown in this section, it is fairly easy to use the search web service for performing searches against the SharePoint index, from outside the SharePoint farm. The drawback here is maintaining the correct binding context if the name or location of the search web service were to change. One way of handling this could be to create a proxy on the organization's primary domain that internally refers to the search web service.

Video tutorials
- How To Install Windows 8

- How To Install Windows Server 2012

- How To Install Windows Server 2012 On VirtualBox

- How To Disable Windows 8 Metro UI

- How To Install Windows Store Apps From Windows 8 Classic Desktop

- How To Disable Windows Update in Windows 8

- How To Disable Windows 8 Metro UI

- How To Add Widgets To Windows 8 Lock Screen

- How to create your first Swimlane Diagram or Cross-Functional Flowchart Diagram by using Microsoft Visio 2010
programming4us programming4us