IReportProviderAsync Interface
Allows you to implement a service that asynchronously resolves a report name to a report instance.
Namespace: DevExpress.XtraReports.Services
Assembly: DevExpress.XtraReports.v24.2.dll
NuGet Package: DevExpress.Reporting.Core
#Declaration
#Remarks
You can create a custom service that implements the IReportProviderAsync interface to resolve a string to a report instance.
The GetModelAsync methods call this service to get a report by its unique name (also referred to as the report URL). When a report contains subreports with the names specified by the XRSubreport.ReportSourceUrl property, the IReportProvider service is used to resolve subreport names.
A custom IReportProviderAsync service has priority over the custom ReportStorageWebExtension service.
In your project, you must bind report controls to the WebDocumentViewerModel or ReportDesignerModel objects originated from controllers. The controller-based models allow you to use asynchronous API and avoid obscure errors that may occur when a subreport fails to load and throws an exception, or when an attempt to refresh a list of predefined dynamic parameter values fails.
A controller must call the WebDocumentViewerClientSideModelGenerator.GetModelAsync or ReportDesignerClientSideModelGenerator.GetModelAsync methods to generate report models and send them to the Document Viewer and End User Report Designer.
#Implementation
Add custom logic to the GetReportAsync method. The method instantiates and returns a report based on the specified report unique name. The following code is the IReportProviderAsync implementation that retrieves a serialized report from the report storage:
using System.IO;
using System.Threading.Tasks;
using DevExpress.XtraReports.Services;
using DevExpress.XtraReports.UI;
using DevExpress.XtraReports.Web.Extensions;
// ...
public class CustomReportProviderAsync : IReportProviderAsync
{
readonly ReportStorageWebExtension reportStorageWebExtension;
public CustomReportProviderAsync(ReportStorageWebExtension reportStorageWebExtension)
{
this.reportStorageWebExtension = reportStorageWebExtension;
}
public async Task<XtraReport> GetReportAsync(string id, ReportProviderContext context)
{
var reportLayout = await reportStorageWebExtension.GetDataAsync(id);
if (reportLayout == null)
return null;
using (var ms = new MemoryStream(reportLayout))
{
var report = XtraReport.FromXmlStream(ms);
return report;
}
}
}
#Registration
- ASP.NET Web Forms and ASP.NET MVC
Call the following methods at application startup:
- DefaultWebDocumentViewerContainer.Register method or the DefaultReportDesignerContainer.Register method to register the service
- DefaultWebDocumentViewerContainer.UseAsyncEngine method or the DefaultReportDesignerContainer.UseAsyncEngine methods, respectively, to enable asynchronous mode.
using DevExpress.XtraReports.Services; // ... void Application_Start() { // ... DevExpress.XtraReports.Web.ReportDesigner.DefaultReportDesignerContainer.Register<IReportProviderAsync, CustomReportProviderAsync>(); DevExpress.XtraReports.Web.WebDocumentViewer.DefaultWebDocumentViewerContainer.Register<IReportProviderAsync, CustomReportProviderAsync>(); //... DevExpress.XtraReports.Web.ReportDesigner.DefaultReportDesignerContainer.UseAsyncEngine(); DevExpress.XtraReports.Web.WebDocumentViewer.DefaultWebDocumentViewerContainer.UseAsyncEngine(); }
- ASP.NET Core
Call the AddScoped method at application startup to register the service and use the ReportingConfigurationBuilder.UseAsyncEngine method to enable asynchronous mode:
using Microsoft.Extensions.DependencyInjection; using DevExpress.XtraReports.Services; var builder = WebApplication.CreateBuilder(args); builder.Services.AddScoped<IReportProviderAsync, CustomReportProviderAsync>(); builder.Services.ConfigureReportingServices(configurator => { configurator.UseAsyncEngine(); }); var app = builder.Build();
#Usage Example
The complete sample project is available on GitHub:
The following code is a controller action method that handles incoming browser requests. It uses a custom IReportProviderAsync service to obtain a subreport when a report is exported to PDF.
using System.Collections.Generic;
using System.ComponentModel.Design;
using System.IO;
using System.Threading.Tasks;
using DevExpress.AspNetCore.Reporting.WebDocumentViewer;
using DevExpress.DataAccess.Sql;
using DevExpress.XtraReports.Services;
using DevExpress.XtraReports.Web.ReportDesigner.Services;
using DevExpress.XtraReports.Web.WebDocumentViewer;
using Microsoft.AspNetCore.Mvc;
// ...
public class HomeController : Controller
{
public IActionResult Index()
{
return View();
}
public async Task<IActionResult> Designer([FromServices] IReportDesignerModelBuilder reportDesignerModelBuilder, [FromQuery] string reportName = "RootReport")
{
var dataSources = new Dictionary<string, object>
{
["Northwind"] = GetNorthwindSqlDataSource()
};
var designerModel = await reportDesignerModelBuilder
.DataSources(dataSources)
.Report(reportName)
.BuildModelAsync();
return View(designerModel);
}
public async Task<IActionResult> Viewer([FromServices] IWebDocumentViewerClientSideModelGenerator modelGenerator, [FromQuery] string reportName = "RootReport")
{
var viewerModel = await modelGenerator.GetModelAsync(reportName, WebDocumentViewerController.DefaultUri);
return View(viewerModel);
}
public async Task<IActionResult> ExportToPdf([FromServices] IReportProviderAsync reportProviderAsync, [FromQuery] string reportName = "RootReport")
{
var report = await reportProviderAsync.GetReportAsync(reportName, null);
var reportServiceContainer = (IServiceContainer)report;
reportServiceContainer.RemoveService(typeof(IReportProviderAsync));
reportServiceContainer.AddService(typeof(IReportProviderAsync), reportProviderAsync);
using (var stream = new MemoryStream()) {
await report.CreateDocumentAsync();
await report.ExportToPdfAsync(stream);
return File(stream.ToArray(), System.Net.Mime.MediaTypeNames.Application.Pdf);
}
}
SqlDataSource GetNorthwindSqlDataSource()
{
// Create a SQL data source with the specified connection string.
SqlDataSource ds = new SqlDataSource("NWindConnectionString");
// Create a SQL query to access the Products data table.
SelectQuery query = SelectQueryFluentBuilder.AddTable("Products").SelectAllColumnsFromTable().Build("Products");
ds.Queries.Add(query);
ds.RebuildResultSchema();
return ds;
}
}
Note
Review the Open a Report in ASP.