Skip to main content

Microsoft Azure Reporting

  • 10 minutes to read

This document describes how to run reporting applications in the Microsoft Azure environment.

Prerequisites

ASP.NET MVC and Web Forms

Before you run web reporting controls on Azure, install the packages as follows:

  • Install the DevExpress.Web.Reporting.Azure NuGet package that contains services for web reporting applications in the Microsoft Azure environment. Review the following help topic for more information: Install DevExpress Controls Using NuGet Packages.

  • Install the latest version of the WindowsAzure.Storage NuGet package and add a binding redirect for the Microsoft.WindowsAzure.Storage.dll assembly:

    <runtime>
    <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
    <dependentAssembly>
    <assemblyIdentity name="Microsoft.WindowsAzure.Storage" publicKeyToken="31bf3856ad364e35" culture="neutral" />
    <bindingRedirect oldVersion="0.0.0.0-9.3.1.0" newVersion="9.3.1.0" />
    </dependentAssembly>
    </assemblyBinding>
    </runtime>
    

    For more information on the redirect technique, review the following document: Redirecting assembly versions.

    Add a reference to the DevExpress.XtraReports.v22.1.Web.Azure.dll assembly to your project. Include the assembly in the deployment file list.

ASP.NET Core

Before you run web reporting controls on Azure, install the DevExpress.AspNetCore.Reporting.Azure NuGet package. This package includes services for web reporting applications in the Microsoft Azure environment. Review the following help topic for more information: Install DevExpress Controls Using NuGet Packages.

Note

If your report contains the XRRichText control, set the AzureCompatibility.Enable property to true at application start. This setting is required so that the control renders correctly when the report is previewed, exported, or printed. If your report does not use the XRRichText control, set the property to false (default value).

Hosting Specifics

Single Instance Hosting

Suppose that your application relies on one of the following hosting service configurations:

In this situation, you must use one of the alternative options descibed below to configure the application.

Option 1: Use Cached Report Source Builder

The Document Viewer component and the Report Designer component in Preview mode require access to the document during its generation.

The Cached Report Source Builder forces reporting components to bind to the CachedReportSourceWeb instance instead of a simple report instance. The CachedReportSourceWeb allows the application to store document pages in a persistent storage (Azure Cloud Storage) during document generation. This storing operation is critical to prevent data loss when an application pool is reloaded.

The following code configures the application to use the Cached Report Source Builder:

  • ASP.NET MVC and Web Forms

    using DevExpress.XtraReports.Web.Azure.WebDocumentViewer;
    // ...
    protected void Application_Start(object sender, System.EventArgs e) {
      //...  
        AzureWebDocumentViewerContainer.UseCachedReportSourceBuilder(cloudStorageConnectionString);
    }
    
  • ASP.NET Core

    using DevExpress.AspNetCore.Reporting;
    using DevExpress.AspNetCore.Reporting.Azure;
    ...
    public void ConfigureServices(IServiceCollection services) {
    ...
      services.ConfigureReportingServices(configurator => {
        configurator.ConfigureWebDocumentViewer(viewerConfigurator => 
          {
            viewerConfigurator.UseAzureCachedReportSourceBuilder(cloudStorageConnectionString);
        });
      });
    }
    

Option 2: Call the UseAzureEnvironment Method

This method is used in v.19.2 and earlier, and it is still applicable. It replaces the Document Viewer and Report Designer internal services with services adjusted for Azure.

The following code calls the UseAzureEnvironment method at application startup:

  • ASP.NET MVC and Web Forms

    using DevExpress.XtraReports.Web.Azure.WebDocumentViewer;
    // ...
    protected void Application_Start(object sender, System.EventArgs e) {
      //...  
        AzureWebDocumentViewerContainer.UseAzureEnvironment(cloudStorageConnectionString);
    }
    
  • ASP.NET Core

    using DevExpress.AspNetCore.Reporting;
    using DevExpress.AspNetCore.Reporting.Azure;
    ...
    public void ConfigureServices(IServiceCollection seravices) {
    ...
      services.ConfigureReportingServices(configurator => {
        configurator.ConfigureWebDocumentViewer(viewerConfigurator => 
          {
            viewerConfigurator.UseAzureEnvironment(cloudStorageConnectionString);
        });
      });
    }
    

This method switches the Web Document Viewer’s internal services to services designed for the decentralized Azure environment. The method also affects the Web Report Designer because the Designer’s preview uses the Web Document Viewer to display a document.

If you use the Report Designer in an ASP.NET MVC or ASP.NET Web Forms application, you can also call the AzureReportDesignerContainer.UseAzureEnvironment method at application startup and specify the Azure Storage connection string as the method’s parameter. The Web Report Designer encrypts the connection information sent to the client. The UseAzureEnvironment method instructs the Report Designer to store this information in Azure Table storage.

The following code calls the UseAzureEnvironment method for the application with the Report Designer:

  • ASP.NET MVC and Web Forms

    using DevExpress.XtraReports.Web.Azure.ReportDesigner;
    // ...
    
    protected void Application_Start(object sender, System.EventArgs e) {
      AzureReportDesignerContainer.UseAzureEnvironment(cloudStorageConnectionString);
    }
    

Multi-instance Hosting

You can host the Web Document Viewer on multiple web application instances if you disable session affinity (ARR affinity).

Create an Azure Storage account to persist report definitions and documents in Azure storage. As a result, you enable the Document Viewer to preserve its state after an application restarts.

Select the most appropriate for your deployment strategy Azure Storage account replication (LRS, ZRS, GRS, RA-GRS). Exclude the Zone Redundant Storage (ZRS) option because it works with blob containers only, and the Web Document Viewer requires both tables and blobs.

To scale out a web application to multiple instances, use one of the alternative options described below:

Option 1: Use the Cached Report Source Builder

The Document Viewer component and the Report Designer component in Preview mode require access to the document while it is being generated.

The Cached Report Source Builder forces reporting components to bind to the CachedReportSourceWeb instance instead of a simple report instance. The CachedReportSourceWeb allows the application to store document pages in a persistent storage (Azure Cloud Storage) while the document generation. This is critical to prevent data loss when the Load Balancer routes a request to an application instance where the document is not generated, or when an application pool is reloaded.

Web Document Viewer: Azure Cloud Storage Diagram

The following code configures the application to use the Cached Report Source Builder:

  • ASP.NET MVC and Web Forms

    using DevExpress.XtraReports.Web.Azure.WebDocumentViewer;
    // ...
    protected void Application_Start(object sender, System.EventArgs e) {
      //...  
        AzureWebDocumentViewerContainer.UseCachedReportSourceBuilder(cloudStorageConnectionString, StorageSynchronizationMode.InterProcess);
    }
    
  • ASP.NET Core

    using DevExpress.AspNetCore.Reporting;
    using DevExpress.AspNetCore.Reporting.Azure;
    using DevExpress.XtraReports.Web.WebDocumentViewer;
    ...
    public void ConfigureServices(IServiceCollection services) {
    ...
      services.ConfigureReportingServices(configurator => {
        configurator.ConfigureWebDocumentViewer(viewerConfigurator => 
          {
            viewerConfigurator.UseAzureCachedReportSourceBuilder(cloudStorageConnectionString, StorageSynchronizationMode.InterProcess);
        });
      });
    }
    

    The StorageSynchronizationMode.InterProcess parameter enables inter-process synchronization.

Option 2: Use Service Bus

Set up the Viewer for a Service Bus. A Service Bus tier should be Standard or Premium (because both Sessions and Topics are required).

The Service Bus requires one of the following NuGet packages (based on the target framework):

Framework Package
ASP.NET Web Forms and MVC WindowsAzure.ServiceBus 2.7.0+
ASP.NET Core Microsoft.Azure.Management.ServiceBus 2.1.0+, Microsoft.Azure.ServiceBus 4.1.1+

Note

The Service Bus packages are installed automatically when you install the DevExpress Azure NuGet package.

To use a service bus, call the UseAzureEnvironment method with parameters that specify the Azure Storage connection string and a connection string to access the service bus at application startup:

  • ASP.NET Web Forms and MVC

    using DevExpress.XtraReports.Web;
    using DevExpress.XtraReports.Web.Azure.WebDocumentViewer;
    // ...
    
    protected void Application_Start(object sender, System.EventArgs e) {
      AzureWebDocumentViewerContainer.UseAzureEnvironment(cloudStorageConnectionString, serviceBusConnectionString);
      ASPxWebDocumentViewer.StaticInitialize();
    }
    

    Make sure that you call the ASPxWebDocumentViewer.StaticInitialize method after all other methods.

  • ASP.NET Core

    using DevExpress.AspNetCore.Reporting;
    using DevExpress.AspNetCore.Reporting.Azure;
    ...
    public void ConfigureServices(IServiceCollection services) {
    ...
      services.ConfigureReportingServices(configurator => {
        configurator.ConfigureWebDocumentViewer(viewerConfigurator => 
          {
            viewerConfigurator.UseAzureEnvironment(cloudStorageConnectionString, serviceBusConnectionString);
        });
      });
    }
    

Option 3: Use Synchronous Document Creation

If a report document is generated asynchronously, and HttpContext.Session is not available in the report’s event handlers, force synchronous document creation as follows:

  1. Create a custom WebDocumentViewerOperationLogger implementation that overrides the BuildStarting method. The method’s code should call the XtraReport.CreateDocument method, as illustrated below:

    using DevExpress.XtraReports.UI;
    using DevExpress.XtraReports.Web.ReportDesigner;
    using DevExpress.XtraReports.Web.WebDocumentViewer;
    
    public class CustomLogger : WebDocumentViewerOperationLogger {
        public override Action BuildStarting(string reportId, string reportUrl, XtraReport report, ReportBuildProperties buildProperties) {   
        report.CreateDocument();
        return null;
        }
        // ...
    }
    
  2. At application startup, call the UseAzureEnvironment method with the parameter that specifies the Azure Storage connection string and register the CustomLogger class implemented in the previous step.

    • ASP.NET Web Forms and MVC

      using DevExpress.XtraReports.Web;
      using DevExpress.XtraReports.Web.Azure.WebDocumentViewer;
      // ...
      
      protected void Application_Start(object sender, System.EventArgs e) {
        AzureWebDocumentViewerContainer.UseAzureEnvironment(cloudStorageConnectionString);
        DefaultWebDocumentViewerContainer.RegisterSingleton<WebDocumentViewerOperationLogger, CustomLogger>();
        ASPxWebDocumentViewer.StaticInitialize();
      }
      

      Make sure that you call the ASPxWebDocumentViewer.StaticInitialize method after all other methods.

    • ASP.NET Core

      using DevExpress.AspNetCore.Reporting;
      using DevExpress.AspNetCore.Reporting.Azure;
      using DevExpress.XtraReports.Web.WebDocumentViewer;
      //...
      public void ConfigureServices(IServiceCollection services) {
        //...
        services.AddDevExpressControls();
        //...
        services.ConfigureReportingServices(configurator => {
          configurator.ConfigureWebDocumentViewer(viewerConfigurator => 
            {
              viewerConfigurator.UseAzureEnvironment(cloudStorageConnectionString);
          });
        });
        services.AddTansient<WebDocumentViewerOperationLogger, CustomLogger>();
      }
      

The user can modify the report in the following ways:

In this situation, the application should not pass the report instance to the Viewer’s OpenReport method. The report instance is not available on other machines that can handle corresponding HTTP requests. Instead, use another OpenReport overload that takes the URL as the parameter. To use a URL to load a report, register a report storage or create and register a class that implements the IWebDocumentViewerReportResolver interface.

Report Serialization

Web Document Viewer in an Azure environment serializes report definitions to XML. The REPX file that is generated is saved in Blob Storage.

A request that submits report parameter values or restores a drill-drown/drill-through/interactive sorting state requires a report instance in the following cases:

  • If the Document Viewer’s request is routed to another server instance (when multiple server instances are used).
  • When the Document Viewer’s request is routed to a single server instance, but the application pool is shut down due to inactivity.

A report instance is restored from an XML file and contains only settings that have been serialized (other settings are lost). You can use a custom WebDocumentViewerOperationLogger implementation to modify a report and apply settings.

Implement Custom Storages

Microsoft Azure is a distributed system, and virtual machines are shared between different clients. Information stored on a virtual machine can be lost when a Load Balancer turns this machine off and switches to a new machine.

To prevent information loss, the Web Document Viewer stores service information in Table Storage and saves document files in Blob Storage.

You can use a custom storage instead of Table and Blob storages. To do this, implement the following interfaces and substitute related services in a container:

Note

Web Document Viewer creates and uses “dxxrreports“ and “dxxrdocuments“ tables in Table Storage, and the “dxxrcommonstorage“ blob container in Blob Storage.

Limitations

PDF Fonts

The PDF export engine used in DevExpress Reporting relies on system GDI calls, some of which are not supported in Azure.

When a web app is hosted under the Free or Shared plan, the following limitations apply:

  • right-to-left languages do not render correctly;
  • only non-embedded fonts are supported.

PDF Rendering

If your Reporting application includes XRPdfContent controls, configure the application to use the Skia rendering engine.

Custom Fonts

Image Rendering

All controls that can be rendered as metafiles or bitmaps are rendered as bitmaps. The XRChart, XRSparkline, XRGauge and WinControlContainer controls are rendered as bitmaps despite their ImageType property value.

Caching Options

Azure Caching Settings

Applications that target ASP.NET Web Forms and MVC frameworks have the following default ‘Time to Live’ settings:

  • Report: 2 minutes.
  • Document: 1 minute.

Use the CacheCleanerSettings class to adjust the cache settings.

Document Viewer Lifecycle

For information about the mechanisms implemented in the Document Viewer, including the client-sever communication protocol and server-side report storage, review the following help topic: Document Viewer Lifecycle.

See Also