Custom Search and URL zones
It's a very common task with SharePoint to create a custom Search web part. The objective ranges from the very intuitive – need to change the search results display - to the very complex perform some complex queries that are not possible Out of the Box. For a large part, customizing the search behavior in Microsoft Office SharePoint Server 2007 is very similar to how it was done in SharePoint Portal Server 2003. The major difference however is how the Search behaves. Since a great deal of time and energy has been spent in completely rewriting the underlying search engine, the results are very obvious. If you have not yet seen the MOSS search behavior, I will suffice it to say that it's pretty close to SharePoint 2003 search on steroids.
For a large part, here's how a typical custom search would look like:
referencing Microsoft.Office.Server.Search and Microsoft.SharePoint.Search depending on whether its OSS or WSS.
//typical initalisation
Microsoft.Office.Server.Search.Query.Query query;
query = new Microsoft.Office.Server.Search.Query.FullTextSqlQuery(ServerContext.Current);
Microsoft.Office.Server.Search.Query.ResultTableCollection rsltTableColl;
//set some properties for the FullTextSqlQuery instance
query.ResultTypes |= Microsoft.Office.Server.Search.Query.ResultType.RelevantResultsl;
query.QueryText = "some query";
//and then execute the query
query.Execute();
This is a typical lab scenario. But something interesting happens when you execute this on an actual farm deployment. Consider a deployment architecture as follows:
You have web application on port 80 as contoso.com. So the root site collection on that web application will be https://contoso.com. Contoso decides that they want to expose the same web application on the intranet, extranet as well as internet zones. So the admin goes ahead and creates extended web applications on port 80 for different URL zones.
So now you have
contoso.com on the default zone
contoso-intra.com on the intranet zone
contoso-extra.com on the extranet zone.
Note that the root site collections will now be identified as
https://contoso.com
https://contoso-intra.com
https://contoso-extra.com
respectively.
Since it's an extended web application, the content is the same across all URL's though the URL's accessed would be different for each. The implicit advantage this offers is the ability to expose the same content to different sets of users that are authenticated using different authentication mechanisms. Now consider say that the custom search web part that you created earlier is deployed in such a scenario.
When a user fires a query on this custom query part, the query executes etc. No problems at all there. But look closer. If you hover over the hyperlinks for the individual items in the search results the URL's will actually be pointing to the URL corresponding to the default URL zone. This is not such a cool thing, since the user on the extranet does not need to know, what the actual content URL is.
Now, just to cover all bases, execute a similar query from the Search box that ships with SharePoint. Irrespective of the zone you are browsing from, the URL's for the search result items are properly structured. What is it that SharePoint is doing but we are not in our code?
PSS actually received a couple of calls on how to get past this seeming bug. For one, there are no articles online or even in the SDK at the moment that explain how this can be done. The answer popped up from a relatively uncanny place – how, SharePoint implements Search.
Solution: Internally, there is a seemingly incongruous property that's being set to get past this weird problem. Now, for the record, the SDK does not glorify this property at all and if you use your favorite web search engine, there would be just a couple of lines describing what this does.
//typical initalisation
Microsoft.Office.Server.Search.Query.Query query;
query = new Microsoft.Office.Server.Search.Query.FullTextSqlQuery(ServerContext.Current);
Microsoft.Office.Server.Search.Query.ResultTableCollection rsltTableColl;
//set some properties for the FullTextSqlQuery instance
query.ResultTypes |= Microsoft.Office.Server.Search.Query.ResultType.RelevantResultsl;
query.QueryText = "some query";
SPSite site = SPControl.GetContextSite(HTTPContext.Current);
query.SiteContext = new Uri(site.Url);
//and then execute the query
query.Execute();
What is this doing? In essence it fetches the current site context from the HTTPContext and then specifies that the query executes under that specific context.
Solution delivered and issue resolved.
~harsh