Skip to content

Instantly share code, notes, and snippets.

@madcodemonkey
Last active February 14, 2024 22:36
Show Gist options
  • Star 8 You must be signed in to star a gist
  • Fork 4 You must be signed in to fork a gist
  • Save madcodemonkey/17216111f8ffa8d4515455fb90e1b4e9 to your computer and use it in GitHub Desktop.
Save madcodemonkey/17216111f8ffa8d4515455fb90e1b4e9 to your computer and use it in GitHub Desktop.
Generate SSRS report using WCF in .NET Core Application
using ServiceReference1;
using System;
using System.Collections.Generic;
using System.IO;
using System.ServiceModel;
using System.Threading.Tasks;
namespace SSRSSimple
{
class Program
{
const string ReportExecution2005EndPointUrl = "https://YourServer.com/ReportServer/ReportExecution2005.asmx";
const string SsrsServiceAccountActiveDirectoryUserName = "someActiveDirectoryNameWithoutDomain";
const string SsrsServiceAccountActiveDirectoryPassword = "somePassword";
const string SsrsServiceAccountActiveDirectoryDomain = "someDomain";
const string ReportPath = "/ProjectName/Reports/Report_Overview_Basic_Without_Rdl_Extension";
const string ReportWidth = "8.5in";
const string ReportHeight = "11in";
const string ReportFormat = "PDF"; // Other options include WORDOPENXML and EXCELOPENXML
const string HistoryId = null;
static void Main(string[] args)
{
RunReport().Wait();
Console.WriteLine("DONE !");
}
private static async Task RunReport()
{
ReportExecutionServiceSoapClient rs = CreateClient();
var trustedHeader = new TrustedUserHeader();
LoadReportResponse loadReponse = await LoadReport(rs, trustedHeader);
await AddParametersToTheReport(rs, loadReponse.ExecutionHeader, trustedHeader);
RenderResponse response = await RenderReportByteArrayAsync(loadReponse.ExecutionHeader, trustedHeader, rs, ReportFormat, ReportWidth, ReportHeight);
SaveResultToFile(response.Result, "SomeFileName.pdf");
}
private static async Task<LoadReportResponse> LoadReport(ReportExecutionServiceSoapClient rs, TrustedUserHeader trustedHeader)
{
// Get the report and set the execution header.
// Failure to set the execution header will result in this error: "The session identifier is missing. A session identifier is required for this operation."
// See https://social.msdn.microsoft.com/Forums/sqlserver/en-US/17199edb-5c63-4815-8f86-917f09809504/executionheadervalue-missing-from-reportexecutionservicesoapclient
LoadReportResponse loadReponse = await rs.LoadReportAsync(trustedHeader, ReportPath, HistoryId);
return loadReponse;
}
private static async Task<SetExecutionParametersResponse> AddParametersToTheReport(ReportExecutionServiceSoapClient rs, ExecutionHeader executionHeader, TrustedUserHeader trustedHeader)
{
// Add parameters to the report
var reportParameters = new List<ParameterValue>();
reportParameters.Add(new ParameterValue() { Name = "ProjectID", Value = "1434" });
reportParameters.Add(new ParameterValue() { Name = "GeographyID", Value = "6071" });
reportParameters.Add(new ParameterValue() { Name = "Radius", Value = "20" });
reportParameters.Add(new ParameterValue() { Name = "PreparedBy", Value = "Dave" });
reportParameters.Add(new ParameterValue() { Name = "PreparedFor", Value = "Someone special" });
reportParameters.Add(new ParameterValue() { Name = "CurrencyId", Value = "142" });
SetExecutionParametersResponse setParamsResponse = await rs.SetExecutionParametersAsync(executionHeader, trustedHeader, reportParameters.ToArray(), "en-US");
return setParamsResponse;
}
private static async Task<RenderResponse> RenderReportByteArrayAsync(ExecutionHeader execHeader, TrustedUserHeader trustedHeader,
ReportExecutionServiceSoapClient rs, string format, string width, string height)
{
string deviceInfo = String.Format("<DeviceInfo><PageHeight>{0}</PageHeight><PageWidth>{1}</PageWidth><PrintDpiX>300</PrintDpiX><PrintDpiY>300</PrintDpiY></DeviceInfo>", height, width);
var renderRequest = new RenderRequest(execHeader, trustedHeader, format, deviceInfo);
//get report bytes
RenderResponse response = await rs.RenderAsync(renderRequest);
return response;
}
private static ReportExecutionServiceSoapClient CreateClient()
{
var rsBinding = new BasicHttpBinding();
rsBinding.Security.Mode = BasicHttpSecurityMode.Transport;
rsBinding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Windows;
// So we can download reports bigger than 64 KBytes
// See https://stackoverflow.com/questions/884235/wcf-how-to-increase-message-size-quota
rsBinding.MaxBufferPoolSize = 20000000;
rsBinding.MaxBufferSize = 20000000;
rsBinding.MaxReceivedMessageSize = 20000000;
var rsEndpointAddress = new EndpointAddress(ReportExecution2005EndPointUrl);
var rsClient = new ReportExecutionServiceSoapClient(rsBinding, rsEndpointAddress);
// Set user name and password
rsClient.ClientCredentials.Windows.AllowedImpersonationLevel = System.Security.Principal.TokenImpersonationLevel.Impersonation;
rsClient.ClientCredentials.Windows.ClientCredential = new System.Net.NetworkCredential(
SsrsServiceAccountActiveDirectoryUserName,
SsrsServiceAccountActiveDirectoryPassword,
SsrsServiceAccountActiveDirectoryDomain);
return rsClient;
}
private static void SaveResultToFile(byte[] result, string fileName)
{
using (var fs = File.OpenWrite($"c:\\temp\\{fileName}"))
using (var sw = new StreamWriter(fs))
{
fs.Write(result);
}
}
}
}
@eternaleap
Copy link

Hi.

Awesome example.

For some reason class RenderRequest wasn't generated inside Reference.cs
Do you know by any chance why it could happen?
I use .net core 3.1 btw.

@madcodemonkey
Copy link
Author

Hi.

Awesome example.

For some reason class RenderRequest wasn't generated inside Reference.cs
Do you know by any chance why it could happen?
I use .net core 3.1 btw.

My only guess is that in Step 4 you may have targeted the wrong endpoint in SSRS. For example, you might have hit reportservice2005 instead of reportexecution2005 see this Stack Overflow article.

Unfortunately, I do not have access to a SSRS server to try .NET Core 3.1. I'm doing mostly Azure Cloud work these days.

@emgullufsen
Copy link

thank you! I'm a programmer for state government in Alaska, porting these old reports and embedding them would have been an entire pain w/o this gist - so thanks!

@jcashwell
Copy link

Thanks so much! Very helpful.

@libotti
Copy link

libotti commented Oct 6, 2021

Thank you so much! You saved me now

@sal-420
Copy link

sal-420 commented Oct 12, 2022

Hi
I'm unable to run a successful test
Any assistance with the below 2 errors is appreciated
TEST 1) The app stops on statement 'LoadReportResponse loadReponse = await rs.LoadReportAsync(trustedHeader...' with no error Try/Catch does not catch the error.

TEST 2) Change 'rsBinding.Security.Mode = BasicHttpSecurityMode.Transport;' to 'BasicHttpSecurityMode.TransportCredentialOnly;;'
thows: The provided URI scheme 'https' is invalid; expected 'http'. (Parameter 'via')

changing Https to http thows: The provided URI scheme 'http' is invalid; expected 'https'. (Parameter 'via')

Test Environment
C# console app
.net 5.0
VS2019
IIS
SSRS server
https://xxxxxx.xxxx./reportserver/ReportExecution2005.asmx

@jambutler
Copy link

Thanks for the nice demo

@MCosta88
Copy link

MCosta88 commented Jan 8, 2023

Hi I'm unable to run a successful test Any assistance with the below 2 errors is appreciated TEST 1) The app stops on statement 'LoadReportResponse loadReponse = await rs.LoadReportAsync(trustedHeader...' with no error Try/Catch does not catch the error.

TEST 2) Change 'rsBinding.Security.Mode = BasicHttpSecurityMode.Transport;' to 'BasicHttpSecurityMode.TransportCredentialOnly;;' thows: The provided URI scheme 'https' is invalid; expected 'http'. (Parameter 'via')

changing Https to http thows: The provided URI scheme 'http' is invalid; expected 'https'. (Parameter 'via')

Test Environment C# console app .net 5.0 VS2019 IIS SSRS server https://xxxxxx.xxxx./reportserver/ReportExecution2005.asmx

Hello,

I have the same problem, did you manage to resolve this issue?

@Seany84
Copy link

Seany84 commented Jun 1, 2023

Hi I'm unable to run a successful test Any assistance with the below 2 errors is appreciated TEST 1) The app stops on statement 'LoadReportResponse loadReponse = await rs.LoadReportAsync(trustedHeader...' with no error Try/Catch does not catch the error.
TEST 2) Change 'rsBinding.Security.Mode = BasicHttpSecurityMode.Transport;' to 'BasicHttpSecurityMode.TransportCredentialOnly;;' thows: The provided URI scheme 'https' is invalid; expected 'http'. (Parameter 'via')
changing Https to http thows: The provided URI scheme 'http' is invalid; expected 'https'. (Parameter 'via')
Test Environment C# console app .net 5.0 VS2019 IIS SSRS server https://xxxxxx.xxxx./reportserver/ReportExecution2005.asmx

Hello,

I have the same problem, did you manage to resolve this issue?

Changing lines 86 & 87 from this:

rsBinding.Security.Mode = BasicHttpSecurityMode.Transport;
rsBinding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Windows;

to this:

rsBinding.Security.Mode = BasicHttpSecurityMode.TransportCredentialOnly;
rsBinding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Ntlm;

This change made it possible for me to connect to the SSRS ASMX web service over HTTP while using Windows Auth to connect.

@karthit
Copy link

karthit commented Nov 28, 2023

Thanks for this nice example, how can i set the timeout property for this particular report execution alone?
Note: i've tried using timeout property on Soap client, which is timeout the current request alone, but the ssrs report which is triggered in ssrs is still active ( ssrs not honoring the timeout setting).
Any help on this would be appreciated.

@sam-wheat
Copy link

This is so helpful. Thank you!

@shimano-zd
Copy link

Thank you so much for this code example together with the helpful advice from @Seany84 about security mode and credential type! I was able to render the PDF and save it successfully :) (using .NET 8 at the moment)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment