This is a migrated thread and some comments may be shown as answers.

HTML5 Report Viewer - Using Models

3 Answers 1322 Views
General Discussions
This is a migrated thread and some comments may be shown as answers.
This question is locked. New answers and comments are not allowed.
Moses Fetters
Top achievements
Rank 1
Moses Fetters asked on 08 Jul 2014, 05:33 PM
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?

3 Answers, 1 is accepted

Sort by
0
Stef
Telerik team
answered on 11 Jul 2014, 01:35 PM
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.

 
0
Moses Fetters
Top achievements
Rank 1
answered on 11 Jul 2014, 03:58 PM
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!
0
Stef
Telerik team
answered on 16 Jul 2014, 06:21 PM
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.

 
Tags
General Discussions
Asked by
Moses Fetters
Top achievements
Rank 1
Answers by
Stef
Telerik team
Moses Fetters
Top achievements
Rank 1
Share this question
or