Programmatically Accessing ReportViewer Webpart through SPLimitedWebpartManager

Thursday, February 11, 2010

18

If you have many pages with SSRS ReportViewerWebparts, you'd probably want to create a feature to programmatically configure the webparts, then deploy the feature with a script.

But, if you try to activate the feature using STSADM, the ReportViewerWebparts will all show up in SPLimitedWebpartManager as ErrorWebparts. In our case, the ReportViewer webpart works fine through the UI, and other webparts on the page show up correctly in the webpart manager.

It turns out that when Sharepoint instantiates a ReportViewer, it tries to get the site URL and browser information from SPContext.Current. But, if you're not adding the webpart through the UI, SPContext.Current is null!

One workaround is to create a dummy SPConext. SPContext.Current is readonly, but it derives from HttpContext.Current, which we can create and populate with the minimum information required to instantiate a ReportViewer:

using(SPWeb web = site.OpenWeb())
{
  if (SPContext.Current == null && HttpContext.Current == null)
  {
    HttpRequest request = 
         new HttpRequest(String.Empty, web.Url, String.Empty);
    HttpResponse response = new HttpResponse(TextWriter.Null);

    HttpContext.Current = new HttpContext(request, response);

    HttpContext.Current.Request.Browser = new HttpBrowserCapabilities();
    HttpContext.Current.Request.Browser.Capabilities =
         new Dictionary();
    HttpContext.Current.Request.Browser.Capabilities["type"] = "IE7";
    HttpContext.Current.Request.Browser.Capabilities["majorversion"] = "7";
    HttpContext.Current.Request.Browser.Capabilities["minorversion"] = "0";
    HttpContext.Current.Items["HttpHandlerSPWeb"] = web;
  }
}

Once SPContext.Current is set, you should be able to get an instance of the ReportViewer webpart from the LimitedWebpartManager as normal:

using(SPLimitedWebPartManager manager =
   web.GetLimitedWebPartManager(pageUrl, PersonalizationScope.Shared))
{
  foreach (WebPart webPart in manager.WebParts)
  {
    Console.Out.WriteLine(webPart.Title);
    Console.Out.WriteLine(webPart.GetType().ToString());
  }
}

Finally, when done using the ReportViewerWebpart, be sure to set HttpContext.Current back to null before performing other operations.

Thanks to BlakeBlackShear's blog post on how to set SPContext.Current.