Serge's Technology View

Talk about Technologies, Software Architecture and Management

Archive for the ‘Web-design’ Category

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!

How to embed Google Docs document into your page

There are plenty of presentations, documents, and spreadsheets we may want to share with the world.

We can use homegrown document handling solutions, use commercial 3rd party solutions or… utilize power provided by Google Docs.

When storing articles on Google Docs you are provided with the option to share them with some people only or with everyone. I like to have option to link my articles from anywhere but I also like to have not just plain page, but a page embedded into my web-site pages.

What it means is that instead of external page, I want to put it in my own box.

There was time when it wasn’t as easy because of the additional code Google was injecting into articles, but time changed and now it is fairly easy and strait forward.

Goals

  • Embed Google Docs document into existing page
  • PHP. This is not really a requirement per se, it is just code below is PHP.
  • Retain copyright information

Solution

The following code snippet allows to get a desired result

// id parameter is used to pass Google Docs arcticle id
// Example: mydocview.php?id=nnnnnnnnnnnnnnnn

$id    = $_REQUEST['id'];
if ($id) {
  $started = "0";
  echo('<div class="googledocs" >Stored and managed via <a title="Learn more about Google Docs" href="http://docs.google.com" target="_blank">Google Docs &copy; -- Web word processing, presentations and spreadsheets.</a></div>');

  // Read document content, parse to normalize and output
  $file = fopen ("http://docs.google.com/View?id=" . $id, "r");
  while (!feof ($file)) {
    $line = fgets ($file, 4096);

    // Parse header info out
    if ($started == "0") {
      if (substr($line, 0, 5) == '<body') { $started = "1"; }
      else { continue; }
    }

    // Parse body content until document content block is detected
    if ($started == "1") {
      if (strstr($line, '<div id="doc-contents">')) { $started = "2"; }
      else { continue; }
    }

    // Output document content
    if ($started == "2") {
      // Stop processing, end of content reached
      if (strstr($line, '<div id="google-view-footer">')) { break; }

      // Normalize image links to keep link back to google docs
      $line = str_replace('src="File?id', 'src="http://docs.google.com/File?id', $line);

      // Normalize links to other articles
      $line = str_replace('href="View?docid=', 'href="/mydocview.php?id=', $line);
      $line = str_replace('href="View?id=', 'href="/mydocview.php?id=', $line);
      $line = str_replace('href="View?docID=', 'href="/mydocview.php?id=', $line);
      $line = str_replace('href="View?', 'href="/mydocview.php?', $line);

      // Output result
      echo($line);
    }
  }
  fclose($file);
}

Sample page:

<html>
<head></head>
<body>
<? // Include code above here
?>
</body>
</html>

Visual Studio 2008 and IIS 7

Deploying ASP.Net applications is always fun when it comes to packages which are more complex then usual and require additional actions taken and this one is not an exception.

I think this topic run into the ground, but it seems to come back again and again. I guess the reason for that is “default” state set for the environment…

After upgrade of operating system to Vista IIS 7 would be installed. This brings some “inconveniences” into usual development process. Aside from worrying about disabling UAC, few other things usually breaks.

One of them is that setup package for ASP.Net application created in Visual Studio starts to fail with the error that installer session closed improperly and process has to be restarted (or similar).

If we look into installer log (check here on how to enable debug mode) the following error could be found:

Action 11:18:53: WEBCA_SetTARGETSITE.
Action start 11:18:53: WEBCA_SetTARGETSITE.
MSI (c) (B4:A4) [11:18:53:657]: Note: 1: 2235 2: 3: ExtendedType 4: SELECT `Action`,`Type`,`Source`,`Target`, NULL, `ExtendedType` FROM `CustomAction` WHERE `Action` = ‘WEBCA_SetTARGETSITE’
MSI (c) (B4:A4) [11:18:53:661]: Creating MSIHANDLE (1) of type 790542 for thread 4260
MSI (c) (B4:4C) [11:18:53:662]: Invoking remote custom action. DLL: C:\Users\SDOSYU~1\AppData\Local\Temp\MSI2978.tmp, Entrypoint: SetTARGETSITE
MSI (c) (B4:F0) [11:18:53:666]: Cloaking enabled.
MSI (c) (B4:F0) [11:18:53:666]: Attempting to enable all disabled privileges before calling Install on Server
MSI (c) (B4!14) [11:18:53:726]: Creating MSIHANDLE (2) of type 790531 for thread 4116
INFO   : [01/02/2009 11:18:53:726] [SetTARGETSITE ]: Custom Action is starting…
INFO   : [01/02/2009 11:18:53:727] [SetTARGETSITE ]: CoInitializeEx – COM initialization Apartment Threaded…
ERROR  : [01/02/2009 11:18:53:729] [SetTARGETSITE ]: FAILED: -2147221164
ERROR  : [01/02/2009 11:18:53:730] [SetTARGETSITE ]: Custom Action failed with code: ‘340′
INFO   : [01/02/2009 11:18:53:731] [SetTARGETSITE  ]: Custom Action completed with return code: ‘340′

Very informational… Who would guess that it simply comes to support for IIS 6 API. In IIS 7 it called “IIS 6 Management compatability”.

Usually this module is not installed by default and we have to actually enable it.
Very simple and very quick solution is to go “Control Panel\Programs and Features\Turn Windows features on or off” and then click the check box.

iis7support

There is one more problem which may be encountered on 64 bit machine – support for 32 bit assemblies is disabled by default. To reenable, change Application Pool Defaults for your IIS 7 installation:
32bitaspon64bitos

ASP.Net/WF : New built-in .Net Charting control

I was always for a “built-in” support of features in modern development environment. Even if it comes in basic form, we, as programmers, should have ability to do “basic” stuff without 3rd party involvement.

There are plenty of 3rd party solutions on the market which would help you include some kind of charting support with your ASP pages and WinForms applications – ChartFX, ComponentArt’s Charting, Dundas Chart - these are just few from many available on the market today.

As it turned out, Microsoft has decided to add out-of-the-box support for Charting as well - <asp:chart runat=”server”/>.
Read about it here - New ASP.NET Charting Control: <asp:chart runat=”server”/> by Scott Guthrie – everything you need to know about the .Net 3.5 framework new addition.

For  additional information also visit Alex Gorev’s blog.

Note 1: Even though caption says it is ASP.Net solution, in the original you would find link to WinForms sample as well.
Note 2: Do not worry about Dundas copyright – “Microsoft acquired Dundas Data Visualization Intellectual Property in April 2007.”

Valid XHTML 1.0 Transitional  Valid CSS!