Quantcast
Channel: The one stop shop for FIXING your Reporting Service's Issues
Viewing all 154 articles
Browse latest View live

ReportViewer 2010 Winforms control takes too much of time to render a local mode report (RDLC) when we launch the application using ClickOnce.

$
0
0

Have you ever wondered why launching an application that has Report viewer 2010 Winforms control through clickonce takes multiple times more time to render the report in Local mode? Try launching the same application directly by double clicking the EXE. Now you will understand what i'm taking about.This behavior certainly relates to the design of your report like amount of data being retrieved and the amount of expression used in the report.

Well, if you're compiling your application in .NET framework 4.0, then you're certainly bound to see the issue irrespective of how you launch the application. But the above observation is related when you run the application hosting report viewer 2010 winforms control in .NET Framework 3.5.

You can find more details on execution mode and the Sandbox execution model directly from Brian's blog @ http://blogs.msdn.com/b/brianhartman/archive/2010/02/18/expression-evaluation-in-local-mode.aspx

Coming back to our scenario of running the application under .NET 3.5, then who causes this impact?

Ok. To come straight to the answer, Clickonce technology chooses Simple Sandboxing execution mode by default. You can understand more about this from http://blogs.msdn.com/b/shawnfa/archive/2006/04/19/579066.aspx

Now in report viewer 2010 control, we use certain application logic to decide whether the report viewer 2010 control should execute in the Sandbox mode or not. Because ClickOnce already set a specific flag regarding the Sandbox execution, in the report viewer when we check the flag it is set to execute in Sandbox mode. So report viewer 2010 control continues to execute the application in the Sandbox mode. Hence even in .NET 3.5 framework, you always have the feeling that your application is actually running under .NET Framework 4.0.

Unfortunately there is no workaround for such scenarios. The options are either to drop ClickOnce or to use older version of the report viewer control.

As an application developer, if you've an application launched through ClickOnce and using older version of ReportViewer control and you've plans to move to Report viewer 2010 or you've already moved to Report Viewer 2010, please do not be surprised if you encounter the above discussed behavior.

 HTH!

Selva.

[The above post is AS-IS and doesn't carry any warranty]

 

 

 


Page break or Interactive height not honored and the report with toggling shows the entire contents in single page

$
0
0

When you have a report that contains multi level / recursive toggling, As a report developer have you ever wondered why my report just shows up in one single page? Have you ever been in a situation where you are forced to think why neither the interactive size nor the page break taking effect on my report? Or as a report consumer, have you ever wondered why this report takes so long to come up? Why my browser seems to be hung?

Well for all of these, the answer just remains one. We'll discuss about that in the below section.

Consider your report design goes like this. You've an inner most group named "Group 1". The Group 1 has a parent group named "Group 2" and the Group 2 has a parent group named "Group 3". So the hierarchy goes like this,

Group 3 -> Group2 -> Group 1 -> Contains the detail rows.

Now, you do not want your report consumers to view all the details in one stretch, and you've decided to implement toggling.

Typically, visibility toggles are used to initially display summary data and to provide the user with the option of seeing more details. For example, you can initially hide a table that displays values for a chart, or hide child groups for a table with nested row or column groups, as in a drilldown report. In the rendered report, the text box displays a plus (+) or minus (-) in addition to its contents. When the user clicks the toggle, the report display is refreshed to show the current visibility settings for items in the report.

Refer http://msdn.microsoft.com/en-us/library/ms156456(SQL.105).aspx on how to implement toggling.

In our report, you've Group 1 whose visibility is controlled by Group 2. Group 2 visibility is controlled by Group 3. Which means, an user has to first expand a row in Group 3 to view the rows under a specific value in Group 2. And has to further expand a row in Group 2 to view the rows under Group 1.

When you view this report in browser and you expand a toggle item. You'll see the entire report contents displayed in a single page or it takes lot of resources and time to display the report, or it is even possible that the report is not even shown making the browser to be in hung state. When you check the task manager, the browser is consuming 100% CPU and the memory for the browser is increasing quite steadily.

The above behavior is By Design. The reason is, all the rows under the parent toggles are kept together. This is to ensure the pagination is consistent even if you expand / collapse multiple toggle members.

So, what is the option for you to ensure the report is paginated and served fast?

Well, there is no easy way around keeping all your toggles intact. The closest possible option is to disable toggling in your report and instead use Document Maps. This will not only make your report more readable but also the report will be served faster with less resource consumptions.

HTH!

Selva.

[All the posts are AS-IS with no warranty]

 

One of the many reasons for Reporting service app domain to unregister

$
0
0

Have you ever wondered why your report processing prematurely terminated? Or While you execute a SSRS web service API call, suddenly you see it failing without any proper information?

For today’s discussion, I’m taking an example where I upload a report using ReportService2010's CreateCatalogItem. While the code is executing you either see a brief pause where the application seems to be hung or it just fails with a Thread abort exception,

Throwing Microsoft.ReportingServices.ReportProcessing.ReportProcessingException: , Microsoft.ReportingServices.ReportProcessing.ReportProcessingException: An unexpected error occurred in Report Processing. ---> System.Threading.ThreadAbortException: Thread was being aborted.

You decide to take a look at the reporting service log file. Ensure you have enabled Verbose logging in your report server instance by following the article,

http://msdn.microsoft.com/en-us/library/ms156500.aspx or using the tool that I developed that can be downloaded from,

http://verboselogger.codeplex.com/

During the failure time frame the log file just shows the following,

processing!ReportServer_0-1!928!05/10/2012-16:58:34:: e ERROR: Throwing Microsoft.ReportingServices.ReportProcessing.ReportProcessingException: , Microsoft.ReportingServices.ReportProcessing.ReportProcessingException: An unexpected error occurred in Report Processing. ---> System.Threading.ThreadAbortException: Thread was being aborted.

runningrequests!ReportServer_0-5!94c!05/10/2012-17:37:07:: v VERBOSE: SoapAction: "http://schemas.microsoft.com/sqlserver/reporting/2010/03/01/ReportServer/CreateCatalogItem"
webserver!ReportServer_0-5!91c!05/10/2012-17:37:07:: i INFO: Reporting Web Server stopped
rshost!rshost!94c!05/10/2012-17:37:10:: w WARN: SID Type was not SidTypeUser. (122)
rshost!rshost!728!05/10/2012-17:37:10:: v VERBOSE: HttpPipeline::DisconnectCallback: releasing pipeline=0x000000000083FE10.
rshost!rshost!94c!05/10/2012-17:37:10:: v VERBOSE: HttpPipelineCallback::EndOfRequest(): releasing pipeline=0x000000000083FE10.
rshost!rshost!94c!05/10/2012-17:37:10:: v VERBOSE: HttpPipeline::ReleaseOnce: releasing pipeline=0x000000000083FE10.
httpruntime!ReportServer_0-5!94c!05/10/2012-17:37:10:: e ERROR: Failed to process request, pipeline=0x83FE10:
rshost!rshost!94c!05/10/2012-17:37:10:: v VERBOSE: HttpPipeline::DoStateProcess failed with hr=0x80131014, pipeline=0x000000000083FE10.
appdomainmanager!DefaultDomain!94c!05/10/2012-17:37:10:: i INFO: Appdomain:3 ReportServer_MSSQLSERVER_0-1-129811569875140647 unregistered.

Well this is what the log file says, Reporting service failed to process request due to an appdomain unregister event.

Though it gives a hint that the processing failed because of the appdomain unload it didn’t give any reason why reporting service process unloaded the app domain.

So all you have to do now is, start scanning the log file upwards from the point of failure. Or another easier option is to search the file for keyword, “appdomainmanager”. This will actually help you to quickly scan the events logged by the App domain manager.

Coming back to scanning the log file, suddenly you would see messages like below,

appdomainmanager!ReportServer_0-1!91c!05/10/2012-16:58:22:: v VERBOSE: Appdomain:3 ReportServer_MSSQLSERVER_0-1-129811569875140647 is about to be unloaded. ShutDownMessage: Change Notification for critical directories.
bin dir change or directory rename
HostingEnvironment initiated shutdown
Change Notification for critical directories.
bin dir change or directory rename
Change Notification for critical directories.
bin dir change or directory rename
Change Notification for critical directories.
bin dir change or directory rename
Change Notification for critical directories.
bin dir change or directory rename
Change Notification for critical directories.
bin dir change or directory rename
Change Notification for critical directories.
bin dir change or directory rename
Change Notification for critical directories.
bin dir change or directory rename
Change Notification for critical directories.
bin dir change or directory rename

Yes, this is the reality. App domain manager says, Change in critical directories has triggered the app domain unloading.

A little bit of research revealed the following,

Here critical directory refers to the <%Installation Directory%\Program Files\Microsoft SQL Server\MSRS10_50.SQL2K8R2\Reporting Services\ReportServer\bin location. (Hint is which app domain is getting unregistered. If it is Report manager then you need to refer the bin directory under ReportManager folder).

So all I did was, ran the application again and just copied a .txt file to the above location. That immediately triggered the app domain unload and ended up terminating all the activities that are currently executing in those app domains. That explains why my report server prematurely terminated its activity.

In a nut shell, if you’ve an application (or manually) that does some custom assembly / resource file deployment followed by reports deployment, then ensure you do a report server service restart between them so that any activity followed by assembly / resource deployment doesn’t fail.

The above scenario is just one sample which I discussed. App domain will get unloaded for other numerous reasons as well. But you need to ensure what triggered it by carefully scanning the log file and correlating the events that you find in the log file during the failure time frame.

Hope this helps!

Selva.
[All the posts are AS-IS and doesn’t carry any warranty]

ReportViewer 2010 control fails with Sys.WebForms.PageRequestManagerTimeoutException: The server request timed out

$
0
0

Think about a scenario where you have a report that takes more than 90 seconds to complete its operation and give the rendered report back to you. The report renders perfectly as expected when you view it from Report manager (For our convenience lets take that the report takes 120 seconds to come up). Now you want this report to be shown to your clients / users in your custom ASP.NET application.

The obvious choice would be to use ReportViewer 2010 web server control. The ReportViewer Web server control is an ASP.NET AJAX control used to host reports in ASP.NET AJAX projects. You can refer here to read more about this control and how to use them in your projects.

In your project you've dragged and dropped the ReportViewer 2010 web server control along with the AJAX ScriptManager which is required to host the report viewer web server control. Then you point the control to load the above discussed report, as soon as the page gets loaded.

When you browse the ASP.NET page that hosts ReportViewer control, it starts rendering the report by displaying the small green icon "Loading...." in the screen. But to your surprise either you get a JavaScript error message on the screen or a small yellow triangle in the IE status bar with the message Done and there is no rendered report displayed as per your request .

When you look in to the message, it shows similar to the following,

Message: Sys.WebForms.PageRequestManagerTimeoutException: The server request timed out.

If you go to Reporting service executionlog table, again to your surprise it says the report has successfully rendered.

Now what's next is going to be important.

The above error in the browser is caused because of the ScriptManager's AsyncPostbackTimeout. By default it is 90 seconds.

http://msdn.microsoft.com/en-us/library/system.web.ui.scriptmanager.asyncpostbacktimeout.aspx

So, all you need to do is, locate the ScriptManager element in your ASPX UI file and change the timeout value to "Do not timeout" as shown below,

<asp:ScriptManager ID="ScriptManager1" runat="server" AsyncPostBackTimeout="0"></asp:ScriptManager> 

Now view the page and the reportviewer web server control should be greatful enough to show you the rendered report.

HTH!

Selva.

[All the posts are AS-IS with no warranty]

Reporting services unexpectedly loads .NET Framework 4.0 by default and fails with HTTP 500 while browsing Report Server and Report manager URL

$
0
0

This week i was working on a challenging case where we've reporting service 2008 R2 installed and when we start the service from Reporting services configuration manager, it starts itself successfully.

When you tried to browse either the report manager url or the report server url, it fails with HTTP 500 error being displayed on the browser.

So, i started with the normal troubleshooting of looking at the Reporting services logfiles, which showed us the following,

library!DefaultDomain!ca0!07/05/2012-02:22:21:: i INFO: Catalog SQL Server Edition = Enterprise
appdomainmanager!DefaultDomain!f38!07/05/2012-02:22:43:: i INFO: Appdomain:8 ReportServer_MSSQLSERVER_0-1-129859465624456482 started.
rshost!rshost!f38!07/05/2012-02:22:43:: i INFO: Application domain type ReportServer statistics: created: 1, unloaded: 1, failed: 0, timed out: 0.
appdomainmanager!DefaultDomain!f38!07/05/2012-02:22:43:: i INFO: Appdomain:9 ReportServer_2-2-129859465635532482 started.
rshost!rshost!f38!07/05/2012-02:22:43:: i INFO: Application domain type ReportServer statistics: created: 2, unloaded: 2, failed: 0, timed out: 0.
appdomainmanager!DefaultDomain!f38!07/05/2012-02:22:43:: i INFO: Appdomain:10 ReportServer_3-3-129859465636468482 started.
rshost!rshost!f38!07/05/2012-02:22:43:: i INFO: Application domain type ReportServer statistics: created: 3, unloaded: 3, failed: 0, timed out: 0.
appdomainmanager!DefaultDomain!f38!07/05/2012-02:22:43:: i INFO: Appdomain:11 ReportServer_4-4-129859465637560482 started.
rshost!rshost!f38!07/05/2012-02:22:43:: i INFO: Application domain type ReportServer statistics: created: 4, unloaded: 4, failed: 0, timed out: 0.
appdomainmanager!DefaultDomain!f38!07/05/2012-02:22:43:: i INFO: Appdomain:12 ReportServer_5-5-129859465638496482 started.
rshost!rshost!f38!07/05/2012-02:22:44:: i INFO: Application domain type ReportServer statistics: created: 5, unloaded: 5, failed: 0, timed out: 0.
appdomainmanager!DefaultDomain!f38!07/05/2012-02:22:44:: i INFO: Appdomain:13 ReportServer_6-6-129859465639432482 started.
rshost!rshost!f38!07/05/2012-02:22:44:: i INFO: Application domain type ReportServer statistics: created: 6, unloaded: 6, failed: 0, timed out: 0.
appdomainmanager!DefaultDomain!f38!07/05/2012-02:22:44:: i INFO: Appdomain:14 ReportServer_7-7-129859465640524482 started.
rshost!rshost!f38!07/05/2012-02:22:44:: i INFO: Application domain type ReportServer statistics: created: 7, unloaded: 7, failed: 0, timed out: 0.
appdomainmanager!DefaultDomain!f38!07/05/2012-02:22:44:: i INFO: Appdomain:15 ReportServer_8-8-129859465641460482 started.
rshost!rshost!f38!07/05/2012-02:22:44:: i INFO: Application domain type ReportServer statistics: created: 8, unloaded: 8, failed: 0, timed out: 0.
appdomainmanager!DefaultDomain!f38!07/05/2012-02:22:44:: i INFO: Appdomain:16 ReportServer_9-9-129859465642396482 started.
rshost!rshost!f38!07/05/2012-02:22:44:: i INFO: Application domain type ReportServer statistics: created: 9, unloaded: 9, failed: 0, timed out: 0.
appdomainmanager!DefaultDomain!f38!07/05/2012-02:22:44:: i INFO: Appdomain:17 ReportServer_10-10-129859465643488482 started.
rshost!rshost!f38!07/05/2012-02:22:44:: i INFO: Application domain type ReportServer statistics: created: 10, unloaded: 10, failed: 0, timed out: 0.
appdomainmanager!DefaultDomain!f38!07/05/2012-02:22:44:: i INFO: Appdomain:18 ReportServer_11-11-129859465644424482 started.
appdomainmanager!DefaultDomain!f38!07/05/2012-02:22:44:: e ERROR: AppDomain ReportServer_11 failed to start. Error: The configuration system has already been initialized.
library!DefaultDomain!f38!07/05/2012-02:22:44:: e ERROR: Throwing Microsoft.ReportingServices.Diagnostics.Utilities.ReportServerHttpRuntimeInternalException: Failed to create HTTP Runtime, Microsoft.ReportingServices.Diagnostics.Utilities.ReportServerHttpRuntimeInternalException: An internal or system error occurred in the HTTP Runtime object for application domain ReportServer_11.  ---> System.InvalidOperationException: The configuration system has already been initialized.
   at System.Configuration.ConfigurationManager.SetConfigurationSystem(IInternalConfigSystem configSystem, Boolean initComplete)
   at System.Web.Configuration.HttpConfigurationSystem.EnsureInit(IConfigMapPath configMapPath, Boolean listenToFileChanges, Boolean initComplete)
   at System.Web.Hosting.HostingEnvironment.Initialize(ApplicationManager appManager, IApplicationHost appHost, IConfigMapPathFactory configMapPathFactory, HostingEnvironmentParameters hostingParameters, PolicyLevel policyLevel, Exception appDomainCreationException)
   at System.Web.Hosting.HostingEnvironment.Initialize(ApplicationManager appManager, IApplicationHost appHost, IConfigMapPathFactory configMapPathFactory, HostingEnvironmentParameters hostingParameters, PolicyLevel policyLevel, Exception appDomainCreationException)
   at System.Web.Hosting.ApplicationManager.CreateAppDomainWithHostingEnvironment(String appId, IApplicationHost appHost, HostingEnvironmentParameters hostingParameters)

 

Well, after starring at the above message for some time as it didn't reveal much, i decided to take a look at the event viewer logs.

Log Name:      Application
Source:        ASP.NET 4.0.30319.0
Date:          7/5/2012 9:03:00 AM
Event ID:      1325
Task Category: None
Level:         Error
Keywords:      Classic
User:          N/A
Computer:      xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

Description:
Failed to initialize the AppDomain:ReportServer_11

Exception: System.InvalidOperationException

Message: The configuration system has already been initialized.

StackTrace:    at System.Configuration.ConfigurationManager.SetConfigurationSystem(IInternalConfigSystem configSystem, Boolean initComplete)
   at System.Web.Configuration.HttpConfigurationSystem.EnsureInit(IConfigMapPath configMapPath, Boolean listenToFileChanges, Boolean initComplete)
   at System.Web.Hosting.HostingEnvironment.Initialize(ApplicationManager appManager, IApplicationHost appHost, IConfigMapPathFactory configMapPathFactory, HostingEnvironmentParameters hostingParameters, PolicyLevel policyLevel, Exception appDomainCreationException)
   at System.Web.Hosting.HostingEnvironment.Initialize(ApplicationManager appManager, IApplicationHost appHost, IConfigMapPathFactory configMapPathFactory, HostingEnvironmentParameters hostingParameters, PolicyLevel policyLevel, Exception appDomainCreationException)
   at System.Web.Hosting.ApplicationManager.CreateAppDomainWithHostingEnvironment(String appId, IApplicationHost appHost, HostingEnvironmentParameters hostingParameters)
   at System.Web.Hosting.ApplicationManager.CreateAppDomainWithHostingEnvironmentAndReportErrors(String appId, IApplicationHost appHost, HostingEnvironmentParameters hostingParameters)

 

Again, neither the event viewer logs didn't reveal much other than giving me a hint that the error is being thrown by ASP.NET 4.0.

Now, this is quite surprising as Reporting Service 2008 R2 was never compiled against .NET 4.0 and it was compiled against .NET 3.5 (Which will still use the .NET Framework 2.0 runtime).

The next immediate question was, under what circumstances an application will be forced to load a different .NET framework (In our case, it is .NET framework 4.0 is being loaded).

To cross verify this i quickly took a Process Explorer trace and found all the .NET 4.0 dll's getting loaded in to the process space.

As a quick check i uninstalled .NET Framework 4.0 and Reporting service started to work without any errors. But unfortunately, there were other applications that are dependent on .NET Framework 4.0 which started to fail.

So in got the .NET Framework 4.0 reinstalled back on the machine and the problem reoccured.

After thinking for sometime, i finally decided to force the application to use a specific .NET Framework by adding the following tag in the Reportinservicesservice.exe.config and Report Server's web.config files.

Ref: http://msdn.microsoft.com/en-us/library/w4atty68.aspx

<configuration>
   <startup>
      <supportedRuntime version="v2.0.50727"/>
   </startup>
</configuration>

After restarting the service, nothing changed and we ran in to the same error.

So we enabled the Fusion logging in the registry to see if there are any assembly binding errors.

Ref: http://blogs.msdn.com/b/suzcook/archive/2003/05/29/57120.aspx

While checking the fusion log for System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089.HTM, i found the following,


The operation was successful.
Bind result: hr = 0x0. The operation completed successfully.

Assembly manager loaded from:  C:\Windows\Microsoft.NET\Framework64\v4.0.30319\clr.dll
Running under executable  C:\Program Files\Microsoft SQL Server\MSRS10_50.MSSQLSERVER\Reporting Services\ReportServer\bin\ReportingServicesService.exe
--- A detailed error log follows.

=== Pre-bind state information ===
LOG: User = xxxxxxxxxxxxxxx
LOG: DisplayName = System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
(Fully-specified)
LOG: Appbase = file:///C:/Program Files/Microsoft SQL Server/MSRS10_50.MSSQLSERVER/Reporting Services/ReportServer/bin/
LOG: Initial PrivatePath = NULL
LOG: Dynamic Base = NULL
LOG: Cache Base = NULL
LOG: AppName = ReportingServicesService.exe
Calling assembly : ReportingServicesAppDomainManager, Version=10.0.0.0, Culture=neutral, PublicKeyToken=89845dcd8080cc91.
===
LOG: This bind starts in default load context.
LOG: Using application configuration file: C:\Program Files\Microsoft SQL Server\MSRS10_50.MSSQLSERVER\Reporting Services\ReportServer\bin\ReportingServicesService.exe.Config
LOG: Using host configuration file:
LOG: Using machine configuration file from C:\Windows\Microsoft.NET\Framework64\v4.0.30319\config\machine.config.
LOG: Version redirect found in framework config: 2.0.0.0 redirected to 4.0.0.0.
LOG: Post-policy reference: System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
LOG: Reusing an assembly instance that was previously loaded (C:\Windows\Microsoft.Net\assembly\GAC_MSIL\System\v4.0_4.0.0.0__b77a5c561934e089\System.dll).

This gave me a hint that there seems to be some kind of redirection that has happened. But even after looking after all the files from fusion logs over hours together and searching in the internet, i didn't get any direction to proceed further.

I compared all the config files from the faulty machine including the machine.config's, web.config's etc. But everything was normal and as expected.

That was the time i turned towards the Mr. dependent tool, "PROCESS MONITOR" from http://technet.microsoft.com/en-US/sysinternals which was written by our esteemed Technical Fellow, Mark Russinovich.

I stopped the Reporting server service from the configuration manager, started the capture in process monitor tool and started the Reporting server service. Then i stopped the trace and saved the file.

I opened the file and started to go through the file to see while initializing the process, what are the registry keys and files that were accessed by the Reporting server service.

Unfortunately everything seems to be fine there as well with all access to the paths succeeding. But again there i saw all the .NET Framewotk 4.0 assemblies being loaded.

So i decided the trace to be compared with a proper working trace from my machine. I used the same Process Monitor tool and captured a working scenario trace.

While going through the working and non working traces simultaneously, line by line something very interesting captured my attention. That is none other than the access to the following registry key,

HKLM\SOFTWARE\Microsoft\.NETFramework\OnlyUseLatestCLR

The result on the working machine for this key was NAME NOT FOUND where as the result from non-working machine was SUCCESS.

I immediately looked at the calls below and found that in my machine the call for policy files was going to 2.0,

HKLM\SOFTWARE\Microsoft\.NETFramework\Policy\v2.0

Where as for non-working scenario it was,

HKLM\SOFTWARE\Microsoft\.NETFramework\Policy\v4.0

So i did a quick check on the internet to see what this key, "OnlyUseLatestCLR" is all about and found the following details.

It is not recommended that you ever set the OnlyUseLatestCLR key. On a normal box, this key does not exist (which is equivalent to setting it to 0).

Setting this key forces all applications to use the latest CLR on the box. Even specifying a non-existent or invalid framework will result in the latest framework.

This completley breaks multi-targeting builds on a box. Also, it will break many applications which cannot be run when this is set.

Then i immediately checked the working machine and the Key was not there where as on the non-working machine the key was there, though with the value set to 0.

All i did was, deleted the key and rebooted the machine.

Well, all the struggle i went through just paid off. It made everything on the machine back ot normal and Reporting Service started to work like a champ!!

Though this took me so much of time and effort to nail this down, but certainly i enjoyed the challenge that was thrown at me.

Please note that this setting is not specific to Reporting Services 2008 R2. It will impact any .NET managed application. So it is worth to keep an eye on this key and ensure you don't set this on your machine, not even to ZERO.

HTH!

Selva.

[All the posts are AS-IS with no warranty]

Reporting service keeps committing physical memory in NUMA architecture even when Reporting services is not under heavy load

$
0
0

Have you worried about Reporting service constanly keeps consuming the physical memory even when the reporting service is not under stressful condition? This specifically happens when you have NUMA architecture enabled on the Server.

So, if you've NUMA architecture enabled and you see yourself running in to this issue, please don't be surprised. The reason is,

It’s a behavior where we just commit memory upto 60% of the configured WorkingSetMaximum, Which by default is equivalent to the available physical memory. The important thing to understand here is we are just committing the memory for ReportingServices, but not using it.

If the system is under memory crunch and there are other processes that require more memory, we immediately release the unused, committed memory, ie.., if there is any memory pressure, we shrink back to the memory amount which Reporting service is currently utilizing.

This behavior should not affect performance/scale of either ReportingServices or any other external process.

But if you feel uncomfortable with this behavior, you need to instruct Reporting service in such a way that it stops assuming the entire available memory belongs to it. By default it does assume.

This can be achieved by seeting the memory limits in rsreportserver.config. You can refer http://msdn.microsoft.com/en-us/library/ms159206(v=sql.105).aspx for this.

You can limit the memory utilization by limiting the value of WorkingSetMaximum and WorkingSetMinimum.

The above article provides some great insight as to how reporting services handles memory and how it reacts to memory pressure. I highly recommend you to carefully go through this article before making any changes.

 HTH!

Selva.

[All the posts are AS-IS without any warranty]

 

ReportViewer control fails with Sys.WebForms.PageRequestManagerServerErrorException: Failed to load viewstate.

$
0
0

Recently i was working on a very interesting scenario. Imagine you've have an ASP.NET web application that hosts ReportViewer web control.

The ReportViewer control pulls a Reporting Services 2008 R2 report. The report contains background images in report body, textbox etc along with DrillThrough actions. When the report is shown in the ReportViewer, there are still some background images getting rendered.  

This background operation is performed asynchronously with the help of streams and hence the report is still visible when the background images are still being rendered.

Before the ReportViewer completes rendering the background image streams, if you click on any of the drillthrough report link, it fails with the following exception.

Sys.WebForms.PageRequestManagerServerErrorException:
Failed to load viewstate.  The control tree into which viewstate is being loaded must match the control tree that was used to save viewstate during the previous request.  For example, when adding controls dynamically, the controls added during a post-back must match the type and position of the controls added during the initial request.

In the Reporting services logs and HTTP logs for the corresponding time frame you would see the following,

HTTP:

09/07/2012 14:29:15 - 10.21.7.82 20480 servername POST /ReportServer/ReportExecution2005.asmx 401 569 0 1.1 servername - - -
09/07/2012 14:29:15 - 10.21.7.82 20480 servername POST /ReportServer/ReportExecution2005.asmx 401 622 0 1.1 servername - - -
09/07/2012 14:29:15 Userdetails 10.21.7.82 20480 servername POST /ReportServer/ReportExecution2005.asmx 500 2491 32 1.1 servername - - -
09/07/2012 14:29:15 - 10.21.7.82 20480 servername POST /ReportServer/ReportExecution2005.asmx 401 569 0 1.1 servername - - -
09/07/2012 14:29:15 - 10.21.7.82 20480 servername POST /ReportServer/ReportExecution2005.asmx 401 622 0 1.1 servername - - -
09/07/2012 14:29:15 Userdetails 10.21.7.82 20480 servername POST /ReportServer/ReportExecution2005.asmx 500 2491 31 1.1 servername - - -

Reporting Services Logs:

chunks!ReportServer_0-1!1238!09/07/2012-15:28:57:: v
VERBOSE: ### ReportSnapshot(7833434d-b2ad-4599-b265-7291dc11ae70) constructor of
existing snapshot.
library!ReportServer_0-1!1238!09/07/2012-15:28:57:: v
VERBOSE: Transaction
commit.
session!ReportServer_0-1!1238!09/07/2012-15:28:57:: v VERBOSE: Found
library!ReportServer_0-1!1238!09/07/2012-15:28:57:: e ERROR: Throwing
Microsoft.ReportingServices.Diagnostics.Utilities.StreamNotFoundException: ,
Microsoft.ReportingServices.Diagnostics.Utilities.StreamNotFoundException: The stream cannot be found. The stream identifier that is provided to an operation cannot be located in the report server database.;

But the issue doesn't happen when you view the report directly from Report manager / Report Server URL's and perform a DrillThrough operation.

Additionally, you'll have the below exception stack thrown by the ASP.NET application when the issue happens.

System.Web; TargetSite:Boolean
HandleError(System.Exception) ; Message:Exception of type 'System.Web.HttpUnhandledException' was thrown.; 
InnerException:System.Web.HttpException (0x80004005): Failed to load viewstate.  The control tree into which viewstate is being loaded must match the control
tree that was used to save viewstate during the previous request.  For example, when adding controls dynamically, the controls added during a post-back must match the type and position of the controls added during the initial request.  
at System.Web.UI.Control.LoadViewStateRecursive(Object savedState)   at
System.Web.UI.Control.LoadChildViewStateByIndex(ArrayList childState)   at
System.Web.UI.Control.LoadViewStateRecursive(Object savedState)   at
System.Web.UI.Control.LoadChildViewStateByIndex(ArrayList childState)   at
System.Web.UI.Control.LoadViewStateRecursive(Object savedState)   at
System.Web.UI.Control.LoadChildViewStateByIndex(ArrayList childState)   at
System.Web.UI.Control.LoadViewStateRecursive(Object savedState)   at
System.Web.UI.Control.LoadChildViewStateByIndex(ArrayList childState)   at
System.Web.UI.Control.LoadViewStateRecursive(Object savedState)   at
System.Web.UI.Control.LoadChildViewStateByIndex(ArrayList childState)   at
System.Web.UI.Control.LoadViewStateRecursive(Object savedState)   at
System.Web.UI.Control.LoadChildViewStateByIndex(ArrayList childState)   at
System.Web.UI.Control.LoadViewStateRecursive(Object savedState)   at
System.Web.UI.Control.LoadChildViewStateByIndex(ArrayList childState)   at
System.Web.UI.Control.LoadViewStateRecursive(Object savedState)   at
System.Web.UI.Control.LoadChildViewStateByIndex(ArrayList childState)   at
System.Web.UI.Control.LoadViewStateRecursive(Object savedState)   at
System.Web.UI.Control.LoadChildViewStateByIndex(ArrayList childState)   at
System.Web.UI.Control.LoadViewStateRecursive(Object savedState)   at
System.Web.UI.Control.LoadChildViewStateByIndex(ArrayList childState)   at
System.Web.UI.Control.LoadViewStateRecursive(Object savedState)   at
System.Web.UI.Page.LoadAllState()   at
System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint);StackTrace:   at
System.Web.UI.Page.HandleError(Exception e)   at
System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint)   at
System.Web.UI.Page.ProcessRequest(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint)   at System.Web.UI.Page.ProcessRequest()   at
System.Web.UI.Page.ProcessRequest(HttpContext context)   at
System.Web.HttpApplication.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute()  
at System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously)  

The reason behind why you see this behavior only from ReportViewer control and not from Report Manager is, As soon as you click on a drillthrough link, the page stops loading completely from Report Manager and Report Server reports, where in the ReportViewer WebForm continues to load the report after the drillthrough report is clicked.

How to FIX this issue?

1. Remove all the background images.

2. Force ReportViewer control not to use the web application session state by implementing the IReportServerConnection / IReportServerConnection2 interface in your application.

REF:

http://msdn.microsoft.com/en-us/library/microsoft.reporting.webforms.ireportserverconnection2.aspx
http://blogs.msdn.com/b/brianhartman/archive/2008/11/21/custom-credentials-in-the-report-viewer.aspx
http://msdn.microsoft.com/en-us/library/ms251661.aspx

Disabling session state (since these are server reports) allows the report to run faster.  You will see a significant performance gain as well as not run into this issue.

HTH!

Selva.

[All the posts are AS-IS without any warranty]

ReportExecutionService.Render method in SharePoint integrated mode

$
0
0

Reporting service provides very convenient way of rendering your reports with the help of Web Service API's. You'll find a whole lot of documents out there in the web. But one thing we often have to search is, what should be the PATH of the report when we use the LoadReport method in order to prepare the report for execution.

The below article beautifully explains the use of Render method in native mode.

http://msdn.microsoft.com/en-us/library/reportexecution2005.reportexecutionservice.render.aspx

 But how can we use this against SharePoint integrated mode? That is what we'll be looking today.

First, the report path should be an absolute URL that includes the details of document library where the report is deployed.

For example, I've a web application on the server where I use the URL http://selvar to reach out to the web application.

I've a document library, Shared Documents where I've deployed the report named SimpleSelect

So, the absolute report URL looks like: http://selvar/Shared%20Documents/SimpleSelect.rdl. Browsing this URL will get you to the report.

If you've reports in sites and site collections, just change the above URL accordingly.

Having said that, we've pretty much framed the URL for report that we'll be rendering using the RENDER method.

In order to add the ReportExecution2005.asmx web service reference to the project, the URL will look like: http://selvar/_vti_bin/reportserver/ReportExecution2005.asmx

With the necessary details in hand, the below is the modified version of sample for the Render method in SharePoint integrated mode.

 

class Program

    {

        static void Main(string[] args)

        {

            ReportExecutionService rs = new ReportExecutionService();

        rs.Credentials = System.Net.CredentialCache.DefaultCredentials;

        rs.Url = "http://selvar/_vti_bin/reportserver/ReportExecution2005.asmx";

 

        // Render arguments

        byte[] result = null;

        string reportPath = "http://selvar/Shared%20Documents/SimpleSelect.rdl";

        string format = "PDF";

        string historyID = null;

        string devInfo = @"<DeviceInfo><Toolbar>False</Toolbar></DeviceInfo>";

        string showHideToggle = null;

        string encoding;

        string mimeType;

        string extension;

        Warning[] warnings = null;

        ParameterValue[] reportHistoryParameters = null;

        string[] streamIDs = null;

       

        ExecutionInfo execInfo = new ExecutionInfo();

        ExecutionHeader execHeader = new ExecutionHeader();

 

        rs.ExecutionHeaderValue = execHeader;

 

        execInfo = rs.LoadReport(reportPath, historyID);

 

        String SessionId = rs.ExecutionHeaderValue.ExecutionID;

 

        Console.WriteLine("SessionID: {0}", rs.ExecutionHeaderValue.ExecutionID);

         try

        {

            result = rs.Render(format, devInfo, out extension, out encoding, out mimeType, out warnings, out streamIDs);

             execInfo = rs.GetExecutionInfo();

             Console.WriteLine("Execution date and time: {0}", execInfo.ExecutionDateTime);

         }

        catch (SoapException e)

        {

            Console.WriteLine(e.Detail.OuterXml);

        }

         // Write the contents of the report to an MHTML file.

        try

        {

            FileStream stream = File.Create("D:\\report.pdf", result.Length);

            Console.WriteLine("File created.");

            stream.Write(result, 0, result.Length);

            Console.WriteLine("Result written to the file.");

            stream.Close();

        }

        catch (Exception e)

        {

            Console.WriteLine(e.Message);

        }

     }

     }

 

HTH!

Selva.

[All the posts are AS-IS without any warranty]


Working with RDLC(2012) and passing parameter to sub report in Report Viewer 2012 control

$
0
0

This is an exact replica of the post: http://blogs.msdn.com/b/selvar/archive/2009/08/30/working-with-rdlc-and-passing-parameter-to-subreport-in-report-viewer-control.aspx 

But the difference is, it is customized for Report Viewer 2012 control as it has quite a good amount of modifications from the earlier post. Hence this is a modified version, customized for Report Viewer 2012.

The tricky part with the RDLC is, even though it gives you the option of creating report parameters, you cannot assign values from a query.

More over you cannot make the parameter prompts visible as you do in RDL.

So the trick here is, the person who is designing the report should use the ASP.NET controls for parameters and pass it along with the query that you’re using it for filing your report data set.

The other way is to define parameters, pass the values to parameters from the ASP.NET control to the Report Viewers Local report parameter collection and then just create filters in the table / matrix / tablix. But the problem here is, your performance of the report can be impacted as the query might bring large number of data for each request (based on the query).

So, I’ll be explaining the concept based on passing the parameters from the ASP.NET controls to the query and get the filtered data for the report data set.

In our sample we’ll be using ADVENTUREWORKS2012 database. The tables which I’ve selected are Department and EmployeeDepartmentHistory.

The objective here is, the main report REPORT1.rdlc will show the Department table details and contains a sub report component with REPORT2.rdlc which displays EmployeeDepartmentHistory. All the data are based on the parameters that we choose in the ASP.NET page which contains the ReportViewer 2012 control.

1. Open Visual Studio 2012 and create an ASP.NET web application. (Choose either VB.NET / C#. I’ll be talking from C# perspective.)

2. If you’d like, delete the existing Default.aspx page and add a new form with the name, Default.aspx.

3. Add a new report item called REPORT1.RDLC.

4. From the project menu, Add a new dataset named DataSet1.xsd.

5. From the Toolbox, drag a TableAdapter, Choose a SQL server that hosts the Adventureworks2012 database and configure it only for select statement against the Department table. The query will look like:

SELECT Name, DepartmentID FROM HumanResources.Department ORDER BY DepartmentID

6. From the project menu, Add another new dataset named DataSet2.xsd.

7. From the Toolbox, drag a TableAdapter, use the same connection string created for Dataset1.xsd in step #5. Configure it only for select statement against the EmployeeDepartmentHistory table. The query will look like:

SELECT DepartmentID, ShiftID, StartDate FROM HumanResources.EmployeeDepartmentHistory order by DepartmentID

8. Now, go back to Report1.rdlc and from ReportData menu, Right click on Datasets, choose Add Dataset and select DataSet1 in Data Source. This will automatically choose the Department dataset that we created in step #5.

clip_image002

9. From the toolbox drag and drop a table component in to REPORT1.

10. From Dataset1, drag and drop the DepartmentID and Name columns in to the report table.

11. Now go to the solution explorer and add a new item, REPORT2.RDLC.

12. From ReportData menu, Right click on Datasets, choose Add Dataset and select DataSet2 in Data Source. This will automatically choose the EmployeeDepartmentHistory dataset that we created in step #7.

clip_image004

13. From the toolbox drag and drop a table component in to REPORT2. Then drag the columns DepartmentID, ShiftID and StartDate.

14. Then add a group based on DepartmentID which displays the DepartmentID in the Group Header.

15. Go back to REPORT1.rdlc and drag a sub report component from the toolbox. Point the sub report to REPORT2.

image

 

16. With this we completed the design of the Dataset1, Dataset2, Report1.rdlc and Report2.rdlc. Now let’s design the ASP.NET page.

17. Switch to the Default.aspx page design layout. Drag and drop a ReportViewer control component in to the page. Go to the properties of the ReportViewer1 (Click on the > icon that appears to the top right on the control) and choose Report1.rdlc from Choose Report drop down. This will add an object data source named Objectdatasource1 in the page. Also make sure the ReportViewer1’s property window, LocalReport’s Report path contains Report1.rdlc specified.

image

 

18. Go to ObjectDatasource1’s properties (Click on the > icon that appears to the top right on the control), select Configure Data Source… and make sure the table adapter is qualified with your project name / namespace is selected there.

image

 

19. Drag and drop a Listbox control, ListBox1 (For multi value parameters).

20. Go to the properties of the ListBox1 (Click on the > icon that appears to the top right on the control) and click on Choose Data Source… link.

21. Choose the following,

Datasource: ObjectDataSource1

Data field for display: Name

Data field for Value: DepartmentID

22. Make sure the selection mode for the ListBox1 is set to Multiple.

23. Now drag a button control, named btnViewReport, adjacent to the ListBox1.

24. Also, drag and drop a ScriptManager from the toolbox in to the page. This is required by the ReportViewer control.

This brings us to the end of the design phase. Let’s step in to the coding part. The coding part needs to be done little carefully. The reason, it has to follow a specific order to get the report properly. The sequence is as follows,

1. Get the list of parameters selected.

2. Build the SQL query with the parameters and get the result in to the corresponding datasets.

3. Bind the datasets back to the reports (Main and sub report).

4. Refresh the control to show the updated report.

Let’s have a look at the code within the PageLoad event of the default.aspx page. Inline Comments are provided to explain the code pieces.

string defaultValue = "'1'";

protected void Page_Load(object sender, EventArgs e)

{

if (!IsPostBack)

{

ReloadReport();

}

}

private void ReloadReport()

{

//Eveytime you add a data source to the report, it adds itself in to

//a collection. Reason, report allows more than one data source to be

//used within itself.Unless you specify the data source with index,

//DataSources[0] will be taken automatically since our report has only

//one data source. In our case for every refresh we re-execute the

//query and get different result set. So to make sure we keep the

//current dataset as default and to prevent data sets getting bulged

//up, we’re making sure to remove the last available data set and then

//add the current data set.

if (this.ReportViewer1.LocalReport.DataSources.Count > 0)

{

this.ReportViewer1.LocalReport.DataSources.RemoveAt(0);

}

//Adding the newly filled data set to the report. After this the Data //Source count will show 1. The first parameter is the name of the data //set bound with the report** and the next is the call to method which //will execute the QUERY and return a data table that contains the //current data.

this.ReportViewer1.LocalReport.DataSources.Add(new ReportDataSource("DataSet1", GetDepartmentData()));

//For the sub report to be processed, we need to add the sub report //processing handler to the main report and that is what is shown //below. The data set processing definition for the sub report will be //defined with in that method.

this.ReportViewer1.LocalReport.SubreportProcessing += new SubreportProcessingEventHandler(localReport_SubreportProcessing);

}

Let’s have a look at the SubreportProcessing event handler:

//All we’ve done here is, we’re binding the data set to appropriate report data source**.

void localReport_SubreportProcessing(object sender, SubreportProcessingEventArgs e)

{

e.DataSources.Add(new ReportDataSource("DataSet1", GetEmployeeData()));

}

** To view the name of the data set (i.e DataSet1) Go to the Report1.rdlc -> Report Data -> Under Datasets, you’ll see the list of data sets, if the report contains more than one.

Now we’re going to look at the method GetEmployeeData () that fetches the data to the data set DataSet2 for Report2.rdlc.

private DataTable GetEmployeeData()

{

//Since string is immutable, we’re using StringBuilder as we’ll be //changing the data frequently based on the parameter selection.

StringBuilder param = new StringBuilder();

//We need to get the selected parameters seperated by “,” and enclosed //within the “’” (i.e ‘1’,’3’,’7’). This is to make sure we‘ve the //proper list of multi value parameters.

foreach (ListItem list in ListBox1.Items)

{

if (list.Selected)

{

param.Append("'" + list.Value + "',");

}

}

string paramvalues = string.Empty;

//Just initializing the parameter values with a default value. This //will come in to picture only during the first exectution as we need //to show some data as soon as the report loads for the first time.

if (param.Length == 0)

{

paramvalues = defaultValue;

}

else

{

//Making sure the last “,” which got added in the above foreach loop is //removed before the values are passed to the queries.

paramvalues = param.ToString().Remove(param.ToString().LastIndexOf(",")).ToString();

}

//Creating a new SQL server connection object.

using (SqlConnection sqlConn = new SqlConnection("Data Source=localhost;Initial Catalog=Adventureworks2012;Integrated Security=SSPI"))

{

//Creating a new SQL Adapter along with the SQL query and the //connection.

SqlDataAdapter adap = new SqlDataAdapter("SELECT DepartmentID, ShiftID, StartDate FROM HumanResources.EmployeeDepartmentHistory where DepartmentID IN (" + paramvalues + ")", sqlConn);

//Create the typed data set of EmployeeDepartmentHistory and fill it //with the data.

DataSet2 ds = new DataSet2();

adap.Fill(ds, "EmployeeDepartmentHistory");

//Return the filled Data Table.

return ds.EmployeeDepartmentHistory;

}

}

Let’s look at the method GetDepartmentData () that fetches the data to the data set DataSet1 for Report1.rdlc / ObjectDataSource1.

private DataTable GetDepartmentData()

{

//Since string is immutable, we’re using StringBuilder as we’ll be //changing the data frequently based on the parameter selection.

StringBuilder param = new StringBuilder();

//We need to get the selected parameters seperated by “,” and enclosed //within the “’” (i.e ‘1’,’3’,’7’). This is to make sure we‘ve the //proper list of multi value parameters.

foreach (ListItem list in ListBox1.Items)

{

if (list.Selected)

{

param.Append("'" + list.Value + "',");

}

}

string paramvalues = string.Empty;

//Just initializing the parameter values with a default value. This //will come in to picture only during the first exectution as we need //to show some data as soon as the report loads for the first time.

if (param.Length == 0)

{

paramvalues = defaultValue;

}

else

{

//Making sure the last “,” which got added in the above foreach loop is //removed before the values are passed to the queries.

paramvalues = param.ToString().Remove(param.ToString().LastIndexOf(",")).ToString();

}

//Creating a new SQL server connection object.

using (SqlConnection sqlConn = new SqlConnection("Data Source=Localhost;Initial Catalog=Adventureworks2012;Integrated Security=SSPI"))

{

//Creating a new SQL Adapter along with the SQL query and the //connection.

SqlDataAdapter adap = new SqlDataAdapter("SELECT DISTINCT DepartmentID, Name FROM HumanResources.Department where DepartmentID IN (" + paramvalues + ")ORDER BY DepartmentID", sqlConn);

//Create the typed data set of Department and fill it

//with the data.

DataSet1 ds = new DataSet1();

adap.Fill(ds, "Department");

//Return the filled Data Table.

return ds.Department;

}

}

Finally, whenever we click on the View Report button, the query has to be executed with the new set of parameters and then the entire above operation as to be executed. The below code invokes it.

protected void btnView_Click(object sender, EventArgs e)

{

ReloadReport();

}

That pretty much concludes our sample. I’ve uploaded the sample as well. Please change the connections string values and try executing the report. Happy programming!!.

HTH!

Selva.

[All the posts are AS-IS with no warranty]

Reporting service ENCRYPTION KEY automated backup REPORT utility

$
0
0

I’ve come across immeasurable number of circumstances where I meet customers with a non working Reporting Service production instance due Encryption key lost or corrupted.

To add more to the agony we end up figuring out that there is no valid encryption key back and hence all your data source information are lost, subscriptions are disabled etc., etc..

This made to think for a while on how this encryption key can be backed up automatically and more importantly with minimal human effort. The process that I’ll be discussing in this blog is just the evolution of the longer accumulation of my thoughts which has bubbled up as a handy tool.

Ever since Reporting service 2000 was released first and till now, the importance of reporting service encryption keys has remained on top of the items to be secured for an obvious reason,

Reporting Services uses encryption keys to secure credentials and connection information that is stored in a report server database. In Reporting Services, encryption is supported through a combination of public, private, and symmetric keys that are used to protect sensitive data. The symmetric key is created during report server initialization when you install or configure the report server, and it is used by the report server to encrypt sensitive data that is stored in the report server. Public and private keys are created by the operating system, and they are used to protect the symmetric key. A public and private key pair is created for each report server instance that stores sensitive data in a report server database.

 

So, if you either loose the encryption keys or corrupt the keys, you’ll lose all your data source connection and other sensitive information that are stored in reporting services. This will result in report execution errors, disabling of subscriptions etc..

Possible reasons for the encryption keys to be corrupted?

The most common mistake that happens is, when you change the Reporting services service credentials from the services.msc. This is certainly not the right approach and just remember, Reporting service encryption key corruption is an irreversible process.So if the key is lost or corrupt, then your production server instance will certainly be down and will not be able to process any report until corrective measures are taken like restoring a valid key back up and if you don’t have one, then reconfiguring all the report data sources.Again remember neither the product support nor the product development team can help you to get the keys back unless you’ve a valid backup of the encryption keys.

When you change the Report Server Windows service account, the asymmetric keys can become invalid, which will disrupt server operations. To avoid this problem, always use the Reporting Services Configuration tool to modify service account settings. When you use the configuration tool, the keys are updated for you automatically. For more information, refer  Configure the Report Server Service Account.

 

Right from day 1, the responsibility of taking periodic reporting service encryption key backup falls on the reporting services server administrator. And the usual way to take the backup is to take it from the Reporting services configuration manager tool or using the RsKeymgmt command line utility.

But, neither of them provides you a way to take periodic encryption key backup, without the human intervention. This is where my thought originated and the end solution is something I’m going to discuss further.

When this thought got originated in my mind, my first objective was to ensure I should just keep it simple. With that simple objective in my mind, it was easier for me to further visualize the things on how I’m going to achieve it.

And now, I’ve a solution in the form of a report it self! Yes, it is as simple as that. All I’ve done is the following simplified process.

1. Developed a custom assembly that makes appropriate WMI calls to create the encryption key backup.

2. A report that calls the custom assembly and takes the backup of encryption key at will.

Apart from taking the encryption key back up, it does log the success / failure event details in to the Application Event logs under the source “BackupSSRSEncKeys”. This will help you in making sure whether the key backup operation is successful or not.

Additionally, if there is an error, you have the option to enable detailed tracing in the report itself which would help you in further troubleshooting. The error details will be logged in the Application event logs under the source named, “BackupSSRSEncKeys”.

 

Recommended usage:
                          Create a simple FILE SHARE subscription for this REPORT with the frequency of execution to be once in a week or as per your organizational requirement. This will automate the encryption key backup process and ensures the back ups are taken in the scheduled intervals.

                           You could visit the FILE SHARE that you specify during the subscription creation, to view the copy of the recently executed report to see whether the backup is successful or any error has occurred.

image

Here are the simple 3 steps that you need to do to automate the encryption key backup process.

Make sure you download the attached Report and the custom assembly, BackupEncKeysWmi.dll from this blog.

 

a) Deploy the assembly:

 

Make sure you copy the assembly named “BackupEncKeysWmi.dll” to the following location:

 

<Installation Directory>:\Program Files\Microsoft SQL Server\MSRSx.Instance name\Reporting Services\ReportServer\bin

 

b) Add entry to the rssrvpolicy.cofig file: [Take the config file backup before modifying the same]

 

1. Open the Rssrvpolicy.config file located in the location:

<Installation Directory>:\Program Files\Microsoft SQL Server\MSRSx.Instance name\Reporting Services\ReportServer

 

2. Locate the CodeGroup section that contains Url="$CodeGen$/*" and go to the closing tag of the same CodeGroup section, which is just below </CodeGroup>.

 

3. Paste the below CodeGroup section immediately below the closing tag which you just located in #2.

 

<CodeGroup

                                                                                                class="UnionCodeGroup"

                                                                                                version="1"

                                                                                                PermissionSetName="FullTrust"

                                                                                                Name="MyCustomCodeGroup"

                                                                                                Description="Code group for BackupEncKeysWmi.">

                                                                                                            <IMembershipCondition class="UrlMembershipCondition"

                                                                                                            version="1"

                                                                                                            Url="<Installation Directory>:\Program Files\Microsoft SQL Server\MSRSx.Instance name\Reporting Services\ReportServer\bin \BackupEncKeysWmi.dll" />

                                                                                    </CodeGroup>

 

4. Make sure you’ve put in the right path location of your assembly in the step #3.

 

5. Save the file and make sure you restart the Reporting Services service from the configuration manager.

 

c) Edit and Upload the report:


Go to your report manager URL and upload the report named “BackupSSRSKeys”,


Few parameters for the report are to be provided through REPORT VARIABLES. It requires the report to be in edit mode either from BIDS / SSDT or Report Builder 2.0 (For RS 2008) / 3.0 (For RS 2008 R2 and above) and then to be re-deployed / saved back to the disk or report server (This is required to be done only for the first time and there after it doesn’t require any edit operation until you decide to change any of the variable values).
Kindly refer the below screen shot:

 

Editing report variables: (Refer the last part of this blog for variable definitions)

BIDS / SSDT:

Go to Report menu -> Report properties and then move to Variables tab.

Report builder 2.0 / 3.0: (This even applies to BIDS / SSDT as well)


Right click
anywhere outside report canvas, select Report properties and go to Variables tab.

clip_image002

 

 

 

That’s it! You’re now ready to offload your encryption key backup process to reporting service itself and that too without the worry of remembering when was the last time that you took the backup.

This encryption key automation solution has been tested on Reporting services 2008 and above running in native mode. It might work with Reporting services 2008 and 2008 R2 in integrated mode. But I’m yet to perform the testing on this.

 

This report is not meant to be executed as an on-demand report (Though it does no harm). The preferred way is to create a subscription for the report and schedule it to run in the desired frequency in which you want the encryption keys backup needs to be taken. This is sole purpose for which I created this report.

 

It is recommended that you override the default security on this report and ensure only necessary users (Reporting server admins preferred) have the browser privilege on this report. This measure is to enforce restricted security on this report and the information’s that are stored within the report.

 

Since the report takes sensitive details like Encryption key backup password, Local Administrator user credentials of Reporting services server, the input details for them have to be provided through REPORT VARIABLES. It requires the report to be in edit mode either from BIDS / SSDT or Report Builder 2.0 (For RS 2008) / 3.0 (For RS 2008 R2 and above) and then to be re-deployed / saved back to the report server (only for the first time and there after it doesn’t require any edit operation until you decide to change the variable values). This measure has been taken to ensure the sensitive details are not exposed. Please refer the screen shots placed at the end of this document on how to access these report variables.

 

General recommendation would be to avoid using any personal user account to be stored in the report variables. Though there are maximum security measures taken in order to safe guard sensitive information, users belonging to local administrators group in Reporting services server can still download the Report and view the stored user credentials. As a best practice, either create a local machine account / domain user account, add it to local administrator group and use it dedicatedly for this purpose as this provides maximum security cushion.

 

If you’ve more than one instance OR Version of Reporting service installed in the same machine, you don’t need to deploy the report in each instance. The backup of encryption keys can be taken on any instance (Need to be run separately for each instance) irrespective of the version, provided if they exist on the same machine. Again this applies only to instances running on or above Reporting service 2008.

 

Report variables and their definitions:

Sl.no

Report variable

Mandatory requirement

1.

keybackuppassword

a. Type a password that protects the encryption key against unauthorized access. Only users who know the password will be able to restore the key that is locked inside the file. If you lose this password, then it is an irreversible process.

 

b. Reporting Services enforces a strong password policy. The password must be at least 8 characters and include a combination of uppercase and lowercase alphanumeric characters and at least one symbol character.

2.

Impersonateusername

(Local Administrator on Reporting Services machine and have WRITE  permission on the Key file path)

a. Provide the user name without any domain prefixes.

b. This user name should be a local administrator on the Reporting Service machine.

c. This will be the user context under which the entire encryption key back up will be executed.

d. The user should have WRITE access on the folder that you specified in parameter #2 (Refer above table).

3.

Impersonateuserdomain

(Domain to which the user specified in variable #2 belong. Ignore, if it is a local machine account)

1. Domain name that the user in parameter #5 belongs to.

2. You can ignore this parameter, if the user is a local machine account in Reporting services server.

3. There is no harm in providing the local machine name as well, in case of Reporting services server local machine account.

4.

Impersonateuserpassword

(Corresponding password for user specified in Variable #2.)

The corresponding password for the user name that is specified in the variable #2.

 

Report Parameters and their definitions:

Sl.no

Report Parameter

Mandatory requirement

1.

Reporting services Instance Name(S) (Separate each instance names with ';' if reporting service is scaled out):

a. At least one report server instance name is required.

b. If the reporting service is scaled out, then make sure you provide all the instance names, each separated by a “;”.

c. One of the way to pick up Reporting service instance name is from the below path,

<Installation Directory>:\Program Files\Microsoft SQL Server\MSRSx.Instance name\Reporting Services

 The section after “MSRSx.” gives you the required Instance name.

2.

Path to store the backup key (UNC path like \\machine1\keys is preferred):

a. This path will be used to store the backed up encryption key.

b. It is preferred if you provide a UNC path. But not restricted to it.

c. Make sure the path does exist else backup operation would fail.

d. The user information that you provide in parameters #5, 6, and 7 should have WRITE access on this folder.

 

3.

Reporting Services Version:

a. This is super important for Reporting service to communicate with the right Reporting service instance.

b. At this point of time, you can take back up Reporting service 2008, R2 and 2012 instances in Native mode.

c. Your option should be one of them.

4.

Enable Advanced Diagnostics (Logged in Application event logs):

a. If you encounter any error message and you want to send the details across to me, then enable it by setting the parameter to “True”.

b. By default, the value is “False”.

 

I sincerely believe this will be a great asset in your organization from saving the Reporting server instance going down unexpectedly due to encryption keys getting corrupted.

Please do let me know if you come across any difficulties in using it, failures and I’ll rectify them.

 

HTH!

Selva.

[All the posts are AS-IS without any warranty]

SSRS SharePoint List data provider querying a SharePoint List in Claims enabled site with Windows and Forms Based Authentication selected

$
0
0

Have you tried creating a report in BIDS / SSDT / Report Builder 3.0 using the Reporting Services(SSRS) SharePoint List extension against a SharePoint list in a Claims based SharePoint site?

The Claims authentication has both Windows and Forms based authentication enabled.

The unique property for the SSRS SharePoint list provider is, it only accepts windows based credentials. So when you use either one of Windows Credentials, Stored credentials (Use as Windows credentials), Prompt for credentials option and execute a query against the SharePoint list provider, visual studio (BIDS / SSDT) would throw the below error.

 

TITLE: Microsoft Visual Studio
------------------------------

Server was unable to process request. ---> Access is denied. (Exception from HRESULT: 0x80070005 (E_ACCESSDENIED))


------------------------------
ADDITIONAL INFORMATION:

Server was unable to process request. ---> Access is denied. (Exception from HRESULT: 0x80070005 (E_ACCESSDENIED)) (System.Web.Services)

------------------------------
BUTTONS:

OK
------------------------------

The point here is, when you get this exception, don’t be surprised. The reason is, A SharePoint web app under any claims authentication type will simply tell you it is in forms authentication mode if you query the AuthenticationMode property.

This behavior is by design as the SSRS client tools like BIDS, SSDT, Report Builder 3.0 are all claims agnostic.

 

Having said that the immediate questions is, then how can I consume SharePoint list provider under these circumstances. For that, I’m listing out 3 options and please feel free to use one of them.

1. Temporarily disable Forms based authentication for the specific Claims enabled SharePoint site and design, test your reports.

2. Deploy the report to the Claims enabled site and execute the report directly from the Document library.

3. Extend the SharePoint web application in a different zone with just Windows authentication selected and use this site for testing.

More on Claims Authentication and Reporting Services can be found here @ http://msdn.microsoft.com/en-us/library/ff487970(v=SQL.105).aspx

HTH!

Selva.

[All the posts are AS-IS without any warranty]

SharePoint web part page hosting ReportViewer web part fails with Sys.WebForms.PageRequestManagerTimeoutException: The server request timed out

$
0
0

Have you ever run in to a scenario where you’ve Reporting service in SharePoint integrated mode. You’ve a web part page that hosts the Report Viewer web part that comes with the Reporting services Add-in.

The report takes more than 90 seconds to complete the rendering.

Under this circumstances, You open the web part page just to ensure the report renders successfully. Everything starts fine and the small green icon "Loading...." is shown in the screen.

All of the sudden, to your surprise you find your web part page suddenly stopped and just displays a blank page. You see a JavaScript error message on the screen or a small yellow triangle in the IE status bar with the message Done and there is no rendered report displayed as per your request.

 

When you look in to the message (Yellow triangle), it shows the error message similar to the following,

Message: Sys.WebForms.PageRequestManagerTimeoutException: The server request timed out.

The above error in the browser is caused because of the ScriptManager's AsyncPostbackTimeout. By default it is 90 seconds.

http://msdn.microsoft.com/en-us/library/system.web.ui.scriptmanager.asyncpostbacktimeout.aspx

So, all you need to do is, locate the ScriptManager element in the master page file that is being used by your site that hosts the web part page and change the timeout value to 0 meaning "Do not timeout".

How to find the Master page used by the site?

Pretty simple. Open your SharePoint 2010 / 2013 Management shell (If UAC is enabled, please open it by right clicking and selecting “as Run as Administrator”).

Once the Management shell initializes itself, run the following PowerShell command:

$web = Get-SPWeb http://yoursiteURL

$web.MasterUrl

Now this will actually give you the master page being used by the site.

In my case it was,

/_catalogs/masterpage/seattle.master

Now, all I had to do was, open the web part page in edit mode using SharePoint Designer (If not installed, please download it as comes free of cost).

Click on the Master Pages sections in the left hand side, Click on the seatle.master page (Or whatever being used in your site) from the Right hand side display and click on Edit file option under Customization.

image

 

Now you’ll be in the HTML view of the same file. Search for ScriptManager in that page and add AsyncPostBackTimeout="0" as shown below.

<asp:ScriptManager id="ScriptManager" runat="server" EnablePageMethods="false" EnablePartialRendering="true" AsyncPostBackTimeout="0" EnableScriptGlobalization="false" EnableScriptLocalization="true" />

image

Save and close the SharePoint designer.

Now view the web part page and you would see the rendered report now. Doesn’t it help you

HTH!

Selva.

[All the posts are AS-IS and with no warranty]

Report Headers and Footers with Microsoft SQL Server Reporting Services

$
0
0

 

You would have seen page headers and page footers for reports (Can be enabled through the Report menu –>  Add Page Header / Add page footer in BIDS).

Have you ever wondered how to have report headers and report footers for your reports? Here you go, look at the below post on how to achieve the same.

As you all are aware Page headers and footers very easy to add and manage. But there is nothing built in as such for report headers / footers.

So any textbox before the start of first data region will serve as report header and any textbox after the last data region will serve as report footer.

Still confused and things are not clear, then look at the below image which will help you to understand things better.

image

Hope this clarifies what is a report header / footer and how to add one in your report.

Enjoy and enhance your reports with this awesome tool.

HTH!

Selva.

[All the posts are AS-IS and doesn’t carry any warranty]

Creating your own report templates when using Microsoft SQL Server Reporting Service

$
0
0

 

When you’re creating a reporting service solution for your organization, the first thing you would decide before going any further with the report design is the finalization of a report template.

A standard template does add professional look to reports that are developed and deployed all across the organization.

How far have we gone and thought about creating a report template with reporting service, that can be used by all the report designers in your organization?

Have you even imagined the amount of consistency, professionalism and time / cost savings that it brings in?

If you have not thought about that, here is the article that will help you in achieving all that it talked above.

A report template is nothing more than a partially completed report (RDL) file. You can add your own report templates to the BIDS report project template items folder.

The default installation path for this folder is (For reporting Service 2008 / R2) C:\Program Files\Microsoft Visual Studio 9.0\Common7\IDE\PrivateAssemblies\ProjectItems\ReportProject.

Ok. Here is how you can create a report template.

1. Open a new Report Server project in your Business Intelligence Development Studio.

2. From the solution explorer, reports folder, Right click and choose Add –> New Item. Select report under the Visual studio installed templates and rename it as per your convenience.

3. Just design the report as any normal report, but without any dataset and data items. You can add the report header / report footer, Page header / Page footer, Your logo, Some image / color background for the report, common globals like Page numbers/ total pages, lines etc.

image

4. Save the report.

5. Now copy the above created RDL file and paste it in the Visual studio project items folder,

C:\Program Files\Microsoft Visual Studio 9.0\Common7\IDE\PrivateAssemblies\ProjectItems\ReportProject.

image

Now, how to use the created report template in your project?

It is as simple as that. All you need to do is, Add a new item in a similar way (From the solution explorer, reports folder, Right click and choose Add –> New Item.)

You’ll see the newly added template under the Visual studio installed templates. Just select that with your own report name. It’ll create a copy of the template and put the report in your project solution.

image

Happy reporting!

HTH!

Selva.

[All the posts are AS-IS and doesn’t carry any warranty]

Invoking the Print dialog for report viewer 2010 control using the JavaScript API

$
0
0

 

Have you tried the new JavaScript libraries exposed by Report viewer 2010 control? Please go through Brian’s blog on JavaScript API and the MSDN documentation on the same.

Ok, now lets see how we can leverage one of the methods to invoke the Print dialog for Report viewer.

We’re going to make use of Microsoft.Reporting.WebFormsClient.ReportViewer.invokePrintDialog Method.

Create a new ASP.NET project in VS 2010 (If you’re using VS 2008 and still want to use RV 2010 , then you need to the change the references accordingly apart from adding the Scriptmanager to the page) and drag and drop a Report Viewer 2010 control in an ASP.NET page (Named ReportViewer1 in our sample).

Set the properties like, Processing mode (Local or Remote), ReportServerURL (Incase of Remote processing mode) and the Report path.

Then switch back to the design view and get in to the HTML view.

Here is the piece of javascript you need to use to complete this exercise. This needs to be put in immediately next to the close of the </form> tag.

<script language="javascript">
         function PrintReport() {
             var viewerReference = $find("ReportViewer1");

             var stillonLoadState = viewerReference.get_isLoading();

             if (!stillonLoadState ) {
                 var reportArea = viewerReference .get_reportAreaContentType();
                 if (reportArea == Microsoft.Reporting.WebFormsClient.ReportAreaContent.ReportPage) {
                     $find("ReportViewer1").invokePrintDialog();
                 }
             }
         }
     </script>

Lets see what the above function mean to you and me.

The ReportViewer client side object inherits from Sys.UI.Control. To obtain a reference to the client side viewer, use the $find method as follows:

var viewerReference  = $find("ReportViewer1");

The identifier you pass to $find corresponds to the ClientID of the ReportViewer server control.

Now having the reference for the client side viewer, you will want to check the state of the viewer before invoking most of the various methods and properties it exposes. When the viewer is in a loading state, most of the functionality of the client viewer is unavailable and will throw an exception if called. So you got to be extra careful here.

The viewer is loading whenever an asynchronous postback is in progress. It is also in the loading state while retrieving a report page. This usually happens during an asynchronous postback, but can also extend beyond the lifetime of the postback, such as while retrieving images displayed on the report page. To check the state of the viewer, use the isLoading property:

var stillonLoadState  = viewerReference .get_isLoading();

Once you have determined that the viewer is no longer loading new data, you can determine what is being displayed using the reportAreaContentType property. It will indicate if the viewer is blank, displaying a report, or displaying an error message:

 

if (!stillonLoadState ) {
var reportArea = viewerReference.get_reportAreaContentType();
if (reportArea == Microsoft.Reporting.WebFormsClient.ReportAreaContent.ReportPage) {
$find("ReportViewer1").invokePrintDialog(); // Perform any operation as per your requirement.
}
}

Finally all you got to do is, put a HTML button on the page named Print and call the PrintReport function (defined in the above javascript) for button’s onClick event.

<input id="Button1" type="button" value="Print Report" onclick="PrintReport();"/>

Now the obvious question that comes is, The Report viewer tool already provides the out of the box print functionality. Then when should I go for the Microsoft.Reporting.WebFormsClient.ReportViewer.invokePrintDialog Method?

1. You want to disable the toolbar for some reason and still want provide Print functionality.

2. You do not want to show the report viewer control itself to the end user, but just provide a link to Print the report directly.

#1 can be easily done by just changing the ShowToolBar property to False.

But implementing #2 will be little tricky. The reason is, the moment you change the visibility of the report viewer control to hidden, the $find method will return NULL, which eventually make the the rest of our operation to fail. But this can be accomplished in a little tricky way and in multiple steps.

1. Turn off the tool bar by changing the ShowToolBar property to False.

2. Then change the Height and Width property of the control to 0.

This will leave the report viewer dis appear at runtime.

But whenever the report viewer loads the report you’ll still get the small animation. If you’re fine with just showing that then it’s ok.

Otherwise you might need to turn off AsyncRendering of the report viewer by changing the AsyncRendering="false".

The below piece of block summarizes what we just discussed.

<rsweb:ReportViewer ID="ReportViewer1" runat="server" Font-Names="Verdana"
            Font-Size="8pt" Height="0px" ProcessingMode="Remote" Width="0px" ShowToolBar="false" AsyncRendering="false">
            <ServerReport ReportPath="/Somereport"
                ReportServerUrl=http://servername/reportserver />
        </rsweb:ReportViewer>

Happy programming using Report viewer 2010 control.

HTH!

Selva.

[All the posts are AS-IS and doesn’t carry any warranty]


Interactive sorting in Reporting service fails with rsReportNotReady exception

$
0
0

Recently i came across an interesting issue where the Interactive sorting in reports fail with the following exception,

The selected report is not ready for viewing. The report is still being rendered or a report snapshot is not available. (rsReportNotReady)

Interestingly after much of the scratches and troubleshooting, we looked at the database level setting by running the following command,

select * from sys.databases

And obsever the columns,

snapshot_isolation_state_desc

is_read_committed_snapshot_on

for report server and report server tempdb databases.

If the values shows ON and 1 for the respective column values, then there lies the problem.

By default these values are OFF and 0 for these databases.

So you need to change them back to the default values by running the following SQL scripts,

 Now try running the report and check the Interactive sorting. This should fix the issue.

ALTER DATABASE ReportServer

SET ALLOW_SNAPSHOT_ISOLATION OFF

 

ALTER DATABASE ReportServerTempDB

SET ALLOW_SNAPSHOT_ISOLATION OFF

 ALTER DATABASE ReportServer

SET READ_COMMITTED_SNAPSHOT OFF

 

ALTER DATABASE ReportServerTempDB

SET READ_COMMITTED_SNAPSHOT OFF

 

 

 HTH!

Selva.

[All the posts are AS-IS and doesn't carry any warranty]

Browsing a report from Report manager / Report server always show page 0 of 0 in the tool bar

$
0
0

Recently i came across another interesting issue where,

When browsing report server URL and then viewing any report that spans multiple pages shows 0 of 0 pages in the tool bar. This also disables the page navigations.

You'll see a very similar behavior when viewing the reports from Report manager as well. The difference here is, the page navigations are enabled and it works eventhough it shows 0 of 0 pages and it doesn't change when we move to next page.

You'll not see any error message either in the page or in the log files.

The same reports work fine from BIDS.

Resolution for this issue is the same as the one which i posted here,

http://blogs.msdn.com/b/selvar/archive/2011/04/28/interactive-sorting-in-reporting-service-fails-with-rsreportnotready-exception.aspx

Following the action plan mentioned in the above blog post should fix this issue.

 HTH!

Selva.

[All the posts are AS-IS and doesn't carry any warranty]

Report builder 3.0 stops responding after you run a query more than two times against a report model when Authentication mode for Reporting Service 2008 R2 is set for Basic or Custom authentication

$
0
0

Recently few of our customers complained about the issue of Report builder 3.0 not responding upon certain operation.

It was very tricly scenario and it took us much time to exactly figure out what could have caused the issue.

This happens only under the following scenarios,

1. Reporting service is set to use either Basic or Custom authentication.

2. When creating a report against Report models.

If you're running your reporting service in any patch level less than CU 7, then you could certainly fall in to the issue if both (1 & 2) are TRUE.

Here is how you can REPRODUCE the behaviour under the above mentioned circumstances,

  • You have a computer that is running Microsoft SQL Server 2008 R2 Reporting Services (SSRS 2008 R2) in native mode.
  • You enable forms-based authentication or basic authentication on an instance of SSRS 2008 R2.
  • You start Microsoft SQL Server 2008 R2 Report Builder 3.0 from Report Manager or from a stand-alone Report builder 3.0 installation on a client computer.

    Note The client computer is not the one that hosts a SSRS 2008 R2 installation.
  • You create a report or shared dataset that is based on a report model project.
  • You run a query either one time in the Query Designer window, and then you click OK or you run the query more than two times in the Query Designer window.

In this scenario, Report Builder 3.0 stops responding.

We from the Microsoft support team and the Product development team worked together to Debug and FIX this issue and the fix is now available as part of Microsoft SQL Server 2008 R2 CU 7.

More details about this issue can be found from the related KB article,

http://support.microsoft.com/kb/2516163

Also the FIX can be downloaded from the above location.

The FIX includes Report server side fix for Report builder 3.0 click once application and also for the stand alone Report builder 3.0 installation.

HTH!

Selva.

[All the posts are AS-IS and doesn't carry any warranty]

Modifying report variables in Reporting service 2008 R2

$
0
0

I've seen multiple times where we create a Read / Write Report variable (Group variables are striclty Read only) but not able to find a way to over write the value during the report execution phase.

Here is a way to do it.

Assume that you've created a report variable named "Reportvariable1".

All you need is a piece of custom code.

Public Function SetVariableValue(val as Microsoft.ReportingServices.ReportProcessing.OnDemandReportObjectModel.Variable)

val.Value = val.Value + 2

End Function

As simple as that. All i'm doing in the function is, take the report variable reference, add 2 to the existing value. That's it.

How you can call this function from your report item?

=Code.SetVariableValue(Variables!Reportvariable1)

This will do the magic. Also note that in the above expression i'm just passing the variable reference and not its value.

You could always make some modifications in the way you want. For example, you want to modify the variable with a customized value and display the same in the textbox, here is what you need to do in the function.

Public Function SetVariableValue(val as Microsoft.ReportingServices.ReportProcessing.OnDemandReportObjectModel.Variable, newval As Integer) as Integer

val.Value = val.Value + newval

Return Val.Value

End Function

And call it from a textbox,

=Code.SetVariableValue(Variables!Reportvariable1, ReportItems!Textbox1.Value)

Hope this helps!

Selva.

[All the posts are AS-IS with no warranty]

ReportViewer 2010 Winforms control takes too much of time to render a local mode report (RDLC) when we launch the application using ClickOnce.

$
0
0

Have you ever wondered why launching an application that has Report viewer 2010 Winforms control through clickonce takes multiple times more time to render the report in Local mode? Try launching the same application directly by double clicking the EXE. Now you will understand what i'm taking about.This behavior certainly relates to the design of your report like amount of data being retrieved and the amount of expression used in the report.

Well, if you're compiling your application in .NET framework 4.0, then you're certainly bound to see the issue irrespective of how you launch the application. But the above observation is related when you run the application hosting report viewer 2010 winforms control in .NET Framework 3.5.

You can find more details on execution mode and the Sandbox execution model directly from Brian's blog @ http://blogs.msdn.com/b/brianhartman/archive/2010/02/18/expression-evaluation-in-local-mode.aspx

Coming back to our scenario of running the application under .NET 3.5, then who causes this impact?

Ok. To come straight to the answer, Clickonce technology chooses Simple Sandboxing execution mode by default. You can understand more about this from http://blogs.msdn.com/b/shawnfa/archive/2006/04/19/579066.aspx

Now in report viewer 2010 control, we use certain application logic to decide whether the report viewer 2010 control should execute in the Sandbox mode or not. Because ClickOnce already set a specific flag regarding the Sandbox execution, in the report viewer when we check the flag it is set to execute in Sandbox mode. So report viewer 2010 control continues to execute the application in the Sandbox mode. Hence even in .NET 3.5 framework, you always have the feeling that your application is actually running under .NET Framework 4.0.

Unfortunately there is no workaround for such scenarios. The options are either to drop ClickOnce or to use older version of the report viewer control.

As an application developer, if you've an application launched through ClickOnce and using older version of ReportViewer control and you've plans to move to Report viewer 2010 or you've already moved to Report Viewer 2010, please do not be surprised if you encounter the above discussed behavior.

As an application developer, if you've an application using Report Viewer 2010 or above and running in .NET Framework 4.0 or above, please do not be surprised if you encounter the above discussed performance behavior. This is by design.

 

 HTH!

Selva.

[The above post is AS-IS and doesn't carry any warranty]

 

 

 

Viewing all 154 articles
Browse latest View live