Wednesday, July 30, 2014

Report execution service authentication errors

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>





No comments:

Post a Comment