WebClient wait operation - Windows Phone 7 - windows-phone-7

I've read that the communications are asynchronous WP7 but there are cases that do not lack this type of communication.
I am using webclient to download content and just want to go to the next operation, after receiving such content.
How is this done?
I'm a noob on this platform.
Cumpz

It sounds like you are looking for a synchronous method. If that is the case, you can do something like this:
AutoResetEvent waitHandle = new AutoResetEvent(false);
WebRequest request = WebRequest.Create(url) as HttpWebRequest;
IAsyncResult asyncResult = request.BeginGetResponse(ar => waitHandle.Set(), null);
if (!waitHandle.WaitOne(30000))
{
throw new TimeoutException("Timed out");
}
using (HttpWebResponse response = request.EndGetResponse(asyncResult) as HttpWebResponse)
{
...

Here is some code which will help you get started using the WebClient class
Create the WebClient
WebClient client = new WebClient())
client.DownloadStringAsync(new Uri("http://www.google.com"));
client.DownloadStringCompleted += new DownloadStringCompletedEventHandler(client_DownloadStringCompleted);
Now, do something once the download string operation has finished
void client_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e)
{
string result = e.Result;
// Do something with the string
DoThingWithString(result)
}

Related

Consume WCF Rest Service Json data across all platform using Shared Code

We were developing a sample MWC application with the logic of Business ,DataAccess,Data Layers.
In core Project we used the following code for consuming data from json parsing. This code works fine for Xamarin.Android and Xamarin.iOS, but for windows phone it shows error as 'System.Net.WebRequest does not contain a definition for GetResponse and no extension method for GetResponse...'
We tried to use Async methods for consuming WCF Rest service json data, but it returned as null before the completed method called.
Is it possible to wait and get data from completed method to return the json collection? if no please suggest how to achieve the same.
public String login<T>(T item) where T : BusinessLayer.Contracts.IBusinessEntity, new()
{
var request = HttpWebRequest.Create(url);
request.ContentType = "application/json";
request.Method = "get";
using (HttpWebResponse response = request.GetResponse() as HttpWebResponse)
{
using (StreamReader reader = new StreamReader(response.GetResponseStream()))
{
var content = reader.ReadToEnd();
string nss = content.ToString();
check = nss;
return nss;
}
}
return Check;
}
Edit: I have included the sample code of Async function.
Before Executing the DownloadStringCompleted event it returns null value. We need that DownloadStringCompleted output string for further process.
Note: We were following the logic of Tasky in Xamarin
async Task<string> AccessTheWebAsync(string url)
{
var webClient = new WebClient();
webClient.DownloadStringCompleted += (sender, e) =>
{
string data = (string)e.Result;
check = data;
};
webClient.DownloadStringAsync(new Uri(url));
return check;
}
public async Task<string> login<T>(T item) where T : BusinessLayer.Contracts.IBusinessEntity, new()
{
return check = await AccessTheWebAsync(item.url);
}
Your asynchronous code is not using Task correctly. It should use TaskCompletionSource to get the job done:
Task<string> AccessTheWebAsync(string url)
{
var source = new TaskCompletionSource<string>();
var webClient = new WebClient();
webClient.DownloadStringCompleted += (sender, e) =>
{
source.TrySetResult((string)e.Result);
};
webClient.DownloadStringAsync(new Uri(url));
return source.Task;
}
Before, your function was returning before the event fired. Using the task source wraps it in a task properly and fixes this problem.
You will also need to hook up the error event and call TrySetException to finish the implementation.

Windows Phone POST method WebClient class

I am new to this forum as well as Windows Phone Development. I am currently developing an app in which I am working with a Web-Service and I need to make a POST request to a web service.
I am trying to accomplish a user login functionality here for which,
-> http://abc.com/login (URI)
-> (PARAMETERS)
apikey: 32 byte long alpha-numeric
username: 3-15 characters
password: 3-15 characters
So for this I am trying to use WebClient class' UploadStringSync method in order to POST the data. My code is as follows.
WebClient wc1 = new WebClient();
wc1.UploadStringAsync(new Uri("http://abc.com/login"),"POST","?apikey=" + Apikey + "&username=username&password=password");
wc1.UploadStringCompleted += new UploadStringCompletedEventHandler(wc1_UploadStringCompleted);
void wc1_UploadStringCompleted(object sender, UploadStringCompletedEventArgs e)
{
MessageBox.Show(e.Result);
}
Execution stops here at MessageBox line and throws message saying 'The remote server returned an error: NotFound.'
Is there any problem with the way I am passing the parameters? I tried to search for the working implementation everywhere but was unable to find it.
Can anybody help me with this? This is a starting point of my project and really need help on this one. Any help would be much appreciated.
try this:
public void Post(string address, string parameters, Action<string> onResponseGot)
{
Uri uri = new Uri(address);
HttpWebRequest r = (HttpWebRequest)WebRequest.Create(uri);
r.Method = "POST";
r.BeginGetRequestStream(delegate(IAsyncResult req)
{
var outStream = r.EndGetRequestStream(req);
using (StreamWriter w = new StreamWriter(outStream))
w.Write(parameters);
r.BeginGetResponse(delegate(IAsyncResult result)
{
try
{
HttpWebResponse response = (HttpWebResponse)r.EndGetResponse(result);
using (var stream = response.GetResponseStream())
{
using (StreamReader reader = new StreamReader(stream))
{
onResponseGot(reader.ReadToEnd());
}
}
}
catch
{
onResponseGot(null);
}
}, null);
}, null);
}
I did this and it worked
WebClient web = new WebClient();
web.Headers[HttpRequestHeader.ContentType] = "application/x-www-form-urlencoded";
web.UploadStringAsync((new Uri("http://www.something.com/?page=something")), "POST", string.Format("v1=onevalue&v2=anothervalue"));
web.UploadStringCompleted += web_UploadStringCompleted;
and after upload is complete to get the html i used htmlagilitypack, you can just get the whole html using e.Result
HtmlDocument doc = new HtmlDocument();
doc.LoadHtml(e.Result);
HtmlNode node = doc.DocumentNode.SelectSingleNode("//body//table");
MessageBox.Show(node.InnerText);

Return response from HTTPWebRequest somehow?

I'm trying to validate a user in my WP7 app by validating username/pass on a server.
In my "validate user" method I create a HTTPWebRequest with the stuff I need validated.
Then as far as I can see, the only option to execute is to use request.BeginGetResponse, with an async callback.
But I want to return the response from the request in the same method that I created the request in, how can I accomplish this?
I'm not sure why you would like to make it return in the calling method. I would just use the standard WebClient behavior like below:
public void ValidateUser()
{
WebClient webClient = new WebClient();
Uri uri = new Uri(url);
webClient.DownloadStringCompleted += new DownloadStringCompletedEventHandler(webClient_DownloadStringCompleted);
webClient.DownloadStringAsync(new Uri(url));
}
void webClient_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e)
{
//Validate result from response by using e.Result
}
BeginGetResponse returns an IAsyncResult which has a wait handle that is signalled when the request completes. All you have to do is wait on this handle: [ doesn't work on WP7 ]
UPDATE: use a ManualResetEvent
var mre = new ManualResetEvent( false );
var iar = myHttpWebRequest.BeginGetResponse( state => mre.Set(), null );
mre.WaitOne();
var response = myHttpWebRequest.EndGetResponse( iar );
The only real way to achieve what you need would be to create an event in your worker class, and fire that event when the async call completes, so (pseudocode)...
void StartDownload(object[] parameters)
{
var req = HttpWebRequest.Create("http://google.com");
req.BeginGetRequestStream(Completed_handler, req);
}
void Completed_handler(object sender, DownloadStringCompletedEventArgs e)
{
var request = (HttpWebRequest)result.AsyncState;
var response = request.EndGetResponse(result);
using (var stream = response.GetResponseStream())
using (var reader = new StreamReader(stream))
{
var contents = reader.ReadToEnd();
NotifyCallerOfContent(contents)
}
}
public event EventHandler<MyCustomEventArgsClass> DownloadHasFinished;
public NotifyCallerOfDownload(string content)
{
if(null != DownloadHasFinished)
{
DownloadHasFinished(this, new MyCustomEventArgsClass(content));
}
}
and then subscribe to the DownloadHasFinished event in your calling class.
As for calling out specifically by a HttpWebRequest, take a look at this question, where you will find some working samples.

how to make HTTP POST using reactive extension on windows phone 7

I found an example about HTTP POST in msdn, but I am wondering how can I make use of reactive extensions here.
using System;
using System.Net;
using System.IO;
using System.Text; using System.Threading;
class HttpWebRequestBeginGetRequest
{
private static ManualResetEvent allDone = new ManualResetEvent(false);
public static void Main(string[] args)
{
// Create a new HttpWebRequest object.
HttpWebRequest request = (HttpWebRequest)WebRequest.Create("http://www.contoso.com/example.aspx");
request.ContentType = "application/x-www-form-urlencoded";
// Set the Method property to 'POST' to post data to the URI.
request.Method = "POST";
// start the asynchronous operation
request.BeginGetRequestStream(new AsyncCallback(GetRequestStreamCallback), request);
// Keep the main thread from continuing while the asynchronous
// operation completes. A real world application
// could do something useful such as updating its user interface.
allDone.WaitOne();
}
private static void GetRequestStreamCallback(IAsyncResult asynchronousResult)
{
HttpWebRequest request = (HttpWebRequest)asynchronousResult.AsyncState;
// End the operation
Stream postStream = request.EndGetRequestStream(asynchronousResult);
Console.WriteLine("Please enter the input data to be posted:");
string postData = Console.ReadLine();
// Convert the string into a byte array.
byte[] byteArray = Encoding.UTF8.GetBytes(postData);
// Write to the request stream.
postStream.Write(byteArray, 0, postData.Length);
postStream.Close();
// Start the asynchronous operation to get the response
request.BeginGetResponse(new AsyncCallback(GetResponseCallback), request);
}
private static void GetResponseCallback(IAsyncResult asynchronousResult)
{
HttpWebRequest request = (HttpWebRequest)asynchronousResult.AsyncState;
// End the operation
HttpWebResponse response = (HttpWebResponse)request.EndGetResponse(asynchronousResult);
Stream streamResponse = response.GetResponseStream();
StreamReader streamRead = new StreamReader(streamResponse);
string responseString = streamRead.ReadToEnd();
Console.WriteLine(responseString);
// Close the stream object
streamResponse.Close();
streamRead.Close();
// Release the HttpWebResponse
response.Close();
allDone.Set();
}
}
I am trying to use the following code, but it does not work. Can anyone help me out on this?
Thanks in advance -Peng
return (from request in
Observable.Return((HttpWebRequest)WebRequest.Create(new Uri(postUrl))).Catch(Observable.Empty<HttpWebRequest>())
.Do(req =>
{
// Set up the request properties
req.Method = "POST";
req.ContentType = contentType;
req.UserAgent = userAgent;
req.CookieContainer = new CookieContainer();
Observable.FromAsyncPattern<Stream>(req.BeginGetRequestStream, req.EndGetRequestStream)()
.ObserveOnDispatcher()
.Subscribe(stream =>
{
stream.Write(formData, 0,
formData.Length);
stream.Close();
})
;
})
from response in
Observable.FromAsyncPattern<WebResponse>(request.BeginGetResponse, request.EndGetResponse)().Catch(Observable.Empty<WebResponse>())
from item in GetPostResponse(response.GetResponseStream()).ToObservable().Catch(Observable.Empty<string>())
select item).ObserveOnDispatcher();
Edit: To make it clear, I want to use the rx to implement the same logic in MSDN example.
in the MSDN example, it seems it first makes async call to write RequestStream, and then in the GetRequestStreamCallback, fires another async call to get the response.
Using Rx, I am able to create 2 observables
1. Observable.FromAsyncPattern(request.BeginGetRequestStream, request.EndGetRequestStream)()
2. Observable.FromAsyncPattern(request.BeginGetResponse, request.EndGetResponse)()
The problem is the second observable depends on the first one's result, so how can I do this in Rx?
In the first observable's subcribe method to create the seond observable? is it the good way?
This is how I am doing it. I configure the two Async patters up front, then use SelectMany to chain them together.
I have cut out the error handling etc from this code to keep it simple and show only the bare minimum to get it working. You should append a .Catch() similar to your own code, and if you want to get more than just a string out (say the response code) then you'll need to create a class/struct to hold all the bits of data you need and return that instead.
public IObservable<string> BeginPost(Uri uri, string postData) {
var request = HttpWebRequest.CreateHttp(uri);
request.Method = "POST";
request.ContentType = "application/x-www-form-urlencoded";
var fetchRequestStream = Observable.FromAsyncPattern<Stream>(request.BeginGetRequestStream, request.EndGetRequestStream);
var fetchResponse = Observable.FromAsyncPattern<WebResponse>(request.BeginGetResponse, request.EndGetResponse);
return fetchRequestStream().SelectMany(stream => {
using (var writer = new StreamWriter(stream)) writer.Write(postData);
return fetchResponse();
}).Select(result => {
var response = (HttpWebResponse)result;
string s = "";
if (response.StatusCode == HttpStatusCode.OK) {
using (var reader = new StreamReader(response.GetResponseStream())) s = reader.ReadToEnd();
}
return s;
});
}
Your problem is your use of Do() here, you need to move the GetRequestStream into your SelectMany (into your "from bla in, from bla in"...), since it only makes sense to get the response stream after you've written the full request. Right now, you're trying to do both concurrently.

httpWebRequest using POST method - receive unexpected xml response

I need to use POST to post a string to server and get xml response, the status code is OK but the string reponse is always ="" (0 byte). Is there any thing wrong with my code? I check the server from blackberry, works fine so the problem must come from my code:
protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e)
{
s = NavigationContext.QueryString["parameter1"];
//string strConnectUrl = "http://www.contoso.com/example.aspx";
base.OnNavigatedTo(e);
// DoWebClient(s);
try
{
HttpWebRequest httpWebRequest = (HttpWebRequest)WebRequest.Create(strConnectUrl);
httpWebRequest.Method = "POST";
httpWebRequest.ContentType = "application/x-www-form-urlencoded;charset=UTF-8";
// start the asynchronous operation
httpWebRequest.BeginGetRequestStream(new AsyncCallback(GetRequestStreamCallback), httpWebRequest);
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString());
}
}
private static void GetRequestStreamCallback(IAsyncResult asynchronousResult)
{
// string XML_REQUEST = "<?xml version=\"1.0\"?><mybroker"><getConnections></mybroker>";
string post = "?&track=love";
try
{
HttpWebRequest request = (HttpWebRequest)asynchronousResult.AsyncState;
// End the operation
Stream postStream = request.EndGetRequestStream(asynchronousResult);
// Convert the string into a byte array.
byte[] postBytes = Encoding.UTF8.GetBytes(post);
// Write to the request stream.
postStream.Write(postBytes, 0, postBytes.Length);
postStream.Close();
// Start the asynchronous operation to get the response
request.BeginGetResponse(new AsyncCallback(GetResponseCallback), request);
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString());
}
}
static Stream str;
static string st;
private static void GetResponseCallback(IAsyncResult asynchronousResult)
{
HttpWebRequest request = (HttpWebRequest)asynchronousResult.AsyncState;
// End the operation
HttpWebResponse response = (HttpWebResponse)request.EndGetResponse(asynchronousResult);
HttpStatusCode rcode = response.StatusCode;
Stream streamResponse = response.GetResponseStream();
StreamReader streamRead = new StreamReader(streamResponse);
//****THIS ALWAYS RETURN "" VALUE, EXPECT TO RETURN XML STRING****
string responseString = streamRead.ReadToEnd();
//Console.WriteLine(responseString);
// Close the stream object
streamResponse.Close();
streamRead.Close();
// Release the HttpWebResponse
response.Close();
}
*EDIT**
The code work, however the server return parameter require the Ampersand(&) which is not allow in silverlight framework I think, remove the & char server response but the result wasn't correct. I will ask a new question refer this Ampersand
Have checked your call using Fiddler. The server is returning an empty body. Your code is working correctly. The problem is server side.
The post value should be "track=love".
I tried and it worked but the response is gzip encoded.
Fiddler says that the request is good, and that the response really is blank. If it's working from Blackberry and not from WP7, could the server be doing some user agent checking and not returning anything because it doesn't recognize the WP7 user agent?
Also, it looks like you're POSTing a query string ("?&track=love") which is sort of unusual. Are you sure that's the right data to be sending in your request?

Resources