# Configuring Resources Storage

## Content

## Introduction

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.

## Built-in Resource Storage Implementations

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.

### File Store

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:

```csharp
using System.IO;

app.UseReportViewer(config =>
{
    var rootDir = new DirectoryInfo(Path.Combine(app.Environment.ContentRootPath, "Reports"));
    config.UseFileStore(rootDir);
});
```

### Embedded Templates

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.

```csharp
using System.IO;

app.UseReportViewer(config =>
{
    config.UseEmbeddedTemplates("MyApp.Resources", Assembly.GetExecutingAssembly());
});
```

### Code-Based Reports

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.

```csharp
using System.Reflection;

app.UseReportViewer(config =>
{
    config.UseCodeBasedSectionReports(Assembly.GetExecutingAssembly(), "MyApp.Reports");
});
```

## Custom Report Provider Implementation

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.

```csharp
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](/activereportsnet/api/v20.1/MESCIUS.ActiveReports.Web.Viewer/GrapeCity.ActiveReports.Web.Viewer.IReportProvider.html) interface. Once implemented, pass the provider instance to `UseReportProvider()` in the configuration.

## Custom Resource Provider Implementation

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](/activereportsnet/api/v20.1/MESCIUS.ActiveReports.Core.Rdl/GrapeCity.ActiveReports.ResourceInfo.html), 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:

```csharp
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](/activereportsnet/api/v20.1/MESCIUS.ActiveReports.Web.Viewer/GrapeCity.ActiveReports.Web.Viewer.IReportResourceProvider.html) interface. Once implemented, pass the provider instance to `UseResourceProvider()` in the configuration.