Progress® Telerik® Reporting R1 2020

How To: Implement a Custom Report Resolver

This article explains how to create a custom report resolver for the Telerik Reporting REST service. In this example, the resolver purpose will be to return a XmlReportSource with an XML report definition obtained from an SQL Server database.

How to implement a custom report resolver:

  1. Create a class which implements the IReportResolver interface. Its Resolve(String) method will be called whenever the engine needs to create a ReportSource instance based on the parameter named report. The value of the report parameter will be initialized with the value of the Report property of the report viewer's ReportSource object.

    class CustomReportResolver : Telerik.Reporting.Services.Engine.IReportResolver
    {
        public Telerik.Reporting.ReportSource Resolve(string reportId)
        {
            var cmdText = "SELECT Definition FROM Reports WHERE ID = @ReportId";
    
            var reportXml = "";
            using (var conn = new System.Data.SqlClient.SqlConnection(@"server=(local)\sqlexpress;database=REPORTS;integrated security=true;"))
            {
                var command = new System.Data.SqlClient.SqlCommand(cmdText, conn);
                command.Parameters.Add("@ReportId", System.Data.SqlDbType.Int);
                command.Parameters["@ReportId"].Value = reportId;
    
                try
                {
                    conn.Open();
                    reportXml = (string)command.ExecuteScalar();
                }
                catch (System.Exception ex)
                {
                    System.Diagnostics.Trace.WriteLine(ex.Message);
                }
            }
    
            if (string.IsNullOrEmpty(reportXml))
            {
                throw new System.Exception("Unable to load a report with the specified ID: " + reportId);
            }
    
            return new Telerik.Reporting.XmlReportSource { Xml = reportXml };
        }
    }
  2. Find the ReportResolver property in the ReportServiceConfiguration settings of the implementation of the ReportsControllerBase class, and set it to an instance of the custom report resolver or to a chain of resolver instances including the custom one:

    public class CustomResolverReportsController : Telerik.Reporting.Services.WebApi.ReportsControllerBase
    {
        static Telerik.Reporting.Services.ReportServiceConfiguration configurationInstance;
    
        static CustomResolverReportsController()
        {
            var resolver = new ReportFileResolver(HttpContext.Current.Server.MapPath("~/Reports"))
                .AddFallbackResolver(new ReportTypeResolver()
                    .AddFallbackResolver(new CustomReportResolver()));
    
            configurationInstance = new Telerik.Reporting.Services.ReportServiceConfiguration
            {
                HostAppId = "Application1",
                ReportResolver = resolver,
                Storage = new Telerik.Reporting.Cache.File.FileStorage(),
            };
        }
    
        public CustomResolverReportsController()
        {
            this.ReportServiceConfiguration = configurationInstance;
        }
    }
  3. Request the report from the HTML5 Report Viewer on the client:

    JavaScript
    <script type="text/javascript">
        $(document).ready(function () {
                $("#reportViewer1").telerik_ReportViewer({
                    serviceUrl: "api/reports/",
                    reportSource: { report: 1 }                
            });
        });
    </script>

    where x.x.x.x is the version of the HTML5 ReportViewer/Telerik Reporting (e.g. 8.1.14.618).

  4. To create the database use the following script:

    USE [master]
    GO
    CREATE DATABASE [Reports]
    CONTAINMENT = NONE
    ON  PRIMARY
    ( NAME = N'Reports', FILENAME = N'C:\Program Files\Microsoft SQL Server\MSSQL11.SQLEXPRESS\MSSQL\DATA\Reports.mdf' , SIZE = 4096KB ,
    
    MAXSIZE = UNLIMITED, FILEGROWTH = 1024KB )
    LOG ON
    ( NAME = N'Reports_log', FILENAME = N'C:\Program Files\Microsoft SQL Server\MSSQL11.SQLEXPRESS\MSSQL\DATA\Reports_log.ldf' , SIZE = 1024KB
    
    , MAXSIZE = 2048GB , FILEGROWTH = 10%)
    GO
    USE [Reports]
    GO
    CREATE TABLE [dbo].[Reports](
    [ID] [int] NOT NULL,
    [Definition] [nvarchar](max) NOT NULL
    ) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
    GO
  5. To enter some data into the database you can manually edit the Reports table. XML report definitions can be obtained from the sample .trdx report files installed together with the product and are located in [Telerik_Reporting_Install_Dir]\Report Designer\Examples.

    In newer versions, all sample reports of the Standalone Report Designer are in TRDP format. You can use the Standalone Report Designer - File - Save As option to convert them to TRDX files.

How to pass Report Parameter values to custom report resolver

The argument that is received in the Resolve method of the Custom Report Resolver is the report property of the report viewer's ReportSource. The parameter values are passed from the viewer in its ReportSource parameters collection and cannot be accessed in the report resolver. Generally, their values are applied later in the workflow by matching the parameter names from the ReportSource returned by the Resolve method and the report parameter names from the report definition. Often, when it is necessary to use a custom report resolver it will be necessary to pass and manipulate also parameter values in it. The workaround that can be used is to concatenate the parameter values in the report property of the viewer's ReportSource. In the Resolve method it will be necessary to split out the parameter values from the report identifier and assign them to the Parameters collection of the server-side ReportSource returned by the Resolve method. For example, if the original client-side ReportSource should pass the following information to the Reporting engine:

JavaScript
reportSource: {
  report: "Product Line Sales.trdp",
  parameters: {
    ProductCategory: "Clothing",
    ProductSubcategory: "Caps"
  }
},

and you would like to manipulate the parameter values in the custom report resolver before sending them to the Reporting engine, you may pass the foloowing client-side ReportSource with report name and parameters' names and values concatenated in a single string:

JavaScript
reportSource: {
  report: "Product Line Sales.trdp|ProductCategory=Clothing|ProductSubcategory=Caps"
},

In the resolver you should use logic for extracting the correct report identifier and parameter values, for example:

C#
public ReportSource Resolve(string report)
{
    var clientReportSourceInfo = report.Split(new char[] { '|' });
    var reportName = clientReportSourceInfo[0];

    ...// create and manipulate the report and assign it to the server-side ReportSource 'serverReportSource'

    for (int parameterNumber = 1; parameterNumber > clientReportSourceInfo.Length; parameterNumber++)
    {
        var parameterInfo = clientReportSourceInfo[parameterNumber].Split(new char[] { '=' });
        var parameterName = parameterInfo[0];
        var parameterValue = parameterInfo[1];

        serverReportSource.Parameters.Add(parameterName, parameterValue);
    }

      ...

    return serverReportSource;
}
In this article
Not finding the help you need?