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);
Related
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.
i am developing an windows phone 8 app , in my app i am calling services and downloading some data into my app .
i am using httpwebrequest for request, but i am not able to set timeout to my httpwebrequest object.
This is how i have created and used my httpwebrequest :-
public async Task<string> ServiceRequest(string serviceurl, string request, string methodname)
{
string response = "";
try
{
var httpwebrequest = WebRequest.Create(new Uri(serviceurl)) as HttpWebRequest;
httpwebrequest.Method = "POST";
httpwebrequest.Headers["SOAPAction"] = "http://tempuri.org/" + iTestservice + "/" + methodname + "";
httpwebrequest.ContentType = "text/xml";
byte[] data = Encoding.UTF8.GetBytes(request);
using (var requestStream = await Task<Stream>.Factory.FromAsync(httpwebrequest.BeginGetRequestStream, httpwebrequest.EndGetRequestStream, null))
{
await requestStream.WriteAsync(data, 0, data.Length);
}
response = await httpRequest(httpwebrequest);
}
catch (Exception ex)
{
return null;
}
return response;
}
public async Task<string> httpRequest(HttpWebRequest request)
{
string received;
using (var response = (HttpWebResponse)(await Task<WebResponse>.Factory.FromAsync(request.BeginGetResponse, request.EndGetResponse, null)))
{
using (var responseStream = response.GetResponseStream())
{
using (var sr = new StreamReader(responseStream))
{
received = await sr.ReadToEndAsync();
}
}
}
return received;
}
My Doubt is :-
1) How can i set timeout property to Httpwebrequest ??
2)What are the different ways in which i can set the timeout property in my windows phone 8 app ??
Please let me know .
Thanks in Advance.
You can't use HttpWebRequest.Timeout on Windows Phone because it doesn't exist for that platform.
If you're open to using a beta library, you could install HttpClient via NuGet and use its Timeout property.
Otherwise, you're probably best off to use TaskEx.Delay, which is part of Microsoft.Bcl.Async. After installing that library, you would replace this line:
response = await httpRequest(httpwebrequest);
with this:
var httpTask = httpRequest(httpwebrequest);
var completeTask = await TaskEx.WhenAny(httpTask, TaskEx.Delay(5000));
if (completeTask == httpTask)
return await httpTask;
else
return null; // timeout
You can use HttpStatusCode.HttpStatusCode is an enum which can be used to get the type of error in HttpWebRequest.
catch(WebException ex)
{
HttpWebResponse response = (HttpWebResponse)ex.Response;
if(response.StatusCode==HttpStatusCode.GatewayTimeout)
{
}
}
The GatewayTimeout indicates that an intermediate proxy server timed out while waiting for a response from another proxy or the origin server.For more information you can refer to the msdn
site for this.Hope it helps
I have a WP7 app where I'm trying to reconstruct an HTTPWebRequest that I have successfully written elsewhere using the synchronous methods (pasted at end) but which doesn't work in WP7, I assume because I'm doing something wrong with the Asynchronous versions of these methods.
I believe the issue stems from the fact that the non-working code on the Compact Framework can only send a bytearray[] - I don't have the option of sending the json string. If I send a bytearray in the code that works, I get an error there too. Is there a different option?
Here is my code - this does not work. The exception is thrown on the 2nd line of the last method - "Using(var respons ...)":
public void CreateUser()
{
var request = (HttpWebRequest)WebRequest.Create("http://staging.cloudapp.net:8080/api/users/");
request.Method = "POST";
request.ContentType = "text/json; charset=utf-8";
request.BeginGetRequestStream(new AsyncCallback(RequestCallback), request);
}
private static void RequestCallback(IAsyncResult result)
{
HttpWebRequest request = (HttpWebRequest)result.AsyncState;
using (Stream postStream = request.EndGetRequestStream(result))
{
User user = new User("Windows", "Phone", "USCA");
Formatting formatting = new Formatting();
JsonSerializerSettings settings = new JsonSerializerSettings();
settings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
string json = JsonConvert.SerializeObject(user, formatting, settings);
byte[] byteArray = Encoding.UTF8.GetBytes(json);
postStream.Write(byteArray, 0, json.Length);
}
request.BeginGetResponse(new AsyncCallback(ResponseCallback), request);
}
private static void ResponseCallback(IAsyncResult result)
{
var request = (HttpWebRequest)result.AsyncState;
using (var response = (HttpWebResponse)request.EndGetResponse(result))
{
using (Stream streamResponse = response.GetResponseStream())
{
StreamReader reader = new StreamReader(streamResponse);
string responseString = reader.ReadToEnd();
reader.Close();
}
}
}
This code works (non-compact framework version of the same request):
HttpWebRequest request = HttpWebRequest.Create("http://staging.cloudapp.net/api/users/") as HttpWebRequest;
request.Method = "POST";
request.ContentType = "text/json";
using (var writer = new StreamWriter(request.GetRequestStream()))
{
User user = new user("Other", "Guy", "USWC");
Formatting formatting = new Formatting();
JsonSerializerSettings settings = new JsonSerializerSettings();
settings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
string json = JsonConvert.SerializeObject(user, formatting, settings);
writer.Write(json);
}
var response = request.GetResponse() as HttpWebResponse;
using (var reader = new StreamReader(response.GetResponseStream()))
{
var responseText = reader.ReadToEnd();
return responseText;
}
thanks for any help!
looks like the server is responding with a "404 not found". Does the resource you are requesting exist at the server?
Does your JSON contain any non 7-bit ASCII characters, as you are currently doing:
byte[] byteArray = Encoding.UTF8.GetBytes(json);
postStream.Write(byteArray, 0, json.Length);
The number of bytes might not be identical to the number of characters in your string, which could lead to a malformed request.
It would be worthwhile using something like Fiddler to verify what is actually going over the wire from the emulator or phone (there are instructions on the Fiddler website for how to do this)
Well - I'm not sure why this problem went away. I liked #RowlandShaw's suggestion, but I didn't actually change anything in the json. Wish I could give a better solution.
I'm struggling a bit to figure out how to use Trello's OAuth API calls from my Windows Phone 7 app. The API isn't really documented, aside from a listing of the endpoints.
Here's what I have so far:
public void OnAuthenticateClicked(object sender, EventArgs e)
{
const string consumerKey = "mykey";
const string consumerSecret = "mysecret";
const string baseUrl = "https://trello.com/1";
var client = new RestClient(baseUrl)
{
Authenticator = OAuth1Authenticator.ForRequestToken(consumerKey, consumerSecret)
};
var request = new RestRequest("OAuthGetRequestToken", Method.POST);
var response = client.ExecuteAsync(request, HandleResponse);
}
private void HandleResponse(IRestResponse restResponse)
{
var response = restResponse;
Console.Write(response.StatusCode);
}
I'm getting a 404 response, so something's not right, obviously.
Any suggestions?
Not using the ExecuteAsync seems to make it work:
RestRequest request = new RestRequest("OAuthGetRequestToken", Method.POST);
IRestResponse response = client.Execute(request);
Console.Write(response.StatusCode);
At one point "oAuth1 is not yet supported in async scenarios (SL and WP)", according to this post by John Sheehan.
I think your base url is incorrect.
Please try the following:
const string baseUrl = "https://api.trello.com/1";
Replace OAuthGetRequestToken with authorize.
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.