[]
When the Report Viewer for web requests a report, the server-side middleware is responsible for resolving the report template by its ID. Report templates can be stored in various locations, such as:
On disk
In a database
Embedded in an assembly
Custom storage solutions
Additionally, reports may rely on other resources like images, drill-through reports, subreports, themes, and more. The middleware must be able to locate and serve these resources efficiently.
This section will guide you through configuring resource storage options, allowing you to implement solutions tailored to your application’s needs.
The Report Viewer middleware provides several built-in options for managing report templates and other resources. You can configure the middleware to use file-based storage, embedded resources, or code-based reports stored in assemblies.
The UseFileStore method configures the middleware to load resources from a specified file directory. All resources are resolved relative to the root directory, which is passed as an argument to the UseFileStore method, as shown below:
using System.IO;
app.UseReportViewer(config =>
{
var rootDir = new DirectoryInfo(Path.Combine(app.Environment.ContentRootPath, "Reports"));
config.UseFileStore(rootDir);
});The UseEmbeddedTemplates method configures the middleware to load report templates and resources that are embedded within an assembly. The first argument of UseEmbeddedTemplates is the resource namespace, and the second argument specifies the assembly containing the embedded resources.
using System.IO;
app.UseReportViewer(config =>
{
config.UseEmbeddedTemplates("MyApp.Resources", Assembly.GetExecutingAssembly());
});If your application uses code-based section reports, which are essentially custom .NET components compiled as part of an assembly, the UseCodeBasedSectionReports method configures the middleware to resolve these reports. The first argument is the assembly containing the compiled reports, and the second argument is the root namespace for these reports.
using System.Reflection;
app.UseReportViewer(config =>
{
config.UseCodeBasedSectionReports(Assembly.GetExecutingAssembly(), "MyApp.Reports");
});If the default storage options don’t meet your needs, you can implement a custom report provider to dynamically resolve reports based on your application’s logic. This method allows you to load reports from any source, such as a database, an API, or an in-memory store, without requiring external resources like images or subreports.
The following example demonstrates how to implement a custom report provider that returns reports based on a simple identifier. The first function passed to the UseReportProvider method should return a stream containing the report template, while the second function should return the report type. You can use ReportType.RdlXml for RDLX reports by default.
using GrapeCity.ActiveReports.Aspnetcore.Viewer;
using GrapeCity.ActiveReports.Web.Viewer;
app.UseReportViewer(config =>
{
config.UseReportProvider(reportId =>
{
// Here, you can retrieve the report from any source, such as a database or memory.
// For example, load an embedded report or generate it programmatically.
var reportStream = GenerateReport(reportId); // Custom logic to provide a report stream
return reportStream;
}, _ => new ReportDescriptor(ReportType.RdlXml));
});If your project requires more complex logic or reusable components, you can implement a custom report provider by defining a class that implements the IReportProvider interface. Once implemented, pass the provider instance to UseReportProvider() in the configuration.
If your reports use additional resources like images, themes, or stylesheets, you can use the UseResourceProvider method to resolve them. The resource argument is an instance of ResourceInfo, which provides details about the resource, such as its name and type. You can implement custom logic to return these resources from memory or other sources. Note that this custom logic should handle all resources, including report templates.
The following example demonstrates how to check if the requested resource is an image and return it from a custom source:
using GrapeCity.ActiveReports.Aspnetcore.Viewer;
using GrapeCity.ActiveReports.Web.Viewer;
app.UseReportViewer(config =>
{
config.UseResourceProvider(resource =>
{
if (resource.Type == GrapeCity.ActiveReports.ResourceType.Image)
{
// Return the image as a MemoryStream (e.g., from a database, file system, or in-memory source)
return new MemoryStream(/* image bytes */);
}
// Return null if the resource is not handled
return null;
});
});If your project requires more complex logic or reusable components, you can implement a custom resource provider by defining a class that implements the IReportResourceProvider interface. Once implemented, pass the provider instance to UseResourceProvider() in the configuration.