在 C# 中使用 WebRequest 时为 Microsoft Report Server 提供凭据
Providing credentials for Microsoft Report Server when using a WebRequest in C#
我想使用我的 C# 代码从我们的 Microsoft Report Server 下载 PDF 报告。我不知道为什么,但我做错了什么。我总是收到身份验证失败 (HTTP 401) 的错误消息。
public static async Task<Stream> DownloadWebDocument(string url) {
if (string.IsNullOrEmpty(url))
throw new ArgumentNullException(nameof(url));
WebRequest request = WebRequest.Create(url);
request.Method = "GET";
request.AuthenticationLevel = System.Net.Security.AuthenticationLevel.MutualAuthRequested;
request.Credentials = new NetworkCredential("MyUsername", "MyPassword", "MyDomain");
//request.Headers.Add("Authorization", $"Basic {Convert.ToBase64String(System.Text.Encoding.Default.GetBytes("MyUsername:MyPassword"))}");
try {
using WebResponse response = await request.GetResponseAsync();
return response.GetResponseStream();
} catch (Exception ex) {
var a = ex.Message;
throw;
}
//return await DownloadWebDocument(uri);
}
这段代码总是会遇到异常。但是为什么?
PS:
根据要求,这是堆栈跟踪。没有内部异常。
bei System.Net.HttpWebRequest.EndGetResponse(IAsyncResult asyncResult)
bei System.Threading.Tasks.TaskFactory`1.FromAsyncCoreLogic(IAsyncResult iar, Func`2 endFunction, Action`1 endAction, Task`1 promise, Boolean requiresSynchronization)
--- Ende der Stapelüberwachung vom vorhergehenden Ort, an dem die Ausnahme ausgelöst wurde ---
bei System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
bei System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
bei System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
bei DE.ZA.TrailerLoadingAssistant.Web.Code.WebHelper.<DownloadWebDocument>d__0.MoveNext() in C:\Users\Reichelt\source\repos\DE.ZA.TrailerLoading\DE.ZA.TrailerLoadingAssistant.Web\Code\WebHelper.cs:Zeile 28.
实际上我使用不同的方法将我的报告呈现为 PDF 文档:
public static byte[] DownloadAsPDF(string ReportServer, string ReportPath)
{
ReportViewer ReportViewer1 = new ReportViewer();
ReportViewer1.ServerReport.ReportServerCredentials = new
CustomReportCredentials("MyUsername", "MyPassword", "MyDomain");
ReportViewer1.ProcessingMode =
Microsoft.Reporting.WebForms.ProcessingMode.Remote;
ReportViewer1.ServerReport.ReportServerUrl = new Uri(ReportServer);
ReportViewer1.ServerReport.ReportPath = ReportPath;
byte[] bytes = ReportViewer1.ServerReport.Render("PDF");
return bytes;
}
public class CustomReportCredentials :
Microsoft.Reporting.WebForms.IReportServerCredentials
{
// local variable for network credential.
private string _UserName;
private string _PassWord;
private string _DomainName;
public CustomReportCredentials(string UserName, string PassWord,
string DomainName)
{
_UserName = UserName;
_PassWord = PassWord;
_DomainName = DomainName;
}
public System.Security.Principal.WindowsIdentity ImpersonationUser
{
get
{
return null; // not use ImpersonationUser
}
}
public ICredentials NetworkCredentials
{
get
{
// use NetworkCredentials
return new NetworkCredential(_UserName, _PassWord,
_DomainName);
}
}
public bool GetFormsCredentials(out Cookie authCookie, out string
user, out string password, out string authority)
{
authCookie = null;
user = password = authority = null;
return false;
}
}
I realized, that if I use request.Credentials = CredentialCache.DefaultCredentials, it works. So there must be something wrong with my credentials. But it's definitely no typo.
我遇到过这个问题,似乎有人在更改网络权限。一周使用 Credentials 就可以了,下周使用 DefaultCredentials 就可以了。真的很奇怪,所以我输入了 Try/Catch 并在服务帐户失败时求助于 DefaultCredentials,请参阅代码注释:
public class SRSHelper
{
private ReportingService2005 rsServ;
private ReportingExecution2005 rsExec = new ReportingExecution2005();
private ReportParameter[] reportParameters;
private ExecutionInfo execInfo = null;
public SRSHelper(string reportUserName, string decryptedPassword, string reportDomain, string reportServerURL)
{
rsServ = new ReportingService2005(reportServerURL);
rsExec.Url = reportServerURL + @"ReportExecution2005.asmx";
System.Net.NetworkCredential creds = new System.Net.NetworkCredential();
creds.UserName = reportUserName;
creds.Password = decryptedPassword;
creds.Domain = reportDomain;
rsExec.Credentials = creds;
rsServ.Credentials = creds;
}
public ReportParameter[] GetSRSReportParameters(string reportName)
{
string report = "/Reporting/" + reportName;
bool forRendering = false;
string historyID = null;
ParameterValue[] values = null;
DataSourceCredentials[] credentials = null;
try
{
return rsServ.GetReportParameters(report, historyID, forRendering, values, credentials);
}
catch
{
//If the Service Account credentials fail to work - try the users credentials - XYZ vendor regularly change things around or the network fails or for some reason beyond our control we have to change the settings.
rsExec.Credentials = System.Net.CredentialCache.DefaultNetworkCredentials;
rsServ.Credentials = System.Net.CredentialCache.DefaultNetworkCredentials;
return rsServ.GetReportParameters(report, historyID, forRendering, values, credentials);
}
}
我想使用我的 C# 代码从我们的 Microsoft Report Server 下载 PDF 报告。我不知道为什么,但我做错了什么。我总是收到身份验证失败 (HTTP 401) 的错误消息。
public static async Task<Stream> DownloadWebDocument(string url) {
if (string.IsNullOrEmpty(url))
throw new ArgumentNullException(nameof(url));
WebRequest request = WebRequest.Create(url);
request.Method = "GET";
request.AuthenticationLevel = System.Net.Security.AuthenticationLevel.MutualAuthRequested;
request.Credentials = new NetworkCredential("MyUsername", "MyPassword", "MyDomain");
//request.Headers.Add("Authorization", $"Basic {Convert.ToBase64String(System.Text.Encoding.Default.GetBytes("MyUsername:MyPassword"))}");
try {
using WebResponse response = await request.GetResponseAsync();
return response.GetResponseStream();
} catch (Exception ex) {
var a = ex.Message;
throw;
}
//return await DownloadWebDocument(uri);
}
这段代码总是会遇到异常。但是为什么?
PS:
根据要求,这是堆栈跟踪。没有内部异常。
bei System.Net.HttpWebRequest.EndGetResponse(IAsyncResult asyncResult)
bei System.Threading.Tasks.TaskFactory`1.FromAsyncCoreLogic(IAsyncResult iar, Func`2 endFunction, Action`1 endAction, Task`1 promise, Boolean requiresSynchronization)
--- Ende der Stapelüberwachung vom vorhergehenden Ort, an dem die Ausnahme ausgelöst wurde ---
bei System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
bei System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
bei System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
bei DE.ZA.TrailerLoadingAssistant.Web.Code.WebHelper.<DownloadWebDocument>d__0.MoveNext() in C:\Users\Reichelt\source\repos\DE.ZA.TrailerLoading\DE.ZA.TrailerLoadingAssistant.Web\Code\WebHelper.cs:Zeile 28.
实际上我使用不同的方法将我的报告呈现为 PDF 文档:
public static byte[] DownloadAsPDF(string ReportServer, string ReportPath)
{
ReportViewer ReportViewer1 = new ReportViewer();
ReportViewer1.ServerReport.ReportServerCredentials = new
CustomReportCredentials("MyUsername", "MyPassword", "MyDomain");
ReportViewer1.ProcessingMode =
Microsoft.Reporting.WebForms.ProcessingMode.Remote;
ReportViewer1.ServerReport.ReportServerUrl = new Uri(ReportServer);
ReportViewer1.ServerReport.ReportPath = ReportPath;
byte[] bytes = ReportViewer1.ServerReport.Render("PDF");
return bytes;
}
public class CustomReportCredentials :
Microsoft.Reporting.WebForms.IReportServerCredentials
{
// local variable for network credential.
private string _UserName;
private string _PassWord;
private string _DomainName;
public CustomReportCredentials(string UserName, string PassWord,
string DomainName)
{
_UserName = UserName;
_PassWord = PassWord;
_DomainName = DomainName;
}
public System.Security.Principal.WindowsIdentity ImpersonationUser
{
get
{
return null; // not use ImpersonationUser
}
}
public ICredentials NetworkCredentials
{
get
{
// use NetworkCredentials
return new NetworkCredential(_UserName, _PassWord,
_DomainName);
}
}
public bool GetFormsCredentials(out Cookie authCookie, out string
user, out string password, out string authority)
{
authCookie = null;
user = password = authority = null;
return false;
}
}
I realized, that if I use request.Credentials = CredentialCache.DefaultCredentials, it works. So there must be something wrong with my credentials. But it's definitely no typo.
我遇到过这个问题,似乎有人在更改网络权限。一周使用 Credentials 就可以了,下周使用 DefaultCredentials 就可以了。真的很奇怪,所以我输入了 Try/Catch 并在服务帐户失败时求助于 DefaultCredentials,请参阅代码注释:
public class SRSHelper
{
private ReportingService2005 rsServ;
private ReportingExecution2005 rsExec = new ReportingExecution2005();
private ReportParameter[] reportParameters;
private ExecutionInfo execInfo = null;
public SRSHelper(string reportUserName, string decryptedPassword, string reportDomain, string reportServerURL)
{
rsServ = new ReportingService2005(reportServerURL);
rsExec.Url = reportServerURL + @"ReportExecution2005.asmx";
System.Net.NetworkCredential creds = new System.Net.NetworkCredential();
creds.UserName = reportUserName;
creds.Password = decryptedPassword;
creds.Domain = reportDomain;
rsExec.Credentials = creds;
rsServ.Credentials = creds;
}
public ReportParameter[] GetSRSReportParameters(string reportName)
{
string report = "/Reporting/" + reportName;
bool forRendering = false;
string historyID = null;
ParameterValue[] values = null;
DataSourceCredentials[] credentials = null;
try
{
return rsServ.GetReportParameters(report, historyID, forRendering, values, credentials);
}
catch
{
//If the Service Account credentials fail to work - try the users credentials - XYZ vendor regularly change things around or the network fails or for some reason beyond our control we have to change the settings.
rsExec.Credentials = System.Net.CredentialCache.DefaultNetworkCredentials;
rsServ.Credentials = System.Net.CredentialCache.DefaultNetworkCredentials;
return rsServ.GetReportParameters(report, historyID, forRendering, values, credentials);
}
}