I am trying to download an XML file from an Azure SQL Report Server that requires authentication to receive the file. I am trying to use two approaches:
Approach 1
In this approach, I tried using the C # console application and downloaded the file from the server. It works great!
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 the Windows Phone application. Now, since ServerReport is not on the Windows phone, I rely on WebClient to download the file. So I am trying to make the code below and it seems to not 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"); }
The following is the result of approach 2: does it seem to redirect 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 approach 2, we don’t notice something?
Update
I am completely new to this azure and web service. Maybe I'll ask some kind of stupid question. Here is what I tried:
- I tried to add the "Service" link to the azure sql report server in my Windows Phone 7 project. One thing I noticed is that I cannot add serice as a "Web link" because it is disabled in the Windows Phone 7 application .
- After adding serive to my application, I get a set of classes. And one of them is ReportExecutionServiceSoapClient;
- ReportExecutionService is not available.
- I'm not quite sure how to use the ReportExecutionServiceSoapClient api to get a cookie that I can use for WebClient.
- Any sample application on how to use these APIs would be great. I tried to search over the Internet, but could not get more information.
Below I tried, but the number of cookies 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;
The following is a ClientConfig file. I 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.
solvable - Finally, I can download the xml file from the Azure Sql report server. - Below is the solution. - First add the service link to the Sql report server. - Then run ReportExecutionServiceSoapClient :: LogonUserAsync. - Use the resulting cookie with 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); }