Skip to content

Instantly share code, notes, and snippets.

@nickalbrecht
Last active January 21, 2018 21:46
Show Gist options
  • Save nickalbrecht/e3e4173fc0dee759e92c29dcd6b43a66 to your computer and use it in GitHub Desktop.
Save nickalbrecht/e3e4173fc0dee759e92c29dcd6b43a66 to your computer and use it in GitHub Desktop.
Series of functions and classes for using SSRS to run reports from inside an ASP.NET Core application
using System.ServiceModel.Channels;
using System.ServiceModel.Description;
using System.ServiceModel.Dispatcher;
internal class ReportingServicesEndpointBehavior : IEndpointBehavior
{
public void AddBindingParameters(ServiceEndpoint endpoint, BindingParameterCollection bindingParameters) { }
public void ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime)
{
clientRuntime.ClientMessageInspectors.Add(new ReportingServicesExecutionInspector());
}
public void ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher) { }
public void Validate(ServiceEndpoint endpoint) { }
}
using System.ServiceModel.Channels;
using System.ServiceModel.Description;
using System.ServiceModel.Dispatcher;
internal class ReportingServicesExecutionInspector : IClientMessageInspector
{
private MessageHeaders headers;
public void AfterReceiveReply(ref Message reply, object correlationState)
{
var index = reply.Headers.FindHeader("ExecutionHeader", "http://schemas.microsoft.com/sqlserver/2005/06/30/reporting/reportingservices");
if (index >= 0 && headers == null)
{
headers = new MessageHeaders(MessageVersion.Soap11);
headers.CopyHeaderFrom(reply, reply.Headers.FindHeader("ExecutionHeader", "http://schemas.microsoft.com/sqlserver/2005/06/30/reporting/reportingservices"));
}
}
public object BeforeSendRequest(ref Message request, IClientChannel channel)
{
if(headers != null)
request.Headers.CopyHeadersFrom(headers);
return Guid.NewGuid(); //https://msdn.microsoft.com/en-us/library/system.servicemodel.dispatcher.iclientmessageinspector.beforesendrequest(v=vs.110).aspx#Anchor_0
}
}
/*
The below code depends on you having the supporting WCF reference to a SSRS endpoint already in your project. This can be done using
https://marketplace.visualstudio.com/items?itemName=WCFCORETEAM.VisualStudioWCFConnectedService
--or--
using SvcUtil.exe
*/
public async Task<byte[]> RenderReport(string report, IDictionary<string, object> parameters, string exportFormat = null)
{
//My binding setup, since ASP.NET Core apps don't use a web.config file
var binding = new BasicHttpBinding(BasicHttpSecurityMode.TransportCredentialOnly);
binding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Ntlm;
binding.MaxReceivedMessageSize = 10485760; //I wanted a 10MB size limit on response to allow for larger PDFs
//Create the execution service SOAP Client
var rsExec = new ReportExecutionServiceSoapClient(binding, new EndpointAddress(reportingServicesUrl));
//Setup access credentials. I use windows credentials, yours may differ
var clientCredentials = new NetworkCredential(reportingServicesUserName, reportingServicesPassword, reportingServicesDomain);
rsExec.ClientCredentials.Windows.AllowedImpersonationLevel = System.Security.Principal.TokenImpersonationLevel.Impersonation;
rsExec.ClientCredentials.Windows.ClientCredential = clientCredentials;
//This handles the problem of "Missing session identifier"
rsExec.Endpoint.Behaviors.Add(new ReportingServicesEndpointBehavior());
//Load the report
var taskLoadReport = await rsExec.LoadReportAsync(report, null);
//Set the parameteres asked for by the report
var reportParameters = taskLoadReport.Parameters.Where(x => parameters.ContainsKey(x.Name)).Select(x => new ParameterValue() { Name = x.Name, Value = parameters[x.Name].ToString() }).ToArray();
await rsExec.SetExecutionParametersAsync(reportParameters, "en-us");
//run the report
const string deviceInfo = @"<DeviceInfo><Toolbar>False</Toolbar></DeviceInfo>";
var response = await rsExec.RenderAsync(new RenderRequest(exportFormat ?? "PDF", deviceInfo));
//spit out the result
return response.Result;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment