Saturday, August 20, 2011

Customize ReportViewerWebPart in C# for all SharePoint Zones

This is one of the major milestone I have achieved recently to customize the report viewer web part for SharePoint sites. The issue I was facing: the SharePoint site which I have developed was too complex and it exposed via 3 zones. http://intranetsite, http://extranetsite, https://internetsite
  1. http://intranetsite – which is Windows based authentication site and for intranet people.
  2. http://extranetsite – Which is Windows based authentication site and for extranet people
  3. http://internetsite – Which is Forms based authentication site and for internet people.

For each sub site in our implementation it should show the SSRS dashboard report of the site we are in which will contains all information of the site through reports. But, SSRS reporting services and report viewer web part has a limitation in SharePoint integration mode:

System.Web.Services.Protocols.SoapException: The specified path refers to a SharePoint zone that is not supported. The default zone path must be used. ---> Microsoft.ReportingServices.Diagnostics.Utilities.SecurityZoneNotSupportedException: The specified path refers to a SharePoint zone that is not supported. The default zone path must be used.

For example, you have added a report viewer web part to a SharePoint page. And when you opened the site in any other zones other than default zone then you will see above exception. So, how to solve this problem??? No way without customizing the default ReportViewerWebPart. So, I chosen this method and the implementation I have done is working very well.

Implementation:
  1. Create a simple C# Project in Visual Studio to create a web part.
  2. The web part contains logic to render Report Viewer Web Part.
  3. The Report Viewer Web Part will take the default zone web url to render reports.
  4. Supply report parameters to the report viewer.
  5. Add any properties to the report viewer web part like toolbar mode, document map mode etc.
CODE:
public class CustomReportViewerWebPart : System.Web.UI.WebControls.WebParts.WebPart
{
#region Properties

#endregion // Properties

#region Constructors

public CustomReportViewerWebPart()
{
this.ExportMode = WebPartExportMode.All;
}

#endregion // Constructors

#region Privates

//-----------------------------------------------------------------
//Simple error handler for pre-render subs
//-----------------------------------------------------------------
private void HandleErrors(Exception ex)
{
Page.Response.Write(ex.ToString());
}

#endregion  // Privates

#region Overrides

//-----------------------------------------------------------------
//Render this Web Part to the output parameter specified.
//-----------------------------------------------------------------

protected override void CreateChildControls()
{
base.CreateChildControls();

try
{
ReportViewerWebPart wp = new ReportViewerWebPart();
this.ChromeType = wp.ChromeType = PartChromeType.None;
wp.PromptAreaMode = CollapsibleDisplayMode.Hidden;
wp.ToolBarMode = ToolBarDisplayMode.None;

string defaultZoneURL = ConfigurationManager.AppSettings["SharePoint_Default_Zone_URL"];
if (string.IsNullOrEmpty(defaultZoneURL))
defaultZoneURL = "http://defaultzoneurl";

string reportPath = ConfigurationManager.AppSettings["SP_Report_Path"];
if (string.IsNullOrEmpty(reportPath))
reportPath = "reportpath"; //If it is the same report everywhere then use it. Otherwise create a web part property. So that user can input report path and use it here.

string parameter1 = "parameter1 value"; 

if (!string.IsNullOrEmpty(defaultZoneURL))
{
if (defaultZoneURL.EndsWith("/"))
defaultZoneURL = defaultZoneURL.Trim('/');

wp.ReportPath = string.Format("{0}{1}", defaultZoneURL, reportPath);

ReportParameterDefaultCollection parame = wp.OverrideParameters;
parame.Add(new ReportParameter("Parameter1", parameter1)); //Add all report parameters here.
Height = Unit.Pixel(1000);
wp.Height = Height.ToString(); //If you are using single report everywhere then you can hard-coded the height property. Otherwise leave it.

this.Controls.Add(wp);
}
}
catch (Exception ex)
{
Literal litMsg = new Literal();
litMsg.Text = "There is some problem in rendering the dashboard report. Please try again later." + ex.Message;
this.Controls.Add(litMsg);
}
}        
#endregion //Overrides
}
I believe the above code is simple to understand and you got it. Please let me know if there are any issues in understanding or run this code. I am always here to help.

Conclusion:
With the above code, you can solve the problem of viewing the report in any zone not only other than "SharePoint default Zone".

Limitation:
As we are customizing the report viewer web part through code, we cannot make the webpart works for all reports. If there are one or two reports in your site and they are in use everywhere then this will be a perfect solution. So, I will work on doing this applying for all reports in couple of days and post in this blog.

Note:
The ReportViewerWebPart class will be reside in the namespace "Microsoft.ReportingServices.SharePoint.UI.WebParts" in the DLL "Microsoft.ReportingServices.SharePoint.UI.WebParts.DLL". The DLL will not be available directly through the file system. You have to get it from GAC. To get it, please follow my another post "How to get the files from GAC in Windows".

This will not be a problem in the new version of Sql Server. Sql Server 2008 R2 AAM has solved this problem. So, this solution will be helpful to the people who are still on earlier versions of 2008 R2. 

8 comments:

  1. Hi,
    i override the parameters as shown above.But one of my parameter is an array. The parameter gets overriden by the array value.
    However if the length of parameter goes above some value.the parameter value fails to override.
    Is there any limitation to the length of an array that can be passed to reportViewer webpart??
    Any help is appreciated.

    Thanks in advance

    ReplyDelete
  2. Hi,
    i override the parameters as shown above.But one of my parameter is an array. The parameter gets overriden by the array value.
    However if the length of parameter goes above some value.the parameter value fails to override.
    Is there any limitation to the length of an array that can be passed to reportViewer webpart??
    Any help is appreciated.

    Thanks in advance

    ReplyDelete
  3. Hi,
    i override the parameters as shown above.But one of my parameter is an array. The parameter gets overriden by the array value.
    However if the length of parameter goes above some value.the parameter value fails to override.
    Is there any limitation to the length of an array that can be passed to reportViewer webpart??
    Any help is appreciated.

    Thanks in advance

    ReplyDelete
  4. avobe code works when it is in the Method CreateChildControl...but want to set report path on Dropdown change and pass the selected value to report path...so i have created Visual web part and writing code on the dropdown change and adding Reportviewer to DIV.

    First time report load perfactoly but on secondt ime chnage of the dropdown it does not refresh and display old report.

    Please hep...Thank you

    ReplyDelete
  5. First, Dropdownlist control should enable option autopostback to true. And then in CreateChildControl you will place the code as is and in the drop down list change event the report viewer the report path and parameters should change to the new values and rebind the reportviewer control. This will reflect the changes. If not working please send me code and I will help you out to get it working. My email address is on the right side of the blog.

    -Praveen.

    ReplyDelete
  6. JJ and Praveen, could you please share the code how to show parameters pane at top of the report? Not at right-side of the report?

    ReplyDelete
  7. And......for anonymous users that want to use this webpart in ReportViewerCustom.aspx?name=report1

    How to say to the webpart the credentials use?

    Thanks

    ReplyDelete
  8. The extended custom web part does not inherit View properties from Reports Viewer. How can I inherit all toolpart properties from parent ReportsViewer web part?

    ReplyDelete