Recap
Search scopes improve the SharePoint search experience by letting users search over a subset of information within an organisation. For example you can create a search scope for a specific project or a group such as Legal or Marketing. Search scopes can either be created globally at the search service application level so they are available to all site collections, or defined within a specific site collection.
Creating search scopes
Global search scopes in SharePoint 2010 can easily be created using PowerShell commands such as New-SPEnterpriseSearchQueryScope. Corey Roth covers this in his article on Creating Enterprise Search Scopes with PowerShell. While the PowerShell method can also be used to create site collection related search scopes you might also want to do this programmatically in a feature receiver. Another thing you might want to do programmatically is to associate a search scope with a display group such as the ‘Search Dropdown’ so it appears in options next to the search box.
As there are problems with some of the methods that can be used to create search scopes and display groups programmatically I’ll detail these in this article. In a follow up article I’ll cover a method of creating scopes and scope display groups that avoids these problems.
The object model classes I will cover in this article are:
- SearchContext
- SearchServiceApplication
- SearchServiceApplicationProxy
SearchContext
This is only included as it is referenced in other articles and was a common way to create scopes in SharePoint 2007 such as in the code shown below.
In SharePoint 2010 this class is marked as obsolete and should not be used. If you use the SearchContext class in your code you will get the following warning at compile time:
“This class is obsolete now. Please use SearchServiceApplication and SearchServiceApplicationProxy instead.”
According to the article Microsoft SharePoint Server 2010: Deprecated Types and Methods:
Obsolete types and methods will continue to work in your custom code and solutions, but they will generate compiler warnings, and you should update your code to use the new types and methods as indicated by the compiler warnings.
So while this might work it may not always function as expected and there is no guarantee it will continue to work in the future. Next we will look at the alternatives suggested in the compiler warning message.
SearchServiceApplication
If you are updating SharePoint 2007 code the SearchServiceApplication class is an obvious choice as it is a suggested alternative to the SearchContext class. The code is slightly more complicated as you need to retrieve various classes relating to the search service application but a similar outcome can be achieved using the code below:
There is a fundamental problem with this code, however (on top of the hardcoded strings and a complete lack of error handling). The code tries to access the search service application database directly without going through the search web service. In a least privilege installation this means that the application pool account of the web application containing the site collection will be used (even if you elevate privileges for this code) and will not have access to the search service application database by default (as least privilege requires separate accounts for search and content). The specific error message you get when running this code is:
System.Data.SqlClient.SqlException: Cannot open database “Search_Service_Application_DB_{…}” requested by the login. The login failed. Login failed for user ‘{0}’. at System.Data.SqlClient.SqlInternalConnection.OnError(SqlException exception, Boolean breakConnection)
In the example above DEVDOMAIN\spcontent is the identity of the application pool of a web application that contains the content sites for which I want to create search scopes. Using the code above the spcontent account is trying to access the database directly as shown below:
This is something to watch out for as if your dev machines are not running a least privilege installation but your production servers are the issue may not manifest itself until it is difficult and costly to fix.
What we need to do is go through the web services so the account running the search web service (in this case an account named DEVDOMAIN\spservices) is used to connect to the database as shown below:
In the screen shot the intuitively named a168dee… application is the search web service.
This brings us on to the next method mentioned as an alternative to the SearchContext class – the SearchServiceApplicationProxy class.
SearchServiceApplicationProxy
This class requires the use of ScopeInfo and DisplayGroupInfo objects and requires some lower level code such as passing around the ID’s of the display groups. This does get around the database access issue metioned above, however, as it goes through the SearchServiceApplicationProxy class which uses the search web service instance.
While this method works, it requires a lot more code than the methods above and isn’t as intuitive. What used to take 9 lines of code in SharePoint 2007 now takes 30 lines and requires us to pass round the Id’s of scopes and display groups and managing the list of display groups in our code.
So to summarise we have found that:
- SearchContext is now obsolete (and can also cause permission issues)
- SearchServiceApplication can lead to permission issues if called from within a feature receiver as it doesn’t use the search web service
- SearchServiceApplicationProxy uses the search web service but requires much more code and is difficult to work with
6d3ea7d6-6c8c-4ccd-85bc-974181fe1f09|0|.0