Last active
January 21, 2018 21:46
-
-
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
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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) { } | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
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