We have a custom web part for our SharePoint 2007 farm that calls a very large report (lots of views and stored procs being called) that is used on hundreds of pages on team sites and MySites. We get notified that the server running Reporting Services gets slammed during the nights when a full crawl is active. When we looked at the logs we can see that the full crawl is requesting the pages with the report on it which initiates this resource-heavy report.
What we want to do is keep the report from being crawled.
Things I've already thought about are,
Using robots meta tag, e.g. <META NAME="ROBOTS" CONTENT="NOHTMLINDEX"/>
, but the web part doesn't have access to the <head>
element, right?
Using crawl rules would work if we didn't have so many pages with the web part on it and new ones get created all the time.
So, is there code to exclude pages the web part is on from being crawled/indexed? We will be moving to SharePoint 2010 so the solution needs to work there as well.
[UPDATE1]
I've tried add the "noindex" class to a DIV that wraps the web part but the content of the web part still shows up in searches. I can see the DIV when I view the HTML source so I know that part is working which leaves me with SharePoint 2007 must not be honoring the 'noindex' class. First attempt:
Panel noCrawlPanel = new Panel();
noCrawlPanel.ID="noindex";
noCrawlPanel.CssClass = "noindex";
ReportView.ServerReport.SetParameters(parameters);
noCrawlPanel.Controls.Add(ReportView);
this.Controls.Add(noCrawlPanel);
[UPDATE2] Another question about noindex pointed to an MSDN article on using class="noindex" in a DIV tag. It mentions that the "noindex" class only works for the DIV tag that contains it and any nested DIV tags will still be crawled. My problem is the Report Viewer creates it's own DIV like so:
<div id="ctl00_m_g_c0778131_60eb_4115_8ec6_24cbffe6fc34_noindex" class="noindex">
<div id="ctl00_m_g_c0778131_60eb_4115_8ec6_24cbffe6fc34_ctl00" onclick="if (document.getElementById('ctl00_m_g_c0778131_60eb_4115_8ec6_24cbffe6fc34_ctl00_ctl00') != null) document.getElementById('ctl00_m_g_c0778131_60eb_4115_8ec6_24cbffe6fc34_ctl00_ctl00').ParametersController.HideActiveDropDown();" onactivate="if (document.getElementById('ctl00_m_g_c0778131_60eb_4115_8ec6_24cbffe6fc34_ctl00_ctl00') != null) document.getElementById('ctl00_m_g_c0778131_60eb_4115_8ec6_24cbffe6fc34_ctl00_ctl00').ParametersController.HideActiveDropDown();" style="display:inline-block;">
and continues into even denser JavaScript. What I'm going to try is putting the "noindex" class directly on the ReportViewer control. Second attempt:
ReportView.CssClass = "noindex";
Assuming that the DIV above is the actual ReportViewer control and now a SharePoint wrapper, I don't need to worry about an existing value for the class. It did occur to me that this might work for DIV's that already have a CSS class:
ReportView.CssClass += " noindex";
[UPDATE3] Here is what I am using now. It is based on the code from this blog post by Scott Tindall which I found in one the answers.
protected override void CreateChildControls()
{
string userAgent = this.Context.Request.UserAgent;
if (userAgent.ToLower().Contains("ms search"))
{
LOG.LogInfo("Page requested by search crawler, removing ReportViewer");
this.Controls.Add(new LiteralControl("Report not available to be crawled for performance reasons - PXD001"));
return;
}
... <normal web part code here>
}
I added the literal text to provide something to test against. If the crawler requests the page then the term 'PXD001' would be easily searchable to prove that the page did get indexed while the report contents did not.
I hard coded the user agent because I doubt Microsoft will change that without going to a new version of SharePoint. It might not work for SharePoint 2010, I still need to test it there. If it changes or we need to support multiple variations, I'll just move it to the web config at that point.