Crystal Reports With BigIP Bang Head Here

Crystal Reports Bang Head HereSometime back during a deployment some head banging occurred thanks to Crystal Reports hard-coding configuration in their application. The really irritating part is the configuration is configurable in the enterprise version. What configuration you ask? The location of the aspnet_client and CrystalReportsViewerX folders. By default Crystal Reports installs CrystalReportsViewerX folder to the default IIS web site,Default Web Site root, C:\inetpub\wwwroot\aspnet_client\system_web\2_0_50727 folder path. If you have a custom web site, for example, My Rocking Web Site, in most cases you can simply copy the aspnet_client/…/CrystalReportsViewerX folder to root of My Rocking Web Site physical path and all is good. What if you want to change the location of the aspnet_client folder? Please do not be mistaken by changing the shared location 1 2, the goal is to change the location of aspnet_client folder to say a virtual directory instead of the root.

You maybe asking yourself why do you want to change the location of aspnet_client folder?

Crystal Reports and BigIP

The reason is the web application in question leverages BigIP to transform the url from http to https. In a previous deployment our Silverlight configuration had to be altered to support BigIP too Hsoting Silverlight Over HTTP Under F5 Big IP.

Deployment Install of Crystal Reports 2008

  • Download the redistributable package from the Business Objects website
  • Install the redistributable package
  • By default Crystal Reports View folder, CrystalReportsViewer4, installs to C:\inetpub\wwwroot\aspnet_client\system_web\2_0_50727
  • Copy the C:\inetpub\wwwroot\aspnet_client folder to physical path of My Rocking Web Site

Decompiler View

You can see from the decompiled source files outlined below the code location is not configurable. However, the lcoation is configurable with the Enterprise version of Crystal Reports.

ViewerGlobal
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public static string ASPNETClientFolderURL
{
  [DummyPermission] get
  {    
    Assembly assembly = typeof (HttpRequest).Assembly;
    AssemblyFileVersionAttribute versionAttribute = (AssemblyFileVersionAttribute) assembly.GetCustomAttributes(typeof (AssemblyFileVersionAttribute), false)[0];
    int length = versionAttribute.Version.LastIndexOf('.');
    StringBuilder stringBuilder = new StringBuilder();
    stringBuilder.Append("/aspnet_client/");
    new FileIOPermission(PermissionState.Unrestricted).Assert();
    stringBuilder.Append(assembly.GetName().Name.Replace('.', '_'));
    CodeAccessPermission.RevertAssert();
    stringBuilder.Append("/");
    stringBuilder.Append(versionAttribute.Version.Substring(0, length).Replace('.', '_'));
    return ((object) stringBuilder).ToString();
  }
}
ExportButton
1
2
3
4
5
6
7
protected override void setOnClickAttribute()
{  
  StringBuilder stringBuilder = new StringBuilder();
  stringBuilder.Append("javascript:");
  stringBuilder.Append(this.Page.ClientScript.GetPostBackEventReference((Control) this, ""));
  this.SetAttribute("onclick", ((object) stringBuilder).ToString());
}
ViewerToolbar
1
2
3
4
5
6
7
8
9
private string getExportDialogPageURL()
{
  return ViewerGlobal.ASPNETClientFolderURL + "/CrystalReportWebFormViewer4/html/crystalexportdialog.htm";
}  

private string getPrintHostPageURL()
{
  return ViewerGlobal.ASPNETClientFolderURL + "/CrystalReportWebFormViewer4/html/crystalprinthost.html";
}
ReportViewer
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
// Add to page load
CrystalReportViewer1.HasExportButton = false;
CrystalReportViewer1.HasPrintButton = false;

private void ExportReport(ExportFormatType peExportType)
{

  //declare a memorystream object that will hold out output
  MemoryStream oStream;

  //here's the instance of a valid report, one which we have already Load(ed)
  ReportDocument crReport = rptDocument;

  /**remember that a valid crystal report has to be loaded before you run this code**/
  //clear the response and set Buffer to true
  Response.Clear();
  Response.Buffer = true;

  switch (peExportType)
  {
      case ExportFormatType.RichText:
          // ...Rich Text (RTF)
          oStream = (MemoryStream) crReport.ExportToStream(CrystalDecisions.Shared.ExportFormatType.RichText);
          Response.ContentType = "application/rtf";
          break;

      case ExportFormatType.PortableDocFormat:
          // ...Portable Document (PDF)
          oStream = (MemoryStream) crReport.ExportToStream(ExportFormatType.PortableDocFormat);
          Response.ContentType = "application/pdf";
          break;

      case ExportFormatType.WordForWindows:
          // ...MS Word (DOC)
          oStream = (MemoryStream) crReport.ExportToStream(ExportFormatType.WordForWindows);
          Response.ContentType = "application/msword";
          break;

      case ExportFormatType.Excel:
          // ...MS Excel (XLS)
          oStream = (MemoryStream) crReport.ExportToStream(ExportFormatType.Excel);
          Response.ContentType = "application/vnd.ms-excel";
          break;

      default:
          //...Portable Document (PDF)
          oStream = (MemoryStream) crReport.ExportToStream(ExportFormatType.PortableDocFormat);
          Response.ContentType = "application/pdf";
          break;
  }


  try
  {
      //write report to the Response stream
      Response.BinaryWrite(oStream.ToArray());
      Response.End();
  }
  catch (Exception ex)
  {
      Console.WriteLine("ERROR: " + Server.HtmlEncode(ex.Message.ToString()));
      CxErrorlogFactory.Log("", ex.Source, ex.Message + ex.StackTrace + ex.InnerException);
  }
  finally
  {
      //clear stream
      oStream.Flush();
      oStream.Close();
      oStream.Dispose();
  }
}

protected void btnExportAsPDF_Click(object sender, EventArgs e)
{
  ExportReport(ExportFormatType.PortableDocFormat);
}

protected void btnExportAsWord_Click(object sender, EventArgs e)
{
  ExportReport(ExportFormatType.WordForWindows);
}

protected void btnExportAsExcel_Click(object sender, EventArgs e)
{
  ExportReport(ExportFormatType.Excel);
}
ReportViewer
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<table width="600" id="table2">
<tr>
  <td align="left" width="200">
       <cc_dxe:ASPxButton ID="btnExportAsPDF" runat="server" Text="Export to PDF" Width="200px"
          OnClick="btnExportAsPDF_Click">
      </cc_dxe:ASPxButton>
  </td>
  <td align="left" width="200">
      <cc_dxe:ASPxButton ID="btnExportAsWord" runat="server" Text="Export to Word" Width="200px"
          OnClick="btnExportAsWord_Click">
      </cc_dxe:ASPxButton>
  </td>
  <td align="left" width="200">
      <cc_dxe:ASPxButton ID="btnExportAsExcel" runat="server" Text="Export to Excel" Width="200px"
          OnClick="btnExportAsExcel_Click">
      </cc_dxe:ASPxButton>
    </td>
</tr>
</table>

Reference

Comments