Silverlight Reporting Support for SSRS reports – Problem and Possible solutions

November 25, 2009

After a long break, working on setting up things with the new company, I am back to blogging and would be involved looking into Silverlight development, Sharepoint and general Business problems which I encounter with my new venture.

I was working on a project a few days before and got to implement reporting support in Silverlight 3 project which doesn’t support Reporting natively or doesnt provides a control similar to ASP.NET ReportViewer Control. In this post we will look into the how we can work around this problem with the best possible solutions available for Silverlight 3.

If you try looking around for solution you will find a solution provided by Perpetuum Software They have offered a solution but due to two things I didnt go for it – 1) The print quality was not good for me 2) Its obviously costing some bucks 🙂

So, I tried to find how can we workaround it in a free way and leveraging the Microsoft ReportViewer Control itself. So, what we can do is we can have ASP.NET report viewer being used by our application being called by Silverlight app, which is being hosted on a ASP.NET page itself. So, from the Silverlight app when a button is clicked or some event occurs we can cause a pop-up to show the report viewer using some javascript etc.

There are 3 possible solutions which a user can go:
1) Use of pop-up window, which is called by an Event in Silverlight app and ASP.NET report viewer is being used as it is in the pop-up window. The Report customization is part of your report development.
The major issue here is pop-up blockers which by default comes with major browser and hence your pop-up would be blocked mostly causing a bad user experience. Good part is the solution works and presents you with the report.

2) Use of iframe on the same page where Silverlight app is also hosted. The iframe is hidden initially and based on the Silverlight Event this iFrame is made visible and hence we see the report inside an iframe.
Good part is it gives a good user experience and the report viewer looks continous and part of application.

3) Use some third party control like Telerik or so and they have HtmlPlaceholder Silverlight control which can be used to provide with the url of Report and it takes care of setting iFrame and writing the javascript for you to make it cross browser compliant. This approach also essentially uses the iframe way to show the reports.

Let’s look into some code snippet below which uses the iFrame way (2 approach as stated above) so that you can use them in your app if you are working out with this problem or scenario:

1) Default.aspx where the Silverlight object is hosted and iframe added by us:
(I have used inline styling for demo here but you should be using proper styling)

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="abc.Web._Default" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "">
<html xmlns="" >
<head id="Head1" runat="server">
    <style type="text/css">
    html, body {
	    height: 100%;
	    overflow: auto;
    body {
	    padding: 0;
	    margin: 0;
    #silverlightControlHost {
	    height: 100%;
    <script type="text/javascript" src="Silverlight.js"></script>
    <script type="text/javascript">
        function onSilverlightError(sender, args) {
            var appSource = "";
            if (sender != null && sender != 0) {
              appSource = sender.getHost().Source;
            var errorType = args.ErrorType;
            var iErrorCode = args.ErrorCode;

            if (errorType == "ImageError" || errorType == "MediaError") {

            var errMsg = "Unhandled Error in Silverlight Application " +  appSource + "\n" ;

            errMsg += "Code: "+ iErrorCode + "    \n";
            errMsg += "Category: " + errorType + "       \n";
            errMsg += "Message: " + args.ErrorMessage + "     \n";

            if (errorType == "ParserError") {
                errMsg += "File: " + args.xamlFile + "     \n";
                errMsg += "Line: " + args.lineNumber + "     \n";
                errMsg += "Position: " + args.charPosition + "     \n";
            else if (errorType == "RuntimeError") {           
                if (args.lineNumber != 0) {
                    errMsg += "Line: " + args.lineNumber + "     \n";
                    errMsg += "Position: " +  args.charPosition + "     \n";
                errMsg += "MethodName: " + args.methodName + "     \n";

            throw new Error(errMsg);
<body style="background-colr:black;">
    <form id="form1" runat="server" style="height:100%">
    <div id="silverlightControlHost">
        <object data="data:application/x-silverlight-2," type="application/x-silverlight-2" width="100%" height="950">
		  <param name="source" value="ClientBin/abc.xap"/>
		  <param name="onError" value="onSilverlightError" />
		  <param name="background" value="white" />
		  <param name="minRuntimeVersion" value="3.0.40624.0" />
		  <param name="autoUpgrade" value="true" />
                  <strong><param value="true" name="windowless" /></strong>
		  <a href="" style="text-decoration:none">
 			  <img src="" alt="Get Microsoft Silverlight" style="border-style:none"/>
	    </object><iframe id="_sl_historyFrame" style="visibility:hidden;height:0px;width:0px;border:0px"></iframe></div>
        <div id="divReport" style="margin: 5% auto 0pt 18%; position: relative; z-index: 5; background-color: white; opacity: 1; float: left;">
         <iframe style="border: medium none ; margin: 0pt auto; z-index: 10; display:none;" id="_report"></iframe>

Here we can see that we are using a iframe which has a style of display:none which hides the iframe when the application loads.

2) In your Silverlight app. Create a button and bind an Event handler to it. In the event handler you can use the below code:

private void Btn_Click(object sender, System.Windows.RoutedEventArgs e)
            Uri sourceUri = new Uri(HtmlPage.Document.DocumentUri, Application.Current.Host.Source.ToString().Substring(0, Application.Current.Host.Source.ToString().IndexOf("ClientBin") - 1) + "/ReportViewerPage.aspx?ReportName=Report1&Client=L1");

            string wid = ContentStackPanel.ActualHeight.ToString();
            string hei = ContentStackPanel.ActualWidth.ToString();

            HtmlPage.Document.GetElementById("_report").SetStyleAttribute("display", "");
            HtmlPage.Document.GetElementById("_report").SetProperty("height", hei);
            HtmlPage.Document.GetElementById("_report").SetProperty("width", wid);
            HtmlPage.Document.GetElementById("_report").SetAttribute("src", sourceUri.ToString());
            //Above code will make the iframe solution work

            //Below code is for using pop-up window. So you can comment the code if you are only using iframe
            if (true == HtmlPage.IsPopupWindowAllowed)
                System.Text.StringBuilder codeToRun = new System.Text.StringBuilder();
                codeToRun.Append("width=" + wid + ",height=" + hei);                
                    MessageBox.Show("You must enable popups to view reports.  Safari browser is not supported.", "Error", MessageBoxButton.OK);
                MessageBox.Show("You must enable popups to view reports.  Safari browser is not supported.", "Error", MessageBoxButton.OK);

In this code we are making the src component of iframe which is a aspx page in the project called ReportViewerPage.aspx and use some query string parameters to pass the report name and parameters.

The iframe style property is changed and its height and width is set to the container above which it has to be shown and then using the windowless param of Silverlight object and CSS of setting position and z-index we can have our iframe show on top of Silverlight giving the user and impression that the reportviewer is part of Silverlight app itself.

3) ReportViewerPage.aspx

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="ReportViewerPage.aspx.cs" Inherits="abc.Web.ReportViewerPage" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "">
<%@ Register Assembly="Microsoft.ReportViewer.WebForms, Version=, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"
    Namespace="Microsoft.Reporting.WebForms" TagPrefix="rsweb" %>
<html xmlns="" >
<head runat="server">
    <form id="form1" runat="server">
        <rsweb:ReportViewer ID="MainReportViewer" runat="server" 
            BackColor="White" >
            <ServerReport DisplayName="MainReport" ReportServerUrl="" />

4) ReportViewerPage.aspx.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using Microsoft.Reporting.WebForms;
using System.Configuration;

namespace abc.Web
    public partial class ReportViewerPage : System.Web.UI.Page
        protected void Page_Load(object sender, EventArgs e)
            MainReportViewer.ProcessingMode = ProcessingMode.Remote;
            MainReportViewer.ZoomMode = ZoomMode.Percent;
            MainReportViewer.ZoomPercent = 100;
            MainReportViewer.ServerReport.ReportPath = ConfigurationSettings.AppSettings["ReportPath"] + this.Request.QueryString["ReportName"];
            MainReportViewer.ServerReport.ReportServerUrl = new Uri(ConfigurationSettings.AppSettings["ReportServerUrl"]);
            List parameters = new List();
            List values = new List();
            ReportParameter oneParamter = new ReportParameter("Client", values.ToArray());
            string apars = this.Request.QueryString["Apar_Id"];
            values = apars.Split(new[] { "," }, StringSplitOptions.None).ToList();
            ReportParameter twoParamter = new ReportParameter("Apar_Id", values.ToArray());

            MainReportViewer.ShowParameterPrompts = false;

This page reads the parameter passed by iframe src property and then parses the query string to make a Report Server call. The parameters are passed using Report parameter and if your report is set to take parameters then these parameters would be used to show the report in the Report Viewer.

You need to provide ReportServer url like http://localhost/ReportServer and ReportPath like “/FirstReport/” which will be appended by specific report name send by the Silverlight app. So finally it should look something like – http://localhost/ReportServer/FirstReport/MyReport

You need to prepare a report for the above to work and have it hosted on your server (localhost or external server) and then point the add in this program to your server.

This overall is a simple way to get the SSRS Report being shown in a ASP.NET along with Silverlight app hosted but giving the impression that Reporting support is part of Silverlight app itself.

I Hope this will solve your problems if you are working on this scenario. Write back if you find any issues or clarification regarding any code.

I have a working solution with my and have tested the code with local and external report server and it works just fine.

Good day!!
bye for now.

Who am I what am I doing?

Who am I what am I doing?