发布时间:2023-10-18
Telerik Reporting拥有直观、无代码的Win、网页与PDF报表的创建功能,直观的设计与具有特定风格的报表,无代码数据打包、向导、语法开发工具、自动操作。分类整理、过滤、有条件格式化、转化器格式,活动报表,水晶报表,附加报表。
本文主要目的是展示在这两种呈现报表的方法(Telerik Report Server (TRS)和Telerik Reporting REST)之间切换是多么容易,我们还将展示每种方法的优缺点,以及如何同时运行两种解决方案并在两者之间切换。
需要注意的一点是:它需要一点设置,您需要有一个ASP. NET Core站点,这用于通过HTML5 Telerik Report查看器调用TRS 和REST报表实例。
技术交流群:726377843 欢迎一起进群讨论
对于在TRS和REST报表之间切换的初始设置,我们需要做以下工作:
确保版本与ASP.NET Core站点上的Telerik Reporting版本匹配。
1. 这涉及到创建一个Telerik Reporting REST服务项目,注意:在本例中创建了一个.NET Framework版本的Reporting REST服务,这是因为已经在.NET框架项目中使用了一些用户函数,这些函数在.NET Core环境中无法工作。另外注意:可以从.NET Core网站和.NET Core Worker调用.NET框架项目(也就是说不需要有一个UI来调用REST项目)。
(或者,您可以使用名为CSharp.NetFramework.ReportingRestServiceCorsDemo的项目。Csproj作为模板随产品安装一起分发,如果您不熟悉CORS配置这可能会加快速度。注意:这可以通过初始的Visual Studio Project对话框使用。)
有必要用下面的代码来修饰Controller类,否则就会出现CORS错误。
[EnableCors(origins: "https://staging.buku.uk" , headers: "*", methods: "*") ] public class ReportsController : ReportsControllerBase
2. 另外,有必要将一些报表放在项目根目录下的一个名为Reports的目录中,您可以使用子目录分隔报表。
3. 使用自定义报表解析器来修复由调用函数提供的连接字符串和参数。在大多数情况下,这是一个Telerik HTML5报表查看器,但是后台任务可以从始终在线的Worker进程中运行。
注意:Booking.Data.NET.Classes.Configuration. _sBookingConnectionString属性解析为基于_nServerInstance变量的连接字符串,即Dev, Staging或Live。
using System.Collections.Generic; using System.IO; using System.Linq; using Telerik.Reporting; using Telerik.Reporting.Services; using Booking.Library.NET.Classes; namespace Booking.Reporting.NET.REST.Classes { public class CustomReportSourceResolver : IReportSourceResolver { public string ReportsPath { get; set; } public CustomReportSourceResolver(string reportsPath) { this.ReportsPath = reportsPath; } public ReportSource Resolve(string reportId, OperationOrigin operationOrigin, IDictionary<string, object> currentParameterValues) { try { string reportPath = Path.Combine(this.ReportsPath, reportId); var reportPackager = new ReportPackager(); Report report = null; using (var sourceStream = System.IO.File.OpenRead(reportPath)) { report = (Report)reportPackager.UnpackageDocument(sourceStream); } if (currentParameterValues.Any(CPV => CPV.Key == "nServerInstance")) { var lnServerInstance = currentParameterValues.Where(CPV => CPV.Key == "nServerInstance").FirstOrDefault().Value; Booking.Data.NET.Classes.Configuration._nServerInstance = (int)(long)lnServerInstance; } ReportConnectionStringManager loReportConnectionStringManager = new ReportConnectionStringManager(Booking.Data.NET.Classes.Configuration._sBookingConnectionString); ReportSource loReportSource = loReportConnectionStringManager.UpdateReportSource(new InstanceReportSource() { ReportDocument = report }); foreach (var parameter in currentParameterValues) { loReportSource.Parameters.Add(parameter.Key, parameter.Value); } return loReportSource; } catch (System.Exception loException) { Logger.LogException(loException); } return null; } } }
选择其中一个或另一个的利弊主要与成本有关。虽然TRS是物有所值的,但一些客户有预算限制,可能会在某些条件下妨碍销售。Buku平台被设计为在客户端基础设施上运行,客户端希望这样做(即,他们自己的服务器和网络,以及产品,可以完全运行在Windows笔记本电脑上)。所以,如果发现一个想要运行软件的客户,他们也必须购买TRS,他们的成本就会显著上升。
REST解决方案可以呈现与TRS解决方案相同的报表,客户端唯一的成本是硬盘空间和计算机功率。(在TRS下面是REST服务的实现,它使这种切换场景变得轻松。)请注意,还将有一个云版本,客户可以在其中注册使用该产品,并且数据位于安全的云中。
TRS解决方案在能够从服务器本身运行报表方面有一些额外的优势,尽管我们没有在Buku平台中完全使用这个特性,客户只能看到Buku平台报表引擎。目前官方正在计划一个额外的Reporting模块,它将允许用户根据预编程的数据源设计自定义报表。
因此 HTML5 Report Viewer 的配置方式是设计考虑的因素之一,它可以在TRS和REST之间来回切换。
下面是报表查看器的顶部,有几点需要注意:
1. TRS具有不需要登录凭据的来宾模式,从URL下面的行中可以看到这一点。
2. REST没有身份验证方法,但是将凭据行保留在原来的位置会被忽略。
3. TRS数据源由TRS数据连接器控制,它实际上是一个连接字符串。对于一些较小的报表,也有一些对象数据源。
4. REST程序总是使用_nServerInstance安排来确定连接字符串,这取决于是Dev、Staging还是Live。
5. 不同类型的报表具有不同类型和数量的参数,但是有些报表使用相同的参数和参数类型,可以对多个报表使用相同的块将它们组合在一起。
$(document).ready(function () { $("#rvMain").telerik_ReportViewer({ reportServer: { url: "@this.Model._sReportingUrl", username: null, password: null }, reportSource: { report: '@this.Model._sReport', parameters: { @switch ((Booking.Library.Classes.Enums.Reports)this.Model._nReport) { case Booking.Library.Classes.Enums.Reports.AdHocSLInvoice1: case Booking.Library.Classes.Enums.Reports.AdHocSLInvoice2: case Booking.Library.Classes.Enums.Reports.AdHocSLCreditNote1: case Booking.Library.Classes.Enums.Reports.AdHocSLCreditNote2: case Booking.Library.Classes.Enums.Reports.AdHocPLInvoice1: case Booking.Library.Classes.Enums.Reports.AdHocPLInvoice2: case Booking.Library.Classes.Enums.Reports.AdHocPLCreditNote1: case Booking.Library.Classes.Enums.Reports.AdHocPLCreditNote2: case Booking.Library.Classes.Enums.Reports.AdHocPLPayment: case Booking.Library.Classes.Enums.Reports.AdHocSLReceipt: { <text> nServerInstance: @Booking.Data.Classes.Configuration._nServerInstance, gTransactionId: '@this.Model._gId.ToString()', gCompanyId: gCompanyId, sCulture: sCompanyCulture </text> } break; case Booking.Library.Classes.Enums.Reports.AdHocDisbursementBatch: { <text> nServerInstance: @Booking.Data.Classes.Configuration._nServerInstance, gBatchId: '@this.Model._gId.ToString()', sCulture: sCompanyCulture </text> } break; case Booking.Library.Classes.Enums.Reports.DisbursementBatch: { <text> nServerInstance: @Booking.Data.Classes.Configuration._nServerInstance, gCompanyId: gCompanyId, dStart: kendo.parseDate('@this.Model._dStart.ToString("dd/MM/yyyy")', "dd/MM/yyyy"), dEnd: kendo.parseDate('@this.Model._dEnd.Date.AddDays(1).ToString("dd/MM/yyyy")', "dd/MM/yyyy"), bPosted: '@this.Model._bPosted.ToString().ToLower()', nReport: @this.Model._nReport, bAll: '@this.Model._bAll.ToString().ToLower()' == 'true', sCulture: sCompanyCulture </text> } break; case Booking.Library.Classes.Enums.Reports.AdHocJournalBatch:
在某些方面,REST报表有一种更简单的机制来保持报告的最新状态,磁盘上的报表是最新的,并且总是保存回磁盘,TRS报告需要发布回服务器。
为了管理切换,我使用了两个控件,一个开关和一个TRS / REST Url字段。开关就是简单的TRS开或关,包含Url的字段将用于TRS https://trs.buku.uk和REST https://rs.buku.uk(报表暂存(RS))。
在使用REST后切换回TRS有点麻烦,因为报表在TRS上经常不是最新的,所以需要再次推送。