I'm trying to execute a report using the ReportExecution2005 service. However, I'm getting the following MessageSecurityException:
The HTTP request is unauthorized with client authentication scheme 'Ntlm'. The authentication header received from the server was 'NTLM'.
The inner exception is a WebException:
The remote server returned an error: (401) Unauthorized
The calling code is as follows:
public static ReportResult ExecuteReport(ReportDefinition report) { // Render arguments string format = "PDF"; byte[] result = null; string reportPath = ConfigurationManager.AppSettings["REPORT_PATH"]; reportPath = Path.Combine(reportPath, report.Name); string historyID = null; string devInfo = @"<DeviceInfo><Toolbar>False</Toolbar></DeviceInfo>"; string encoding = ""; string mimeType = ""; string extension = ""; Warning[] warnings = null; string[] streamIDs = null; var res = new ReportService.ReportExecutionServiceSoapClient(); string user = ConfigurationManager.AppSettings["REPORT_USERNAME"]; string pass = ConfigurationManager.AppSettings["REPORT_PASSWORD"]; var creds = new NetworkCredential(user, pass, ConfigurationManager.AppSettings["REPORT_DOMAIN"]); res.ClientCredentials.Windows.ClientCredential = creds; var parameters = new ParameterValue[report.Parameters.Count]; int i = 0; foreach (var item in report.Parameters) { if (!string.IsNullOrEmpty(item.Value)) { var pv = new ParameterValue(); pv.Name = item.Key; pv.Value = item.Value; parameters[i] = pv; i++; } } var userHeader = new TrustedUserHeader(); ServerInfoHeader serverHeader; ExecutionInfo2 execInfo; var execHeader = res.LoadReport2(userHeader, report.Name, historyID, out serverHeader, out execInfo); res.SetExecutionParameters2(execHeader, userHeader, parameters, "en-us", out execInfo); serverHeader = res.Render2(execHeader, userHeader, format, devInfo, PageCountMode.Actual, out result, out extension, out mimeType, out encoding, out warnings, out streamIDs); var repResult = new ReportResult(); repResult.Data = new MemoryStream(result); repResult.Encoding = encoding; repResult.ReportName = report.Name; return repResult; } } public class ReportDefinition { public string Name { get; set; } public Dictionary<string, string> Parameters { get; set; } public ReportDefinition() { Parameters = new Dictionary<string, string>(); } } public class ReportResult { public string ReportName { get; set; } public string Encoding { get; set; } public MemoryStream Data { get; set; } }
The relevant (AFAIK) portion of the web.config looks like this:
<system.serviceModel><bindings><basicHttpBinding><binding name="ReportExecutionServiceSoap"><security mode="TransportCredentialOnly"><transport clientCredentialType="Ntlm" proxyCredentialType="Ntlm" realm=""/><message clientCredentialType="UserName" algorithmSuite="Default"/></security></binding></basicHttpBinding></bindings><client><endpoint address="http://sqlfarm:80/ReportServer_JCAPPS/ReportExecution2005.asmx" binding="basicHttpBinding" bindingConfiguration="ReportExecutionServiceSoap" contract="ReportService.ReportExecutionServiceSoap" name="ReportServiceSoap"><identity><servicePrincipalName value=""/></identity></endpoint></client></system.serviceModel>