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.
Related
So I'm trying to send a multiform POST to API with http client but it's just hang there indefinetly. I test this code in console and it worked as it should, but then I try to run it like this for the UI
private static async Task<string> ApiTask(...)
{
var SourceStream = File.Open(imgpath,FileMode.Open);
var FileStreamContent = new StreamContent(SourceStream);
FileStreamContent.Headers.ContentType = MediaTypeHeaderValue.Parse("image/jpeg");
var client = new HttpClient();
using (var formData = new MultipartFormDataContent())
{
formData.Add(new StringContent("this is a test"),"comment");
formData.Add(new StringContent("Command: detect"),"message");
formData.Add(fileStreamContent, "image","image.jpg");
var response = await client.PostAsync(url,formData).ConfigureAwait(false);
var responseString = await response.Content.ReadAsStringAsync().ConfigureAwait(false);
return responseString
}
}
And I'm calling it from the EventHandler
public async void buttnclck(object sender, EventArgs e)
{
var task = await ApiTask(...);
lblresult.Text = task;
}
but as I said the code just stay in de .PostAsync line indefinetly or when a System.Threading.Task.TaskCanceledException is thrown.
So what I missing here? I thing I was handeling the async/await methods just fine but it's clear I'm not. I tried also with .Result but it won't work even and would throw System.AggregateException. So please help, been trying to make it work modifying the code as other suggested responses but still not working
EDIT:
after couple of hours debugging and searching I find out my problem relies in formData.Add(FileStreamContent, "image","image.jpg"); maybe I'm not serializing the image correctly? How can I fix this??
There is another question about this, but it doesn't have a functioning solution at the end, and the only good answer, for some reason, doesn't work, not for the guy who ask it, not for me either.
This such question is here:
How to post data using HttpClient?
Given the corresponding aclarations, this is the code I have so far:
The methods to call the method who connects with the web server:
private void Button_Click(object sender, System.EventArgs e)
{
//. . . DO SOMETHING . . .
PopulateListView();
//. . . DO SOMETHING ELSE . . .
}
private void PopulateListView()
{
//. . . DO SOMETHING . . .
list = await "http://web.server.url".GetRequest<List<User>>();
//. . . DO SOMETHING ELSE . . .
}
The method than connects with the web server:
public async static Task<T> SendGetRequest<T>(this string url)
{
try
{
var uri = new Uri(url);
HttpClient client = new HttpClient();
//Preparing to have something to read
var formContent = new FormUrlEncodedContent(new[]
{
new KeyValuePair<string, string>("OperationType", "eaf7d94356e7fd39935547f6f15e1c4c234245e4")
});
HttpResponseMessage response = await client.PostAsync(uri, formContent);
#region - - Envio anterior (NO FUNCIONO, SIN USO) - -
//var stringContent = new StringContent("markString");
//var sending = await client.PostAsync(url, stringContent);
//MainActivity.ConsoleData = await client.PostAsync(url, stringContent);
#endregion
//Reading data
//var response = await client.GetAsync(url);
var json = await response.Content.ReadAsStringAsync();
MainActivity.ConsoleData = json.ToString();
return Newtonsoft.Json.JsonConvert.DeserializeObject<T>(json);
}
catch(Exception ex)
{
Console.WriteLine("Error: "+ex.ToString());
return default(T);
}
}
You maybe guessed it, but I'm trying to make a method that send some data (through POST) called "markString" to a web-server than receive it and, depending of the "markString" it returns certain json Objects.
This web server is already working properly (I tested it out with some plug-in, it work like it should)
This method is supposed to send the "markString" and receive the data back so then i can use it in the app.
I'm making a Xamarin Android application.
Also have in mind than I don't have any connection problem at all, in fact the app is sending data in an excellent matter when I try to do it using web client, but I want it to send it using HttpClient.
The problem
The code is not returning anything. Any request for information, clarification, question, constructive comments or anything than can lead to an answer would be greatly appreciated too.
Thanks in advance.
Most deadlock scenarios with asynchronous code are due to blocking further up the call stack.
By default await captures a "context" (in this case, a UI context), and resumes executing in that context. So, if you call an async method and the block on the task (e.g., GetAwaiter().GetResult(), Wait(), or Result), then the UI thread is blocked, which prevents the async method from resuming and completing.
void Main()
{
var test = SendGetRequest("http://www.google.com");
test.Dump();
}
public async static Task<string> SendGetRequest(string url)
{
try
{
var uri = new Uri(url);
HttpClient client = new HttpClient();
//Preparing to have something to read
var formContent = new FormUrlEncodedContent(new[]
{
new KeyValuePair<string, string>("OperationType", "eaf7d94356e7fd39935547f6f15e1c4c234245e4")
});
HttpResponseMessage response = await client.PostAsync(uri, formContent);
#region - - Envio anterior (NO FUNCIONO, SIN USO) - -
//var stringContent = new StringContent("markString");
//var sending = await client.PostAsync(url, stringContent);
//MainActivity.ConsoleData = await client.PostAsync(url, stringContent);
#endregion
//Reading data
//var response = await client.GetAsync(url);
var json = await response.Content.ReadAsStringAsync();
return json;
}
catch (System.Exception ex)
{
Console.WriteLine("Error: " + ex.ToString());
return string.Empty;
}
}
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"
I couldn't find from search anyone having similar issues so:
I'm trying to get XML from server with HttpClient, but my UI freezes weirdly at line "task.Wait()". This is the code:
public void register() {
String data = "register=" + (accountName) + "&email0=" +
(email) + "&email1=" + (otherEmail);
var task = MakeRequest(data);
task.Wait(); //freezes here
var response = task.Result;
String resultstring = response.Content.ReadAsStringAsync().Result;
}
private static async Task<System.Net.Http.HttpResponseMessage> MakeRequest(String data)
{
var content = new StringContent(data, Encoding.UTF8, "application/x-www-form-urlencoded");
var httpClient = new System.Net.Http.HttpClient();
System.Net.Http.HttpResponseMessage responseMessage=null;
try
{
responseMessage = await httpClient.PostAsync(server, content);
}
catch(Exception ex)
{
responseMessage.ReasonPhrase = string.Format("RestHttpClient.SendRequest failed: {0}", ex);
}
return responseMessage;
}
Any help is greatly appreciated!
It's not freezing weirdly at all - it's freezing entirely reasonably.
You're calling task.Wait(), which stops your UI thread from doing any more work until that task has completed. However, that task itself needs to get back to the UI thread when the task returned by httpClient.PostAsync completes, in order to continue with the rest of your async method.
Basically, you shouldn't use Task.Wait() or Task.Result unless you know for sure that the task itself won't be blocked waiting to continue on the thread you're currently executing on.
Ideally, your register method (which should be Register to follow .NET naming conventions) should be asynchronous as well, so you can await the task returned by MakeRequest.
Additionally, you should probably change the way MakeRequest awaits the task - as the rest of that method doesn't really need to run on the UI thread, you can use:
responseMessage = await httpClient.PostAsync(server, content).ConfigureAwait(false);
Finally, this line:
responseMessage.ReasonPhrase = string.Format("RestHttpClient.SendRequest failed: {0}", ex);
... will throw a NullReferenceException if it ever executes. If an exception is thrown, responseMessage will still be null.
Answer of Jon Skeet solved my problem, and here is the working code, if some other beginner is having same problems.
public async void Register{
String data = "register=" + (accountName) + "&email0=" +
(email) + "&email1=" + (otherEmail);
var task = await MakeRequest(data);
String resultstring = taskContent.ReadAsStringAsync().Result;
}
private static async Task<System.Net.Http.HttpResponseMessage> MakeRequest(String data)
{
var content = new StringContent(data, Encoding.UTF8, "application/x-www-form-urlencoded");
var httpClient = new System.Net.Http.HttpClient();
return await httpClient.PostAsync(server, content).ConfigureAwait(false);
}
Thank you very much!
I previously posted a question about using HTTPClient with async/await. Now I'm trying to figure out how to do this in such a way as to actually make the Post calls execute at the same time while still being able to handle the resulting HttpResponseMessage.
This is what I've come up with. However, being a noob to await/async, I'm still unsure about if I'm doing this correctly or not. Could someone verify that this is the proper way to do this ... or at least a proper way.
public async Task ProcessAsync() {
//Query lists
List<Member> list = dbContext.Users.Where(u => u.IsMember).ToList();
//Add members to mailing list through web service
await AddMembersAsync(list);
}
private async Task AddMembersAsync(List<Member> members) {
using(var _client = new HttpClient()) {
//Initialize Http Client
...
var responses = await Task.WhenAll(members.Select(x => PostMemberAsync(x,_client)));
await Task.WhenAll(responses.Select(r => ProcessResponseAsync(r,client)));
}
}
private async Task<HttpResponseMessage> PostMemberAsync(Member member, HttpClient client) {
var jss = new JavaScriptSerializer();
var content = jss.Serialize(new MemberPost() {
email_address = member.email,
...
});
return await client.PostAsync("uri",new StringContent(content, Encoding.UTF8, "application/json"));
}
private async Task ProcessResponsesAsync(HttpResponseMessage response, HttpClient client) {
if(response.IsSuccessStatusCode) {
var responseText = await response.Content.ReadAsStringAsync();
var jss = new JavaScriptSerializer();
var userid = jss.Deserialize<MemberResponse>(responseText);
//Store mailing user's id
...
}
response.Dispose();
}
This appears to me like it would be correct. However, I have a slight problem with this. I need to tie each HttpResponseMessage to the member for which the message was created. My current code only returns Task but the response message does not contain a link to the user. (The service I'm posting to returns an id specific to the service. I need to keep track of that Id for each user so that I have a link between the member id and the service id).
Does my requirement of linking the id from the response message to the member make it unrealistic to use the above code or is there a way to somehow return the member as part of the task results?
I'm suggesting this without trying it out so please be careful but I would replace these two lines:
var responses = await Task.WhenAll(members.Select(x => PostMemberAsync(x,_client)));
await Task.WhenAll(responses.Select(r => ProcessResponseAsync(r,client)));
with this:
await Task.WhenAll(members.Select(async x =>
{
var response = await PostMemberAsync(x, _client);
await ProcessResponseAsync(response, client, x);
}));
And of course you need to enhance ProcessResponseAsync by the argument Member
I need to tie each HttpResponseMessage to the member for which the message was created.
When doing asynchronous programming, I find it useful to avoid side effects. In other words, if you have a method that calculates or determines something, return that value from the method rather than saving it in some member variable.
private async Task<MemberResponse> ProcessResponseAsync(HttpResponseMessage response, HttpClient client)
{
using (response)
{
if(response.IsSuccessStatusCode)
{
var responseText = await response.Content.ReadAsStringAsync();
var jss = new JavaScriptSerializer();
var userid = jss.Deserialize<MemberResponse>(responseText);
return userid;
}
else
{ ... }
}
}
Add a small helper method, and your calling code becomes quite clean:
private async Task<HttpResponseMessage> ProcessMemberAsync(Member member, HttpClient client)
{
var response = await PostMemberAsync(member, client);
return await ProcessResponseAsync(response, client);
}
private async Task AddMembersAsync(List<Member> members)
{
using(var client = new HttpClient())
{
... // Initialize HttpClient
var responses = await Task.WhenAll(members.Select(x => ProcessMemberAsync(x, client)));
for (int i = 0; i != members.Count; ++i)
{
var member = members[i];
var response = responses[i];
...
}
}
}