Thursday, March 4, 2010

ReportViewer control does not render appropriately on IIS7 websites

http://blogs.msdn.com/vijaysk/archive/2009/01/14/report-viewer-toolbar-does-not-render-properly-on-iis-7-0.aspx

In case the URL above stopped working, I thought it might be a good idea to copy its contents here.

I was recently working on a reporting web application that uses the Report Viewer ( ReportViewer ) control that ships with SQL Server Reporting Services (SSRS). The Report Viewer control was rendering perfectly when I was developing using Visual Studio 2008. The trouble started when I published the web application to an IIS 7.0 server. The Toolbar was completely broken and showed up something like this.




Initially it looked like just the images where missing. But the toolbar was completely broken. The toolbar of the Report Viewer control relies on images and JavaScript that are generated dynamically. It uses a call to the Reserved.ReportViewerWebControl.axd to dynamically generate the images and the JavaScript. Something like

GET /Reserved.ReportViewerWebControl.axd?OpType=Resource&Version=9.0.30729.1&Name=Microsoft.Reporting.WebForms.Icons.NextPage.gif HTTP/1.1

GET /Reserved.ReportViewerWebControl.axd?OpType=Resource&Version=9.0.30729.1&Name=Microsoft.Reporting.WebForms.Icons.LastPage.gif HTTP/1.1

When you use the Report Viewer Control Visual Studio edits your web.config to map a Http Handler to respond to these requests.






The above entry tells ASP.NET that whenever a call is made to ReportViewerWebControl.axd use the Microsoft.Reporting.WebForms.HttpHandler assembly to execute it.

This mapping is very important because if you remove it the web server will return a 404 “File Not Found” error code because the ReportViewerWebControl.axd does not exist physically on the server.

Strangely when I checked the IIS 7.0 logs for the broken scenario I found that all requests for ReportViewerWebControl.axd had failed with a 404.

With IIS 7.0 there was an architectural change. There were changes to the web.config structure as well. The section that was under the has now moved to under

Visual Studio had edited the web.config based on the IIS 6.0 model and had made an entry for the Http Handler under the section. With IIS 7.0 this section is no longer read. So we need to make the proper entries for the Http Handler that handles the calls to ReportViewerWebControl.axd






IIS 7.0 will now understand that whenever a call is made to ReportViewerWebControl.axd it needs to route it to the Http Handler Microsoft.Reporting.WebForms.HttpHandler

Notes : ConnectionString Checks ...

1. When you pull in the DB tables into a dbml file, the ConnectionString property under the Properties window of the dbml file gets set to/points to the DB whose tables you pulled into the dbml file.

2. So, what we need to do is always clear the ConnectionString property and set it to None.

3. The reason we need to always make sure that the ConnectionString property in the property pages of the .dbml file is set to None is as follows :

let us say, we created the dbml file off of Dev/Test DB tables, the connectionString will automatically get updated to point to DEV/Test. Now you keep working on your changes/updates in the code and when it is time to promote to live, all that you do is change the Web.Config file to point to Live DB (you have forgotten in the long process of making changes that you had created your dbml from a DEV/Test DB). But the ConnectionString of the dbml file is still pointing to DEV/TEST...This can lead to a lot of problems, which will show up in the form of data not showing appropriately/suitably for the front-end users, because what they are entering may be partly going into Live, partly into DEV, who knows where ..

To AVOID these issues always make sure you follow these steps to ensure that your dataSource is what it needs to be, both at the time of Testing and Promoting to LIVE :

Say you are promoting to LIVE :

a. Your dbml file should contain tables from the LIVE DB.
b. The ConnectionString property in the Property pages of the dbml file should be set to NONE.
c. Everywhere where it needs to be, the Web.Config should have the ConnectionString set to the LIVE DB.
d. Inside the source code you should be explicitly passing the DSN to any calls to the DataContext Class objects, defined in the dbml designer file. DataContext classes contain definitions of all the tables and fields inside the database.
In other words, do not use any parameterless DataContext class constructors -- pass to them the specific ConnectionString variable that you want your source code to point to.
e. before promoting, put a Breakpoint on one of the constructors of a DataContext class and check the value of the DSN/ConnectionString in the Watch window to make sure it is pointing to the right Database.

When DEPLOYING REPORTS (REPORTING SERVICES REPORTS TO THE REPORTS SERVER)

1. If there are going to be several reports based on the data in one common database, create a SHARED DATASOURCE. Make sure it points to the correct datasource. You may want to deploy this Shared dataSource to the report server.

2. Make sure that each report is pointing to this shared datasource or if each report has its own datasource, make sure it is pointing to the correct datasource (Test/DEV/Live) before deploying to the Report server.

3. Also, always go under Project Properties to make sure that you are pointing to the correct Report Server URL/address so when you deploy your reports, they get deployed on the correct Report server.