Friday, September 17, 2010

Using custom URL with Microsoft SQL Server Reporting Services

Last week we were faced to following problem: the customer uses SSRS on a server. The SSRS are installed in the server’s root (as by default): http://server.domain.tld/ReportServer. On the same server runs another custom solution under http://server.domain.tld/CustomSolution. The security regulations restrict browsing access to the root folders of the web sites: only URLs starting with http://server.domain.tld/CustomSolution are permitted, all others (also the SSRS URL is blocked from browsing on the workstations). The goal is to let the users load and see the SSRS reports.

The first idea was to configure the default SSRS URLs using SSRS configuration tool or modifying rsreportserver.config manually – as described in http://msdn.microsoft.com/en-us/library/bb677364.aspx. So we tried to configure SSRS to run in http://server.domain.tld/CustomSolution/ReportServer. It didn’t work because there’s a collision between ASP.NET and SSRS http handlers: both are trying to process the request, but ASP.NET by default wins.

Since the URLs with root folder other than CustomSolution are blocked only on the workstations and not on the servers, we decided to implement following solution:

  • add a new aspx WebForm containing just ReportViewer WebControl – ReportViewerPage.aspx;
  • initialize the ReportViewer WebControl with ReportServer URL and Report Path on page load;
  • put this WebForm under the permitted URL (for example, http://server.domain.tld/CustomSolution/Reports/ReportViewerPage.aspx).

…and it works!

Solution steps

  1. Create a WebForm ReportViewerPage.aspx (source below).
    This form contains ReportViewer WebControl, which is initialized in OnLoad() method. The two request parameters: “report” and “reportServer” are used to initialize the ReportViewer WebControl’s parameters ReportPath and ReportServerUrl respectively.
  2. Put this form under an unblocked path (for example, http://server.domain.tld/CustomSolution/ReportServer/ReportViewerPage.aspx);
  3. Add following line to <httpHanlders> section of your web.config:

    <add verb="*" path="Reserved.ReportViewerWebControl.axd" type = "Microsoft.Reporting.WebForms.HttpHandler, Microsoft.ReportViewer.WebForms, Version=8.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />

    ATTENTION: .NET 4.0/SQL 2008 R2 may have to change Version from 8.0.0.0 to 10.0.0.0 – both in web.config and .aspx file!
  4. Browse the reports using ReportViewerPage.aspx: specify report path and report server URL in the request as follows:

    http://server.domain.tld/CustomSolution/ReportServer/ReportViewerPage.aspx?report=%2fCustomeReports%2fReport1&reportServer=http:%2f%2fserver.domain.tld%2fReportServer

    Be aware to replace all the slashes ‘/’ in the URL with %2f and …enjoy!

image

ReportViewerPage.aspx:

<%@ Page Language="C#" AutoEventWireup="true" %>
<%@ Register Assembly="Microsoft.ReportViewer.WebForms, Version=8.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" Namespace="Microsoft.Reporting.WebForms" TagPrefix="rsweb" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<script runat="server">
    protected override void  OnLoad(EventArgs e)
    {
        if (!IsPostBack)
        {
            if (Request["report"] != null)
            {
                // set report path
                this.ReportViewer.ServerReport.ReportPath = Request["report"];
            }
            if (Request["reportServer"] != null)
            {
                // set report server URL
                this.ReportViewer.ServerReport.ReportServerUrl = new Uri(Request["reportServer"]);
            }
        }
        base.OnLoad(e);
    }
</script>

<html xmlns="http://www.w3.org/1999/xhtml">’
<head runat="server">
    <title>ReportViewer</title> 
</head>
<body>
<form id="form1" runat="server">
<!--  mb: required for ReportViewer usage -->
<asp:ScriptManager ID="ScriptManager" runat="server">’
</asp:ScriptManager>
<div>
<!-- mb: ReportViewer WebControl itself -->
<rsweb:ReportViewer ID="ReportViewer" runat="server" ProcessingMode="Remote" Width="2200px" Height="1000px">
</rsweb:ReportViewer>
</div>
</form>
</body>
</html>

No comments: