New to Telerik Reporting? Download free 30-day trial

Displaying Report Books and Reports containing Sub Reports from the Report Server through Custom Report Source Resolver

Environment

Product Progress® Telerik® Reporting
.NET Framework Version 4.5

Description

Sometimes you want to be able to render reports stored in your Report Server in a custom Reporting REST Service, rather than in your Report Server's instance. This can be done through the use of a Custom Report Source Resolver, as shown in the Displaying Reports From Report Server Through Custom Report Source Resolver KB article.

Even though the aforementioned article covers the base scenario, when you are working with a more complex report, for example a Report Book or a Report that contains SubReport items, you may encounter additional difficulties.

To cover these scenarios we will implement a Custom Report Source Resolver that retrieves a ReportBook containing Reports which have Sub Reports in their definitions.

Solution

The general idea behind this solution is the following: 1. Find all report sources that point to reports, residing in the Report Server instance. 2. Retrieve the report definitions from the Server using the ReportServerClient class, and wrap them in an InstanceReportSource. 3. Replace the original report sources (as they are invalid outside of the Report Server environment) with the InstanceReportSources created in the previous step. 4. Repeat the above for every nested report (SubReport/Report Book member).

<div class='tabbedCode'><pre lang="C#"><code>public class CustomReportSourceResolver : IReportSourceResolver
{
    public Telerik.Reporting.ReportSource Resolve(string reportId, OperationOrigin operationOrigin, IDictionary&lt;string, object&gt; currentParameterValues)
    {
        var report = GetReportDocument(reportId);
        InstanceReportSource rs = new InstanceReportSource() { ReportDocument = report };
        return rs;
    }

    public IReportDocument GetReportDocument(string reportId)
    {
        var categoryAndReport = reportId.Split(new char[] { '/' });
        var categoryName = categoryAndReport[0];
        var reportName = categoryAndReport[1];

        var settings = new Telerik.ReportServer.HttpClient.Settings()
        {
            BaseAddress = "http://localhost:83/"
        };
        Telerik.Reporting.IReportDocument report = null;

        using (var rsClient = new ReportServerClient(settings))
        {
            rsClient.Login("admin", "password");
            var categories = rsClient.GetCategories();
            var myCategoryId = categories.Where(item =&gt; item.Name == categoryName).First().Id;
            var reportInfos = rsClient.GetReportInfosInCategory(myCategoryId);
            var myReportId = reportInfos.Where(item =&gt; item.Name == reportName).First().Id;

            var reportDefinition = rsClient.GetLatestReportRevision(myReportId);
            var extension = reportDefinition.Extension;

            using (var sourceStream = new MemoryStream(reportDefinition.Content))
            {
                if (extension.Contains("trdx"))
                {
                    using (System.Xml.XmlReader xmlReader = System.Xml.XmlReader.Create(sourceStream))
                    {
                        ReportXmlSerializer xmlSerializer = new ReportXmlSerializer();

                        report = ResolveSubReports((Report)xmlSerializer.Deserialize(xmlReader));
                    }
                }
                else
                {
                    var reportPackager = new ReportPackager();
                    if (extension.Contains("trbp"))
                    {
                        report = ResolveReportBookMembers((ReportBook)reportPackager.UnpackageDocument(sourceStream));
                    }
                    else
                    {
                        report = ResolveSubReports((Report)reportPackager.UnpackageDocument(sourceStream));
                    }
                }
            }
        }
        return report;
    }

    public ReportBook ResolveReportBookMembers(ReportBook reportBook)
    {
        var invalidReportSourceIds = reportBook.ReportSources.Select(x =&gt; ((UriReportSource)x).Uri).ToList();
        reportBook.ReportSources.Clear();
        foreach (var id in invalidReportSourceIds)
        {
            IReportDocument report = GetReportDocument(id);
            InstanceReportSource reportIRS = new InstanceReportSource() { ReportDocument = report };
            reportBook.ReportSources.Add(reportIRS);
        }
        return reportBook;
    }

    public Report ResolveSubReports(Report report)
    {
        foreach (ReportItem reportItem in report.Items.Find(typeof(SubReport), true))
        {
            var id = ((UriReportSource)((SubReport)reportItem).ReportSource).Uri;
            var subReport = GetReportDocument(id);
            var subReportIRS = new InstanceReportSource() { ReportDocument = subReport };

            ((SubReport)reportItem).ReportSource = subReportIRS;
        }
        return report;
    }
}

See Also

In this article