Showing posts with label Search. Show all posts
Showing posts with label Search. Show all posts

Friday, 17 February 2012

Search result URLs not correctly mapped to the current zone when the content is crawled in a different farm

This one is just a nice-to-know. I didn't know about this setting, so I'll briefly document it here for future reference.

Situation
The set-up consists of a typical enterprise services farm (http://technet.microsoft.com/en-us/library/cc560988.aspx#Enterprise):

  • Farm A hosts the collaboration web-applications, in which the users upload their documents and other content.
  • Farm B is a remote services farm and hosts the cross-farm service applications. This includes all of our search service application(s). These service applications are published and then consumed on Farm A. 
Farm B crawls farm A using the web-application's default zone url, e.g. http://sps2010. When a user performs a search in farm A on the default zone, all of his search results link back to the default zone. So far so good.

The problem
Now lets say we add a new Intranet AAM zone on farm A's web-applications, which points to http://sps2010intra. When a user performs a search from that zone, all of his search results will again refer to the default zone!

The explanation
This is actually pretty logical: the content is crawled on farm B, using the default zone's URL.
In a single farm setup, the search service application will have access to the crawled web-application's alternate access mappings and will take those into account when a query is done on the crawled content.
Here however, the search service application is hosted on a different farm (farm B) and that search service application doesn't know how the alternate access mapping is set up on farm A!

The solution
When you google this problem, you will get a lot of posts saying that you need to use the Server Name Mapping setting on your search service application. There's a good overview of this setting here.

Personally I would not recommend using that approach, as it only works for one AAM zone.  There's no way to map multiple zones (intranet AND internet for instance) using the server name mapping route.

A much more flexible solution is to mimic the crawled content farm's alternate access mappings on the remote services farm. If you did set-up server name mappings to fix this: delete them and recrawl! ;)
  1. Open the central admin site on your remote services farm (farm B).
  2. Click on Application Management and select Configure alternate access mappings (in the web applications section).
  3. Now click on Map to external resource in the toolbar. This little bugger allows you to create an alternate access mapping for resources that aren't in the farm.
  4. Give it a meaningful name, like Collab {Name of the crawled webApp}. Enter the crawled web-application's default zone URL in the URL protocol, host and port field.
  5. Click on Save to create the external resource AAM. Now you can set this resource up as if it were a web-application on your remote services farm!
  6. Use Edit Public URLs and Add Internal URLs to configure the external resource's AAM just like it is set up on your crawled farm (farm A).
That's it ... no need to recrawl or anything. If all was done well, search results on the content farm (Farm A) will now be correctly translated according to their zone, even while the content was indexed on another farm.





SP2010 - Search Crawl not working on remote services farm


A quick post on two issues I've encountered lately. Both are related to SharePoint 2010 Search crawls that suddenly stopped working.
I'm just going to post the symptoms and what worked as solution for me.

The SharePoint set-up consists of two farms:
  • Farm A hosts the collaboration web-applications, in which the users upload their documents
  • Farm B hosts most of the service applications, including the search service application(s). These search service applications crawl content from Farm A. Furthermore, these service applications are consumed on Farm A (so people on that farm can search the crawled content).

Issue #1
The crawl log was filled with the following errors when crawling farm A:
The SharePoint item being crawled returned an error when requesting data from the web service. ( Error from SharePoint site: Value does not fall within the expected range. ).

Solution
Apparently there was an issue with the web-apps that were being crawled. In order to get them crawled again, I
  1. Detached the content databases linked to the web-apps on farm A
  2. Removed the web-app (make sure to delete the related IIS site)
  3. Recreate the web-app
  4. Attach the old content db again
Simple as that.

Issue #2
Some weeks later, my crawl log got filled with this lovely message:
The SharePoint item being crawled returned an error when requesting the data from the web service. ( Error from SharePoint site: *** Could not find part of the path 'c:\TEMP\gthrsvc_OSearch14\{random-text}.tmp' 

Solution
Despite the error, that path was indeed present on all my machines in farm B. I tried fiddling with the permissions on that folder, but nothing helped.

In the end I just:
  1. Removed the consumed search service applications on farm A.
  2. Removed the search service application(s) on farm B
  3. Recreated the search service application(s) on farm B. Luckily for me, I had already scripted this procedure in PowerShell.
  4. Publishd the service apps again on farm B and consume them on farm A.
  5. Recrawled all content
Conclusion: if some part of SharePoint is fucked up, you can usually fix it by removing & recreating it :)

Thursday, 17 March 2011

"This Site" search scope in an anonymous, publicly available site

It's been a while, but I finally encountered a little SharePoint 2007 issue that wasn't properly solved before on these internets :)

Scenario
The setup consists of a MOSS 2007 publishing site, that is publicly available to anonymous users. The site itself has activated the LockDown feature, preventing anonymous users from viewing SharePoint application & admin pages.
Furthermore, the publishing site has a Search Center set up, which is used to display the search results.
Pretty basic setup if you ask me.

Problem
As you would've guessed by the title, the problem lies in the This Site contextual search scope.

Scope dropdown on default search control

Searches on the custom All Sites scope were no problem, those were displayed in a nice results overview in the search center.
But if an anonymous user launched a query on that contextual This Site: ... scope, he would receive a login-prompt. Not quite the functionality you want to see on a public-facing site.

Cause
The cause has already been mentioned in this post. Apparently the default search control uses 2 different URLs to display its search results:
  • Custom scope queries (the ones you manage in site collection admin pages) are redirected to the search center's results pages.
  • Contextual scope queries (like This Site) are redirected to /_layouts/OSSSearchResults.aspx, regardless of the search center settings.

Unfortunately, thanks to the lockdown feature, the /_layouts/OSSSearchResults.aspx page will be blocked for anonymous users ... resulting in a login prompt when a user launches a query on a contextual scope.

Solution
I wouldn't write this post if there was an easy solution :)
Some blogs have already covered some possible workarounds to this, but I wasn't satisfied with their solutions: some involved modifying out-of-the-box SharePoint pages (blasphemy!) or writing a custom search control from scratch.

I went for a workaround based on .NET reflection.
I admit it, it's not that kosher, but at least this approach left most of the original search box's functionality untouched + it's a lot less work than writing a control from scratch.
The following code will subclass the default searchbox and overwrite the contextual scope's result-page URL with the value set in the public SearchResultPageURL property. This will ensure that any query (on both custom and contextual scope) will be redirected to the same page: the search center's results page.

/// 
/// Customized SearchBox that will override the contextual scope's result page
/// (/_layouts/OSSSearchResults.aspx?k=test&cs=This%20Site&...) with the URL 
/// defined in the SearchResultPageURL property.
/// 
public class SearchBox : SearchBoxEx
{
 protected override void CreateChildControls()
 {
  base.CreateChildControls();

  try
  {
   FieldInfo[] fields = typeof(SearchBoxEx).GetFields(BindingFlags.NonPublic | BindingFlags.Instance);
   FieldInfo ossSearchResultField = null;
   int i = 0;
   while (ossSearchResultField == null && i < fields.Length)
   {
    if (fields[i].Name.Equals("m_strOssSearchResultsUrl", StringComparison.InvariantCultureIgnoreCase))
    {
     ossSearchResultField = fields[i];
    }
    i++;
   }

   // Field found -> set its value to the search center's URL
   if (ossSearchResultField != null && !string.IsNullOrEmpty(SearchResultPageURL))
   {
    ossSearchResultField.SetValue(this, SearchResultPageURL);
   }
  }
  catch (Exception ex)
  {
   // Do some logging
  }
 }
}
Just add this control to your masterpage instead of the default search control and you'll be able to use contextual scopes in a public-facing, anonymous SharePoint publishing site without getting login-prompts.
Or just use it if you want to make sure that all search results are displayed using the same results page.
<CustomControls:SearchBox ID="SearchBox" 
  RegisterStyles="false" 
  TextBeforeDropDown="..." 
  TextBeforeTextBox="..."
  TextBoxWidth="100"
  UseSiteDefaults="true" 
  DropDownModeEx="ShowDD" 
  SuppressWebPartChrome="true"
  runat="server" />