Telerik Reporting R1 2017

ReportSource Model Binding

The HTML5 Report Viewer comes with an MVC wrapper that does all the JavaScript configuration of the report viewer for you. Another advantage of the wrapper is the fact that you can work with strongly typed data rather than writing URI’s, parameters and report sources as simple strings.

That is - when you are using the MVC wrapper you can actually pass the report source created by you instead of typing a string. If your scenario is more complex there is a fallback option which lets you use a string, but that is in case you are using XmlReportSource or InstanceReportSource and you can resolve your reports in the REST service using your own algorithm.

Getting started

Lets start with the model now. In case all you need is a report viewer that is used to display various reports you can have a simple model to create a strongly typed view - just use the report source, like this (TypeReportSource or UriReportSource):

@model Telerik.Reporting.UriReportSource

Then you can use it directly when you are initializing the report viewer:

@(Html.TelerikReporting().ReportViewer()
       .Id("reportViewer1")
       .ServiceUrl("/api/reports/")
       .TemplateUrl("/ReportViewer/templates/telerikReportViewerTemplate.html")
       .ReportSource(Model)
       .ViewMode(ViewMode.Interactive)
       .ScaleMode(ScaleMode.Specific)
       .Scale(1.0)
       .PersistSession(false)
)

Change report viewer according to the report type

Now in case you have a more complex scenario where the report viewer depends on the displayed report you can create a more complex view model that contains your data, including the report source. Lets take as example the scenario where you need to change the template of the report viewer when you are displaying reports that are not suitable for printing. In that case you will have to create two templates for the report viewer - the default one and the one that has no print button. Then you have to create a view model with two properties - the first will contain the uri to the template and the second the report source. Check this snippet:

public class TemplatedReportViewerViewModel
{
    public string TemplateUri { get; set; }
    public UriReportSource ReportSource { get; set; }
}

Once you have the model you should create your own logic to populate it (note that the MVC View is not a suitable place for that logic). Then use the model for your view to make it strongly typed:

@(Html.TelerikReporting().ReportViewer()
       .Id("reportViewer1")
       .ServiceUrl("/api/reports/")
       .TemplateUrl(Model.TemplateUri)
       .ReportSource(Model.ReportSource)
       .ViewMode(ViewMode.Interactive)
       .ScaleMode(ScaleMode.Specific)
       .Scale(1.0)
       .PersistSession(false)
)

Using custom report resolver

There are cases when the supported report sources (Type and Uri) will not be enough. Perhaps you have created a CustomReportResolver in the REST service and since it accepts string as an argument you might also want to directly use a string as your report source. This is possible again through the ReportSource method. The last two overloads of the ReportSource method accept a string as their first argument. This means that the ReportSource can still be strongly typed, but to a string instead of a ReportSource. This gives you the option to implement any custom logic that you need based on that string. For example you could pass the id of the report in the database:

@(Html.TelerikReporting().ReportViewer()
       .Id("reportViewer1")
       .ServiceUrl("/api/reports/")
       .TemplateUrl("/ReportViewer/templates/telerikReportViewerTemplate.html")
       .ReportSource("73")
       .ViewMode(ViewMode.Interactive)
       .ScaleMode(ScaleMode.Specific)
       .Scale(1.0)
       .PersistSession(false)
)

You can also add parameters, like this:

@(Html.TelerikReporting().ReportViewer()
       .Id("reportViewer1")
       .ServiceUrl("/api/reports/")
       .TemplateUrl("/ReportViewer/templates/telerikReportViewerTemplate.html")
       .ReportSource("73", new Dictionary<string, object>() { { "parameter1", "value1" }, { "parameter2", "value2" } })
       .ViewMode(ViewMode.Interactive)
       .ScaleMode(ScaleMode.Specific)
       .Scale(1.0)
       .PersistSession(false)
)

The view can also be strongly typed:

@(Html.TelerikReporting().ReportViewer()
       .Id("reportViewer1")
       .ServiceUrl("/api/reports/")
       .TemplateUrl("/ReportViewer/templates/telerikReportViewerTemplate.html")
       .ReportSource(Model.ReportSource, Model.Parameters)
       .ViewMode(ViewMode.Interactive)
       .ScaleMode(ScaleMode.Specific)
       .Scale(1.0)
       .PersistSession(false)
)

Finally on the server side your custom report resolver can implement the custom logic that will take in consideration the id and create a report source as per your needs:

class ModelBindingReportResolver : Telerik.Reporting.Services.Engine.IReportResolver
{
    public Telerik.Reporting.ReportSource Resolve(string reportId)
    {
        var report = new Invoice();
        if (true) // condition here
        {
            // prepare your report here
        }
        else
        {
            // do something else with report here
        }

        return new Telerik.Reporting.InstanceReportSource { ReportDocument = report };
    }
}