Amorphous Blob
Amorphous Blob

Reputation: 215

Rendering SSRS in C# console app; where to find SSRS ReportExecutionService?

In a C# console app I’m trying to render an SSRS report on our reporting server, then I’ll stream it out to a PDF file. I’ve found multiple bits of documentation but I’m running into a roadblock… how do I add a reference to the Report Execution Service?

I was able to follow the first step in the code samples… I add a Service Reference / clicked Add Web Reference, typed in http://ServerName/ReportServer_XXX/reportservice2010.asmx, (where I got ReportServer_XXX by remoting to the server and running the RS Config Manager). Then I’m able to do:

var rs = new ReportingService.ReportingService2010();
rs.Credentials = System.Net.CredentialCache.DefaultCredentials;
// etc.

The next step is to add a web reference to the ReportExecutionService, which is what has the Render() method to actually output the PDF as an array of bytes. However, when I type in the URL: http://ServerName/ReportServer_XXX/reportexecutionservice2010.asmx (or ...2005.asmx), it brings up a heading of ServerName/ReportServer_XXX - / and under that the folders in our SSRS site (Chapters, Finance, Marketing, etc). The “Add Reference” button is grayed out.

What am I doing stoopid? Thanks!

Upvotes: 4

Views: 5831

Answers (2)

An alternative it would be to make a WebRequest. I've created this function:

  public static byte[] GenerateReport(string ReportServer, string Username, string Password, string Domain, string ReportPath, string Format, string Parameters)
  {

      ReportPath = ReportPath.Replace("/", "%2f").Replace(" ", "+");
      string URL = ReportServer + "?" + ReportPath + $"&rs:Command=Render&rs:Format=" + Format + "&rs:ParameterLanguage=en-GB" + "&" + Parameters;
      WebRequest Req = WebRequest.Create(URL);
      Req.Credentials = new NetworkCredential(Username, Password, Domain);
      Req.Timeout = Convert.ToInt32(ConfigurationManager.AppSettings["SSRSTimeout"]);
      Stream WebStream = Req.GetResponse().GetResponseStream();
      MemoryStream MemStream = new MemoryStream();
      WebStream.CopyTo(MemStream);
      long Len = MemStream.Length;
      byte[] ReportReturn = new byte[Len];
      MemStream.Seek(0, SeekOrigin.Begin);
      MemStream.Read(ReportReturn, 0, (int)Len);
      WebStream.Close();
      MemStream.Close();
      MemStream.Dispose();
      return ReportReturn;
  }

Use:

  string Domain = ConfigurationManager.AppSettings["SSRSDomain"];
  string Username = ConfigurationManager.AppSettings["SSRSUser"];
  string Password = ConfigurationManager.AppSettings["SSRSPass"];
  string ReportServer = ConfigurationManager.AppSettings["SSRSServer"];

  string ReportPath = "/Report Path/ReportName";
  string Params = "ParamName=ParamValue";

  byte[] ReportData = GenerateReport(ReportServer, Username, Password, Domain, ReportPath, "PDF", Params);

  File.WriteAllBytes(AppDomain.CurrentDomain.BaseDirectory + @"\" + "savedfilename.pdf", ReportData);

Upvotes: 3

Steve_Malcolm
Steve_Malcolm

Reputation: 53

You are doing nothing stupid at all. However, you might want to change that URL to something like this.

ReportExecutionService rexec = new ReportExecutionService();
rexec.Credentials = System.Net.CredentialCache.DefaultCredentials;
rexec.Url = "http://<your report server>/reportserver/ReportExecution2005.asmx";

I know that it's counter-intuitive. I am using SSRS 2017 and VS 2017 and it's still "2005". The following is SSRS boiler-plate from Microsoft:

string encoding = null;
Warning[] warnings = null;
string[] streamIDs = null;
ExecutionInfo execInfo = new ExecutionInfo();
ExecutionHeader execHeader = new ExecutionHeader();
rexec.ExecutionHeaderValue = execHeader;
execInfo = rexec.LoadReport(reportPath, historyID);
rexec.SetExecutionParameters(parameters, "en-us");
Console.WriteLine("SessionID: {0}", rexec.ExecutionHeaderValue.ExecutionID);
try
{
    Console.WriteLine(reportName.ToString());
    result = rexec.Render(format, devInfo, out string extension, out string 
        mimeType, out encoding, out warnings, out streamIDs);
    execInfo = rexec.GetExecutionInfo();
    Console.WriteLine("Execution date and time: {0}", execInfo.ExecutionDateTime);
}
catch (SoapException e)
{
    Console.WriteLine(e.Detail.OuterXml);
    Dts.Events.FireError(0, "Error ",e.Message+ "\r" + e.StackTrace, String.Empty,0);
    Dts.TaskResult = (int)ScriptResults.Failure;
}

Upvotes: 3

Related Questions