New to Telerik Reporting? Download free 30-day trial

How to implement a report definition storage

This article describes how to use the Web Report Designer to design reports that are stored in a custom storage location.

Overview

Out-of-the-box we provide a FileDefinitionStorage that is configured to use the file system. To open reports stored differently, you need to implement the IDefinitionStorage interface. This will enable the web designer to load reports from a custom location, such as a database, cloud, in-memory, etc.

The Web Report Designer previews the reports in Html5 Report Viewer. The latter utilizes a Telerik Reporting REST Service to render the reports. The client-side reportSource sent by the web designer is resolved to a server-side ReportSource by the Resolve method of the Reporting REST Service ReportSource Resolver. The ReportSource resolver is supposed to read report definitions created with the web report designer. For that reason, in the most of the cases when creating custom IDefinitionStorage it will be necessary to create also a custom ReportSource resolver that is able to read the report definitions from the storage and return them as valid server-side ReportSources.

Implement Custom Storage

The purpose of the report definition storage is to describe how to browse, open, save, and delete reports from the Web Report Designer. The storage is configured as a setting of the ReportDesignerController.

The default implementation of the storage is the FileDefinitionStorage. It provides functionality for working with TRDP/TRDX report files stored on the server-side file system. To load the reports from a custom storage, change the implementation of the definition storage like this:


public class CustomDefinitionStorage : IDefinitionStorage
{
    public Task<ResourceFolderModel> CreateFolderAsync(CreateFolderModel model)
    {
        // Creates a folder using the provided model.
        throw new NotImplementedException();
    }

    public Task<ResourceFolderModel> GetFolderAsync(string uri)
    {
        // Retrieves the existing folder model by the provided URI.
        throw new NotImplementedException();
    }

    public Task DeleteFolderAsync(string uri)
    {
        // Deletes a folder by the provided URI.
        throw new NotImplementedException();
    }

    public Task<IEnumerable<ResourceModelBase>> GetFolderContentsAsync(string uri)
    {
        // Gets all resources contained in the given URI.
        throw new NotImplementedException();
    }

    public Task<ResourceFolderModel> RenameFolderAsync(RenameFolderModel model)
    {
        // Renames a folder located at model.OldUri.
        throw new NotImplementedException();
    }

    public Task<byte[]> GetAsync(string resourceName)
    {
        // Finds a resource by its name and returns its contents as byte array.
        throw new NotImplementedException();
    }

    public Task DeleteAsync(string uri)
    {
        // Deletes the given resource
        throw new NotImplementedException();
    }

    public Task<ResourceFileModel> GetModelAsync(string uri)
    {
        // Returns the resource model at provider URI or null if not found.
        throw new NotImplementedException();
    }

    public Task<ResourceFileModel> RenameAsync(RenameResourceModel model)
    {
        // Renames the given resource
        throw new NotImplementedException();
    }

    public Task<ResourceFileModel> SaveAsync(SaveResourceModel model, byte[] resource)
    {
        // Saves the raw data of a resource and returns its model.
        throw new NotImplementedException();
    }
}

Then you can set the new definition storage implementation in the ReportDesignerController.

public ReportDesignerController()
{
    //...

    this.ReportDesignerServiceConfiguration = new ReportDesignerServiceConfiguration
    {
        DefinitionStorage = new CustomDefinitionStorage(),
        SettingsStorage = new FileSettingsStorage(this.reportsSettingsPath)
    };
}
In this article