I need to open a report that has subreports, so far managed to do.
Came the need to change the connection of the run-time report and then follow the articles of you I implemented an object that changes the connection string, but my subreport always gets the wrong path, that is, the main report opens but the subreport has problem in the path of the file in the same directory. I've tried to solve the path of the subreport and did not succeed, can anyone help me?
Below is my code:
Code my view
01.
@model Samich.Relatorios.ViewModels.SGO.RelAdvertenciaMotoristaViewModel
02.
03.
@{
04.
Layout = null;
05.
}
06.
<!DOCTYPE html>
07.
<
html
xmlns
=
"http://www.w3.org/1999/xhtml"
>
08.
<
head
>
09.
<
title
>Telerik MVC HTML5 Report Viewer</
title
>
10.
11.
<
meta
http-equiv
=
"X-UA-Compatible"
content
=
"IE=edge"
>
12.
13.
<
meta
name
=
"viewport"
content
=
"width=device-width, initial-scale=1, maximum-scale=1"
/>
14.
15.
<
script
src
=
"http://code.jquery.com/jquery-1.9.1.min.js"
></
script
>
16.
17.
<
link
href
=
"http://kendo.cdn.telerik.com/2015.3.930/styles/kendo.common.min.css"
rel
=
"stylesheet"
/>
18.
<
link
href
=
"http://kendo.cdn.telerik.com/2015.3.930/styles/kendo.blueopal.min.css"
rel
=
"stylesheet"
/>
19.
20.
<!--kendo.web.min.js or kendo.all.min.js can be used as well instead of the following custom Kendo UI-->
21.
<
script
src
=
"@Url.Content("
~/ReportViewer/js/kendo.subset.2015.3.930.min.js")"></
script
>
22.
23.
<
style
>
24.
#reportViewer1 {
25.
position: relative;
26.
width: 1300px;
27.
height: 900px;
28.
font-family: Verdana, Arial;
29.
}
30.
</
style
>
31.
32.
<
script
src
=
"@Url.Content("
~/ReportViewer/js/telerikReportViewer-10.1.16.615.min.js")"></
script
>
33.
34.
</
head
>
35.
<
body
>
36.
37.
@{
38.
Dictionary<
string
, object> parametros = new Dictionary<
string
, object>();
39.
parametros.Add("DataOcorrencia", Model.DataOcorrencia);
40.
}
41.
42.
@(Html.TelerikReporting().ReportViewer()
43.
.Id("reportViewer1")
44.
.ServiceUrl(Url.Content("/api/reports"))
45.
//.ReportSource("_SGO_Relatorio_Ocorrencia_Monitoramento.trdp", parametros)
46.
.ReportSource("_SGO_Relatorio_Ocorrencia_Monitoramento.trdx", parametros)
47.
//.ReportSource("_SGO_Relatorio_Ocorrencia_Monitoramento.trdx")
48.
//.ReportSource(Model.ReportSource)
49.
50.
.ViewMode(ViewMode.PrintPreview)
51.
.ScaleMode(ScaleMode.FitPageWidth)
52.
.Scale(1.0)
53.
.PersistSession(false)
54.
.PrintMode(PrintMode.AutoSelect)
55.
)
56.
57.
</
body
>
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
</
html
>
Code my controller RelAdvertenciaMotorista
01.
using
System;
02.
using
System.Web.Mvc;
03.
using
Samich.Relatorios.ViewModels.SGO;
04.
using
Samich.Relatorios.Helpers;
05.
using
Telerik.Reporting;
06.
using
System.Collections.Generic;
07.
using
System.IO;
08.
using
Telerik.Reporting.Services.WebApi;
09.
using
Telerik.Reporting.Services;
10.
using
Telerik.Reporting.Cache.File;
11.
using
System.Collections.ObjectModel;
12.
13.
namespace
Samich.Relatorios.Controllers.SGO
14.
{
15.
public
class
RelAdvertenciaMotoristaController : Controller
16.
{
17.
public
ActionResult GerarRelatorio()
18.
{
19.
20.
21.
////Crio e populo a ViewModel com os dados do novo relatório
22.
RelAdvertenciaMotoristaViewModel vm =
new
RelAdvertenciaMotoristaViewModel();
23.
vm.DataOcorrencia = DateTime.Now;
24.
//vm.ReportSource = reportSource;
25.
26.
//Chamo a ViewModel que contém o relatório
27.
return
View(
"../SGO/RelAdvertenciaMotorista/GerarRelatorio"
, vm);
28.
}
29.
}
30.
}
Code my class ReportConnectionStringManager
001.
using
System;
002.
using
System.Linq;
003.
using
Telerik.Reporting;
004.
005.
namespace
Samich.Relatorios.Helpers
006.
{
007.
public
class
ReportConnectionStringManager
008.
{
009.
readonly
string
connectionString;
010.
011.
public
ReportConnectionStringManager(
string
connectionString)
012.
{
013.
this
.connectionString = connectionString;
014.
}
015.
016.
public
ReportSource UpdateReportSource(ReportSource sourceReportSource)
017.
{
018.
if
(sourceReportSource
is
UriReportSource)
019.
{
020.
var uriReportSource = (UriReportSource)sourceReportSource;
021.
022.
//Monto o caminho do arquivo aqui, pois podem existir subreports no relatório e
023.
//a rotina pega os mesmos dinamicamente
024.
if
(!uriReportSource.Uri.Contains(@
"\Reports\"
))
025.
{
026.
uriReportSource.Uri = System.Web.HttpContext.Current.Server.MapPath(@
"~/Reports/"
+ uriReportSource.Uri);
027.
028.
}
029.
030.
031.
var reportInstance = DeserializeReport(uriReportSource);
032.
ValidateReportSource(uriReportSource.Uri);
033.
this
.SetConnectionString(reportInstance);
034.
035.
return
CreateInstanceReportSource(reportInstance, uriReportSource);
036.
}
037.
038.
if
(sourceReportSource
is
XmlReportSource)
039.
{
040.
var xml = (XmlReportSource)sourceReportSource;
041.
ValidateReportSource(xml.Xml);
042.
var reportInstance =
this
.DeserializeReport(xml);
043.
this
.SetConnectionString(reportInstance);
044.
return
CreateInstanceReportSource(reportInstance, xml);
045.
}
046.
047.
if
(sourceReportSource
is
InstanceReportSource)
048.
{
049.
var instanceReportSource = (InstanceReportSource)sourceReportSource;
050.
this
.SetConnectionString((ReportItemBase)instanceReportSource.ReportDocument);
051.
return
instanceReportSource;
052.
}
053.
054.
if
(sourceReportSource
is
TypeReportSource)
055.
{
056.
var typeReportSource = (TypeReportSource)sourceReportSource;
057.
var typeName = typeReportSource.TypeName;
058.
ValidateReportSource(typeName);
059.
var reportType = Type.GetType(typeName);
060.
var reportInstance = (Report)Activator.CreateInstance(reportType);
061.
this
.SetConnectionString((ReportItemBase)reportInstance);
062.
return
CreateInstanceReportSource(reportInstance, typeReportSource);
063.
}
064.
065.
throw
new
NotImplementedException(
"Handler for the used ReportSource type is not implemented."
);
066.
}
067.
068.
ReportSource CreateInstanceReportSource(IReportDocument report, ReportSource originalReportSource)
069.
{
070.
var instanceReportSource =
new
InstanceReportSource { ReportDocument = report };
071.
instanceReportSource.Parameters.AddRange(originalReportSource.Parameters);
072.
return
instanceReportSource;
073.
}
074.
075.
void
ValidateReportSource(
string
value)
076.
{
077.
if
(value.Trim().StartsWith(
"="
))
078.
{
079.
throw
new
InvalidOperationException(
"Expressions for ReportSource are not supported when changing the connection string dynamically"
);
080.
}
081.
}
082.
083.
084.
public
Report DeserializeReport(UriReportSource uriReportSource)
085.
{
086.
var settings =
new
System.Xml.XmlReaderSettings();
087.
settings.IgnoreWhitespace =
true
;
088.
089.
//Monto o caminho do arquivo aqui, pois podem existir subreports no relatório e
090.
//a rotina pega os mesmos dinamicamente
091.
if
(!uriReportSource.Uri.Contains(@
"\Reports\"
))
092.
{
093.
uriReportSource.Uri = System.Web.HttpContext.Current.Server.MapPath(@
"~/Reports/"
+ uriReportSource.Uri);
094.
}
095.
096.
using
(var xmlReader = System.Xml.XmlReader.Create(uriReportSource.Uri, settings))
097.
{
098.
var xmlSerializer =
new
Telerik.Reporting.XmlSerialization.ReportXmlSerializer();
099.
var report = (Telerik.Reporting.Report)xmlSerializer.Deserialize(xmlReader);
100.
return
report;
101.
}
102.
}
103.
104.
Report DeserializeReport(XmlReportSource xmlReportSource)
105.
{
106.
var settings =
new
System.Xml.XmlReaderSettings();
107.
settings.IgnoreWhitespace =
true
;
108.
var textReader =
new
System.IO.StringReader(xmlReportSource.Xml);
109.
using
(var xmlReader = System.Xml.XmlReader.Create(textReader, settings))
110.
{
111.
var xmlSerializer =
new
Telerik.Reporting.XmlSerialization.ReportXmlSerializer();
112.
var report = (Telerik.Reporting.Report)xmlSerializer.Deserialize(xmlReader);
113.
return
report;
114.
}
115.
}
116.
117.
void
SetConnectionString(ReportItemBase reportItemBase)
118.
{
119.
if
(reportItemBase.Items.Count < 1)
120.
return
;
121.
122.
if
(reportItemBase
is
Report)
123.
{
124.
var report = (Report)reportItemBase;
125.
126.
127.
if
(report.DataSource
is
SqlDataSource)
128.
{
129.
var sqlDataSource = (SqlDataSource)report.DataSource;
130.
sqlDataSource.ConnectionString = connectionString;
131.
}
132.
foreach
(var parameter
in
report.ReportParameters)
133.
{
134.
if
(parameter.AvailableValues.DataSource
is
SqlDataSource)
135.
{
136.
var sqlDataSource = (SqlDataSource)parameter.AvailableValues.DataSource;
137.
sqlDataSource.ConnectionString = connectionString;
138.
}
139.
}
140.
}
141.
142.
foreach
(var item
in
reportItemBase.Items)
143.
{
144.
//recursively set the connection string to the items from the Items collection
145.
SetConnectionString(item);
146.
147.
//set the drillthrough report connection strings
148.
var drillThroughAction = item.Action
as
NavigateToReportAction;
149.
if
(
null
!= drillThroughAction)
150.
{
151.
var updatedReportInstance =
this
.UpdateReportSource(drillThroughAction.ReportSource);
152.
drillThroughAction.ReportSource = updatedReportInstance;
153.
}
154.
155.
if
(item
is
SubReport)
156.
{
157.
var subReport = (SubReport)item;
158.
159.
160.
161.
//UriReportSource uri = new UriReportSource() { Uri = System.Web.HttpContext.Current.Server.MapPath(@"~/Reports/SGO_Ocorrencias.trdx") };
162.
//subReport.ReportSource = uri;
163.
164.
subReport.ReportSource =
this
.UpdateReportSource(subReport.ReportSource);
165.
continue
;
166.
}
167.
168.
//if (item is DetailSection)
169.
//{
170.
// //Seta o uri paulo
171.
// var detailSectionItem = (DetailSection)item;
172.
173.
// detailSectionItem.Items.ToList().ForEach(x => {
174.
// if (x is SubReport)
175.
// {
176.
// var subReportX = (SubReport)x;
177.
178.
// string nameReport = ((ReportItemBase)(((InstanceReportSource)subReportX.ReportSource).ReportDocument)).Name;
179.
// var uriItem = new UriReportSource() { Uri = nameReport + ".trdx" };
180.
181.
// if (!uriItem.Uri.Contains(@"\Reports\"))
182.
// {
183.
// uriItem.Uri = System.Web.HttpContext.Current.Server.MapPath(@"~/Reports/" + uriItem.Uri);
184.
// }
185.
186.
// subReportX.ReportSource = uriItem;
187.
// }
188.
// });
189.
//}
190.
191.
192.
//Covers all data items(Crosstab, Table, List, Graph, Map and Chart)
193.
if
(item
is
DataItem)
194.
{
195.
var dataItem = (DataItem)item;
196.
if
(dataItem.DataSource
is
SqlDataSource)
197.
{
198.
var sqlDataSource = (SqlDataSource)dataItem.DataSource;
199.
sqlDataSource.ConnectionString = connectionString;
200.
continue
;
201.
}
202.
}
203.
204.
}
205.
}
206.
}
207.
}
Code my class MyResolver
01.
using
System;
02.
using
System.Collections.Generic;
03.
using
System.Linq;
04.
using
System.Text;
05.
using
System.Threading.Tasks;
06.
using
Telerik.Reporting;
07.
using
Telerik.Reporting.Services.Engine;
08.
09.
namespace
Samich.Relatorios.Helpers
10.
{
11.
public
class
MyResolver : IReportResolver
12.
{
13.
public
Telerik.Reporting.ReportSource Resolve(
string
report)
14.
{
15.
Report reportInstance =
null
;
16.
17.
//Obtenho a string de conexão que irei usar para o relatório.
18.
var stringConexao = System.Configuration.ConfigurationManager.ConnectionStrings[
"LinaveConnectionString"
].ConnectionString;
19.
20.
//retrieve an instance of the report
21.
var uriReportSource =
new
UriReportSource { Uri = report };
22.
23.
//Passo a string de conexão para a classe ReportConnectionStringManager que será
24.
//responsável por alterar todas as conexões de dentro do relatório
25.
var newReport =
new
ReportConnectionStringManager(stringConexao);
26.
27.
//retrieve an instance of the report
28.
reportInstance = newReport.DeserializeReport(uriReportSource);
29.
30.
//Atualizo o relatório com a nova conexão
31.
var reportSource = newReport.UpdateReportSource(uriReportSource);
32.
33.
//change the report's DataSource settings
34.
(reportInstance.DataSource
as
Telerik.Reporting.SqlDataSource).ConnectionString = stringConexao;
35.
36.
//change a nested data item's DataSource
37.
//((reportInstance.Items.Find("table1", true)[0] as Telerik.Reporting.Table).DataSource = GetStoredOnTheServerData();
38.
//set report parameters values
39.
//reportInstance.ReportParameters["UserId"].Value = GetUserId();
40.
//}
41.
return
new
InstanceReportSource { ReportDocument = reportInstance };
42.
}
43.
44.
45.
}
46.
}
Code my ReportController
01.
namespace
Samich.Relatorios.Controllers
02.
{
03.
using
Helpers;
04.
using
System.IO;
05.
using
System.Net.Http;
06.
using
System.Web;
07.
using
System.Web.Http;
08.
using
Telerik.Reporting.Cache.File;
09.
using
Telerik.Reporting.Services;
10.
using
Telerik.Reporting.Services.WebApi;
11.
12.
//The class name determines the service URL.
13.
//ReportsController class name defines /api/report/ service URL.
14.
public
class
ReportsController : ReportsControllerBase
15.
{
16.
static
ReportServiceConfiguration configurationInstance;
17.
18.
static
ReportsController()
19.
{
20.
//This is the folder that contains the report definitions
21.
//In this case this is the Reports folder
22.
var appPath = HttpContext.Current.Server.MapPath(
"~/"
);
23.
var reportsPath = Path.Combine(appPath,
"Reports"
);
24.
25.
//Add resolver for trdx/trdp report definitions,
26.
//then add resolver for class report definitions as fallback resolver;
27.
//finally create the resolver and use it in the ReportServiceConfiguration instance.
28.
//var resolver = new ReportFileResolver(reportsPath)
29.
// .AddFallbackResolver(new ReportTypeResolver());
30.
31.
//Setup the ReportServiceConfiguration
32.
configurationInstance =
new
ReportServiceConfiguration
33.
{
34.
HostAppId =
"Html5App"
,
35.
Storage =
new
FileStorage(),
36.
ReportResolver =
new
MyResolver(),
37.
//ReportResolver = resolver
38.
// ReportSharingTimeout = 0,
39.
// ClientSessionTimeout = 15,
40.
};
41.
}
42.
43.
public
ReportsController()
44.
{
45.
//Initialize the service configuration
46.
this
.ReportServiceConfiguration = configurationInstance;
47.
}
48.
}
49.
}