HTML5 Report Viewer - Using Models

Thread is closed for posting
4 posts, 0 answers
  1. Moses Fetters
    Moses Fetters avatar
    5 posts
    Member since:
    May 2006

    Posted 08 Jul 2014 Link to this post

    I've recently began updating one of our projects from Reporting Q1 2013 to Q2 2014, but have ran into the problem of trying to pass a Model to an objectdatasource.  Previously, I used http://blogs.telerik.com/careypayette/posts/13-03-26/telerik-reporting-in-mvc-sure-it-takes-8-quick-steps- to display the ReportViewer using .aspx and would use an InstanceReportSource to render the report:

    aspx View
    <%@ Page Language="C#" Inherits="System.Web.Mvc.ViewPage<MyProject.Models.MyModel>" %>

    protected override void OnLoad(EventArgs e)
        {
            base.OnLoad(e);
            var instanceReportSource = new InstanceReportSource();
     
            Report report = new Report1(Model);
     
            instanceReportSource.ReportDocument = report;
     
            ReportViewer1.ReportSource = instanceReportSource;
            ReportViewer1.ViewMode = ViewMode.Interactive;
        }

    Report class:
    using MyProject.Models;

    namespace Admissions.Reports
    {
        using Telerik.Reporting;
     
        public partial class Report1 : Report
        {
            public Report1()
            {
                InitializeComponent();
            }
     
            public Report1(MyModel model) : this()
            {
                DataSource = model;
            }
        }
    }


    With the new version of Telerik Reporting, InstanceReportSource is obsolete when using the new razor syntax to generate the report so we have to use UriReportSource or TypeReportSource.

    @{
        var uriRS = new UriReportSource() { Uri = "1"};
    }
    @(
    Html.TelerikReporting().ReportViewer().Id("reportViewer1")
       .ServiceUrl("/api/reports/")
       .TemplateUrl("/Content/ReportViewer/templates/telerikReportViewerTemplate.html")
            .ReportSource(uriRS)
            .ViewMode(ViewModes.INTERACTIVE)
            .ScaleMode(ScaleModes.SPECIFIC)
            .Scale(1.0)
            .PersistSession(false)
          )

    I've tried to use a custom report resolver (example at bottom of OP (http://www.telerik.com/forums/%27bad-request%27---%27missing-report-name%27-when-using-instancereportsource-in-asp-net-mvc-report-viewer), and was able to pass data in using InstanceReportSource, but I wasn't able to attach any report parameters since the Model is being populated inside of the resolver (which I'd prefer not to do) and the report is created in the resolver and not actually using any parameters from the view.

    namespace Admissions.Controllers
    {
        public class ReportsController : ReportsControllerBase
        {
            protected override ICache CreateCache()
            {
                return Telerik.Reporting.Services.Engine.CacheFactory.CreateFileCache();
            }
     
            protected override IReportResolver CreateReportResolver()
            {
                return new CustomReportResolver();
            }
        }
     
        public class CustomReportResolver : IReportResolver
        {
            public ReportSource Resolve(string reportId)
            {
                var report = new Report();
     
                report = new Report1(new DashboardViewModel { TotalRolesCount = "Hello Report World" });
     
                var irs = new InstanceReportSource { ReportDocument = report };
     
                return irs;
            }
        }
    }

    Has anyone found a way to pass the Model directly into the report, (var report = new Report1(Model) ); or a solution that would work equally well?
  2. Stef
    Admin
    Stef avatar
    3053 posts

    Posted 11 Jul 2014 Link to this post

    Hi Moses,

    The HTML5 Report Viewer is entirely HTML/CSS/JS based widget, which needs the ReportViewer-x.x.x.x.js(css) and telerikReportViewerTemplate.html template files to work. It also requires a running instance of the Telerik Reporting REST Service - the possible service's implementations are Web API and ServiceStack based. By default we provide 


    To create a Web application project that uses the viewer and the Reporting REST Web API, follow the steps listed in the following articles:

    1. HTML5 Report Viewer jQuery widget /How To: Use HTML5 Report Viewer extension in an ASP.NET MVC application
    2. How To: Add Telerik Reporting REST Web API to Web Application



    Then if you need to make customizations over the reports as changing data, you can use a Custom Report Resolver. The string received by the resolver's Resolve method comes from the set viewer's reportSource.report option. Regardless the logic added in the Resolve method as a result you just need to return a valid report source object, which can be also an InstanceReportSource.

    The data retrieval can be accomplished in the Resolve method as well, or through an ObjectDataSource in the report, where the data source component will wrap a data retrieval method getting data based on report parameters e.g. as in the Using Parameters with the ObjectDataSource Component article.


    Regards,
    Stef
    Telerik
     

    Check out the Telerik Platform - the only platform that combines a rich set of UI tools with powerful cloud services to develop web, hybrid and native mobile apps.

     
  3. DevCraft banner
  4. Moses Fetters
    Moses Fetters avatar
    5 posts
    Member since:
    May 2006

    Posted 11 Jul 2014 in reply to Stef Link to this post

    Thank you for confirming my setup.  I've been able to view reports fine if I use other datasources, so I know the basic configuration is working fine.  I'm still left with 2 questions though:
    1.  Is using an InstanceReportSource still considered a viable method since it's  considered obsolete due to REST?
    2. Since the resolver is ran after the controller action and after the view is rendered, how can I pass the populated viewModel into the report?  I'd prefer to not have to do my business logic within the resolver if I can help it, since it would make it difficult to pass parameters into my queries. 

    Here is my current configuration:

    Controller action:
    public virtual ActionResult Report()
    {
        var query = new GetMyQuery();
        var viewModel = _queryProcessor.Process(query);
        return View(Views.Report, viewModel);
    }

    .cshtml view:
    @model MyProject.ViewModels.DashboardViewModel
    @section header
    {
        <link href="/Content/ReportViewer/styles/telerikReportViewer-8.1.14.618.css" rel="stylesheet" />
        <style>
            #reportViewer1 {
                bottom: 5px;
                left: 400px;
                overflow: hidden;
                position: absolute;
                right: 400px;
                top: 200px;
            }
        </style>
        <script src="http://code.jquery.com/jquery-1.9.1.min.js"></script>
    }
    @{
        var uriRS = new UriReportSource {Uri = "1"};
    }
    <div class="widget-body">
        <div class="row-fluid" role="grid">
            <div class="span12" style="padding-bottom: 20px;">
                @(Html.TelerikReporting().ReportViewer().Id("reportViewer1")
                      .ServiceUrl("/api/reports/")
                      .TemplateUrl("/Content/ReportViewer/templates/telerikReportViewerTemplate.html")
                      .ReportSource(uriRS)
                      .ViewMode(ViewModes.INTERACTIVE)
                      .ScaleMode(ScaleModes.SPECIFIC)
                      .Scale(1.0)
                      .PersistSession(false)
                      )
            </div>
        </div>
    </div>
    @section scripts
    {
        <script src="/Content/ReportViewer/js/telerikReportViewer-8.1.14.618.js"></script>
        <link href="/Content/kendo/2014.1.318/kendo.common.min.css" rel="stylesheet" />
        <link href="/Content/kendo/2014.1.318/kendo.blueopal.min.css" rel="stylesheet" />
        <link href="//netdna.bootstrapcdn.com/font-awesome/3.2.1/css/font-awesome.css" rel="stylesheet">
    }

    Reports Controller:
    using MyProject.Reports;
    using Telerik.Reporting;
    using Telerik.Reporting.Cache.Interfaces;
    using Telerik.Reporting.Services.Engine;
    using Telerik.Reporting.Services.WebApi;
     
    namespace MyProject.Controllers
    {
        public class ReportsController : ReportsControllerBase
        {
            protected override ICache CreateCache()
            {
                return Telerik.Reporting.Services.Engine.CacheFactory.CreateFileCache();
            }
     
            protected override IReportResolver CreateReportResolver()
            {
                return new CustomReportResolver();
            }
        }
     
        public class CustomReportResolver : IReportResolver
        {
            public ReportSource Resolve(string reportId)
            {
                var irs = new InstanceReportSource { ReportDocument = new Report1(*viewModel*)};
                return irs;
            }
        }
    }

    Report:
    using MyProject.ViewModels;
    using Telerik.Reporting;
     
    namespace MyProject.Reports
        public partial class Report1 : Report
        {
            public Report1()
            {
                InitializeComponent();
            }
     
            public Report1(DashboardViewModel viewModel) : this()
            {
                DataSource = viewModel;
            }
        }
    }
    Note:  Also have a ObjectDataSource created within the VS2012 report designer with the business object pointing to the viewModel.

    If anyone has any working examples similar to this, it would be much appreciated.  I feel like I'm very close to having this working if I can get the viewModel into the report.

    Thanks!
  5. Stef
    Admin
    Stef avatar
    3053 posts

    Posted 16 Jul 2014 Link to this post

    Hi Moses,

    The HTML5 Report Viewer and the Reporting REST service does not use the MVC concept. Thus if you have a model containing data or other information required in your reports, you need to implement a logic to access that model in the reports' controller e.g. to store the data and access it by key in the service's resolver, or to modify the reports to use such data source component, that wraps a data retrieval method having access to that model.

    An example for accessing data from a database, which database could be filled in any of the custom actions in the application, is illustrated in the How To: Implement a Custom Report Resolver article.

    A demo of a report that uses a custom data retrieval method is available in the local examples under C:\Program Files (x86)\Telerik\Reporting Q2 2014\Examples\CSharp\ReportLibrary\DataBinding. The ListBoundReport uses an ObjectDataSource to retrieve data from a custom business object. This business object can be modified anywhere in the application, when the report is requested its ObjectDataSource will search for the assigned data retrieval method and will get the data.
    Another good example is available in the Connecting Telerik Reporting to OData feeds blog post.


    I hope the above information helps you.

    Regards,
    Stef
    Telerik
     

    Check out the Telerik Platform - the only platform that combines a rich set of UI tools with powerful cloud services to develop web, hybrid and native mobile apps.

     
Back to Top