I am a beginner in WP7. I need to send a request to the server. The request included username, password and an authentication header. If succeeded I get some data from the server in xml form. How can I send the request to the server?
You certainly shouldn't be using the WebClient class as this executes on the UI thread so will cause the app to lock, instead look at the HttpWebRequest class.
There is a good example here: http://www.codeproject.com/Articles/156610/WP7-WebClient-vs-HttpWebRequest
To add headers, you can access the HttpWebRequest.Headers property so you could add a basic authorization header as per this http://devproj20.blogspot.com/2008/02/assigning-basic-authorization-http.html
Alternatively, you can use the HttpWebRequest.Credentials property (see http://msdn.microsoft.com/en-us/library/system.net.httpwebrequest.credentials.aspx for more details)
You'd want to check the status code of the response to verify if the authentication was successful, so you'd access the HttpWebResponse.StatusCode property and see if if it is 401 (unauthorized).
Try this one:
WebClient webClient = new WebClient();
webClient.DownloadStringCompleted += (s, e) =>
{
string xml = e.Result;
};
webClient.DownloadStringAsync(new Uri("http://..." + your params));
void SendRequest()
{
WebClient wc = new WebClient();
wc.DownloadStringAsync(new Uri("http://somesite.com/webservice"));
wc.DownloadStringCompleted +=DownloadStringCompleted;
}
void DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e)
{
Debug.WriteLine("Web service says: " + e.Result);
}
Related
I'm trying to develop a function that downloads a file in a FTP directory. I try this way
static void descargarFic(string ficFTP, string user, string pass, string dirLocal)
{
Library.WriteErrorLog(ficFTP + " -> " + dirLocal);
try
{
WebClient client = new WebClient();
client.Credentials = new NetworkCredential(user, pass);
client.DownloadFile(ficFTP, dirLocal);
Library.WriteErrorLog("Done");
client.Dispose();
}
catch(Exception e)
{
Library.WriteErrorLog(e.Message);
}
}
The WriteErrorLog write on a file the string passed. So, I'm calling that function in this way:
descargarFic("ftp://something-here/incoming/file.xml.gz", "anonymous", "password", #"C:\folder1\file.xml.gz");
But I receive the exception Exception during a WebClient request for a FTP download when I try to download it.
I'm pretty sure that it's some kind of problem with the URI, but I didn't realize where it is.
EDIT: Using Library.WriteErrorLog(e.InnerException);
The exception given is
The given access path's format is not supported.
I am developing an application for the Windows Phone 7. I am making a GET request to a JSON service. The return type of the request is an object.
My question is, how do I create a string from the information in the object. The code below is what I am using to make the request and process the response.
HttpWebRequest carRequest = (HttpWebRequest)WebRequest.Create(carUrl);
carRequest.Method = "GET";
carRequest.BeginGetResponse(new AsyncCallback(ProcessResponse), carRequest);
private void ProcessResponse(IAsyncResult asyncResult)
{
HttpWebRequest request = (HttpWebRequest)asyncResult.AsyncState;
WebResponse response = (HttpWebResponse)request.EndGetResponse(asyncResult);
StreamReader sr = new StreamReader(response.GetResponseStream());
Car.car = (Car)JsonConvert.DeserializeObject(sr.ReadToEnd(), typeof(Car));
Deployment.Current.Dispatcher.BeginInvoke(() =>
{
NavigationService.Navigate(new Uri("/SearchResults.xaml", UriKind.Relative));
});
}
Why not use a WebClient?
private void DownloadString()
{
var wc = new WebClient();
wc.DownloadStringCompleted += MyHandler;
wc.DownloadStringAsync(carUrl);
}
void MyHandler(object sender, DownloadStringCompletedEventArgs e)
{
var result = e.Result;
}
Note that this is a general solution for downloading a string. If you are resolving JSON, then use one of the methods included in JSON.Net for this kind of interaction.
Also note that you may want to stash your result object somewhere so it can be accessed on your search result page, or do the downloading/deserialising there.
You should be able to use the JsonConvert.SerializeObject as detailed below :-
http://james.newtonking.com/projects/json/help/SerializingJSON.html
I took an example of filling in a form in C# from another question, but when I run the code I just get the page back again (as if i didn't submit anything). I tried manually going to the URL and added ?variable=value&variable2=value2 but that didn't seem to pre-populate the form, not sure if that is why this isn't working.
private void button2_Click(object sender, EventArgs e)
{
var encoding = new ASCIIEncoding();
var postData = "appid=001";
postData += ("&email=chris#test.com");
postData += ("&receipt=testing");
postData += ("&machineid=219481142226.1");
byte[] data = encoding.GetBytes(postData);
var myRequest =
(HttpWebRequest)WebRequest.Create("http://www.example.com/licensing/check.php");
myRequest.Method = "POST";
myRequest.ContentType = "application/x-www-form-urlencoded";
myRequest.ContentLength = data.Length;
var newStream = myRequest.GetRequestStream();
newStream.Write(data, 0, data.Length);
newStream.Close();
var response = myRequest.GetResponse();
var responseStream = response.GetResponseStream();
var responseReader = new StreamReader(responseStream);
label2.Text = responseReader.ReadToEnd();
}
To submit a form programmatically, the general idea is that you want to impersonate a browser. To do this, you'll need to find the right combination of URL, HTTP headers, and POST data to satisfy the server.
The easiest way to figure out what the server needs is to use Fiddler, FireBug, or another tool which lets you examine exactly what the browser is sending over the wire. Then you can experiment in your code by adding or removing headers, changing POST data, etc. until the server accepts the request.
Here's a few gotchas you may run into:
first, make sure you're submitting the form to the right target URL. Many forms don't post to themselves but will post to a different URL
next, the form might be checking for a session cookie or authentication cookie, meaning you'll need to make one request (to pick up the cookie) and then make a subsequent cookied request to submit the form.
the form may have hidden fields you forgot to fill in. use Fiddler or Firebug to look at the form fields submitted when you fill in the form manually in the browser, and make sure to include the same fields in your code
depending on the server implementation, you may need to encode the # character as %40
There may be other challenges too, but those above are the most likely. To see the full list, take a look at my answer to another screen-scraping question.
BTW, the code you're using to submit the form is much harder and verbose than needed. Instead you can use WebClient.UploadValues() and accomplish the same thing with less code and with the encoding done automatically for you. Like this:
NameValueCollection postData = new NameValueCollection();
postData.Add ("appid","001");
postData.Add ("email","chris#test.com");
postData.Add ("receipt","testing");
postData.Add ("machineid","219481142226.1");
postData.Add ("checkit","checkit");
WebClient wc = new WebClient();
byte[] results = wc.UploadValues (
"http://www.example.com/licensing/check.php",
postData);
label2.Text = Encoding.ASCII.GetString(results);
UPDATE:
Given our discussion in the comments, the problem you're running into is one of the causes I originally noted above:
the form might be checking for a session cookie or authentication
cookie, meaning you'll need to make one request (to pick up the
cookie) and then make a subsequent cookied request to submit the form.
On a server that uses cookies for session tracking or authentication, if a request shows up without a cookie attached, the server will usually redirect to the same URL. The redirect will contain a Set-Cookie header, meaning when the redirected URL is re-requested, it will have a cookie attached by the client. This approach breaks if the first request is a form POST, because the server and/or the client isn't handling redirection of the POST.
The fix is, as I originally described, make an initial GET request to pick up the cookie, then make your POST as a second request, passing back the cookie.
Like this:
using System;
public class CookieAwareWebClient : System.Net.WebClient
{
private System.Net.CookieContainer Cookies = new System.Net.CookieContainer();
protected override System.Net.WebRequest GetWebRequest(Uri address)
{
System.Net.WebRequest request = base.GetWebRequest(address);
if (request is System.Net.HttpWebRequest)
{
var hwr = request as System.Net.HttpWebRequest;
hwr.CookieContainer = Cookies;
}
return request;
}
}
class Program
{
static void Main(string[] args)
{
var postData = new System.Collections.Specialized.NameValueCollection();
postData.Add("appid", "001");
postData.Add("email", "chris#test.com");
postData.Add("receipt", "testing");
postData.Add("machineid", "219481142226.1");
postData.Add("checkit","checkit");
var wc = new CookieAwareWebClient();
string url = "http://www.example.com/licensing/check.php";
// visit the page once to get the cookie attached to this session.
// PHP will redirect the request to ensure that the cookie is attached
wc.DownloadString(url);
// now that we have a valid session cookie, upload the form data
byte[] results = wc.UploadValues(url, postData);
string text = System.Text.Encoding.ASCII.GetString(results);
Console.WriteLine(text);
}
}
I created a simple SL 4 app to connect to Google Analytics but I keep getting the following exception:
{System.Security.SecurityException: Security error.
at System.Net.Browser.BrowserHttpWebRequest.InternalEndGetResponse(IAsyncResult asyncResult)
at System.Net.Browser.BrowserHttpWebRequest.EndGetResponse(IAsyncResult asyncResult)
at GoogleAnalytics.Silverlight.MainPage.<>c__DisplayClass4.<GetResponseCallback>b__3()}
I think it has something to do with xss but I'm not sure how to get around that. The following code works fine in a console app but doesn't in SL.
The UI has a textblock control, here's the code:
private byte[] _data;
public MainPage()
{
InitializeComponent();
this.Loaded += new RoutedEventHandler(MainPage_Loaded);
}
private void MainPage_Loaded(object sender, RoutedEventArgs e)
{
string requestData = "Email=email#gmail.com" +
"&Passwd=password" +
"&source=Test-App" +
"&accountType=GOOGLE" +
"&service=analytics";
_data = Encoding.UTF8.GetBytes(requestData);
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(new Uri("https://www.google.com/accounts/ClientLogin", UriKind.Absolute));
request.Method = "POST";
request.ContentType = "application/x-www-form-urlencoded";
request.ContentLength = _data.Length;
request.BeginGetRequestStream(GetRequestStreamCallback, request);
}
private void GetRequestStreamCallback(IAsyncResult asynchronousResult)
{
this.Dispatcher.BeginInvoke(() =>
{
try
{
HttpWebRequest request = (HttpWebRequest)asynchronousResult.AsyncState;
Stream stream = request.EndGetRequestStream(asynchronousResult);
stream.Write(_data, 0, _data.Length);
stream.Close();
request.BeginGetResponse(GetResponseCallback, request);
}
catch (Exception e)
{
textBlock.Text = e.ToString();
}
});
}
private void GetResponseCallback(IAsyncResult asynchronousResult)
{
this.Dispatcher.BeginInvoke(() =>
{
try
{
HttpWebRequest request = (HttpWebRequest)asynchronousResult.AsyncState;
HttpWebResponse response = (HttpWebResponse)request.EndGetResponse(asynchronousResult);
Stream stream = response.GetResponseStream();
StreamReader streamReader = new StreamReader(stream, Encoding.UTF8);
textBlock.Text = streamReader.ReadToEnd().Split(new string[] { "Auth=" }, StringSplitOptions.None)[1];
streamReader.Close();
response.Close();
}
catch (Exception e)
{
textBlock.Text = e.ToString();
}
});
}
Update: fixed a typo.
Thanks
Just some tipps, i haven't tested your code yet, but they might help.
Use a WebClient for Web requests, it's much less and cleaner code... You will find examples on MSDN <- this link also contains almost all interesting topics on Silverlight Web/http/https requests and security - a must read in your scenario
Problems might occur if you're testing from a wrong environment like testing the Silverlight object from a local file url (web Url starting with file:///...). Create a Web-Project in your service, configure the Silverlight Project to run in that created Web project under the Test Web Server or the local IIS
I know, no code examples just links or tipps, they might help you though.
Best regards
UPDATE
What exactly are you trying to do? If you want to track, I've seen a few ready solutions for silverlight, for example Silverlight Analytics or Tracking Silverlight. Here is another known solution.
Silverlight cannot connect to GA services, I either have to use a service or JavaScript then pass the data to Silverlight.
I have been using the following code to obtain a simple web response from Apache 2.2 in SilverLight to no avail.
private void bDoIt_Click(object sender, RoutedEventArgs e)
{
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(new Uri("/silverlight/TestPage2.html"));
request.Method = "POST";
request.ContentType = "text/xml";
request.BeginGetRequestStream(new AsyncCallback(RequestProceed), request);
}
private void RequestProceed(IAsyncResult asuncResult)
{
HttpWebRequest request = (HttpWebRequest)asuncResult.AsyncState;
StreamWriter postDataWriter = new StreamWriter(request.EndGetRequestStream(asuncResult));
postDataWriter.Close();
request.BeginGetResponse(new AsyncCallback(ResponceProceed), request);
}
private void ResponceProceed(IAsyncResult asuncResult)
{
HttpWebRequest request = (HttpWebRequest)asuncResult.AsyncState;
HttpWebResponse responce = (HttpWebResponse)request.EndGetResponse(asuncResult);
StreamReader responceReader = new StreamReader(responce.GetResponseStream());
string responceString = responceReader.ReadToEnd();
txtData.Text = responceString;
}
Does anyone no a better method of doing this?
Have you tried WebClient? This exists on silverlight, and might make life easier. Presumably you'd want UploadStringAsync.
Also - I believe you need to use and absolute url; if you don't want to hard code (quite reasonably), you can get your host from:
string url = App.Current.Host.Source.AbsoluteUri;
Then use string / etc methods to make the correct "http://yoursite/whatever/your.page";
Note that silverlight only allows (IIRC) connections to the host site.
You can do the BeginGetResponse call as the first call in your sample test case, the BeginGetRequestStream call is only needed if you are intending to pass some POST data to the requested page.