Accessing the ReportExecutionService.Render method when reporting service (2008 / R2) is in Forms based authentication (Using ReportingService.LogonUser method)
Recently was working on an interesting sample which will help you to render a report using the web service API where reporting service is in Forms Based Authentication (FBA). This code was tested with SSRS 2008 and SSRS 2008 R2 (KJ). The reason for publishing this code is, this is different from the conventional windows authentication.
1. First you need to make sure your Reporting Service installation is working fine with the FBA implementation.
2. Create a new ASP.NET web application project and add the references to the following web service end points,
ReportService2005.asmx (If you're using SSRS 2008 R2, please make sure to start using ReportService2010.asmx as ReportService 2005.asmx is deprecated) and ReportExecution2005.asmx.
3. Refer the following self explanatory code and use them in your reference. (Attached the full source code and the project with the BLOG post)
protected void Page_Load(object sender, EventArgs e)
{
RenderReport report = new RenderReport();
byte [] result = report.RenderReportToPDF();
//To display the PDF in web browser, set the right content type.
Response.ContentType = "Application/pdf";
//Write the byte array to the default output stream.
Response.OutputStream.Write(result, 0, result.Length);
//Flush the contents to be displayed in the browser.
Response.Flush();
}
//Clash to take care of report rendering
public class RenderReport : ReportingService2005
{
//Change to point to your report.
private string ReportPath = "/Test";
private string m_authCookieName;
private Cookie m_authCookie;
public RenderReport()
{
// Set the server URL. You can pull this from a config file or what ever way you want to make it dynamic.
base.Url = https://kaneco1/reportserver2008/reportservice2005.asmx;
// Calling the LogonUser method defined in the ReportService2005.asmx end point.
// The LogonUser method authenticates the specified user to the Report Server Web Service when custom authentication has been configured.
// This is to authenticate against the FBA code and then store the cookie for future reference.
try
{
base.LogonUser("FBA username", "password", null);
}
catch (Exception
)
{
}
}
/// <summary>
/// Overriding the method defined in the base class.
/// </summary>
/// <param name="uri"></param>
/// <returns></returns>
protected override WebRequest GetWebRequest(Uri uri)
{
HttpWebRequest request;
request = (HttpWebRequest)HttpWebRequest .Create(uri);
request.Credentials = base .Credentials;
request.CookieContainer = new CookieContainer ();
if (m_authCookie != null
)
{
request.CookieContainer.Add(m_authCookie);
}
return request;
}
/// <summary>
/// Overriding the method defined in the base class.
/// </summary>
/// <param name="request"></param>
/// <returns></returns>
protected override WebResponse GetWebResponse(WebRequest request)
{
WebResponse response = base .GetWebResponse(request);
string cookieName = response.Headers["RSAuthenticationHeader"];
if (cookieName != null)
{
m_authCookieName = cookieName;
HttpWebResponse webResponse = (HttpWebResponse )response;
Cookie authCookie = webResponse.Cookies[cookieName];
// save it for future reference and use.
m_authCookie = authCookie;
}
return response;
}
/// <summary>
///Simplified implementation from https://msdn.microsoft.com/en-us/library/reportexecution2005.reportexecutionservice.render.aspx
/// Additionaly it is autheticating against the custom security extension. In our case it is FBA.
/// </summary>
/// <returns>Byte array containing the rendered report in PDF format </returns>
public byte [] RenderReportToPDF()
{
//Create a proxy object for ReportExecution2005.asmx referenced in the project.
//You can pull this from a config file or what ever way you want to make it dynamic.
ReportExecutionService rs = new ReportExecutionService ();
rs.Url = "https://kaneco1/ReportServer2008/ReportExecution2005.asmx";
//Simplified code from https://msdn.microsoft.com/en-us/library/reportexecution2005.reportexecutionservice.render.aspx
byte[] result = null;
string reportPath = "/SimpleSelect" ;
string format = "PDF"
string historyID = null;
string devInfo = "";
string encoding;
string mimeType;
string extension;
//Since warning is definied in both ReportService2005 and ReportExecution2005 endpoints,
//qualifying it with the appropriate namespace.
WebServiceFBARenderMethod.RE2K5.Warning[] warnings = null;
string[] streamIDs = null;
//Attaching the cookie received from the LogonUser method in the constructor.
//Only when autheticated, it will proceed further with ReportExecution2005.asmx end point calls.
if (null != m_authCookie)
{
//Store the cookie in the cookie container within ReportExecutionService object.
//So any subsequent call will make use of this authenticated cookie and will be succeeding.
rs.CookieContainer = new CookieContainer();
rs.CookieContainer.Add(m_authCookie);
ExecutionInfo execInfo = new ExecutionInfo();
ExecutionHeader execHeader = new ExecutionHeader();
rs.ExecutionHeaderValue = execHeader;
execInfo = rs.LoadReport(reportPath, historyID);
try
{
result = rs.Render(format, devInfo, out extension, out encoding, out mimeType, out warnings, out streamIDs);
}
catch (SoapException e)
{
}
}
else
{
//Logic to recall the LogonUser code with proper username / password.
}
//Byte array containing the rendered report in PDF.
return result;
HTH!
Selva.
[All the posts are AS - IS and doesn't carry any warranty]
Comments
- Anonymous
January 18, 2011
The comment has been removed - Anonymous
January 29, 2011
Could you please try the same after applying CU 3 or above and let me how that goes. FIX included in CU 3, support.microsoft.com/.../2283036 HTH! Selva. [Posted AS-IS with no warranty]