|  | 
| 1 |  | -# Web Reporting - Async Report Storage | 
|  | 1 | +# How to Use the Asynchronous Engine for Web Reporting  | 
|  | 2 | +  | 
|  | 3 | +## Overview  | 
|  | 4 | +This example demonstrates how to use v20.2 services, which allow you to save, load, and export reports asynchronously.  | 
|  | 5 | +This application registers services with the **IReportProviderAsync** interface. The latter allows you to perform the following tasks asynchronously:  | 
|  | 6 | +- open subreports from the master report;  | 
|  | 7 | +- resolve a unique identifier to a report (an operation that affects the Designer Preview and Document Viewer performance).  | 
|  | 8 | +In general, asynchronous operation mode gives you the following advantages:  | 
|  | 9 | +- it handles threads in web applications more cautiously and returns threads to the thread pool while the operation is in progress.   | 
|  | 10 | +- You can write safe asynchronous code in a project with a third-party library that uses only asynchronous API.  | 
|  | 11 | +  | 
|  | 12 | +## Implementation Details  | 
| 2 | 13 | 
 | 
| 3 |  | -Todo | 
|  | 14 | +### Perequisites  | 
|  | 15 | + | 
|  | 16 | +To get you started, we created a sample project with our ASP.NET Core Reporting Project Template.  | 
|  | 17 | + | 
|  | 18 | +### Report Provider  | 
|  | 19 | + | 
|  | 20 | +We declared a new code unit - `CustomReportProviderAsync.cs` with a class that implements the **DevExpress.XtraReports.Services.IReportProviderAsync** interface and calls the report storage's **GetDataAsync** method.  | 
|  | 21 | + | 
|  | 22 | +### Report Storage  | 
|  | 23 | + | 
|  | 24 | +To implement a custom report storage with asynchronous methods, we declared a new code unit - `CustomReportStorageWebExtension.cs`. The CustomReportStorageWebExtension class inherits from the [ReportStorageWebExtension](https://docs.devexpress.com/XtraReports/DevExpress.XtraReports.Web.Extensions.ReportStorageWebExtension) and overrides all its public methods. Note that methods, which cannot be used in asynchronous mode, throw exceptions. | 
|  | 25 | + | 
|  | 26 | +### Report Model and Controllers | 
|  | 27 | + | 
|  | 28 | +We used the **GetModelAsync** methods in the Home controller to generate report models and send them to the End User Report Designer and Document Viewer.   | 
|  | 29 | +ASP.NET Core Razor helpers cannot use asynchronous API if the Bind method receives a report instance or a string (ReportUrl) as a parameter. You must bind report controls to the [ReportDesignerModel](https://docs.devexpress.com/XtraReports/DevExpress.XtraReports.Web.ReportDesigner.ReportDesignerModel) or [WebDocumentViewerModel](https://docs.devexpress.com/XtraReports/DevExpress.XtraReports.Web.WebDocumentViewer.WebDocumentViewerModel) objects originated from controllers. The controller-based model allows you to use async API and avoid obscure problems. Such problems may occur when a subreport fails to load and throws an exception, or when a dynamic list of parameter values fails to retrieve its data. | 
|  | 30 | + | 
|  | 31 | +### ExportToPdf Action  | 
|  | 32 | + | 
|  | 33 | +The export action takes advantage of the **IReportProviderAsync** service that resolves report ID to a report and expedites the load of subreports without the need for the web report controls. We used the DI container to inject the **IReportProviderAsync** service into the XtraReport instance. Then, we can call the asynchronous **CreateDocumentAsync** and **ExportToPdfAsync** methods. | 
|  | 34 | + | 
|  | 35 | +### Enable Asynchronous Services | 
|  | 36 | + | 
|  | 37 | +Request handlers in ASP.NET Core applications are asynchronous. To enable asynchronous services, we called the **UseAsyncEngine** method at application startup: | 
|  | 38 | + | 
|  | 39 | +```csharp | 
|  | 40 | +services.ConfigureReportingServices(configurator => {  | 
|  | 41 | +    configurator.ConfigureReportDesigner(designerConfigurator => {  | 
|  | 42 | +        //..  | 
|  | 43 | +    });  | 
|  | 44 | +    configurator.ConfigureWebDocumentViewer(viewerConfigurator => {  | 
|  | 45 | +        //..  | 
|  | 46 | +    });  | 
|  | 47 | +    configurator.UseAsyncEngine();  | 
|  | 48 | +}); | 
|  | 49 | +```  | 
|  | 50 | +  | 
|  | 51 | +## Notes  | 
|  | 52 | + | 
|  | 53 | +You can use an asynchronous engine in the following scenarios:  | 
|  | 54 | +- Handle the End User Report Designer and Web Document Viewer events to load data or create a document asynchronously. The key point is that these actions can be performed in the context of the current HTTP request in the [WebDocumentViewerOperationLogger](https://docs.devexpress.com/XtraReports/DevExpress.XtraReports.Web.WebDocumentViewer.WebDocumentViewerOperationLogger) and  [PreviewReportCustomizationService](https://docs.devexpress.com/XtraReports/DevExpress.XtraReports.Web.ReportDesigner.Services.PreviewReportCustomizationService) class methods.  | 
|  | 55 | +- Drill Through navigation in the Web Document Viewer. Use the  **IDrillThroughProcessorAsync** interface.  | 
|  | 56 | +- If an application uses JWT-based Authentication, use the **IWebDocumentViewerExportResultUriGeneratorAsync** interface to load exported documents to the storage asynchronously.  | 
|  | 57 | +  | 
0 commit comments