When it comes to designing Page/RDL reports, it is common to store the report and its resources like images, styles, master reports, etc., at a shared location like in a database or on the cloud so that everyone across the team can use them. This action also keeps the backup safe. However, when a report is rendered in the viewer, the viewer cannot access its resources while looking at the physical location.

Getting Started: WinForms/WPF Viewer vs. JavaScript Viewer

To resolve this problem, ActiveReports provides an abstract class, ResourceLocator, which helps to load the resources at the time of rendering when the viewer cannot find them at the physical location. The documentation provides a detailed implementation if the report is to be rendered in the WinForms/WPF Viewer.

However, the same approach does not work while previewing the report in the JSViewer because viewers differ in terms of rendering methods.

For the JSViewer, you need to use the PersistenceFilter class from the GrapeCity.ActiveReports.Rdl.Persistence namespace to dynamically load the resources in the report. This class is used to perform custom actions on the report object and is used with ResourceLocator to fulfill the purpose. How? Let us demonstrate how by dynamically loading the master report as a resource while previewing the RDL report in the JS viewer.

How to Load Resources in Page/RDL Reports When Previewing in the JSViewer

What is a Master Report

Master Reports are like dynamic templates designed for use with content reports. They help create reports that share common elements such as a logo in the page header or a web site link in the page footer section. Master Reports are designed with controls, code, data sources, and layout properties that cannot be modified from content reports. They are generally placed at a shared location like in a database to be used across the team. However, the JSViewer does not load the master report while previewing the content reports directly. It is important to follow the steps below to achieve the same result.

Loading Master Reports Dynamically in the JavaScript Viewer

To get started, grab the MasterReport from the database using the ResourceLocator:

public class MasterReportResourceLocator : ResourceLocator  

{  
        public override Resource GetResource(ResourceInfo resourceInfo)  
        {  
            Resource _resource;  
            if (resourceInfo.Name.Equals("Master.rdlx-master"))  
            {  
                //Getting the Master Report from the DB  
                var stream = new MemoryStream(GetMasterReport());  
                if (stream != null)  
                {  
                   //Assigning the master report to the resource object  
                    _resource = new Resource(stream, null);  
                }  
            }  
            return _resource;  
        }       

}

Now, customize the JSViewer's reporting service to load the MasterReport from the ResourceLocator with help from the PersistenceFilter class.

Building the JavaScript Viewer's Reporting Service

Create the JSViewer reporting service in the "Startup.cs" class:

app.UseReporting(settings =>  
           {  
              //Customizing the report service. It will call the GetReport method to get the report content  
               settings.UseCustomStore(GetReport);  
               settings.UseCompression = true;  
           });  

Create the GetReport method to load the report Ccntent.

private object GetReport(string arg)  
        {  
            baseDirectory = AppDomain.CurrentDomain.BaseDirectory + "\\Reports\\";  
            string reportPath = baseDirectory + arg;  
           //Load Content Report from the database  
            var stream = new MemoryStream(GetContentReport());  
           // Create the object of the ResourceLocator  
            var resourceLocator = new MasterReportResourceLocator();  
            if (stream == null)  
                throw new ReportNotFoundException();  
            using (var reader = new StreamReader(stream))  
            {  
                 //It allows to create the instance of ReportDefinition and bind it with the ResourceLocator  
                var report = GrapeCity.ActiveReports.Rdl.Persistence.PersistenceFilter.Load(reader, resourceLocator);  
                 report.Site = new ReportSite(resourceLocator);  
                if (string.IsNullOrEmpty(report.Name))  
                    report.Name = arg;  

report.DataSources[0].ConnectionProperties.ConnectString = String.Format("provider=Microsoft.Jet.OLEDB.4.0;data source={0}MasterData.mdb;", baseDirectory);  
                return report;  
            } 

Use the ISite to bind the ResourceLocator with the report.

public class ReportSite : ISite  
{  

private readonly ResourceLocator _resourceLocator;

  public ReportSite(ResourceLocator resourceLocator)  

{  
        _resourceLocator = resourceLocator;  

}

public object GetService(Type serviceType) =>  
        serviceType == typeof(ResourceLocator) ? _resourceLocator : null;  

public IComponent Component => null;  

public IContainer Container => null;  

public bool DesignMode => false;  

public string Name { get; set; }  
}

How to Load Resources in Page/RDL Reports When Previewing in the JSViewer

Download the sample here.

Moving Forward with Other Resources in the JSViewer

And this is done. Follow the same approach to load any other type of resource in your Page/RDL reports. If you are trying to load any other resource type in your reports and need help previewing in the JSViewer, please add a comment in the section below.

Try ActiveReportsJS free for 30 days

Deliver customized, professional reports in less time

Download Now!