Quantcast
Channel: Brian Hartman's Report Viewer Blog
Viewing all 31 articles
Browse latest View live

Visual Studio 2010 SP1

$
0
0

Earlier this month, we released Visual Studio 2010 SP1.  The service pack is available for download from here and the updated Report Viewer redistributable can be found here.

We always prioritize our efforts based on feedback we receive through Connect as well as through the forums and other channels.  If you are running into problems with the product and believe you have encountered a bug, please file the issue at Connect so that we can investigate it.  We review those issues regularly and adjust our priorities accordingly.

This service pack contains a number of important fixes to the viewer runtime and design time components.  The list below is not an exhaustive list of fixes, but it does touch on the most common and visible issues that have been reported.

  • The most widely reported issue we have addressed is the use of nested objects in object data sources.  Attempting to reference nested objects in report expressions resulted in #Error.  I wrote about this problem previously.  This issue was fixed in the CTP for this release, though some customers continued to report the problem.  After investigating these instances, we discovered an additional requirement – in addition to requiring the objects to be serializable, this update also requires them to be public in order for the serializer to handle them correctly.
  • We have improved the rendering performance of the ASP.Net report viewer when rendering large HTML pages.
  • Data sets in subfolders of the VS project are now usable at design time.
  • Fixed a Visual Studio crash when using the Dataset Properties dialog in some projects that contained an edmx schema.
  • Fixed an issue in which a WinForms report viewer embedded in a WPF application resulted in an exception unloading an AppDomain while closing the application.
  • Fixed a problem in which some icons used in the calendar date picker for parameter prompts would not display.
  • Fixed an issue in which rendering a report would change the thread culture.
  • Fixed an HTML display problem with consolidated images (such as charts and gauges).
  • Fixed a GDI display problem with the WinForms report viewer that resulted in the page being displayed zoomed even at 100%.

AsyncRendering and all the Baggage that Comes With It

$
0
0

The AsyncRendering property on the ASP.Net ReportViewer control is one of the most misunderstood properties on the ReportViewer.  And that’s our fault.  There are a lot of side effects to setting this property that you wouldn’t expect from the name.  In fact, most of the time that I see users setting this property they are doing it for the side effects rather than for its true intention.  Those side effects are gone in Visual Studio 2010 because you can get the effects you want in either mode.  But to understand how things have changed, let’s first go through some background information.


The intention of AsyncRendering


Traditionally, the HTML of a web page is not sent to the browser until all of the web controls on the page have generated their content.  For controls such as text boxes and buttons, this makes perfect sense.  But the ReportViewer is much more complicated than that.  It can take the viewer a long time to generate the HTML for a report.  In most cases, it makes more sense to send the rest of the page back to the browser and then make another request to get the report content asynchronously.  This allows the user to interact with the rest of the page as well as see a “loading indicator” so that they know the server is doing something.  This is the default behavior – AsyncRendering = true.


But there are also cases where you want the block the entire page until the report is processed.  A good example is a dashboard type of page that is rendering several small reports, perhaps each one containing a single chart or small table.  In this case, you may not want the user to be bombarded with multiple wait indicators.  If you know the reports are quick to process, blocking the page for a short time may be a better overall experience.  This is the intention of AsyncRendering = false.


Asynchronous mode in Visual Studio 2005 and 2008


The mode you choose has a significant effect on the HTML that is ultimately generated.  The ReportViewer control was originally designed long before the appearance of ASP.Net AJAX.  When you render a report synchronously, the HTML for the report content is embedded directly in the entire page.  But when you render asynchronously, the ReportViewer uses a frame.  The frame content is retrieved by the browser separately from the main page, so it allows the main page to be visible while the report is generated in a separate request to the web server.


Frames are at the root of all of the side effects to AsyncRendering.  The use of frames results in the following differences between the two modes:



  • The document map is only visible in asynchronous mode, in part because it relies on frames to handle resizing relative to the report area.

  • Because the report is rendered in a frame and not part of the ASP.Net page that hosts the viewer, there is no chance for developers to handle events that occur while processing the report.  The most frequent complaint we receive in this area is the inability to handle the ReportError event when rendering asynchronously.

  • The size of the frame is difficult for the viewer to calculate and is therefore usually wrong.  It’s based on the sizing mode of the viewer (percentage or fixed size), the height of the toolbar, and the existence of parameters.  This is the leading cause to seeing an excessive number of scrollbars in the viewer, particularly when using standards mode or non-IE browsers.  Developers often switch to synchronous rendering to alleviate this.

  • Along a similar line to sizing of the frame is the fact that the SizeToReportContent property is ignored in asynchronous mode.  The frame does not adjust its size based on the content, so there is no easy way to show an arbitrary report embedded in a page without scrollbars, unless you switch to synchronous mode.

These side effects tend to rank higher in terms of requirements when building an application than whether the report shows up synchronously.  So it’s no surprise that these issues became the driving factor in which mode developers choose.

The Story in Visual Studio 2010


One of the biggest features of the ASP.Net ReportViewer in VS 2010 is the fact that it relies heavily on ASP.Net AJAX.  By default, the viewer will use asynchronous postbacks for all of its operations.  This means that we no longer need to rely on frames to retrieve report data asynchronously from the rest of the ASP.Net page.  With VS 2010, once a report has finished loading, the HTML displayed in the browser will be the same, regardless of whether you use synchronous or asynchronous rendering.


All of the previous side effects of AsyncRendering are now gone.  Both modes support the document map.  Both modes support the SizeToReportContent property.  Asynchronous postbacks are generally treated the same as traditional postbacks, so you can handle events that occur during report processing.  And because of the extensive work we’ve put into this release for standards mode HTML and Firefox and Safari rendering, you should never see double (or triple!) scrollbars in the viewer.


With VS 2010, AsyncRendering has returned to its true intention – it controls whether the initial processing of the report blocks the entire ASP.Net page, and nothing else.


 

Expression Evaluation in Local Mode

$
0
0

RDL and RDLC files contain expressions written in VB.Net.  As .Net code, expressions can potentially perform any operations, including accessing the file system or running native code.  Code access security (CAS) for expressions is therefore critically important.


When a report is deployed to a report server, the report definition goes through a publishing phase that extracts the expressions and compiles them into an assembly.  The assembly, often referred to as the expression host assembly, is then used when the report is executed to evaluate the expressions.  When using local mode, the same process happens in memory when a report definition is supplied to LocalReport.


Visual Studio 2005 and 2008


In Visual Studio 2005 and 2008, there are two ways to load the expression host assembly: into the current AppDomain or into a sandbox AppDomain.


Loading the expression host into the current AppDomain means that it is loaded into the same AppDomain in which the ReportViewer is running.  This has an advantage of improved performance as well as giving you more flexibility over the CAS policy.  Since you create the AppDomain in which the viewer runs, you can also grant a specific set of permissions to any external assemblies loaded by the expression host.  One clear disadvantage, however, is that the assembly will not be unloaded until the entire AppDomain is unloaded, typically when the application shuts down.  If you process lots of reports during in your application, the result is in an effective memory leak each time a new report is processed.  This may be ok for a short lived winforms application that displays a small number of reports, but it doesn’t make as much sense for an ASP.Net application.


Running in the current AppDomain is the default.  However, if you have switched to another mode, you can switch back using ExecuteReportInCurrentAppDomain.  If your report references external assemblies, the viewer will not load them unless you specifically allow it via AddTrustedCodeModuleInCurrentAppDomain.


The sandbox AppDomain is a more restrictive environment for evaluating expressions.  Any assembly loaded into the sandbox AppDomain is granted only Execution permission.  You can switch execution to the sandbox using ExecuteReportInSandboxAppDomain.  In theory, using a separate AppDomain prevents the memory leak.  However, due to the implementation of the sandbox AppDomain in the VS 2005 and 2008 report viewers, the sandbox AppDomain is not unloaded.


Visual Studio 2010


The ReportViewer in VS 2010 is a multi-targeted assembly.  That means that is can be loaded into a .Net 3.5 or a .Net 4.0 application.  When running under .Net 3.5, all of the same rules and methods noted above are applicable.  However, the CLR security team made changes to code access security in .Net 4.0, so there are corresponding changes in the ReportViewer as well:



  • Executing in the current AppDomain is no longer supported, so using a sandbox is the default mode when running in .Net 4.0.  Two new methods have been added to better control the permissions of the sandbox AppDomain so that you don’t see any loss of functionality:  AddFullTrustModuleInSandboxAppDomain and SetBasePermissionsForSandboxAppdomain.

  • ExecuteReportInCurrentAppDomain, AddTrustedCodeModuleInCurrentAppDomain, and ExecuteReportInSandboxAppDomain have been marked as obsolete.  While it is perfectly acceptable to use them in a .Net 3.5 application, they won’t have any effect when you compile for .Net 4.0.  Going forward, we recommend using the sandbox AppDomain even under .Net 3.5 because setting the correct security policy on the current AppDomain is an error prone task.  The new methods will work under both frameworks and is the best approach if you want to write in a framework agnostic way.

If you do nothing, the default behavior under .Net 4.0 will result in the same permissions for the expression host as the default behavior in VS 2008.  You will be running in a sandbox AppDomain (versus the default of the current AppDomain in VS 2008), but the permissions for the expression host will be the same.


As part of the security changes to the CLR in .Net 4.0, an application configuration flag, NetFx40_LegacySecurityPolicy, can be specified to use the .Net 3.5 security model in .Net 4.0.  If this flag is specified, the report viewer will behave just as it would under .Net 3.5, meaning that the obsolete methods will function correctly.


Regardless of which framework version you use with the VS 2010 report viewer, the issue surrounding the sandbox AppDomain leak has been fixed.  The sandbox AppDomain is shared resource across multiple instances of the viewer.  A new AppDomain is created periodically (if there is a need) and used by all local mode requests in the process.  Once all reports referencing the old AppDomain have completed, the old domain will unload.

We Need Your Help

$
0
0

The forums, Connect, and direct feedback through this blog and others have always helped shape Reporting Services.  We’re grateful for all of the input we’ve received.  But if you’re looking to make an even bigger contribution to the future of SQL Server Reporting Services, we have some great opportunities for you.  We’ve got some exciting ideas in the pipeline and we need your help to make them happen.  There are new positions open for testers in all of the Reporting Services component teams.  If you are interested in taking the next step in a challenging career, review the job postings below and contact us through the Microsoft careers site to see if we’re the right fit for you.


https://careers.microsoft.com/JobDetails.aspx?jid=12566


https://careers.microsoft.com/JobDetails.aspx?jid=12565


https://careers.microsoft.com/JobDetails.aspx?jid=13048


https://careers.microsoft.com/JobDetails.aspx?jid=12043

Reports Never Stop Loading With VS 2010

$
0
0

I’ve received a number of questions from people who have run into problems after upgrading their web application from VS 2008 to VS 2010.  Once upgraded, the report viewer shows the loading indicator indefinitely – the report never loads.  So what happened?


In an earlier post, I talked about the changes we made to AsyncRendering.  Asynchronous rendering no longer renders the report content in an iframe.  Instead, it uses ASP.Net AJAX to perform an asynchronous postback to get the report data.  In most of the cases I’ve seen, this change is at the heart of the problem.


With the iframe model, the report data was retrieved through the report viewer’s HTTP handler.  This request is distinct from a request to the ASPX page itself that contains the report viewer control.  The communication between the browser and the web front end would be something like this:



  1. Browser makes a GET request to the ASPX page to get the page content and a loading indicator for the report

  2. Browser makes a GET request to the HTTP handler to get the HTML for the report (this is the iframe content)

  3. Browser makes GET requests to the HTTP handler to get all the images in the report

But with VS 2010, there are no more frames.  Instead, we use ASP.Net postbacks to render the report.  The new communication sequence is:



  1. Browser makes a GET request to the ASPX page to get the page content and a loading indicator for the report.

  2. Browser makes a POST request to the ASPX page to get the HTML for the report (this content is in an UpdatePanel).

  3. Browser makes GET requests to the HTTP handler to get all the images in the report

In step 2, previously only the ReportViewer code would run to get the report content.  But now the request to get the report content runs the ASP.Net page, including any code you have placed in the page.


Why does this matter?  In the cases I’ve seen in the forums and on Connect, code was added to the load event of the page that altered the state of the report viewer.   The most common example I’ve seen is user code calling SetParameters in the load event, though there are several methods and properties that will trigger this.  Changing the parameter values tells the ReportViewer that it needs to restart report processing.  Effectively, it tells the viewer to return to step 1 – put the loading indicator in the browser and restart report processing.  If you do this during every postback, the viewer never successfully completes step 2.  It just goes into an infinite loop.


Calling methods like SetParameters isn’t cheap.  Each call triggers a round trip to the report server.  So it’s a call you want to minimize anyway.  By only calling SetParameters during the initial GET request or only when parameter values have actually changed, you can improve the performance of your application and break the loop.  A simple check of IsPostBack before calling SetParameters is usually sufficient.

Visual Studio 2010 is Now Available

$
0
0

As many of you know, Visual Studio 2010 was released last week.  We’ve done a lot of work to the ReportViewer control in this release:


  • Support for ASP.Net AJAX

  • Support for the SQL 2008 RDLC schema, including tablix, rich text, and enhanced charts and gauges

  • Significant improvement to support for standards mode and non-IE browsers

  • A new javascript API for the ASP.Net viewer for use on the client

  • Many API updates to both the ASP.Net and winforms controls

The runtime redistributable has been posted and is available from http://www.microsoft.com/downloads/details.aspx?FamilyID=a941c6b2-64dd-4d03-9ca7-4017a0d164fd.  The language packs will be posted as the localized versions of Visual Studio become available.


With every release, we prioritize our efforts based on the feedback we receive from you.  As always, we look forward to your feedback and suggestions on areas we can improve.

Upgrading Web Application Projects to VS 2010

$
0
0

A number of people have posted questions about upgrading their VS 2008 web applications using the ReportViewer control to VS 2010.  The upgrade process is not automatic.  Before I get into the steps required to upgrade your applications to the VS 2010 ReportViewer, I’d like to take a moment to explain why this upgrade process is not automatic.

The VS 2008 ReportViewer can be used in the VS 2010 shell.  While you won’t get the design time experience associated with the 2008 viewer, it will function correctly at runtime.  Certainly, we want everyone to upgrade to the new version, but there are a few reasons you might not want to, and therefore why we don’t upgrade everything automatically:

  • Using the VS 2010 ASP.Net ReportViewer requires ASP.Net AJAX.  While this has not been an issue for most people, it is a new requirement and requires some changes to your ASP.Net pages.
  • The VS 2010 ReportViewer will not work against a SQL 2005 report server in server mode.  If you plan to connect to a SQL 2005 report server, you will need to stay on the VS 2008 version.
  • There are a few API changes that break backwards compatibility in the strict sense.  In response to customer feedback, some methods changed from a return value of void to something more useful.  These changes don’t require you to change your code, but they do require a recompilation.  Assembly version redirection won’t work.

After you load your web application in VS 2010, you will need to perform the following manual steps to get your application back to a fully working state:

  1. In the assembly references section of the solution explorer, remove any references to 9.0 ReportViewer assemblies and add their 10.0 equivalent.  Depending on the versions of the ReportViewer you have installed on your development machine, this may have been done for you.
  2. In the web.config file, locate all references to the ReportViewer assembly and replace the 9.0.0.0 version string with 10.0.0.0.  The public key token did not change in 10.0.  In a typical web.config file, there are four references to the report viewer:
    1. A reference to Microsoft.ReportViewer.WebForms in the system.web/compilation/assemblies section
    2. A reference to Microsoft.ReportViewer.Common in the system.web/compilation/assemblies section
    3. A reference to the RdlBuildProvider in system.web/compilation/buildProviders section
    4. A reference to the HTTP handler in the system.web/httpHandlers section.  Depending on the version of IIS that you are targeting, a similar reference may also be in the system.webServer/handlers section.
  3. In each ASPX file that references the ReportViewer control, a register tag was added when you first inserted a ReportViewer control on the page.  This reference also needs to be updated from 9.0.0.0 to 10.0.0.0.
  4. If you did not already have an ASP.Net AJAX ScriptManager on the page, you will need to add one to the top of the page.  It is located in the AJAX Extensions section of the Toolbox.

ASP.Net ReportViewer Samples

$
0
0

We have recently posted a number of samples that use the ASP.Net ReportViewer. These sample applications cover a wide range of topics. You’ll see sample code for long standing ReportViewer concepts such as hooking up data sources to subreports and implementing a custom toolbar. There are also several samples covering areas that are new to the Visual Studio 2010 ReportViewer, such as the JavaScript API.

Take a look, and as always, let us know of other samples you would like to see.

http://code.msdn.microsoft.com/reportviewer


Nested Objects in Local Mode

$
0
0

As I have mentioned before, the Reporting Services team regularly reviews the bug reports and feature requests that come in via Connect.  Shortly after the release of Visual Studio 2010, we started to receive a few requests and questions through Connect.  One of them, however, stood out from all the others in terms of volume – nested objects in local mode were failing with #Error.  It wasn’t long before calls started to come in through customer support as well.

As we started to investigate the problem, it became clear that this wasn’t a simple issue.  The further we dug into the code, the more we realized that this wasn’t going to be easy to fix.  There was a lot of pressure to publish a hotfix to immediately fix the problem.  However the architecture change needed was of sufficiently high risk that we didn’t want to rush this out and break something else.  Since this has been such a high volume problem, I want to dedicate an article to not only explaining the fix, but also some history into the problem.

Report Processing in VS 2005 and VS 2008

The processing engine used by the VS 2005/2008 ReportViewer in local mode is based on the SQL Server 2005 report processing engine.  That engine reads the entire data set and processes the entire report before rendering the first page.  That means that any data needed to evaluate expressions on any of the pages is calculated up front.  When you are using an object data source, the object sits in memory from the time you hand it to the Report Viewer up until it is used to evaluate expressions.  The pre-calculated expressions are stored in a report snapshot along with a serialized version original object data.

During most interactivity with the report, such as navigating pages or expanding drilldowns, only the calculated expression values are referenced.  The original data isn’t touched.  This works just fine for the vast majority of cases.  If the original data isn’t touched, then why do we store it?  There is one case in VS 2005/2008 where we do need to recalculate some of the expression values – during an end user sort.  Resorting the data has the potential to change the report in far more significant ways than any other interactivity.  The original data is needed to recalculate the expression values in this case.

During our investigation into the nested objects problem, we learned that there is one case that doesn’t work in VS 2005/2008 – nested objects in local mode after a user sort.  The processing engine in those releases was correctly serializing all of the top level properties into the report snapshot.  But it failed to do this correctly for nested objects.  Enabling user sort is not the most frequently used feature in RDL, but it seems that in all of the years local mode was available, no one, including us, used it local mode with an object data source that uses nested objects.  In VS 2005/2008, this scenario produces the same #Error that has become such a hot topic in VS 2010.

Report Processing in VS 2010

Something obviously changed in VS 2010 to make this problem much more apparent.  The change is rooted in the fact that the VS 2010 local mode is based on a newer version of the report processing engine – the SQL Server 2008 version.  One of the major updates in that processing engine is that it is an on-demand processing engine.  Unlike previous versions where all report expressions were calculated up front, this engine only calculates the expressions that are needed at the moment.  This tends to improve performance since we never spend time calculating values that you don’t ask to see.

One of the consequences to this workflow change is that the snapshot is created first, with processing and rendering always executing off of that snapshot.  The in-memory objects from the object data source are never directly used by the renderer as was the case before.  The same serialization problem we had in earlier versions was unknowingly carried forward into VS 2010.  But now it happens with any rendering of the report, not just after a user sort.

The Fix

We spent a great deal of time evaluating this problem and quickly realized that it wasn’t going to be an easy fix.  It was certainly too big to address in a hotfix.  But we have fixed this in Visual Studio 2010 SP1, with one caveat.  In order to make nested objects available to the processing engine, they must be placed in the report snapshot.  Therefore, in order to get nested objects working again, we are adding the requirement that the objects in your data hierarchy be serializable.  This allows us to place them in the snapshot and make them available to the processing engine for expression evaluation.  This has the added benefit of not only bringing us to parity with VS 2005/2008, but also fixing the long broken user sort scenario.

Thank you for your patience with this issue and thanks to all of you who have worked with us directly in analyzing this problem.   I certainly apologize for the delay in getting this fix out to you, but I hope that this delay has allowed us to deliver the cleanest and least impactful fix.

The Invisible ReportViewer

$
0
0

An interesting bug report came in recently regarding toggling the Visible property on the ASP.Net ReportViewer.  It’s fairly subtle and I don’t believe many people are running into it.  But the solution isn’t obvious, so I want to make the information available in case you run into it.

The bug report placed a ReportViewer control on a page and initialized it in a standard way, such as declaratively in the ASPX file or in the Init event at the page level.  The only thing that was unique to this particular page was that the viewer was initially hidden (ReportViewer.Visible = false).  The viewer was made visible in response to a user action on the page, such as a button click.  The problem happens during the button click event: while the control itself became visible, the report content did not.

The underlying bug comes from the way the ReportViewer tracks changes internally.  In this case, the report definition is specified during the initial GET request and persisted by the report viewer.  On a later postback, the viewer is made visible.  The bug in the viewer is that while it does track the fact that the report definition has changed, it doesn’t keep that information across postbacks.  Since the viewer becomes visible during a different postback than the one in which the report definition is specified, the ReportViewer doesn’t recognize that it needs to initiate processing of the report when it becomes visible.

Fortunately, there are two easy ways to work around this problem:

  1. Postpone setting the report definition until you make the ReportViewer visible.
  2. When making the ReportViewer visible, also make a trivial change to the ReportViewer to trigger a definition change.  The easiest way to do this is to toggle the value of ReportViewer.ProcessingMode (e.g. set it from Remote to Local then back again).

Visual Studio 2010 SP1

$
0
0

Earlier this month, we released Visual Studio 2010 SP1.  The service pack is available for download from here and the updated Report Viewer redistributable can be found here.

We always prioritize our efforts based on feedback we receive through Connect as well as through the forums and other channels.  If you are running into problems with the product and believe you have encountered a bug, please file the issue at Connect so that we can investigate it.  We review those issues regularly and adjust our priorities accordingly.

This service pack contains a number of important fixes to the viewer runtime and design time components.  The list below is not an exhaustive list of fixes, but it does touch on the most common and visible issues that have been reported.

  • The most widely reported issue we have addressed is the use of nested objects in object data sources.  Attempting to reference nested objects in report expressions resulted in #Error.  I wrote about this problem previously.  This issue was fixed in the CTP for this release, though some customers continued to report the problem.  After investigating these instances, we discovered an additional requirement – in addition to requiring the objects to be serializable, this update also requires them to be public in order for the serializer to handle them correctly.
  • We have improved the rendering performance of the ASP.Net report viewer when rendering large HTML pages.
  • Data sets in subfolders of the VS project are now usable at design time.
  • Fixed a Visual Studio crash when using the Dataset Properties dialog in some projects that contained an edmx schema.
  • Fixed an issue in which a WinForms report viewer embedded in a WPF application resulted in an exception unloading an AppDomain while closing the application.
  • Fixed a problem in which some icons used in the calendar date picker for parameter prompts would not display.
  • Fixed an issue in which rendering a report would change the thread culture.
  • Fixed an HTML display problem with consolidated images (such as charts and gauges).
  • Fixed a GDI display problem with the WinForms report viewer that resulted in the page being displayed zoomed even at 100%.
Viewing all 31 articles
Browse latest View live


<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>