Expanding Horizons: Restrict a Customized Search to an Individual, New, Programatically-Created Content Source

 

On the surface, SharePoint can easily seem like a restrictive end-user, UI-based application;  perhaps because it contains so much functionality out-of-the-box, I think it can be easy to forget -- or fail to realize -- just how flexible the product is.  I like to think of SharePoint as a platform for application development as well as a shipped product, and this topic is an attempt to show just one way in which SharePoint can be expanded and adapted to various needs.

 

Let's say, for fun, you want to be able to programatically create a new Windows Sharepoint Services 2.0 site, and immediately enable a custom search in Sharepoint Portal Server 2003 -- using either the Search.asmx Web Service, or the QueryProvider class from the Microsoft.Sharepoint.Portal.Search namespace -- to be able to search a new, programatically-created Content Source that is restricted exclusively to the newly-created site.

 

Picture an application that allows end users to fill out a form to create a new WSS site.  After the form is submitted, the new site is created, and can be individually searched from a custom search page, either in Sharepoint Portal Server 2003, or in plain old ASP.NET.

 

Sounds like a good time, no?

 

Out-of-the-box, you can easily add the new site to the site directory, and can enable it for searching from within the Non_Portal_Content Content Index.  However, such unrestricted searches will return data from ALL Content Sources in Non_Portal_Content, including any and all other WSS sites.

 

So, what do we do?

 

Our first step will be to add a new WSS Site programatically.  This is relatively simple, and samples abound in the SDK:

 

Creating or Deleting a Site or a Site Collection

https://msdn.microsoft.com/library/en-us/spptsdk/html/tsptCreatingDeletingWebs.asp?frame=true

 

Next, we'll need to programatically create a Content Source.  This is less straightforward, and isn't specifically documented in the SPPTSDK, so I've created a quick sample in C# that does the job:

 

==

string sPortalURI = "https://<portalname>"; //TODO: change to valid Portal server URL

string sIndexDNS = "<SERVERNAME>"; //TODO: change to valid Index server DNS name

string sContentSourceURI = "https://<server>/sites/<sitename>"; //TODO: change to valid site URL

string sContentSourceDisplayName = "My Content Source"; //TODO: change

string sSourceGroupName = "My Source Group"; //TODO: change

 

TopologyManager oTopology = new TopologyManager();

PortalContext oContext = PortalApplication.GetContext(oTopology.PortalSites[new System.Uri(sPortalURI)]);

 

SearchSite oSite = new SearchSite();

 

oSite.Connect(sIndexDNS, oContext.SiteId.ToString());

 

Microsoft.SharePoint.Portal.Admin.Search.SearchCatalog oCatalog = oSite.GetCatalog("Non_Portal_Content");

 

Microsoft.SharePoint.Portal.Admin.Search.SearchContentSource oSource = oCatalog.AddContentSource(sContentSourceURI,

sSourceGroupName,

0,

5,

true,

null,

null);

 

oSource.DisplayName = sContentSourceDisplayName;

 

oCatalog.StartCrawlFrom(sContentSourceURI, SearchCatalog.CrawlType.FullCrawl);

==

 

This sample adds a new Content Source restricted to an individual WSS Site to the Non_Portal_Content catalog/index, and immediately begins a crawl of the new source.

 

Lastly, we'll need to create the MSSQLFT syntax that will allow us to restrict our searches to the newly-created Content Source.  Submitting searches with the QueryProvider or with the Search.asmx Web Service are also fairly well-documented, so I won't bother going over those steps, but here's a link:

 

Query Service

https://msdn.microsoft.com/library/en-us/spptsdk/html/cSPSQueryService.asp?frame=true

 

QueryProvider Class

https://msdn.microsoft.com/library/en-us/spptsdk/html/cQueryProvider.asp?frame=true

 

[NOTE that the QueryProvider class is not supported for use outside of an ASP.NET environment (e.g. Windows Applications).]

 

The syntax just requires adding a bit to the WHERE clause in order to restrict the search properly.  Here's a very very simple example:

 

=====

select

"urn:schemas.microsoft.com:fulltextqueryinfo:sdid", "DAV:displayname",

"DAV:href"

from

(TABLE Portal_Content..Scope() UNION ALL TABLE Non_Portal_Content..Scope())

where

((("urn:schemas.microsoft.com:fulltextqueryinfo:displaytitle" LIKE 'Microsoft%'))) AND ((("urn:schemas.microsoft.com:fulltextqueryinfo:sourcegroup" LIKE 'My New Source Group')))

=====

 

Where "My New Source Group" is the name of the newly-created source group, and "Microsoft" is the display title for which we are searching.

 

With all this done, we should be able to create an application like mentioned above, and automate much of the tasks that would otherwise require someone to manually create sites and content sources through the UI.  This topic may not have immediate utility, but -- hopefully -- it does provide some insight into some of the automation-type tasks and various applications that can be created using the SharePoint APIs and Web Services.

 

-R