Call UI thread in HttpWebRequest.BeginGetResponse - c#

Good night, I'm trying to call the UI thread, to update a proprety actualy, inside HttpWebRequest.BeginGetResponse method by using CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync method. But it does not work, I do not know how it works actually. There is my code:
private void DebutReponse(IAsyncResult resultatAsynchrone)
{
HttpWebRequest requete = (HttpWebRequest)resultatAsynchrone.AsyncState;
Stream postStream = requete.EndGetRequestStream(resultatAsynchrone);
string donneesAEnvoyer = "username=" + Name + "&password=" + Password + "&email=" + Email;
string lol = donneesAEnvoyer;
byte[] tableau = Encoding.UTF8.GetBytes(donneesAEnvoyer);
postStream.Write(tableau, 0, donneesAEnvoyer.Length);
postStream.Close();
requete.BeginGetResponse(FinReponse, requete);
}
private void FinReponse(IAsyncResult resultatAsynchrone)
{
HttpWebResponse aResp = null;
try
{
HttpWebRequest requete = (HttpWebRequest)resultatAsynchrone.AsyncState;
WebResponse webResponse = requete.EndGetResponse(resultatAsynchrone);
Stream stream = webResponse.GetResponseStream();
StreamReader streamReader = new StreamReader(stream);
string reponse = streamReader.ReadToEnd();
stream.Close();
streamReader.Close();
webResponse.Close();
//ErrorGridHeight = new GridLength(0.3, GridUnitType.Star);
ErrorMsg = msgSucceed;
}
catch (WebException e)
{
if (e.Response != null)
{
aResp = e.Response as HttpWebResponse;
}
}
if (aResp != null)
await errorFunc();
}
private async Task errorFunc()
{
await CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () => ErrorMsg = msgFailed);
}
I have an error telling me that I can only use the await operator inside an async method who return a Task. I have no idea how it works.
EDIT:
Ok so I changed my code a little bit to avoid the problem of this function:
requete.BeginGetResponse(FinReponse, requete);
because she want a function with a specific prototype so I did this:
private async Task lol(IAsyncResult resultatAsynchrone)
{
HttpWebResponse aResp = null;
try
{
HttpWebRequest requete = (HttpWebRequest)resultatAsynchrone.AsyncState;
WebResponse webResponse = requete.EndGetResponse(resultatAsynchrone);
Stream stream = webResponse.GetResponseStream();
StreamReader streamReader = new StreamReader(stream);
string reponse = streamReader.ReadToEnd();
stream.Close();
streamReader.Close();
webResponse.Close();
//ErrorGridHeight = new GridLength(0.3, GridUnitType.Star);
ErrorMsg = msgSucceed;
}
catch (WebException e)
{
if (e.Response != null)
{
aResp = e.Response as HttpWebResponse;
}
}
if (aResp != null)
await errorFunc();
}
private void FinReponse(IAsyncResult resultatAsynchrone)
{
Task.Run(() => lol(resultatAsynchrone));
}
private async Task errorFunc()
{
await CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () => ErrorMsg = msgFailed);
}
The only problem is that it does not change the proprety, it does not go into the set of my proprety. And I have an exeption which is:
System.NotImplementedExeption
Thank you for the help.

Try to change your errorFunc() to this.
private void errorFunc()
{
CoreApplication.MainView.CoreWindow.Dispatcher.BeginInvoke(() =>
{
ErrorMsg = msgFailed;
});
}
I also found another place, where you're trying to change ErrorMsg witouth calling the UI thread. It's the line with code ErrorMsg = msgSucceed;. I suggest to use the same way, so replace the line with this:
CoreApplication.MainView.CoreWindow.Dispatcher.BeginInvoke(() =>
{
ErrorMsg = msgSucceed;
});

You have to do FinReponse method async to be able to use await operator into it:
private async void FinReponse(IAsyncResult resultatAsynchrone)

So I found the answer to access the UI, I have to use:
Deployment.Current.Dispatcher.BeginInvoke(()=>mym());
and it works perfectly.
Thanks for everythings.

Related

UI blocked by Task

I have the following code that gets data from a site
private void BeginCreationButton_Click(object sender, RoutedEventArgs e)
{
//Log("INFO", "Beggining ad creation");
GeneralProgressBar.Visibility = Visibility.Visible;
foreach(var ad in ads)
{
string adUh = string.Empty;
string errorMsg = string.Empty;
bool error = false;
//Task<string> uhFetch = Task<string>.Factory.StartNew(() => GetUhForAdvert());
Task task = Task.Factory.StartNew(() =>
{
HttpWebRequest newPromoRequest = WebRequest.Create("https://www.randomsite.com") as HttpWebRequest;
newPromoRequest.CookieContainer = Cookies;
newPromoRequest.Method = "GET";
newPromoRequest.Accept = "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8";
string uh = string.Empty;
HttpWebResponse response = (HttpWebResponse)newPromoRequest.GetResponse();
if (response.StatusCode == HttpStatusCode.OK)
{
using (Stream s = response.GetResponseStream())
{
using (StreamReader sr = new StreamReader(s, Encoding.GetEncoding(response.CharacterSet)))
{
HtmlDocument doc = new HtmlDocument();
doc.Load(sr);
adUh = doc.DocumentNode.SelectNodes("//form")[0].SelectNodes("//input")[0].Attributes[2].Value;
}
}
}
});
try
{
task.Wait();
}
catch (AggregateException ae)
{
ae.Handle((x) =>
{
errorMsg = x.Message + " | " + x.StackTrace;
error = true;
return error;
});
}
if (error)
{
Log("ERROR", errorMsg);
}
Log("INFO", adUh);
}
}
However, while the task is executing, the UI is getting blocked but I'm not sure why it's happening. Not sure if it's the stream reading or HTML processing part as I'm using the Request code on other parts of my project without those two componentss and it works like a charm.
Don't block your UI thread using task.Wait();. Make your button click handler async like this:
private async void BeginCreationButton_Click(object sender, RoutedEventArgs e)
{
// code here...
}
...and where you call:
task.Wait();
...call it like this:
await task;
Also, you shouldn't need to use Task.Factory.StartNew, you could simplify by just using (HttpWebResponse)await newPromoRequest.GetResponseAsync(); and wrapping all the code of your task inside your try catch block.
EDIT: You can read Stephen Cleary's blog for a detailed explanation about this subject.

Properly handle WebRequests

I have a dynamic page with a .JSON file, and I'm using my C# program to access it every x number of seconds, to determine if something has been changed or not. Everything works flawlessly as long as I have Internet connection, if for whatever reason I lose it, then my program crashes as the ex.Response is a null. I was wondering if there's a better way of handling the following code:
void Function(){
while(true){
jList = new System.Web.Script.Serialization.JavaScriptSerializer().Deserialize<jsonList>(GET(jsonUrl));
//SOME THINGS I DO with the data above here
Thread.Sleep(5000);
}}
string GET(string url)
{
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
try
{
WebResponse response = request.GetResponse();
using (Stream responseStream = response.GetResponseStream())
{
StreamReader reader = new StreamReader(responseStream, Encoding.UTF8);
return reader.ReadToEnd();
}
}
catch (WebException ex)
{
WebResponse errorResponse = ex.Response;
if (ex.Response != null) {
using (Stream responseStream = errorResponse.GetResponseStream())
{
StreamReader reader = new StreamReader(responseStream, Encoding.GetEncoding("utf-8"));
String errorText = reader.ReadToEnd();
// log errorText
}
}
throw;
}
}
Perhaps I should ping it first, and see if I get a reply, and only then Perform the WebRequest function?
EDIT:
After adding this
public bool getResponse(string URL)
{
try
{
WebClient wc = new WebClient();
string HTMLSource = wc.DownloadString(URL);
return true;
}
catch (Exception)
{
return false;
}
}
And use it as
void Function(){
while(true){
if (!getResponse(jsonUrl))
{
return;
}
jList = new System.Web.Script.Serialization.JavaScriptSerializer().Deserialize<jsonList>(GET(jsonUrl));
//SOME THINGS I DO with the data above here
Thread.Sleep(5000);
}}
My C# application waits a bit, and then exits normally. Why?
The program '[10476] Kiosk2.vshost.exe' has exited with code 0 (0x0).
Alright, well this seems to work fine for me.
public void Update() //CALLED IT void FUNCTION earlier
{
while (true)
{
while (getResponse(jsonUrl))
{
jList = new System.Web.Script.Serialization.JavaScriptSerializer().Deserialize<jsonList>(GET(jsonUrl));
//I DO SOME STUFF HERE
//INTERESTING STUFF
Thread.Sleep(5000);
}
}
}
And seconds function:
public bool getResponse(string URL)
{
try
{
WebClient wc = new WebClient();
string HTMLSource = wc.DownloadString(URL);
return true;
}
catch (Exception)
{
return false;
}
}

C# read from HttpResponseMessage

I am using .net's Httpclient for the first time and finding it very hard. I have managed to call the server and receive response from it but stuck at reading from the response. Here is my code:
if (Method == HttpVerb.POST)
response = client.PostAsync(domain, new StringContent(parameters)).Result;
else
response = client.GetAsync(domain).Result;
if (response != null)
{
var responseValue = string.Empty;
Task task = response.Content.ReadAsStreamAsync().ContinueWith(t =>
{
var stream = t.Result;
using (var reader = new StreamReader(stream))
{
responseValue = reader.ReadToEnd();
}
});
return responseValue;
}
responseValue has {} in it although the service is returning data. How should I fix the issue?
The project is in .Net 4.
You are creating an asynchronous task but not waiting for it to complete before returning. This means your responseValue never gets set.
To fix this, before your return do this:
task.Wait();
So your function now looks like this:
if (Method == HttpVerb.POST)
response = client.PostAsync(domain, new StringContent(parameters)).Result;
else
response = client.GetAsync(domain).Result;
if (response != null)
{
var responseValue = string.Empty;
Task task = response.Content.ReadAsStreamAsync().ContinueWith(t =>
{
var stream = t.Result;
using (var reader = new StreamReader(stream))
{
responseValue = reader.ReadToEnd();
}
});
task.Wait();
return responseValue;
}
If you prefer to use await (which you possibly should), then you need to make the function this code is contained in async. So this:
public string GetStuffFromSomewhere()
{
//Code above goes here
task.Wait();
}
Becomes:
public async string GetStuffFromSomewhere()
{
//Code above goes here
await ...
}
Try this
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(obj.Url);
HttpWebResponse response = null;
try
{
response = request.GetResponse() as HttpWebResponse;
}
catch (Exception ex)
{
}

How to Send POST Request in windows Phone 8 and get its Response in json

I am trying to call a web service
which returns a JSON response. So far my code is working fine for GET Request but now services on server are POST and I have no idea how to do that! Below is the code for GET Request:
private void callSigninWebservice()
{
setProgressIndicator(true);
SystemTray.ProgressIndicator.Text = "Signing in please wait";
try
{
WebClient webClient = new WebClient();
Uri uri = new Uri(GlobalVariables.URL_USER +
GlobalVariables.URL_STUDENT_SIGNIN_MODE_LOGIN +
GlobalVariables.URL_EMAIL + tbUsername.Text +
GlobalVariables.URL_PASSWORD + tbPassword.Password);
webClient.DownloadStringCompleted += new DownloadStringCompletedEventHandler(webClient_DownloadStringCompleted);
webClient.DownloadStringAsync(uri);
}
catch (Exception ex)
{
MessageBox.Show(ex.Message + "error came here 1");
}
}
For Response
void webClient_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e)
{
try
{
JObject parentObj = JObject.Parse(e.Result);
String strResult = (String)parentObj[SigninData.JSON_result];
bool bolresult = strResult.Equals(SigninData.JSON_result_success, StringComparison.Ordinal);
if (bolresult)
{
JObject dataObj = (JObject)parentObj[SigninData.JSON_data];
setUserData(dataObj);
NavigationService.Navigate(new Uri("/BasePage.xaml", UriKind.RelativeOrAbsolute));
}
else
{
String error = (String)parentObj[SigninData.JSON_data];
MessageBox.Show("Error : " + error);
}
setProgressIndicator(false);
}
catch (Exception)
{
setProgressIndicator(false);
}
}
This is a simple way of making a post request and receiving a response in JSON for future parse:
internal static async Task<String> GetHttpPostResponse(HttpWebRequest request, string postData)
{
String received = null;
request.Method = "POST";
request.ContentType = "application/x-www-form-urlencoded";
byte[] requestBody = Encoding.UTF8.GetBytes(postData);
// ASYNC: using awaitable wrapper to get request stream
using (var postStream = await request.GetRequestStreamAsync())
{
// Write to the request stream.
// ASYNC: writing to the POST stream can be slow
await postStream.WriteAsync(requestBody, 0, requestBody.Length);
}
try
{
// ASYNC: using awaitable wrapper to get response
var response = (HttpWebResponse)await request.GetResponseAsync();
if (response != null)
{
var reader = new StreamReader(response.GetResponseStream());
// ASYNC: using StreamReader's async method to read to end, in case
// the stream i slarge.
received = await reader.ReadToEndAsync();
}
}
catch (WebException we)
{
var reader = new StreamReader(we.Response.GetResponseStream());
string responseString = reader.ReadToEnd();
Debug.WriteLine(responseString);
return responseString;
}
return received;
}

Converting ordinary Http Post web request with Async and Await

How I can convert my traditional HttpWebRequest "POST" call with Async / Await pattern, Here with this I am attaching my current code, Any one please help me to convert this code using Async / Await pattern for windows phone 8.
public void GetEnvironmentVariables(Action<Credentials> getResultCallback, Action<Exception> getErrorCallback)
{
CredentialsCallback = getResultCallback;
ErrorCallback = getErrorCallback;
var uri = new Uri(BaseUri);
var request = (HttpWebRequest)WebRequest.Create(uri);
request.Method = "POST";
request.ContentType = "application/json";
var jsonObject = new JObject
{
new JProperty("apiKey",_api),
new JProperty("affiliateId",_affid),
};
var serializedResult = JsonConvert.SerializeObject(jsonObject);
byte[] requestBody = Encoding.UTF8.GetBytes(serializedResult);
request.BeginGetRequestStream(GetRequestStreamCallback, new object[] { request, requestBody });
}
private void GetRequestStreamCallback(IAsyncResult asynchronousResult)
{
var request = (HttpWebRequest)((object[])asynchronousResult.AsyncState)[0];
using (var postStream = request.EndGetRequestStream(asynchronousResult))
{
var byteArray = (byte[])((object[])asynchronousResult.AsyncState)[1];
// Write to the request stream.
postStream.Write(byteArray, 0, byteArray.Length);
}
request.BeginGetResponse(GetResponseCallback, request);
}
private void GetResponseCallback(IAsyncResult asynchronousResult)
{
var request = (HttpWebRequest)asynchronousResult.AsyncState;
try
{
var response = (HttpWebResponse)request.EndGetResponse(asynchronousResult);
if (response != null)
{
var reader = new StreamReader(response.GetResponseStream());
string responseString = reader.ReadToEnd();
Credentails = JsonConvert.DeserializeObject<Credentials>(responseString);
if (Credentails != null && string.IsNullOrEmpty(Credentails.Err))
CredentialsCallback(Credentails);
else
{
if (Credentails != null)
ErrorCallback(new Exception(string.Format("Error Code : {0}", StorageCredentails.Err)));
}
}
}
catch (WebException we)
{
var reader = new StreamReader(we.Response.GetResponseStream());
string responseString = reader.ReadToEnd();
Debug.WriteLine(responseString);
ErrorCallback(we);
}
}
Since Windows Phone 8 doesn't seem to offer the TAP methods you need such as GetRequestStreamAsync the first thing to do is write a little wrapper to provide them for yourself:
public static class WebRequestAsyncExtensions
{
public static Task<Stream> GetRequestStreamAsync(this WebRequest request)
{
return Task.Factory.FromAsync<Stream>(
request.BeginGetRequestStream, request.EndGetRequestStream, null);
}
public static Task<WebResponse> GetResponseAsync(this WebRequest request)
{
return Task.Factory.FromAsync<WebResponse>(
request.BeginGetResponse, request.EndGetResponse, null);
}
}
Note the use of Task.Factory.FromAsync - this is the preferred way to get an await-friendly wrapper around an APM-based async API such as those offered by WebRequest. This is far more efficient than using Task.Factory.StartNew as suggested by someone else, because that would spin up a new thread, whereas this won't need to.
With this in place, you can now write your code in the same way you would on platforms where these TAP-style methods are available (e.g. Windows 8 store apps, desktop apps, etc.):
public async Task GetEnvironmentVariablesAsync(Action<Credentials> getResultCallback, Action<Exception> getErrorCallback)
{
CredentialsCallback = getResultCallback;
ErrorCallback = getErrorCallback;
var uri = new Uri(BaseUri);
var request = (HttpWebRequest) WebRequest.Create(uri);
request.Method = "POST";
request.ContentType = "application/json";
var jsonObject = new JObject
{
new JProperty("apiKey",_api),
new JProperty("affiliateId",_affid),
};
var serializedResult = JsonConvert.SerializeObject(jsonObject);
byte[] requestBody = Encoding.UTF8.GetBytes(serializedResult);
// ASYNC: using awaitable wrapper to get request stream
using (var postStream = await request.GetRequestStreamAsync())
{
// Write to the request stream.
// ASYNC: writing to the POST stream can be slow
await postStream.WriteAsync(requestBody, 0, requestBody.Length);
}
try
{
// ASYNC: using awaitable wrapper to get response
var response = (HttpWebResponse) await request.GetResponseAsync();
if (response != null)
{
var reader = new StreamReader(response.GetResponseStream());
// ASYNC: using StreamReader's async method to read to end, in case
// the stream i slarge.
string responseString = await reader.ReadToEndAsync();
Credentails = JsonConvert.DeserializeObject<Credentials>(responseString);
if (Credentails != null && string.IsNullOrEmpty(Credentails.Err))
CredentialsCallback(Credentails);
else
{
if (Credentails != null)
ErrorCallback(new Exception(string.Format("Error Code : {0}", StorageCredentails.Err)));
}
}
}
catch (WebException we)
{
var reader = new StreamReader(we.Response.GetResponseStream());
string responseString = reader.ReadToEnd();
Debug.WriteLine(responseString);
ErrorCallback(we);
}
}
Note the four lines with // ASYNC: comments - these show where I've made changes. I've collapsed your method down to one, because that's a) possible once you're using async and await and b) much easier than trying to pass things from one method to the next using state arguments.
Notice that the second and fourth of these actually makes async some things you were previously doing synchronously: writing data into the request stream, and reading data out of the response stream. For a small request this probably doesn't matter, but if large amounts of data are being transferred, a synchronous call to Write or ReadToEnd may block. Fortunately, although Windows Phone 8 appears to be missing the TAP methods on WebRequest, it does offer them on Stream and StreamReader so this works without needing to write any extension methods.
I'm new to the community, so here goes my first post. In this case, you can return anytype using a generic Task. This has worked well for me in the past.
Server Side
public class MyController : ApiController
{
public Task<string> PostAsync()
{
return Task.Factory.StartNew(() =>
{
return "populate me with any type and data, but change the type in the response signature.";
});
}
}
Client Side
public class HomeController : Controller
{
public Task<ViewResult> Index()
{
return Task.Factory.StartNew(() =>
{
var model = "use a provider, get some data, or something";
return View(model);
});
}
}
This should do the job:
public async void GetEnvironmentVariables(Action<Credentials> getResultCallback, Action<Exception> getErrorCallback) {
CredentialsCallback = getResultCallback;
ErrorCallback = getErrorCallback;
var uri = new Uri(BaseUri);
var request = (HttpWebRequest)WebRequest.Create(uri);
request.Method = "POST";
request.ContentType = "application/json";
var jsonObject = new JObject {
new JProperty("apiKey", _api),
new JProperty("affiliateId", _affid),
};
var serializedResult = JsonConvert.SerializeObject(jsonObject);
var requestBody = Encoding.UTF8.GetBytes(serializedResult);
var requestStream = request.GetRequestStream();
requestStream.Write(requestBody, 0, requestBody.Length);
await GetResponse(request);
}
private async Task GetResponse(WebRequest request) {
Stream resStream = null;
try {
var response = await request.GetResponseAsync();
if (response == null) {
return;
}
resStream = response.GetResponseStream();
if (resStream == null) {
return;
}
var reader = new StreamReader(resStream);
var responseString = await reader.ReadToEndAsync();
Credentails = JsonConvert.DeserializeObject<Credentials>(responseString);
if (Credentails != null && string.IsNullOrEmpty(Credentails.Err)) {
CredentialsCallback(Credentails);
}
else {
if (Credentails != null) {
ErrorCallback(new Exception(string.Format("Error Code : {0}", StorageCredentails.Err)));
}
}
}
catch (WebException we) {
if (resStream != null) {
var reader = new StreamReader(resStream);
var responseString = reader.ReadToEnd();
Debug.WriteLine(responseString);
}
ErrorCallback(we);
}
}

Categories

Resources