问题
I am trying to download a xml file from Azure SQL reporting server which requires authentication to get the file. I am trying below 2 approaches:
Approach 1
In this approach i tried below c# console application and it downloads the file from server. It works fine!
void DownloadFile(string uname, string password)
{
ServerReport report = new ServerReport();
report.ReportServerUrl = new System.Uri("https://xxxxx.reporting.windows.net/ReportServer", System.UriKind.Absolute);
report.ReportPath = "/Demo2.rdl";
report.ReportServerCredentials.SetFormsCredentials(null, uname, password, "xxxxx.reporting.windows.net");
byte[] data = report.Render("XML");
FileStream fs = new FileStream(@"c:\output.xml", FileMode.Create);
fs.Write(data, 0, data.Length);
fs.Close();
}
Approach 2
Now i want to download the same file from a windows phone application. Now since ServerReport is not present in windows phone i am relying in WebClient to download the file. So i am trying below code and it doesn't seem to work:
void DownloadFile(string uname, string password)
{
WebClient webClient = new WebClient();
webClient.Credentials = new NetworkCredential(uname, password, "xxxxx.reporting.windows.net");
webClient.DownloadFile("https://xxxxx.reporting.windows.net/ReportServer?%2fDemo2.rdl&rs:Command=Render&rs:Format=XML", @"c:\output.xml");
}
Below is the output of approach 2 : Looks like it is re-directing to the login page?
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" >
<html lang="en-US">
<head id="Head1"><meta http-equiv="Content-Type" content="text/html;charset=ISO-8859-1" /><link rel="Stylesheet" type="text/css" href="Public/Logon.css" /><title>
Windows Azure SQL Reporting
</title></head>
<body >
<form name="Logon" method="post" action="logon.aspx?ReturnUrl=%2fReportServer%3f%252fDemo2.rdl%26rs%3aCommand%3dRender%26rs%3aFormat%3dXML&%2fDemo2.rdl&rs%3aCommand=Render&rs%3aFormat=XML" id="Logon">
<input type="hidden" name="__VIEWSTATE" id="__VIEWSTATE" value="/XXXX" />
<input type="hidden" name="__EVENTVALIDATION" id="__EVENTVALIDATION" value="/YYYY" />
<h1 id="Title"><span id="LblTitleContent">Windows Azure</span></h1>
<hr />
<div class="ClsIntro">
<span id="LblIntro"></span>
</div>
<div class="ClsInput">
<div>
<label for="TxtUser" id="LblUser">User name</label>
</div>
<div>
<input name="TxtUser" type="text" id="TxtUser" tabindex="1" />
</div>
</div>
<div class="ClsInput">
<div>
<label for="TxtPwd" id="LblPwd">Password</label>
</div>
<div>
<input name="TxtPwd" type="password" id="TxtPwd" tabindex="2" />
</div>
</div>
<div class="ClsSignIn">
<input type="submit" name="BtnLogon" value="Sign in" id="BtnLogon" tabindex="4" /><input type="image" name="BtnLogonArrow" id="BtnLogonArrow" tabindex="5" src="Public/WhiteRightArrow.png" alt="Sign in" align="baseline" border="0" />
</div>
<div class="ClsErrMsg">
<span id="lblMessage"></span>
</div>
<hr />
</form>
</body>
</html>
What could be the problem with the approach 2, are we missing any thing?
Update
I am quite new to this azure and web services. I might be asking some silly question. Here is what i tried:
- I tried adding a "Service reference" to azure sql reporting server in my windows phone 7 project. One thing i noted was that i can not add the serice as "Web reference" as it is disabled in windows phone 7 application.
- After adding serive to my app i am getting set of classes. And one of them is ReportExecutionServiceSoapClient;
- ReportExecutionService is not available.
- I am not quite sure on how to use ReportExecutionServiceSoapClient api to get the cookie which i can use for WebClient.
- Any sample application on how to use these APIs would be great. I tried searching over internet but couldn't get more information.
Below is what i tried but the cookie count is null.
ReportExecutionServiceSoapClient client = new ReportExecutionServiceSoapClient(); void MainPage_Loaded(object sender, RoutedEventArgs e) { client.ClientCredentials.UserName.UserName = "XXXX"; client.ClientCredentials.UserName.Password = "XXXX"; client.CookieContainer = new CookieContainer(); client.LogonUserCompleted += new EventHandler<System.ComponentModel.AsyncCompletedEventArgs>(client_LogonUserCompleted); client.LogonUserAsync("XXXX", "XXXX", "xxxx.reporting.windows.net"); } void client_LogonUserCompleted(object sender, System.ComponentModel.AsyncCompletedEventArgs e) { int count = client.CookieContainer.Count; // NULL COOKIE COUNT!!! }
Below is ClientConfig file. I have added enableHttpCookieContainer="true".
<configuration>
<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding name="ReportExecutionServiceSoap" maxBufferSize="2147483647"
enableHttpCookieContainer="true"
maxReceivedMessageSize="2147483647">
<security mode="Transport" />
</binding>
</basicHttpBinding>
</bindings>
<client>
<endpoint address="https://xxxx.reporting.windows.net:443/ReportServer/ReportExecution2005.asmx"
binding="basicHttpBinding" bindingConfiguration="ReportExecutionServiceSoap"
contract="SqlReportingService.ReportExecutionServiceSoap"
name="ReportExecutionServiceSoap" />
</client>
</system.serviceModel>
</configuration>
- Please let me know what is missing.
SOLVED - Finally i am able to download xml file from Azure Sql reporting server. - Below is the solution. - First add a service reference to the Sql reporting server. - Then do a ReportExecutionServiceSoapClient::LogonUserAsync. - Use the obtained cookie with the WebClient for further request.
public class WebClientExtended : WebClient
{
private CookieContainer myContainer;
private HttpWebRequest myRequest;
[SecuritySafeCritical]
public WebClientExtended()
{
}
[SecuritySafeCritical]
public WebClientExtended(CookieContainer containter)
{
myContainer = containter;
}
public CookieContainer Cookies
{
get { return myContainer; }
set { myContainer = value; }
}
protected override WebRequest GetWebRequest(Uri address)
{
myRequest = (HttpWebRequest)base.GetWebRequest(address);
myRequest.Method = "GET";
myRequest.CookieContainer = Cookies;
return myRequest;
}
protected override WebResponse GetWebResponse(WebRequest request, IAsyncResult result)
{
return myRequest.EndGetResponse(result);
}
}
ReportExecutionServiceSoapClient rs = new ReportExecutionServiceSoapClient();
string servername = "XXXX.reporting.windows.net";
string uname = "XXXX";
string password = "XXXX";
public void LoadReport()
{
rs.ClientCredentials.UserName.UserName = uname;
rs.ClientCredentials.UserName.Password = password;
rs.CookieContainer = new CookieContainer();
rs.LogonUserCompleted += new EventHandler<System.ComponentModel.AsyncCompletedEventArgs>(rs_LogonUserCompleted);
rs.LogonUserAsync(uname, password, servername);
}
void rs_LogonUserCompleted(object sender, System.ComponentModel.AsyncCompletedEventArgs e)
{
WebClientExtended webClient = new WebClientExtended(rs.CookieContainer);
webClient.Credentials = new NetworkCredential(uname, password, servername);
webClient.DownloadStringCompleted += new DownloadStringCompletedEventHandler(webClient_DownloadStringCompleted);
webClient.DownloadStringAsync(new Uri(String.Format("https://{0}/ReportServer?%2fDemo2.rdl&rs:Command=Render&rs:Format=XML", servername)));
}
void webClient_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e)
{
MessageBox.Show(e.Result);
}
回答1:
The ServerReport
class will call the LogonUser
method on the ReportExecutionService
to get a Forms Authentication cookie which will be used in all other requests (like rendering to XML).
Using credentials on the WebClient in your WP7 application doesn't cover this. You have 2 options:
- Try to get a cookie by calling LogonUser and use it in your WebClient
- Don't use WebClient but render the report through the ReportExecutionService
Take a look at the Windows Azure SQL Reporting: using SOAP APIs blog post to get started with this service in SQL Azure.
回答2:
In approach Update: You might actually have received cookies even if code says that those are not present. Those are just hidden somewhere inside CookieContainer because of "security thing".
Just try to insert same instance of CookieContainer to next WebRequest and try if it authenticates.
来源:https://stackoverflow.com/questions/13854356/downloading-xml-file-from-sql-reporting-server