Calling an async method - c#

I'm new to using async methods and could use some help. Winforms .Net 4.5 program: ReadInputFile loops through each line in a csv file and calls the async method UpdatePOS_Monitor which posts to the API. Everything is working so far (my database is getting the new rows) but I don't know how to exit the application when ReadInputFile is done because it is calling an async method. Or if ReadInputFile will get ahead of itself with this setup? I'm guessing I need to be 'awaiting' somewhere but don't know what to do? Thank you.
private void ReadInputFile()
{
var reader = new StreamReader(File.OpenRead(FilePath + #"\" + FileNameAdd));
while (!reader.EndOfStream)
{
var line = reader.ReadLine();
var values = line.Split(',');
var Newline = new RevenueLine();
Newline.ClubID = values[0];
Newline.Date = values[1];
Newline.Department = values[2];
Newline.Description = values[3];
Newline.Chits = Convert.ToInt32(values[4]);
Newline.Sales = values[5];
UpdatePOS_Monitor(Newline);
}
}
private async void UpdatePOS_Monitor(RevenueLine line)
{
HttpClient client = new HttpClient();
try
{
string json = JsonConvert.SerializeObject(line);
HttpResponseMessage wcfResponse = await client.PostAsync(API_Address, new StringContent(json, Encoding.UTF8, "application/json"));
}
catch
{
}
}

If you're using async/await, the whole chain of methods has to be async, all the way down to the root (e.g., to the UI control event handler). In your case it means that ReadInputFile has to be async, and UpdatePOS_Monitor has to be async Task rather than async void:
// root event handler
private async void button_Click(object s, EventArgs e)
{
await ReadInputFile();
}
private async Task ReadInputFile()
{
var reader = new StreamReader(File.OpenRead(FilePath + #"\" + FileNameAdd));
while (!reader.EndOfStream)
{
var line = await reader.ReadLineAsync();
var values = line.Split(',');
var Newline = new RevenueLine();
Newline.ClubID = values[0];
Newline.Date = values[1];
Newline.Department = values[2];
Newline.Description = values[3];
Newline.Chits = Convert.ToInt32(values[4]);
Newline.Sales = values[5];
await UpdatePOS_Monitor(Newline);
}
}
private async Task UpdatePOS_Monitor(RevenueLine line)
{
using (HttpClient client = new HttpClient())
{
string json = JsonConvert.SerializeObject(line);
HttpResponseMessage wcfResponse = await client.PostAsync(API_Address, new StringContent(json, Encoding.UTF8, "application/json"));
}
}
Note also await reader.ReadLineAsync, await UpdatePOS_Monitor(Newline) and the removal of catch {} inside UpdatePOS_Monitor (it's almost always a bad idea to swallow exceptions like that).

Related

Why HttpClient.Post method is not Executing all the Methods?

Here I wrote small function as
public override void OnAuthorization(System.Web.Http.Controllers.HttpActionContext actionContext)
{
//Here im Calling one Private Methode
GetValiedSession("22");
if(1==1{
}
else
//SomeCode
GetValiedSession
public async Task<bool> GetValiedSession(string _SesToken)
{
string Baseurl = WebConfigurationManager.AppSettings["Baseurl"];
var values = new Dictionary<string, string>{
{ "securityToken","_SesToken"},
};
using (var client = new HttpClient())
{
var _json = JsonConvert.SerializeObject(values);
var content = new StringContent(_json, Encoding.UTF8, "application/json");
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
var response = await client.PostAsync(Baseurl + "validate/session", content);
var responseString = await response.Content.ReadAsStringAsync();
return false;
}
on the above code
var response = await client.PostAsync(Baseurl + "validate/session", content);
after this code its Executing if(1==1){---}
Please guide me how can I stop that until its execute.
Convert your Sync method to async If you can (This means you need to change your base method) and put change GetValiedSession("22"); to await GetValiedSession("22");
public override async Task OnAuthorization(System.Web.Http.Controllers.HttpActionContext actionContext)
{
//Here im Calling one Private Methode
await GetValiedSession("22");
if(1==1{
}
else
//SomeCode
}
or simply use your method synchronously
GetValiedSession("22").GetAwaiter().GetResult();

ASP.NET Api Client

I'm learning how to create WEB-API client
I've created some simple API:
[HttpGet]
public IHttpActionResult GetInfo()
{
return Ok("Its working!");
}
[HttpPost]
public IHttpActionResult PostInfo(ClientDataDto dto)
{
try
{
someMethod(dto.IdKlienta, dto.Haslo, dto.IdZgloszenia, dto.HardwareInfo, dto.SoftwareInfo);
return Ok("sent");
}
catch
{
return BadRequest();
}
}
For now I just trying to call GET method.
When I use Fiddler with addr
localhost:someport/api/Client2
its working
but when i try to do it by client, which code is below:
private static HttpClient client = new HttpClient();
static void Main(string[] args)
{
#region TESTONLY
var debug = new XMLData();
string HardwareInfoXML = debug.HardwareXML;
string SoftInfoXML = debug.SoftwareXML;
int id_zgloszenia = 20;
int idKlienta = 25;
//haslo = "202cb962ac59075b964b07152d234b70";
#endregion
var data = new ClientDataDto() { HardwareInfo = HardwareInfoXML, SoftwareInfo = SoftInfoXML, IdKlienta = idKlienta, IdZgloszenia = id_zgloszenia };
RunAsync(data);
}
private static async Task RunAsync(ClientDataDto data)
{
var stringContent = new StringContent(JsonConvert.SerializeObject(data), Encoding.UTF8, "application/json");
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
client.BaseAddress = new Uri(#"http://localhost:7774/api/client2/");
var url = new Uri(#"http://localhost:7774/api/client2/");
var res1 = await client.GetAsync(url);
var res = await client.PostAsync(url, stringContent);
res.EnsureSuccessStatusCode();
}
Application closing without any info at
var res1 = await client.GetAsync(url);
I have checked to see all exceptions in Debug exception Windows, but it is just closing after trying call GetAsync
PostASync doesn't work too.
What is wrong here?
i'm really sorry that i've posted simpe problem.
sulotion is to add .Wait() on RunAsync(data);
RunAsync(data).Wait();

C# HttpClient POST'ing Async

I want to send a http post that can take a couple of seconds to reply without freezing my UI, currently this code just hangs my application when the method is callled.
What am I doing wrong and how do i achieve my goal?
private async Task<string> DoHttpClientPost(string method, IDictionary<string, object> args = null)
{
{
HttpClientHandler handler = new HttpClientHandler()
{
AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate
};
handler.Proxy = null;
HttpResponseMessage response;
using (var myHttpClient = new HttpClient(handler))
{
myHttpClient.DefaultRequestHeaders.ExpectContinue = false;
myHttpClient.DefaultRequestHeaders.Add("Accept-Charset", "ISO-8859-1,utf-8");
myHttpClient.DefaultRequestHeaders.Add(APPKEY_HEADER, CustomHeaders.GetValues(APPKEY_HEADER));
myHttpClient.DefaultRequestHeaders.Add(SESSION_TOKEN_HEADER, CustomHeaders.GetValues(SESSION_TOKEN_HEADER));
myHttpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json-rpc"));
var call = new JsonRequest { Method = method, Id = 1, Params = args };
var jsonObject = JsonConvert.Serialize<JsonRequest>(call);
var content = new StringContent(jsonObject.ToString(), Encoding.UTF8, "application/json-rpc");
response = await myHttpClient.PostAsync(new Uri(EndPoint), content);
}
Console.WriteLine("\nCalling: " + method + " With args: " + JsonConvert.Serialize<IDictionary<string, object>>(args));
string jsonResponse = await response.Content.ReadAsStringAsync();
return jsonResponse;
}
}
public T Invoke<T>(string method, IDictionary<string, object> args = null)
{
if (method == null)
throw new ArgumentNullException("method");
if (method.Length == 0)
throw new ArgumentException(null, "method");
var jsonString = DoHttpClientPost(method, args).Result;
var jsonResult = JsonConvert.Deserialize<JsonResponse<T>>(jsonString);
return jsonResult.Result;
}
var jsonString = DoHttpClientPost(method, args).Result;
This is your culprit. If you call .Result on a Task from the UI thread it will hang.
You'll need to async all the way up - so Invoke should be async and return a Task<T> and await the DoHttpClientPost call, the caller should be async etc. etc. etc.
You have to make two changes
Modify this line from
response = await myHttpClient.PostAsync(new Uri(EndPoint), content);
to
response = await myHttpClient.PostAsync(new Uri(EndPoint), content).ConfigureAwait(false);
And looks like your intention is to wait for the post call to complete and return the results, so modify this line from
var jsonString = DoHttpClientPost(method, args).Result;
to
var jsonStringTask = DoHttpClientPost(method, args);
jsonStringTask.Wait(); //wait for http post call to complete.
var jsonString = jsonStringTask.Result;

Endless wait for async Web Response

i have the following problem, i try to wait for for an Async Web Response.
But it never finished.
public string getTermine(string trmId)
{
System.Threading.Tasks.Task<string> lisi = LoadTermine((HttpWebRequest)WebRequest.Create("http://" + curent.usrCH + apiKey + curent.phrase + apiTrmIDIS + trmId));//Request get String result like http://ajax.googleapis.com/ajax/services/search/web?v=1.0&start="+i+"&q=
lisi.Wait();
return lisi.Result;
}
private async System.Threading.Tasks.Taskstring>LoadTermine(HttpWebRequest myRequest)
{
//List<Termine> terminListe = new List<Termine>();
List<Appointment> Resu = null;
using (WebResponse response = await myRequest.GetResponseAsync())
{
using (System.IO.StreamReader reader = new System.IO.StreamReader(response.GetResponseStream()))
{
Resu = reader.ReadToEnd();
}
}
return Resu;
}
P.S. I cant use and synchronous request because this methods are an part of the Base code which is used by iOS, WinPhone and Android and i dont know why i cant get an synchronous WebResponse.
You are creating a deadlock by calling .Result on the task.
You could do something like this where the remoteUrl variabled is the url of your web service
private async System.Threading.Tasks.Task<string> LoadTermineAsync(HttpWebRequest myRequest)
{
using (var client = new HttpClient()) {
using (var request = new HttpRequestMessage(HttpMethod.Get, myRemoteUrl)) {
var response = await client.SendAsync(request).ConfigureAwait(false);
var result = await response.Content.ReadAsStringAsync().ConfigureAwait(false);
return result;
}
}
}
For more info on Async/Await
And this evolve video is a little bit more advanced.

Webclient UploadStringCompleted event not being called

I'm writing unit tests for some of the web services we've developed. I have a [TestMethod] that posts to a webservice as rest. Works great however it doesn't trigger the eventhandler method that I created. Through debugging, I've noticed that the eventhandler is getting excluder after the testmethod is executed. It goes to testcleanup.
Has anyone encountered this problem? Here's the code
[TestMethod,TestCategory("WebServices")]
public void ValidateWebServiceGetUserAuthToken()
{
string _jsonstringparams =
"{ \"Password\": \"xxx\", \"UserId\": \"xxxx\"}";
using (var _requestclient = new WebClient())
{
_requestclient.UploadStringCompleted += _requestclient_UploadStringCompleted;
var _uri = String.Format("{0}?format=Json", _webservicesurl);
_requestclient.Headers.Add(HttpRequestHeader.ContentType, "application/json");
_requestclient.UploadStringAsync(new Uri(_uri), "POST", _jsonstringparams);
}
}
void _requestclient_UploadStringCompleted(object sender, UploadStringCompletedEventArgs e)
{
if (e.Result != null)
{
var _responsecontent = e.Result.ToString();
Console.WriteLine(_responsecontent);
}
else
{
Assert.IsNotNull(e.Error.Message, "Test Case Failed");
}
}
The problem is is that UploadStringAsync returns void (i.e. it's fire and forget) and doesn't inherently let you detect completion.
There's a couple of options. The first option (which is the one I'd recommend) is to use HttpClient instead and use the PostAsync method--which you can await. In which case, I'd do something like this:
[TestMethod, TestCategory("WebServices")]
public async Task ValidateWebServiceGetUserAuthToken()
{
string _jsonstringparams =
"{ \"Password\": \"xxx\", \"UserId\": \"xxxx\"}";
using (var httpClient = new HttpClient())
{
var _uri = String.Format("{0}?format=Json", _webservicesurl);
var stringContent = new StringContent(_jsonstringparams);
stringContent.Headers.ContentType = new MediaTypeHeaderValue("application/json");
HttpResponseMessage response = await httpClient.PostAsync(_uri, stringContent);
// Or whatever status code this service response with
Assert.AreEqual(HttpStatusCode.Accepted, response.StatusCode);
var responseText = await response.Content.ReadAsStringAsync();
// TODO: something more specific to your needs
Assert.IsTrue(!string.IsNullOrWhiteSpace(responseText));
}
}
The other option is to change your complete event handler to signal back to your test that the upload is completed and in your test, wait for the event to occur. For example:
[TestMethod, TestCategory("WebServices")]
public void ValidateWebServiceGetUserAuthToken()
{
string _jsonstringparams =
"{ \"Password\": \"xxx\", \"UserId\": \"xxxx\"}";
using (var _requestclient = new WebClient())
{
_requestclient.UploadStringCompleted += _requestclient_UploadStringCompleted;
var _uri = String.Format("{0}?format=Json", _webservicesurl);
_requestclient.Headers.Add(HttpRequestHeader.ContentType, "application/json");
_requestclient.UploadStringAsync(new Uri(_uri), "POST", _jsonstringparams);
completedEvent.WaitOne();
}
}
private ManualResetEvent completedEvent = new ManualResetEvent(false);
void _requestclient_UploadStringCompleted(object sender, UploadStringCompletedEventArgs e)
{
if (e.Result != null)
{
var _responsecontent = e.Result.ToString();
Console.WriteLine(_responsecontent);
}
else
{
Assert.IsNotNull(e.Error.Message, "Test Case Failed");
}
completedEvent.Set();
}
Besides the answers posts above, I've also added a method to support httpwebresponse so I don't have to wait for the event.
public static AuthTokenResponse GetUserToken(string username, string password)
{
string _jsonstringparams =
String.Format("{{ \"Password\": \"{0}\", \"UserId\": \"{1}\"}}", password, username);
string _webservicesurl = ConfigurationManager.AppSettings["WebservicesUrl"];
HttpWebRequest _requestclient = (HttpWebRequest)WebRequest.Create(String.Format("{0}?format=Json", _webservicesurl));
_requestclient.ContentType = "application/json";
_requestclient.Method = "POST";
using (var streamWriter = new StreamWriter(_requestclient.GetRequestStream()))
{
streamWriter.Write(_jsonstringparams);
streamWriter.Flush();
streamWriter.Close();
var httpResponse = (HttpWebResponse)_requestclient.GetResponse();
using (var streamReader = new StreamReader(httpResponse.GetResponseStream()))
{
_responsecontent = streamReader.ReadToEnd();
}
AuthTokenResponse _clienttoken = JsonConvert.DeserializeObject<AuthTokenResponse>(_responsecontent);
return _clienttoken;
}
}

Categories

Resources