Return value after UploadStringCompleted event raised? - c#

I able to upload data from client side, and got the response. My question is how to return a value from LoginRequest method after UploadStringCompleted event was completed.
Or How to return a value from UploadStringCompleted event. Please See my code below.
But When I am doing return "true" line is executed before webClientLogin_UploadStringCompleted method called.
Below link have something similar but I didn't get answer for my question
Click [here] (Return value of UploadStringAsync().?)
Thanks in Advance.
public string LoginRequest(string token)
{
WebClient client = new WebClient();
JavaScriptSerializer serializer = new JavaScriptSerializer();
var result= serializer.Serialize(token);
client .Headers["ContentType"] = "application/json";
client.UploadStringCompleted += new UploadStringCompletedEventHandler(webClientLogin_UploadStringCompleted);
client.UploadStringAsync(URI, HTTP_POST, result);
return "true";
}
private void webClientLogin_UploadStringCompleted(object sender, UploadStringCompletedEventArgs e)
{
var validate = JsonConvert.DeserializeObject<string>(e.Result);
}
Shall I do anything with AutoResetEvent or ManualReSetEvent?

You should not return anything from the LoginRequest method. Instead do the things that you want to do from the webClientLogin_UploadStringCompleted event. because it will get called when the upload is completed.

You can use UploadStringTaskAsync which returns a Task<string> allowing you to use async/await. Try this:
public async Task<string> LoginRequest(string token)
{
JavaScriptSerializer serializer = new JavaScriptSerializer();
var result = serializer.Serialize(token);
WebClient client = new WebClient();
client.Headers["ContentType"] = "application/json";
var response = await client.UploadStringTaskAsync(URI, HTTP_POST, result);
// do something with the response here, eg. JsonConvert.DeserializeObject();
return "true";
}
Also, why return true as a string? Use a boolean if you can.

Related

HttpResponseMessage to string

I am calling a method of which returns Task, in the calling method I need to read the response in form of string.
Here's the code that I have put:
static public async Task<HttpResponseMessage> Validate(string baseUri,HttpContent content) {
HttpResponseMessage response = new HttpResponseMessage();
response = await client.PostAsync(baseUri,content);
return response;
}
public string test(){
string postJson = "{Login = \"user\", Password = \"pwd\"}";
HttpContent stringContent = new StringContent(postJson,
UnicodeEncoding.UTF8, "application/json");
HttpResponseMessage result=Validate(Uri,stringContent);
var json = result.Content.ReadAsStringAsync().Result;
}
I expect string but this error is thrown:
Cannot implicitly convert type
'System.Threading.Tasks.Task<System.Net.Http.HttpResponseMessage>' to
'System.Net.Http.HttpResponseMessage'
Your problem is at:
HttpResponseMessage result=Validate(Uri,stringContent);
Validate is returning a task, not a HttpResponseMessage.
Change that to:
var result = Validate(Uri,stringContent).Result;
Just to clean up the code a bit and avoid using Result if you can afford to change it like:
static public async Task<HttpResponseMessage> Validate(string baseUri, HttpContent content)
{
return await client.PostAsync(baseUri,content);
}
public async Task<string> test()
{
var postJson = "{Login = \"user\", Password = \"pwd\"}";
var stringContent = new StringContent(postJson, UnicodeEncoding.UTF8, "application/json");
var result = await Validate(Uri,stringContent);
return await result.Content.ReadAsStringAsync();
}
Be consistent with your coding style. As to why calling .Result is bad, as people are pointing out in the comments, check this blog.
Method Validate returns the task and is asynchronous. Basically you can call this method in two different ways:
1) await the result of Validate in another async method, like this...
public async Task<string> test() {
string postJson = "{Login = \"user\", Password = \"pwd\"}";
HttpContent stringContent = new StringContent(postJson,
UnicodeEncoding.UTF8, "application/json");
HttpResponseMessage result = await Validate(Uri,stringContent);
var json = result.Content.ReadAsStringAsync().Result;
}
2) block current execution while waiting for this resul, like this...
public string test() {
string postJson = "{Login = \"user\", Password = \"pwd\"}";
HttpContent stringContent = new StringContent(postJson,
UnicodeEncoding.UTF8, "application/json");
HttpResponseMessage result = Validate(Uri,stringContent).Result;
var json = result.Content.ReadAsStringAsync().Result;
}
Choose the 1st way by default unless you really have an urge to block the calling thread.
Note that when using 2nd solution in WinForms, WPF or ASP.NET apps you will probably have a deadlock. modifying Validate method like this should solve the problem:
response = await client.PostAsync(baseUri,content).ConfigureAwait(false);
Just for readability change the method name from Validate(..) to ValidateAsync(..). Just to make clear that this method returns a task and you have to await it.
You're missing an await when calling your Validate method. If you do not want or can make the caller async then use the method GetAwaiter().GetResult() and you'll get what you want.
Replace ReadAsStringAsync().Result with ReadAsStringAsync().GetAwaiter().GetResult()
Like others wrote in comments calling .Result is bad because it could cause locks. The same applies in general to GetAwaiter().GetResult() but calling them is preferred over calling Result. The best option is to use await/async.
When you want to know whats the difference between GetAwaiter().GetResult() vs calling Result you can read this:
Is Task.Result the same as .GetAwaiter.GetResult()?
You can easily write:
var json = result.Content.ReadAsStringAsync().GetAwaiter().GetResult();

HttpClient.PostAsync terminates program with exit code 0

Have look around the web and not found any answers.. I did find a post here with my same problem but it does not resolve my issue.
(HttpClient.PostAsync knocks out the app with exit code 0)
When I run this code, the post to vendorAddress works.
but when I get to post PaymentTerms the program terminates on the postAsync function with no error message, code or anything.
I don't understand why it works for one but not the other..
I have taken the same Url and json text and done a post thru chrome using the postman plugin. Both calls work and I can get results back.
I have changed my post to use WebClient and both call work and I get results.
but I need to keep HTTPClient service in my code.
Any suggestions?
static void Main(string[] args)
{
RunAsync().Wait();
}
static async Task RunAsync()
{
try
{
// works
var result = await enconPostData("vendorAddress", JsonVendorAdd);
// does not work. fails on postAsync
var result1 = enconPostData("PaymentTerms", null);
}
catch (Exception e)
{
Console.WriteLine(e.Message);
}
}
static public async Task<string> enconPostData(string datatype, Object[] jsObject)
{
////jsObject is a json string/object////
string jsonString = null, URIaddress = null;
switch (datatype)
{
case "vendorAddress":
// Create Json Object to post
//EnVendors enconvend = new EnVendors();
EnVendors envend = new EnVendors();
envend.data = (Vendor[])jsObject;
URIaddress = baseUrl + "api/CONTACTS/UpdateXXXXXX";
// Serialize to a JsonString
jsonString = JsonConvert.SerializeObject(enconvend);
break;
case "PaymentTerms":
ContractInput entermdate = new ContractInput();
//Set JsonObject here with dates
entermdate.DateFrom = new DateTime(2016, 10, 1);
entermdate.DateTo = new DateTime(2016, 10, 30);
URIaddress = baseUrl + "api/PaymentTerms/ActiveXXXXXX";
// Serialize to a JsonString
jsonString = JsonConvert.SerializeObject(entermdate);
break;
}
return await PostAsync(URIaddress, jsonString);
}
static public async Task<string> PostAsync(string uri, string jsonString)
{
// Post to API Call
using (var Client = new HttpClient())
{
/////////
/// program aborts here at PostAsync on PaymentTerms Call. works fine for vendorAddress
////////
var response = await Client.PostAsync(uri, new StringContent(jsonString, Encoding.UTF8, "application/json"));
//will throw an exception if not successful
response.EnsureSuccessStatusCode();
string content = await response.Content.ReadAsStringAsync();
return await Task.Run(() => content);
}
}
Well, I have figured out my issue on reviewing my post here.
I had a break point set, so the red color of the break point made it hard to see my problem.
on line 22 of my example
var result1 = enconPostData("PaymentTerms", null);
is missing the await command
var result1 = await enconPostData("PaymentTerms", null);
once I added that.. I get my results, and the program did not terminate.
synchronous call vs asynchronous call
Thanks all.. just needed a new perspective i guess.

Async function call issue

I am working on a Windows Phone application. While invoking the below function, after executing this line:
HttpResponseMessage response = await client.GetAsync(connection1).ConfigureAwait(false);
it skips the rest of the code and control goes to the parent function and execute the rest of the code there and come back to this function again. How to fix this problem?
public async void vehicleValidation()
{
//isValidVehicle = true;
var client = new System.Net.Http.HttpClient();
//string connection = "http://mymlcp.co.in/mlcpapp/get_slot.php?vehiclenumber=KL07BQ973";
string connection1 = string.Format("http://mymlcp.co.in/mlcpapp/?tag=GetIsValidUser&employeeId={0}&name={1}",txtVeh.Text,"abc");
HttpResponseMessage response = await client.GetAsync(connection1).ConfigureAwait(false);
//var response = await client.GetAsync(connection1);
// HttpResponseMessage response = client.GetAsync(connection1).Result;
var cont = await response.Content.ReadAsStringAsync();
var floorObj = Newtonsoft.Json.Linq.JObject.Parse(cont);
//var resp = await (new MLCPClient()).GetIsValidUser(txtVeh.Text, "xyz");
if (String.IsNullOrEmpty(floorObj["error"].ToString()) || floorObj["error"].ToString().Equals("true"))
{
isValidVehicle = false;
}
else
{
isValidVehicle = true;
}
}
You should never have async void unless you are writing a event handler, you need to make your function return a Task and then await the function in your parent function.
Read "Async/Await - Best Practices in Asynchronous Programming" for a introduction on the best practices like never doing async void and making your code "async all the way"

How to collect the returned value of an awaited method in a variable in another method

So I am trying to grab the source code from a url and here is my code:
public async Task<string> grabPageHtml(Uri pageUrl)
{
var request = WebRequest.Create(pageUrl) as HttpWebRequest;
request.Method = "GET";
WebResponse responseObject = await Task<WebResponse>.Factory.FromAsync(
request.BeginGetResponse,
request.EndGetResponse, request);
var responseStream = responseObject.GetResponseStream();
var sr = new StreamReader(responseStream);
received = sr.ReadToEndAsync().Result;
return received;
}
The code works correctly and returns the sourcecode. The problem is assigning "received" to a string variable in another method.
Tried this:
string pageHtml = grabPageHtml(pageUrl)
but pageHtml outputs System.Threading.Tasks.Task'1[System.String] to the console instead of the source code.
pageHtml outputs System.Threading.Tasks.Task1[System.String]` to the
console instead of the source code.
That's because your method returns a Task<string>, not a string. You need to extract that string result somehow. It should be:
public async Task FooAsync()
{
string pageHtml = await GrabPageHtmlAsync(pageUrl);
Console.WriteLine(pageHtml);
}
As a side note, don't block on async code. Using Task.Result may lead to deadlocks. Also, using HttpClient would make your code a bit cleaner, removing the need to call FromAsync:
public Task<string> GrabPageHtmlAsync(Uri pageUrl)
{
var httpClient = new HttpClient();
return httpClient.GetStringAsync(pageUrl);
}

how to modify object which is not in the same thread

I am working on a async web request. and need to depends on the response to do a message return.
was thinking to do sth like following
// creating request
string messageToReturn = string.empty;
request.BeginGetResponse(ar =>
{
HttpWebRequest req2 = (HttpWebRequest)ar.AsyncState;
var response = (HttpWebResponse)req2.EndGetResponse(ar);
// is it safe to do this?
messageToReturn = "base on respone, assign different message";
}, request);
// will i get any response message? i will always get empty right?
// since response is handle in another thread
return messageToReturn;
what is the best way to do that?
You are right, that variable will always be empty because you fired off an asyncronous request with the BeginGetResponse method. So really you have a few options here. You can either block the executing thread until the response comes back (probably a really bad idea unless you have a very strong argument for doing this), or you could use an event based asynchronous pattern to alert callers when your response returns...
Consider some of your code wrapped in a method
public void GetMessageAsync()
{
string messageToReturn = string.empty;
request.BeginGetResponse(ar =>
{
HttpWebRequest req2 = (HttpWebRequest)ar.AsyncState;
var response = (HttpWebResponse)req2.EndGetResponse(ar);
// is it safe to do this?
messageToReturn = "base on respone, assign different message";
}, request);
}
To wire up an event based pattern here. We define a custom EventArgs class and a custom event which callers can listen for and which we will fire when the response comes back.
public class StringEventArgs : EventArgs
{
public string Message { get; set; }
}
public event EventHandler<StringEventArgs> MessageReturned;
public void GetMessageAsync()
{
//string messageToReturn = string.empty;
request.BeginGetResponse(ar =>
{
HttpWebRequest req2 = (HttpWebRequest)ar.AsyncState;
var response = (HttpWebResponse)req2.EndGetResponse(ar);
//messageToReturn = "base on respone, assign different message";
this.MessageReturned(this, new StringEventArgs { Message = response.ToString() });
}, request);
}

Categories