I have been working recently on a couple of applications that are going to be run on Windows Azure. Both are business applications and have a variety of reports incorporated into them. One was a brand new application , and we opted to use SQL Server reporting services in Azure for it. That was still when the SSRS on Azure was in beta and prices were not yet published. Prices are available now, and you can look at them here. Our application is using on-demand reports, so we have to have them available pretty much 24/7. This comes out to about $630 a month, which was way too high based on our requirements. The other application was already using Crystal Reports, so we decided to switch to Crystal purely based on pricing.
Another things we deiced to do is isolate our Crystal reports viewer into its own web role. This way we can scale reporting solution separately from main web / WCF application that affects user interactions. I did not want interactivity speed to suffer just because one user wanted to run a large report. I believe that with the cloud applications one should always break them down into such a number of roles, as to provide as many points of scaling as possible. Another important point is that I can have just two reports web roles for maybe 10 web roles with the main application. Bottom line is that we concentrate on scalability and cost efficiency.
The next step was to get them running. My search of the internet yielded this post on Stack Overflow. I need to thank Colin Farr for his excellent post to get me started. Stack overflow indicated a number of issues even with specified approach, including a necessity to manually copy files around and so forth. After I experimented with various things, I found the following way actually worked for me.
After I created a new web role application, I just included the latest version of Crystal run time, just like post indicated. Here is how my project looks like:
ReportViewer.aspx page is a standard ASPX page contains Crystal Reports viewer and the code to setup and run the report based on a query string. I used pretty much the same approach I described in my previous posts dedicated to reports with Silverlight applications. Another thing we decided to do is deploy reports to Azure blob storage. In my reports viewer page I download the file from blob storage into temporary folder, then use it as any other crystal report, loading the document from the file.
Here are the properties for Crystal run time file. I setup my start up script exactly the same way.
If we take a look at what is in my startup script (StartUp.cmd), it calls Crystal Reports install, then copies the scripts and styles that Crystal viewer needs from wwwroot folder to my site folder.
msiexec.exe /I "CRRuntime_64bit_13_0_4.msi" /qn robocopy D:inetpubwwwroot E:sitesroot /S
All web roles machines our app is installed up look the same, with the site being installed on E drive.
And the actual call to my start up command is contained inside by service configuration file, ServiceDefinition.csddef.
<?xml version="1.0" encoding="utf-8"?> <ServiceDefinition name="ReportsWindowsAzure" xmlns="http://schemas.microsoft.com/ServiceHosting/2008/10/ServiceDefinition"> <WebRole name="MyReports" vmsize="Small"> <Sites> <Site name="Web"> <Bindings> <Binding name="Endpoint1" endpointName="Endpoint1" /> </Bindings> </Site> </Sites> <Endpoints> <InputEndpoint name="Endpoint1" protocol="http" port="8080" /> </Endpoints> <Imports> <Import moduleName="Diagnostics" /> <Import moduleName="RemoteAccess" /> </Imports> <Startup> <Task commandLine="StartUp.cmd" executionContext="elevated" taskType="background"/> </Startup> </WebRole> </ServiceDefinition>
I tested this multiple times by re-deploying the upgrade to ensure everything works properly because the article on Stack Overflow implied issues. I did not have any issues, and everything worked as expected. I also used awesome feature of Azure that allowed me to remote into the machine. This helped me a ton in order to troubleshoot problems.