Serge's Technology View

Talk about Technologies, Software Architecture and Management

Posts Tagged ‘crystal reports viewer’

Crystal Reports 2008 and ASP.Net : speed up the first session

Did you ever noticed that after restart of the IIS ASP.Net page which has Crystal Reports Viewer would take much longer to come up?

Some of it is expected since on initial start up, a number of Crystal assemblies and objects need to be created and this does take time.
I want to emphasize that discussion below is related to the first run of any reports. We have to actually restart/reset IIS to see problem again.

Note: There was a question about IIS’ Application Pools recycling which could cause similar effect. Make sure your application pool is set properly.

Setting up a playground

Let’s assume ASP.Net pages were already migrated to use .Net 3.x and look at what happen behind the scene.

Remember that after restart IIS starts from ground up. This means several things in respect to our page content:

  • .Net assemblies need to be preloaded and validated if necessary.
    Since Crystal Reports 2008 comes as .Net 2.0-based core and we may already moved to .Net 3.x, CR2008 Engine and some additional files need to be loaded and validated aside from one which already used by any previously loaded pages.
  • For each session engine would create a cached version of RPT file in temp folder.
  • Some code would have to be brought to the client machine for Viewer to operate properly.
  • Database connection established, data retrieved, processed, paged and sent to the client Viewer.

That about it, now we ready to work with reports. Please notice that after that initial load, any other reports would come up faster. We could even close the browser or use another browser (ex. go from IE to FF) and it would be still faster than the first time, so there is something important about the first step above…

Combing the sand

Let’s try to break the IIS initialization process to get more detailed view.

Since we already had some ASP.Net pages loaded before coming to CR related page, we could disregard .Net core initialization procedure. It is there on IIS side: used and ready.

Ok, next thing is CR engine related stuff. There is some 5Mb of files in crystalreportviewers12 folder to support CR Viewer in ASP.Net and we need to send some of them over the network. In addition to that there is Crystal Reports Engine assemblies which need to be loaded by IIS at the time of the first use. And this is our spot to dig.

If we try and trace what exactly going on we would notice that aside from IIS loading a few dozen assemblies, there is also process associated with trying connect to CRL.VERISIGN.NET.

What is it?

“Problem” is that assemblies are Authenticode signed and therefore need to be verified or it technical terms they need to be checked against Certificate Revocation List (CRL) by Publisher for Code Access Security (CAS).

Default behavior is that they need to be verified by the certificate authority. If certificate is not present on the same machine (I have my doubts that SAP doing anything about that, but I could be wrong), validation need to be done via central repository mentioned above, or if machine does not have network/internet access the .NET thread might timeout waiting to connect.

Yes, by performing strong name signing of assemblies or placing the CA certificate on the same machine issue would be avoided, but it seems not being a case.

Building the castle

Since assemblies are provided by SAP, we cannot remove digital signature and it is a hassle to keep certificates current by obtaining them from CA every time they expire. Let’s concentrate on the Publisher mentioned above and turn it off.

It is all-or-nothing solution since it would require turning off CRC for the entire IIS.

When working with regular .Net apps, it can be done on the app level (assuming we already have fix for .Net 2.0) by adding the following section in <Application>.exe.config

<configuration>
  <runtime>
    <generatePublisherEvidence enabled="false"/>
  </runtime>
</configuration>

This new element described in this MSDN article. Interesting note there (why not to turn it then by default? Oh, security concerns… UAC anyone?):

We recommend that services use the <generatePublisherEvidence> element to improve startup performance. Using this element can also help avoid delays that can cause a time-out and the cancellation of the service startup.

Since there is no such config file for our ASP.Net app (web.config would not work here, because it defines settings that are only AppDomain wide and we need process wide for aspnet_isapi.dll being the hosting environment for the runtime), we would have to turn code access security (CAS) publisher policy off for the entire IIS.
There are two options:

  • Create a file called w3wp.exe.config (for IIS6, or aspnet_wp.exe.config for IIS5). This will affect all .NET based web applications on the system.
  • Or to specify this in machine.config, but then this affects every .NET application on the machine and is not available for override in individual Apps.

Adding the summer cabin

There is one more step which could be taken to improve performance by preloading some of the core assemblies while site visitor is doing something else.
I wouldn’t go into much details here, since it is implementation/application environment specific, but just give a hint:

  • some other place in application, create a background process which would create CR document object, load some not essential report file, retrieve some data and then disapear without the trace. This would allow Crystal Reports Engine being initialized in the background offsetting time needed for the actual CR related page load. Don’t force garbage collection though, this may cancel desired effect.

Results

In some situation I observed 50% to 70% drop in start-up time…
Have fun!

Expiration of CrystalReport Viewer pages with long running queries

Wow! It worked…

I continue my journey with Crystal Reports Viewer (CRV) inside ASP.Net pages.
Topic of this post is to discuss problems and solutions related to long running queries in CRV.

Before continue I would like to thank Daniel Paulsen from SAP team for his help resolving the issue discussed below.

What are we talking about here?

As it usually happens at some point there is to much data/not optimal query/broken indexes/etc and it is takes significant time to return a result for CR report. As a result ASP.Net page with CRV start to throw errors, acts erratically, and overall strange.

Since we know that it is ASP.net and CRV uses page state and session information then we have usual suspects - session timeout and execution timeout.

Easy? Not so fast… Lets time our query – if it is more then 10 but less then 20 minutes then reason is not an ASP.Net timeout, but CR Engine timeouts.

Crystal Reports Engine Timeouts

Aside from timeouts imposed by .net infrastructure, there are two others which are introduced by Crystal Report itself.

Symptoms:

  • Error similar to ‘Request timed out because there has been no reply from the server in N ms’
  • First Page of the report is displayed but attempt to go to the next page gives JS error related to invalid object ID
  • If report require parameter entry, they are requested again

Cause:

Crystal Reports by default has a timeout of 10 minutes (600,000 ms) before deciding that no data is returned by the query.
Depend on how code behind is implemented for the report page, timeout error may cause different problems and be hidden.

Solution:

Per Daniel’s suggestion I have changed the following settings to a bigger number and it did solve the problem for me

HKEY_LOCAL_MACHINE\SOFTWARE\Business Objects\Suite 12.0\Report Application Server\Client SDK\CorbaAdapter\WaitReplyTimeout = 600000

and

HKEY_LOCAL_MACHINE\SOFTWARE\Business Objects\Suite 12.0\Report Application Server\InprocServer\EnterpriseRequestTimeout = 600000

Final Note:

There are other settings which are allowed to be set for the CR engine as described in Developer’s Guide for CR 2008 under “Configuring your Web.Config file“. It worth to know about some of them.

Crystal Reports 2008 : hacking datetime parameter format – reloaded

Few weeks ago I have wrote on how to hack Crystal Reports 2008 ASP.Net Viewer control to suppress time part in the parameter calendar control.

With release of Service Pack 1 for Crystal Reports 2008, suggested solution no longer works since structure of the files has been changed.

So I went digging around again. Forgot to mention last time, but in situations like this, scripting debugging supported in Visual Studio really helps (if you are not familiar with JS debugging check following links [1] [2] for more info.

Note. It is interesting to observe how code is changing over time. And after some analisys, I would say that SAP development team is one click away from adding ability to suppress time parts for datetime parameters: only one thing missing – new property on parameter level which would allow specify how to treat it (date, time or datetime). Question is if they will decide to do so.

I will be using Visual Studio 2008 and run against my WebDev.WebServer.

After creating simple CrystalReports ASP.Net application with report which has datetime parameter, lets see what exactly is happening here.

Step 1 Step 2

Let’s run an application up to the point when engine would request parameter values being entered (Img 1).

And then let’s open Solution Explorer in Visual Studio (Img 2).
You would notice a few JavaScript files, where one we were looking for - promptengine_calendar2.js.

While having page open, dbl-click on the file in Solution Explorer and look around. (In my case actual file location is C:\Windows\Microsoft.NET\Framework\v2.0.50727\ASP.NETClientFiles\crystalreportviewers12\prompting\js\, but may vary.)

Internal Calendar control (which reside in Calendar.js file) relay on setShowTime method to manage visibility and behaviour of the calendar and this is where we will “hack” our way in.

As usual code below only highlights changes to the code in promptengine_calendar2.js file.
This time I am making no changes to the data, only how it is displayed and extracted from the calendar control. And it seems to work much better then prior solution.
Make sure you have the copy of original file backed up.

/** First, lets add one more variable to control data flow **/
    bobj.prompt.Calendar = function
    ...
       this.isDateTimeData = false;
    }
...
    /** While suppressing DateTime format we still need to know original type of the data **/
    setIsDateTime : function(isDateTime) {
       // this.isDateTime = isDateTime;
       this.isDateTimeData = isDateTime;
       this.isDateTime = false;
    },
...
    /** while suppressing time part, it is still need to be returned back in to parameter form **/
    _getStringValue : function(dateValue) {
        var format = this.isDateTime ? this.dateTimeFormat : this.dateFormat;

        if ((!this.isDateTime) &amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp; this.isDateTimeData) {
                format = format + ' 00:00:00';
        }

        return  bobj.external.date.formatDate(dateValue, format);     
       
    },

Changes are very isolated and allows a) hide time entry box and b) properly return data back into parameter form.

This solution is generic and applies to all datetime parameters visible. As a result, calendar control become for date entry only, while resetting time portion. User can still enter time part if necessary, but on the page level.

Again, make sure that file with changes we just made is replaced everywhere. Depend on your development and production environment you may have few other locations for it.

Crystal Reports 2008 : hacking datetime parameter format

One would think that this should be a no-brainer : ability to specify an edit format for date/time parameter in Crystal Reports. Not so fast…

Problem is as following:

ASP.Net Web client with Crystal Reports Viewer control is used.

When our report is based of some stored procedure which uses datetime parameter, it will inherit it as is and when report parameter entry form is displayed we would be asked to enter both date and time portion.

While, in general, it is OK, some reports are really interested only in date part being entered and time should be always set to 00:00:00. So we are forced to type time every time because if it is not provided calendar control would try to set time part initially to current time.

After some research off the Internet, visiting SAP forums, it is appear to be engine limitation. But we would want to overcome it somehow.

DISCLAIMER: solution below could only be used as a last resort and only if your business logic requires using date only params. And while it is only applies to calendar control, it is not per se a generic solution. This is a first “rough” attempt of achieving desired result and may lack some features otherwise expected.

It has been reported that solution above only works for current month. Since we are now using Crystal Reports 2008 with SP1, I would address this issue in my new post below.

IMPORTANT! With release of Service Pack 1 for Crystal Reports 2008, method blow is no longer applicable since structure of the files has changed. Please refer to this new post for more information.

Otherwise, Where there is a will, there is a way…

Fortunately we have access to internals behind the parameter handlers in Crystal Report Viewer web control.

Navigate to one of following locations:

  • C:\Inetpub\wwwroot\aspnet_client\system_web\2_0_50727\crystalreportviewers12\
  • C:\windows\Microsoft.NET\Framework\v2.0.50727\ASP.NETClientFiles\crystalreportviewers12\
  • C:\Program Files\Business Objects\Common\4.0\crystalreportviewers12\

and locate the file called allInOne.js – this is our victim. This file contains all JS code behind for CRV control which would be used by your web-site.

IMPORTANT: always create a backup copy before making any modifications.

(more…)

Valid XHTML 1.0 Transitional  Valid CSS!