Export a parameterized SSRS report from C# code - c#

Currently I have SQL Reporting Services 2005 set up, with the report manager at a URL on which users can access reports. The reports are working great there.
My issue is trying to generate these reports in C# .net 4.0 code without any user interaction (such as using the report viewer on screen). I would like to generate and export a report to a PDF file in a C# .net application. The reports have required parameters so I would need to pass the parameters to the report. How can I do this?
I have been searching around online, and either I'm using the wrong keywords or there isn't much information on this. I am quite amazed at how difficult it has been to find information on this, as I would expect it to be a fairly common question. Any and all advice / help is appreciated.

I've not used the 2005 version of the ReportViewer much. But you should be able to do something like this:
ServerReport serverReport = new ServerReport();
serverReport.ReportPath = "path/to/report";
serverReport.ReportServerCredentials = ...;
serverReport.ReportServerUrl = "http://....";
serverReport.SetParameters(...);
string mimeType;
string encoding;
string extension;
string[] streams;
Warning[] warnings;
byte[] asPdf = serverReport.Render("PDF", string.Empty, out mimeType, out encoding, out extension, out streams, out warnings);
The general takeaway being that ServerReport and LocalReport were both designed to be usable outside of a ReportViewer.

string outputPath = "C:\Temp\PdfReport.pdf";
ReportViewer reportViewer = new ReportViewer();
reportViewer.ServerReport serverReport = new ServerReport();
reportViewer.ServerReport.ReportPath = #"path/to/report";
reportViewer.ServerReport.ReportServerUrl = new Uri(#"http://...");
reportViewer.ProcessingMode = ProcessingMode.Local;
reportViewer.ServerReport.ReportServerCredentials.NetworkCredentials = new
System.Net.NetworkCredential(username, password, domain)
List<ReportParameter> parameters = new List<ReportParameter>();
parameters.Add(new ReportParameter("parameterName", "value"));
string mimeType;
string encoding;
string extension;
string[] streams;
Warning[] warnings;
byte[] pdfBytes= serverReport.Render("PDF", string.Empty, out mimeType,
out encoding, out extension, out streams, out warnings);
// save the file
using (FileStream fs = new FileStream(outputPath, FileMode.Create))
{
fs.Write(pdfBytes, 0, pdfBytes.Length);
fs.Close();
}

I had a similar issue where I wanted to open the report as a PDF. If you just need to open a pdf with parameters in a browser window then you can use the report server itself and specify Format=PDF as a querystring option.
Example:
http://myServer/ReportServer/Pages/ReportViewer.aspx?%2fMyApplicationReports%2fAcutalReportFileName&rs:Command=Render&rs:Format=PDF&ParamOneId=31943&ParamTwoDate=17072015
I hope this saves someone else out there some time!

Related

Execute SSRS Report from C# save as PDF

So, here's my delema.
The title says it all. I cannot seem to find any guidance on how to execute a SSRS report remotely and save it as a PDF.
I have tried to follow the below article.
Using Reporting Services (SSRS) as a reference in an ASP.NET Core site
However, when I add the Service Reference to my project some of the methods seem to have the wrong signatures.
For example.
rsExec.LoadReportAsync(report, null);
in my reference the first parameter is a TrustedUserHeader object.
Does anyone have a good starting point on how to execute an SSRS report from C#? I cannot find any simple example.
I do this by using Microsoft.Reporting.Webforms and the following method:
using Microsoft.Reporting.WebForms;
...
public byte[] ExportToExcel(string reportName, string[] paramNames, string[][] paramDic)
{
// Variables
Warning[] warnings;
string[] streamIds;
string mimeType;
string encoding;
string extension;
ReportViewer rv = new ReportViewer { ProcessingMode = ProcessingMode.Remote };
rv.AsyncRendering = false;
ServerReport sr = rv.ServerReport;
sr.ReportServerUrl = new Uri("http://<server>/reportserver");
sr.ReportPath = "/<report path>/" + reportName;
if (paramNames.Length != 0)
{
List<ReportParameter> paramList = paramNames.Select((t, i) => new ReportParameter(t, paramDic[i])).ToList();
rv.ServerReport.SetParameters(paramList);
}
return rv.ServerReport.Render("Excel", null, out mimeType, out encoding, out extension,
out streamIds, out warnings);
}
The byte array can then be sent to the client via Response or saved to a file to be emailed/transferred later.
The first parameter is the name of the report, the second is an array of parameter names, and the third is an array of arrays containing the parameter values. I wrote this method early in my career and I wouldn't write it this way now. If you use this, I would refactor the code to take two parameters: reportName and a Dictionary called parameters or something like that to manage the parameter values.

Unable to render Report into PDF in Windows Server 2012

I'm facing one of the most strangest technical problem in .NET. I've written following logic to export report to PDF which is working in all the systems except Windows Server 2012. What could be the problem? I tried using the latest Microsoft.ReportViewer.Winforms.dll, but that too didn't help. Please help me if someone has any idea to deal with this.
reportViewer = new ReportViewer();
Warning[] warnings;
string[] streamids;
string mimeType, encoding, filenameExtension;
Assembly assembly = Assembly.LoadFrom(report.AssemblyName);
Stream stream = assembly.GetManifestResourceStream(report.ReportName);
reportViewer.LocalReport.LoadReportDefinition(stream);
//reportViewer.LocalReport.DataSources.Clear();
//reportViewer.ProcessingMode = ProcessingMode.Local;
//lr = reportViewer.LocalReport;
//lr.ReportPath = "Reports\\CommentReport.rdlc";
reportViewer.LocalReport.DataSources.Clear();
foreach (var dataSource in report.DataSources)
{
reportViewer.LocalReport.DataSources.Add(new ReportDataSource(dataSource.Key, dataSource.Value));
}
pdfByteArray = reportViewer.LocalReport.Render("PDF", null, out mimeType, out encoding, out filenameExtension, out streamids, out warnings);

Is there any way to ask a ReportViewer if the result of the query inside a Report will yield more than 65k rows?

I have my reports in a Reporting Services server, inside my .rdl there is a query that accepts parameters. I pass those parameters with an instance of ReportViewer. I have a method that downloads the result of the report in Excel format without using the ReportViewer directly. The method is the following:
private void CreateEXCEL(Dictionary<string, string> parametros, string nombreReporte)
{
// Variables
Warning[] warnings;
string[] streamIds;
string mimeType = string.Empty;
string encoding = string.Empty;
string extension = string.Empty;
// Setup the report viewer object and get the array of bytes
string ReportServerURL = ConfigurationManager.AppSettings["ReportServerCompletitudURL"];
string ReportName = ConfigurationManager.AppSettings["ReportNameRankingVentaPDV"] + "/" + nombreReporte;
MyReportViewer.Reset();
MyReportViewer.ProcessingMode = ProcessingMode.Remote;
MyReportViewer.ServerReport.ReportPath = ReportName;
MyReportViewer.ServerReport.ReportServerUrl = new Uri(ReportServerURL);
List<ReportParameter> parameters = new List<ReportParameter>();
foreach (var d in parametros)
{
parameters.Add(new ReportParameter(d.Key, d.Value));
}
MyReportViewer.ServerReport.SetParameters(parameters);
byte[] bytes = MyReportViewer.ServerReport.Render("EXCEL", null, out mimeType, out encoding, out extension, out streamIds, out warnings);
// Now that you have all the bytes representing the PDF report, buffer it and send it to the client.
Response.Buffer = true;
Response.Clear();
Response.ContentType = mimeType;
Response.AddHeader("content-disposition", "attachment; filename=" + nombreReporte + "." + extension);
Response.BinaryWrite(bytes); // create the file
Response.Flush(); // send it to the client to download
}
Now the idea is that I can't create a file with more that 65536 rows as an Excel file, the idea is to "Ask" if the result of the query inside the Report will yield more than 65k rows, then use csv format.
I dont see that reportviewer server control have a method that checks the result of the query.
I don't want to use pagebreaks inside the SSRS reports. Is there any way to ask in my code behind?
Not sure if this helps but this is a work around for exporting to excel.
Create a parent group on the tablix (or table, or list) and in the Group on: field enter the expression below.
Add Page break between each instance of a group
=CInt(Ceiling(RowNumber(nothing)/65000))
See Question on Here.
I found the solution to this particular problem like this:
Put this expression in my "Details" Group. In Disabled property: =IIF(rownumber(nothing) mod 10000=0,false,true) BreakLocation: End.
After this change, I can save this excel divided in different worksheets in the same excel sheet for every 10k rows. I tried doing the ceiling but if you have a rownumber expression inside that group it wont work.

Save SSRS Report as PDF in C# programmatically

I've read through multiple articles regarding this issue however they have all ended up with it not working, or are in vb.net.
What I currently have:
The reports are accessed via a URL which renders them as a PDF and saves them in the downloads folder when the user clicks on a button, these are given generic names such as OrderReport, OrderReport(1)... and so on.
var orderNum = 1;
"http://Server/ReportServer_Name/Pages/ReportViewer.aspx?%2fOrderReport&rs:Command=Render&OrderID=" + orderNum + "&rs:ClearSession=true&rs:Format=PDF"
What I am trying to acheive:
I would like to use C# to fetch this report if possible, and then specify a name for the PDF file and save it in the correct location.
so for example I would like to save this report in a temporary folder for now "C:\temp" with the name OrderID-1. I am using C#
I have added in a ServiceReference into the Project i am using called ReportTestings so the reference is
using ReportTestings;
and the Web Reference URL:
http://Server/ReportServer_Name/ReportExecution2005.asmx
(removed the actual names for security reasons)
so based on all of this information above could someone point me in the right direction or give an example part of code, Thankyou for all that read this post or help
using this code i get this error :(+ e
{"Access to the path 'C:\\Program Files (x86)\\IIS Express\\report1one.pdf' is denied."} System.Exception {System.UnauthorizedAccessException})
code:
ReportExecutionService rs = new ReportExecutionService();
rs.Credentials = new NetworkCredential("username", "password", "domain");
rs.Url = "http://Server/ReportServer_Name/reportexecution2005.asmx";
// Render arguments
byte[] result = null;
string reportPath = "/Invoice";
string format = "PDF";
string historyID = null;
string devInfo = #"<DeviceInfo><Toolbar>False</Toolbar></DeviceInfo>";
// Prepare report parameter.
ParameterValue[] parameters = new ParameterValue[3];
parameters[0] = new ParameterValue();
parameters[0].Name = "InvoiceID";
parameters[0].Value = "2";
DataSourceCredentials[] credentials = null;
string showHideToggle = null;
string encoding;
string mimeType;
string extension;
Warning[] warnings = null;
ParameterValue[] reportHistoryParameters = null;
string[] streamIDs = null;
ExecutionInfo execInfo = new ExecutionInfo();
ExecutionHeader execHeader = new ExecutionHeader();
rs.ExecutionHeaderValue = execHeader;
execInfo = rs.LoadReport(reportPath, historyID);
rs.SetExecutionParameters(parameters, "en-us");
String SessionId = rs.ExecutionHeaderValue.ExecutionID;
Console.WriteLine("SessionID: {0}", rs.ExecutionHeaderValue.ExecutionID);
try
{
result = rs.Render(format, devInfo, out extension, out encoding, out mimeType, out warnings, out streamIDs);
execInfo = rs.GetExecutionInfo();
Console.WriteLine("Execution date and time: {0}", execInfo.ExecutionDateTime);
}
catch (SoapException e)
{
Console.WriteLine(e.Detail.OuterXml);
}
// Write the contents of the report to an MHTML file.
try
{
FileStream stream = File.Create("report1one.pdf", result.Length);
Console.WriteLine("File created.");
stream.Write(result, 0, result.Length);
Console.WriteLine("Result written to the file.");
stream.Close();
}
catch (Exception e)
{
Console.WriteLine(e.Message);
}
The webservice URL you are using (ReportService2012) is for managing the report server objects.
If you need to render reports, you should be using the ReportExecution2005 webservice.
To get started, you should take a look at the Render method.
To specify credentials you can add the folowing line (I'm the same variable name used in your link: RS2005):
RS2005.Credentials = new System.Net.NetworkCredential("username", "password", "domain");
EDIT:
Your access denied error occurs when your application try to save the file with your web application, so you should use an absolute path or resolve it using Server.MapPath
I recommend an amazingly simple implementation that I found at Crafted For Everyone. The author shows how to add a Service Reference to the SSRS server, and then provides sample code that worked for me on the first try.
It saves the report to a local file, but it is easy to send the report in an email (not included in sample.

Search for available reports on server using C#

I would like to somehow cycle through my Reporting Server and display available reports to the user. Is this possible?
My Code is as follows (still in development):
ServerReport sr = new ServerReport();
sr.ReportPath = reportViewer1.ServerReport.ReportPath;
sr.ReportServerUrl = new Uri(Path);
ReportParameterInfoCollection rpc = sr.GetParameters();
if (rpc.Count > 0)
Console.WriteLine("New");
string outputPath = #"C:\Temp\PdfReport.pdf";
string mimeType;
string encoding;
string extension;
string[] streams;
Warning[] warnings;
byte[] pdfBytes= sr.Render("PDF", string.Empty, out mimeType,
out encoding, out extension, out streams, out warnings);
// save the file
using (FileStream fs = new FileStream(outputPath, FileMode.Create))
{
fs.Write(pdfBytes, 0, pdfBytes.Length);
fs.Close();
}
I use the ReportingService2010 web service to retrieve all deployed items (data sources, shared data sets and reports) and also to deploy directly to Reporting Services.
Here is just one example of the many methods available:
http://msdn.microsoft.com/en-us/library/reportservice2010.reportingservice2010.listchildren.aspx
The ListChildren method will return all items (as a CatalogItem object) under a folder. If you give it the root folder, it will return everything. You should then be able to determine what item each CatalogItem represents.
Hope that helps,
Ash
For anyone else having this problem and would like more information about Ash Shah's answer, see this SO post:
How do I get a list of the reports available on a reporting services instance

Categories