Upgrading RDLC reports to Report Viewer 2010 in an ASP.NET web application
One of the web applications I am working on is an ASP.NET MVC 2 site targeting .NET 3.5 SP1 that uses the Microsoft Report Viewer control with local-mode RDLC reports. I initially developed this application using Visual Studio 2008. The client was OK if I started to use Visual Studio 2010, as long as I didn’t require .NET 4.0 just yet. The multi-targeting features of VS2010 were working great. I had started really enjoying VS 2010 and had no intention to go back to 2008. Then I needed to do some report work so I double clicked one of my RDLC files and was surprised to see this message box:
Microsoft Visual Studio
---------------------------
Microsoft Report DesignerDo you want to convert this report to RDLC 2008 format? Please click OK to proceed or Cancel to open it in the XML editor.
My heart sunk and my blood ran cold. What have I done? I was afraid I would need to go back to VS 2008 just to keep the reports compatible with .NET 3.5! Fortunately, converting to the new Report Viewer control turned out to be OK (so far), but there were some surprises along the way.
It’s all good (mostly)
There are lots of nice new ajax, visual, and internal things about the new control but two of the highlights for me were:
- Compatible with .NET 3.5 SP1 and .NET 4.0
- Looks better in more browsers
- Rendering is simplified and more standards compliant. I was able to put the strict DOCTYPE back in the page and (eventually) get resizing to work. More on resizing later.
Upgrading
The upgrading process was pretty straightforward.
- Install the Report Viewer 2010 Redistributable (This will need to be installed on any server to which you deploy).
- Convert RDLC files to new RDL 2008 schema. Simply opening the RDLC in Visual Studio 2010 converts to the new schema and automatically makes a backup.
- Change assembly reference to the new 10.0.0.0 version of Microsoft.ReportViewer.WebForms.dll
- Change version number in assembly names in web.config
- You’ll see things in web.config that look similar to the following, make sure the version is 10.0.0.0
Microsoft.ReportViewer.WebForms, Version=10.0.0.0, Culture=neutral, PublicKeyToken=B03F5F7F11D50A3A
- You’ll see things in web.config that look similar to the following, make sure the version is 10.0.0.0
- Change version number in any *.aspx pages that include the report viewer control registration
- <%@ Register Assembly="Microsoft.ReportViewer.WebForms, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"
Namespace="Microsoft.Reporting.WebForms" TagPrefix="rsweb" %>
- <%@ Register Assembly="Microsoft.ReportViewer.WebForms, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"
- Include a ScriptManager on any *.aspx page that has a ReportViewer, or if you have a common master page that your reports share like I did, you can put it there, once for all.
- <asp:ScriptManager ID="ScriptManager1" runat="server">
</asp:ScriptManager>
- <asp:ScriptManager ID="ScriptManager1" runat="server">
Some surprises that required rework
- The data sets must be flat. In some of my reports I took advantage of the fact that in the previous Report Viewer you could refer to properties of child objects. You used to be able to do this:
=Fields!ChildObject.Value.ChildProperty
Now the data set need to be flat. This means that I needed to flatten out my domain objects by pulling properties from the child objects up to the parent object. This could have been a big problem, but luckily the way I had structured my code allowed me to fairly easily define a flat report object and bind to that instead. - Getting the report to fill the browser with 100% height and resize dynamically was trickier than I hoped. And this is the main reason I wanted to write this post.
Making the report viewer resize
I used the incredibly powerful jQuery.UI.Layout already in this site, so I just continued to use it on the report pages. The trick to getting the report control to resize properly in my case was to find the report viewer control and call recalculateLayout() whenever the browser was resized. This happens on line 22 in the code below:
1: <%@ Page Language="C#" %>
2: <%@ Register Assembly="Microsoft.ReportViewer.WebForms, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"
3: Namespace="Microsoft.Reporting.WebForms" TagPrefix="rsweb" %>
4: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
5: <html xmlns="http://www.w3.org/1999/xhtml">
6: <head>
7: <title>Sample Report</title>
8: <script type="text/javascript" src="../../Scripts/jquery-1.4.2.min.js" ></script>
8: <script type="text/javascript" src="../../Scripts/jquery.layout.js" ></script>
10: <script type="text/javascript">
11: $(document).ready(function () {
12: $('body').layout({
13: north__paneSelector: "#HeadingPane",
14: center__paneSelector: "#ContentPane",
15: resizable: false,
16: closable: false,
17: north__size: 20,
18: spacing_open: 0,
19: spacing_closed: 0,
20: center__onresize: function () {
21: var reportViewer = $find("ReportViewer");
22: reportViewer.recalculateLayout();
23: }
24: });
25: });
26: </script>
27: </head>
28:
29: <body>
30: <form id="form1" runat="server">
31: <asp:ScriptManager ID="ScriptManager1" runat="server">
32: </asp:ScriptManager>
33:
34: <div id="HeadingPane">
35: Page header content like site navigation goes here
36: </div>
37:
38: <div id="ContentPane">
39:
40: <asp:ObjectDataSource ID="SampleDataSource" runat="server" SelectMethod="GetSampleData"
41: TypeName="MyApp.Reports.ReportDataSource">
42: </asp:ObjectDataSource>
43:
44: <rsweb:ReportViewer ID="ReportViewer" runat="server" Font-Names="Verdana"
45: Font-Size="8pt" Height="100%" Width="100%" ShowBackButton="false">
46: <LocalReport ReportPath="SampleReport.rdlc">
47: <DataSources>
48: <rsweb:ReportDataSource DataSourceId="SampleDataSource" Name="SampleData" />
49: </DataSources>
50: </LocalReport>
51: </rsweb:ReportViewer>
52:
53: </div>
54: </form>
55: </body>
56: </html>