Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / Languages / C#

SQL Reporting Services 2008 R2 problem with streamIDs always being nothing, still you can print programmatically

4.90/5 (3 votes)
20 May 2013CPOL4 min read 34.8K   331  
An application which prints reports developed in SSRS 2008R2 using a Windows or web application.

Introduction

This article is about an application which prints reports developed in SSRS 2008R2 using a Windows or web application. The program uses ReportExecutionService to print the report. The class is designed in a way that it is able to print multiple pages of reports in an SSRS 2008R2 environment. The program will give you an understanding of how we can construct a webrequest and build command to extract streams to print multiple pages.

Background

Our client has a Windows application which is used to manage their accounts and business transactions. We have developed SSRS Reporting Service 2005 for reporting purposes. They were able to view the invoicing reports and print those reports. After some time we got new requirement for bar code implementation. We need to show job number as a bar code in the report. In order to support the Barcode we used simple barcode font code 32. The problem with the SSRS 2005 is that it is not capable of embedding font in the text box. When we export the report in pdf the font is not getting exported. We are getting the number values instead of bar code.

We googled a lot and found out, to have this functionality we need to embed font in text box. SSRS 2005 report’s text box doesn’t have this property. When we search on internet we found that SSRS 2008R2 reporting Services supports for Rich Text box. We decided to give it a try.

We migrated our 2005 reports in 2008 reports it faced very few challenges after migration . We implemented the barcode Font in the reports. When we extracted the report in PDF it worked perfectly fine. We were very happy with our results. So we decided to run our basic test for printing functionality and the problem began.

Our old printing functionality was using ReportExecutionService for printing. We have used SreamID to get how many pages are available for printing. When we tried to print we were getting only one page to print. If there are multiple pages in the invoice document they are missed. If we export the report in PDF it is exporting perfectly.

Process

When we debugged the issue we found that the problem is with the ReportingService.Render function’s StreamID. We used the reporting service Render method to traverse through the pages as follows. If you look at the below code the streamIDs return the count of the pages. It gives you the numbers of stream contents in the report.

VB
firstPage = rs.Render(format, deviceInfo, extension, encoding, mimeType, warnings, streamIDs)
' The total number of pages of the report is 1 + the streamIDs
 
'streamIDs used to get the number of the pages. 
_numberOfPages = streamIDs.Length + 1
 
pages = New Byte(_numberOfPages - 1)() {}
 
' The first page was already rendered
 
pages(0) = firstPage
 
Dim pageIndex As Integer = 1
 
Do While pageIndex < _numberOfPages
    ' Collect the number of pages. 
    deviceInfo = String.Format("<DeviceInfo><OutputFormat>{0}</" & _ 
   "OutputFormat><StartPage>{1}</StartPage></DeviceInfo>", "emf", pageIndex + 1)
    pages(pageIndex) = rs.Render(format, deviceInfo, extension, encoding, mimeType, warnings, streamIDs)
    pageIndex += 1
Loop

By setting up the deviceinfo with the following information we actually were able to get new pages:

XML
"<DeviceInfo><OutputFormat>{0}</OutputFormat><StartPage>
  {1}</StartPage></DeviceInfo>", "emf", pageIndex + 1

When we shifted to SSRS 2008R2, we were not able to do this because the StreamID returns empty array for some reason. We searched on the net and found out the reason behind this is the architectural changes; in SSRS 2008R2 as compared to SSRS 2005 the StreamId will always return an empty array. The reason behind is the on-demand page processing has been introduced in SSRS 2008R2.

Using the code

The below implemented code will give you the exact solution for printing multiple pages without streaming using the StreamId variable.

I am assuming that you have already added the ReportExecution2005.asmx as a web reference in your project for the 2005 SSRS Reporting Service.

Building Request

We are building an initial request in string. Using this request we are telling the server to render all the requests.

C#
string requestUri = string.Format("{0}{1}{2}{3}&rs:Command=Render&rs:" & _ 
    "Format=IMAGE&rc:OutputFormat=EMF", report.Url, "?", ReportPath, uRrlparamaters); 

This is the command which helps to create the HTTP request. This request is to notify the user, process the current request, and also keep rendering the remaining pages.

//&rs:Command=Render&rs:Format=IMAGE&rc:OutputFormat=EMF

We have created a Web request using the above constructed string. In addition we are passing the parameter persistStreams for the first page. Once we have the first page we will start asking for the next page until the pages are over.

C#
CookieContainer cookies = new CookieContainer();
WebRequest request = WebRequest.Create(requestUri + persistStreams);
(request as HttpWebRequest).CookieContainer = cookies;

Now the below code will explain how to get all the pages. The while loop we are using because we need to access all the pages of the SSRS reports. In this while loop we are requesting pages till the last page. To execute a continuous request we need to provide authentication for the server. The SSRS server needs authentication for rendering the report. We need to provide authentication = true for every request we make. The complete code can be found in my source code.

Once we create a request, we need to get a response from that request. We collect the response in a WebResponse object. Once we get the response we copy the data in the byte array and add in the MemoryStream for printing purpose. We also create a List of MemoryStream objects which can contain each page in its memory. If we get the page then we will add the page in to the list.

Once we add the page in the memory stream we ask for another page. If the memory stream is 0 then it will break the while loop and you will have the collection of streams for printing.

C#
while (true)
{
    //Authenticates the request with the current logged in windows user credentials.
    request.UseDefaultCredentials = true;
 
    // Get the corresponding web  response for the request object.
    WebResponse response = request.GetResponse();
 
    //Read the response stream.
    Stream s = null;
    MemoryStream ms = new MemoryStream();
        int count = 0;
    byte[] data = null;
 
    s = response.GetResponseStream();
    data = new byte[1024];
 
    do
    {
        count = s.Read(data, 0, data.Length);
        ms.Write(data, 0, count);
    } while (count > 0);
 
    // Set the memory stream position to beginning so we can read it from the start.
    ms.Seek(0, SeekOrigin.Begin);
 
    if (ms.Length == 0)
    {
        break;
    }
    //If not end of pages then add the current stream to the list.
    m_streams.Add(ms);
 
    //Request for the subsecuent pages.
    request = WebRequest.Create(requestUri + getNextStream);
    (request as HttpWebRequest).CookieContainer = cookies;
}

Points of Interest

Actually I have never used this type of page rendering for printing. The SSRS reports are hosted on the server and works as a website but we were dependent on the solution of the stream ID. This solution helped to resolve and upgrade our application to work like the previous one.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)