InvalidLastName
2006-06-13 23:20:52 UTC
(Sorry, this is a re-post via fixed no-spam email alias with my subscription)
Hi,
We are building a custom report viewer for our web application for rendering reports by calling reporting services web services (SOAP over HTTP).
The custom report viewer also perform text replacement to replace any reference pointing to report server in the output from Render method so we don't have to make the report server middle-tier public accessible (As my understanding is built-in report viewer, Microsoft.Reporting.WebForms.ReportViewer, still requires the report server be accessible by clients for images, drilldown, drill-through links)
The problem we currently encounter is the ReportExecutionService.ToggleItem method only toggle items after the first Render
Here is our scenario:
Request 1:
Build custom RDL
Load RDL by calling ReportExecutionService.LoadReportDefinition( ... )
Save the execution ID for later requests
Call Render method
Perform text replacement to replace all the report server references with our custom link, which will intercept the requests to report server middle-tier
return the result to client
Request 2 (user clicks on the drilldown link) :
retrieve the execution ID from the first request
get toggle item id from request
call ReportExecutionService.ToggleItem( ... ), the method returns true, which means the item is found
Call Render method
Perform text replacement to replace all the report server references with our custom link, which will intercept the requests to report server middle-tier
return the result to client
(So far everything works fine)
Request 3 (user clicks on another drilldown link) :
retrieve the execution ID from the first request
get toggle item id from request (different to the request 2)
call ReportExecutionService.ToggleItem( ... ), the method returns true, which means the item is found.
Call Render method
Perform text replacement to replace all the report server references with our custom link, which will intercept the requests to report server middle-tier
return the result to client
(See same output as request 2 ( item id passed in request 3 is not expanded)
I wrote a console application to demonstrate this behavior
(In this console application I used a modified version of "/AdventureWorks Sample Reports/Company Sales" report by replacing the shared data source with private data source, which is required when using LoadReportDefinition
source code of console application:
using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using PlayRSSAPI.ReportService2005;
using PlayRSSAPI.ReportExecution2005;
using System.Xml;
namespace PlayRSSAPI
{
class Program
{
static void Main(string[] args)
{
ReportingService2005 rs = new ReportingService2005();
rs.Credentials = System.Net.CredentialCache.DefaultCredentials;
rs.Url = "http://rdserver/reportserver/reportservice2005.asmx";
Property pName = new Property();
pName.Name = "Name";
Property pDesc = new Property();
pDesc.Name="Description";
Property[] properties = new Property[2];
properties[0] = pName;
properties[1] = pDesc;
// "Copy of Company Sales" is modified version of "/AdventureWorks Sample Reports/Company Sales"
// "Copy of Company Sales" used private datasource instead of shared datasource so the
string reportName = "/AdventureWorks Sample Reports/Copy of Company Sales";
//string reportName = "/AdventureWorks Sample Reports/SalesOrderDetail";
try
{
byte[] b = rs.GetReportDefinition(reportName);
MemoryStream strm = new MemoryStream(b);
XmlDocument doc = new XmlDocument();
doc.Load(strm);
// potentially we will add some columns into RDL here ...
MemoryStream strmOut = new MemoryStream();
doc.Save(strmOut);
byte[] rdlOut = strmOut.ToArray();
ReportExecution2005.ReportExecutionService res = new ReportExecutionService();
res.Url = "http://rdserver/reportserver/ReportExecution2005.asmx";
res.Credentials = System.Net.CredentialCache.DefaultCredentials;
ReportExecution2005.Warning[] warning;
ExecutionInfo ei = res.LoadReportDefinition(rdlOut, out warning);
string format = "HTML4.0"; // "HTML";
string historyID = null;
string devInfo = @"<DeviceInfo><Toolbar>True</Toolbar><Section>1</Section><HTMLFragment>False</HTMLFragment></DeviceInfo>";
string encoding;
string mimeType;
string extension;
string[] streamIDs = null;
ReportExecution2005.Warning[] warnings = null;
byte[] rptOut = null;
bool resToggle = false;
FileStream stream = null;
// first render call
rptOut = res.Render(format, devInfo, out extension, out encoding, out mimeType, out warnings, out streamIDs);
stream = File.Create("C:\\Temp\\report.htm", rptOut.Length);
stream.Write(rptOut, 0, rptOut.Length);
Console.WriteLine("Result written to the file.");
stream.Close();
res = null;
// we are creating a second ReportExecutionService to mimic the page transition in web application
ReportExecutionService res2 = new ReportExecutionService();
res2.ExecutionHeaderValue = new ExecutionHeader();
res2.ExecutionHeaderValue.ExecutionID = ei.ExecutionID;
res2.Credentials = System.Net.CredentialCache.DefaultCredentials;
resToggle = res2.ToggleItem("7"); // expand "Components" block in the report
Console.WriteLine(string.Format("Toggle Item 7 {0} ", (resToggle?"OK":"Failed")));
resToggle = res2.ToggleItem("11"); // expand "2002" block in the report
Console.WriteLine(string.Format("Toggle Item 11 {0} ", (resToggle?"OK":"Failed")));
// Second Render with 2 items toggled
rptOut = res2.Render(format, devInfo, out extension, out encoding, out mimeType, out warnings, out streamIDs);
stream = File.Create("C:\\Temp\\report_toggle_7_11.htm", rptOut.Length);
stream.Write(rptOut, 0, rptOut.Length);
Console.WriteLine("Result written to the file.");
stream.Close();
res2 = null;
// we are creating third ReportExecutionService to mimic the page transition in web application
ReportExecutionService res3 = new ReportExecutionService();
res3.ExecutionHeaderValue = new ExecutionHeader();
res3.ExecutionHeaderValue.ExecutionID = ei.ExecutionID;
res3.Credentials = System.Net.CredentialCache.DefaultCredentials;
resToggle = res3.ToggleItem("27"); // expand "2003" block.
Console.WriteLine(string.Format("Toggle Item 27 {0} ", (resToggle?"OK":"Failed")));
// Third Render, this returns the same result as second Render call
rptOut = res3.Render(format, devInfo, out extension, out encoding, out mimeType, out warnings, out streamIDs);
stream = File.Create("C:\\Temp\\report_toggle_7_11_21.htm", rptOut.Length);
stream.Write(rptOut, 0, rptOut.Length);
Console.WriteLine("Result written to the file.");
stream.Close();
}
catch(Exception ex)
{
Console.WriteLine(ex.ToString());
}
Console.Read();
}
}
}
Hi,
We are building a custom report viewer for our web application for rendering reports by calling reporting services web services (SOAP over HTTP).
The custom report viewer also perform text replacement to replace any reference pointing to report server in the output from Render method so we don't have to make the report server middle-tier public accessible (As my understanding is built-in report viewer, Microsoft.Reporting.WebForms.ReportViewer, still requires the report server be accessible by clients for images, drilldown, drill-through links)
The problem we currently encounter is the ReportExecutionService.ToggleItem method only toggle items after the first Render
Here is our scenario:
Request 1:
Build custom RDL
Load RDL by calling ReportExecutionService.LoadReportDefinition( ... )
Save the execution ID for later requests
Call Render method
Perform text replacement to replace all the report server references with our custom link, which will intercept the requests to report server middle-tier
return the result to client
Request 2 (user clicks on the drilldown link) :
retrieve the execution ID from the first request
get toggle item id from request
call ReportExecutionService.ToggleItem( ... ), the method returns true, which means the item is found
Call Render method
Perform text replacement to replace all the report server references with our custom link, which will intercept the requests to report server middle-tier
return the result to client
(So far everything works fine)
Request 3 (user clicks on another drilldown link) :
retrieve the execution ID from the first request
get toggle item id from request (different to the request 2)
call ReportExecutionService.ToggleItem( ... ), the method returns true, which means the item is found.
Call Render method
Perform text replacement to replace all the report server references with our custom link, which will intercept the requests to report server middle-tier
return the result to client
(See same output as request 2 ( item id passed in request 3 is not expanded)
I wrote a console application to demonstrate this behavior
(In this console application I used a modified version of "/AdventureWorks Sample Reports/Company Sales" report by replacing the shared data source with private data source, which is required when using LoadReportDefinition
source code of console application:
using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using PlayRSSAPI.ReportService2005;
using PlayRSSAPI.ReportExecution2005;
using System.Xml;
namespace PlayRSSAPI
{
class Program
{
static void Main(string[] args)
{
ReportingService2005 rs = new ReportingService2005();
rs.Credentials = System.Net.CredentialCache.DefaultCredentials;
rs.Url = "http://rdserver/reportserver/reportservice2005.asmx";
Property pName = new Property();
pName.Name = "Name";
Property pDesc = new Property();
pDesc.Name="Description";
Property[] properties = new Property[2];
properties[0] = pName;
properties[1] = pDesc;
// "Copy of Company Sales" is modified version of "/AdventureWorks Sample Reports/Company Sales"
// "Copy of Company Sales" used private datasource instead of shared datasource so the
string reportName = "/AdventureWorks Sample Reports/Copy of Company Sales";
//string reportName = "/AdventureWorks Sample Reports/SalesOrderDetail";
try
{
byte[] b = rs.GetReportDefinition(reportName);
MemoryStream strm = new MemoryStream(b);
XmlDocument doc = new XmlDocument();
doc.Load(strm);
// potentially we will add some columns into RDL here ...
MemoryStream strmOut = new MemoryStream();
doc.Save(strmOut);
byte[] rdlOut = strmOut.ToArray();
ReportExecution2005.ReportExecutionService res = new ReportExecutionService();
res.Url = "http://rdserver/reportserver/ReportExecution2005.asmx";
res.Credentials = System.Net.CredentialCache.DefaultCredentials;
ReportExecution2005.Warning[] warning;
ExecutionInfo ei = res.LoadReportDefinition(rdlOut, out warning);
string format = "HTML4.0"; // "HTML";
string historyID = null;
string devInfo = @"<DeviceInfo><Toolbar>True</Toolbar><Section>1</Section><HTMLFragment>False</HTMLFragment></DeviceInfo>";
string encoding;
string mimeType;
string extension;
string[] streamIDs = null;
ReportExecution2005.Warning[] warnings = null;
byte[] rptOut = null;
bool resToggle = false;
FileStream stream = null;
// first render call
rptOut = res.Render(format, devInfo, out extension, out encoding, out mimeType, out warnings, out streamIDs);
stream = File.Create("C:\\Temp\\report.htm", rptOut.Length);
stream.Write(rptOut, 0, rptOut.Length);
Console.WriteLine("Result written to the file.");
stream.Close();
res = null;
// we are creating a second ReportExecutionService to mimic the page transition in web application
ReportExecutionService res2 = new ReportExecutionService();
res2.ExecutionHeaderValue = new ExecutionHeader();
res2.ExecutionHeaderValue.ExecutionID = ei.ExecutionID;
res2.Credentials = System.Net.CredentialCache.DefaultCredentials;
resToggle = res2.ToggleItem("7"); // expand "Components" block in the report
Console.WriteLine(string.Format("Toggle Item 7 {0} ", (resToggle?"OK":"Failed")));
resToggle = res2.ToggleItem("11"); // expand "2002" block in the report
Console.WriteLine(string.Format("Toggle Item 11 {0} ", (resToggle?"OK":"Failed")));
// Second Render with 2 items toggled
rptOut = res2.Render(format, devInfo, out extension, out encoding, out mimeType, out warnings, out streamIDs);
stream = File.Create("C:\\Temp\\report_toggle_7_11.htm", rptOut.Length);
stream.Write(rptOut, 0, rptOut.Length);
Console.WriteLine("Result written to the file.");
stream.Close();
res2 = null;
// we are creating third ReportExecutionService to mimic the page transition in web application
ReportExecutionService res3 = new ReportExecutionService();
res3.ExecutionHeaderValue = new ExecutionHeader();
res3.ExecutionHeaderValue.ExecutionID = ei.ExecutionID;
res3.Credentials = System.Net.CredentialCache.DefaultCredentials;
resToggle = res3.ToggleItem("27"); // expand "2003" block.
Console.WriteLine(string.Format("Toggle Item 27 {0} ", (resToggle?"OK":"Failed")));
// Third Render, this returns the same result as second Render call
rptOut = res3.Render(format, devInfo, out extension, out encoding, out mimeType, out warnings, out streamIDs);
stream = File.Create("C:\\Temp\\report_toggle_7_11_21.htm", rptOut.Length);
stream.Write(rptOut, 0, rptOut.Length);
Console.WriteLine("Result written to the file.");
stream.Close();
}
catch(Exception ex)
{
Console.WriteLine(ex.ToString());
}
Console.Read();
}
}
}