My method is calling a web service and working asynchronusly.
When getting response, everything works fine and I am getting my response.
The problem starts when I need to return this response.
here is the code of my method:
public async Task<string> sendWithHttpClient(string requestUrl, string json)
{
try
{
Uri requestUri = new Uri(requestUrl);
using (var client = new HttpClient())
{
client.DefaultRequestHeaders.Clear();
...//adding things to header and creating requestcontent
var response = await client.PostAsync(requestUri, requestContent);
if (response.IsSuccessStatusCode)
{
Debug.WriteLine("Success");
HttpContent stream = response.Content;
//Task<string> data = stream.ReadAsStringAsync();
var data = await stream.ReadAsStringAsync();
Debug.WriteLine("data len: " + data.Length);
Debug.WriteLine("data: " + data);
return data;
}
else
{
Debug.WriteLine("Unsuccessful!");
Debug.WriteLine("response.StatusCode: " + response.StatusCode);
Debug.WriteLine("response.ReasonPhrase: " + response.ReasonPhrase);
HttpContent stream = response.Content;
var data = await stream.ReadAsStringAsync();
return data;
}
}
}
catch (Exception ex)
{
Debug.WriteLine("ex: " + ex.Message);
return null;
}
and I am calling it this way:
Task <string> result = wsUtils.sendWithHttpClient(fullReq, "");
Debug.WriteLine("result:: " + result);
but when printing result I am seeing something like this: System.Threading.Tasks.Task
how can I get the result string as I did with data inside my method.
You need to do this since you are calling the async method synchronously:
Task<string> result = wsUtils.sendWithHttpClient(fullReq, "");
Debug.WriteLine("result:: " + result.Result); // Call the Result
Think of the Task<string> return type as a 'promise' to return a value in the future.
If you called the async method asynchronously then it would be like the following:
string result = await wsUtils.sendWithHttpClient(fullReq, "");
Debug.WriteLine("result:: " + result);
An asynchronous method returns a task, representing a future value. In order to get the actual value wrapped in that task, you should await it:
string result = await wsUtils.sendWithHttpClient(fullReq, "");
Debug.WriteLine("result:: " + result);
Note that this will require your calling method to be asynchronous. This is both natural and correct.
Related
I want to translate a given string to a specific language and print the translation to console , but my console prints nothing , I am also trying to catch some error , but my console still prints nothing, anyone know why ?
Here are my headers:
using Newtonsoft.Json;
using System.Net.Http;
using NPOI.SS.Formula.Functions;
I have defined the necessary key and region and url attribute inside class block , but it just won't work like this :
public const string subscriptionKey = "mykey";
public const string region = "myregion";
public const string endpoint="https://api.cognitive.microsofttranslator.com/";
mykey consists of my subscription key and myregion consists of my region
Here is my main:
TranslateString();
Here is my implementation of method TranslateString
public static async void TranslateString()
{
string route = "translate?api-version=3.0&from=en&to=fr&to=zu";
string xmlString = "Hello , welcome";
try
{
object[] body = new object[] { new { Text = xmlString } };
var requestBody = JsonConvert.SerializeObject(body);
using (var client = new HttpClient())
using (var request = new HttpRequestMessage())
{
request.Method = HttpMethod.Post;
request.RequestUri = new Uri(endpoint + route);
request.Content = new StringContent(requestBody, Encoding.UTF8, "application/json");
request.Headers.Add("Ocp-Apim-Subscription-Key", subscriptionKey);
request.Headers.Add("Ocp-Apim-Subscription-Region", region);
HttpResponseMessage response = await client.SendAsync(request).ConfigureAwait(false);
if (response.IsSuccessStatusCode)
{
Console.WriteLine("Success , translated text:");
string result = await response.Content.ReadAsStringAsync();
Console.WriteLine(result);
}
else
{
Console.WriteLine("Error: " + response.StatusCode + " " + response.ReasonPhrase);
}
}
}
catch (Exception ex)
{
Console.WriteLine("Error:" + ex.Message);
}
Here is your code with minimal changes to make it produce an output. The relevant change is for TranslateString() to return a Task, so that the main thread waits for the async call to complete. Another option would have been to make this a synchronous call.
This uses the .Net built-in Json serializer instead of Newtonsoft for simplicity.
This compiles as is using .Net7 with C#10, and your key and region filled in.
using System.Net;
using System.Text;
using System.Text.Json;
const string subscriptionKey = "mykey";
const string region = "myregion";
const string endpoint = "https://api.cognitive.microsofttranslator.com/";
Console.WriteLine("Program Start");
await TranslateString();
static async Task TranslateString()
{
string route = "translate?api-version=3.0&from=en&to=fr&to=zu";
string xmlString = "Hello , welcome";
try
{
object[] body = new object[] { new { Text = xmlString } };
var requestBody = JsonSerializer.Serialize(body);
using (var client = new HttpClient())
using (var request = new HttpRequestMessage())
{
request.Method = HttpMethod.Post;
request.RequestUri = new Uri(endpoint + route);
request.Content = new StringContent(requestBody, Encoding.UTF8, "application/json");
request.Headers.Add("Ocp-Apim-Subscription-Key", subscriptionKey);
request.Headers.Add("Ocp-Apim-Subscription-Region", region);
HttpResponseMessage response = await client.SendAsync(request).ConfigureAwait(false);
if (response.IsSuccessStatusCode)
{
Console.WriteLine("Success , translated text:");
string result = await response.Content.ReadAsStringAsync();
Console.WriteLine(result);
}
else
{
Console.WriteLine("Error: " + response.StatusCode + " " + response.ReasonPhrase);
}
}
}
catch (Exception ex)
{
Console.WriteLine("Error:" + ex.Message);
}
}
The output is:
Program Start
Success , translated text:
[{"translations":[{"text":"Bonjour , bienvenue","to":"fr"},{"text":"Sawu , wamukelekile","to":"zu"}]}]
You will need to add deserializing the output.
I am trying to display the URL of the selected image to be uploaded. However, when I run the program it tells me Newtonsoft.Json.JsonReaderException: Unexpected character encountered while parsing value: h. Path '', line 0, position 0. and that there is an issue with the parsing in the deserialization. However, I do not see any issues with the deserialization. Am I not seeing something that is causing this? The web api returns the AbsoluteUri for my file that has been uploaded which I made it into a string... so it returns var absoluteUrl = blob.Uri.AbsoluteUri.ToString();.
private async Task<HttpResponseMessage> UploadFileSelected()
{
// Create the content
var content = new MultipartFormDataContent();
content.Headers.ContentDisposition = new ContentDispositionHeaderValue("form-data");
content.Add(new StreamContent(fileStream, Convert.ToInt32(fileStream.Length)), "file", fileName);
string url = "https://localhost:5011";
var response = await _httpClient.PostAsync($"{url}/api/fileupload", content);
response.EnsureSuccessStatusCode();
var responseContent = await response.Content.ReadAsStringAsync();
var result = JsonConvert.DeserializeObject<HttpResponseMessage>(responseContent);
message = "Uploaded!!";
fileurl = responseContent;
Console.Write("result: " + result);
Console.WriteLine("url: " + fileurl);
return await Task.FromResult(result);
}
Endpoint:
[HttpPost]
public async Task<IActionResult> Upload()
{
try
{
var formCollection = await Request.ReadFormAsync();
var file = formCollection.Files.First();
if (file.Length > 0)
{
var container = new BlobContainerClient(_azureConnectionString, "container");
var createResponse = await container.CreateIfNotExistsAsync();
if (createResponse != null && createResponse.GetRawResponse().Status == 201)
await container.SetAccessPolicyAsync(PublicAccessType.Blob);
var blob = container.GetBlobClient(file.FileName);
await blob.DeleteIfExistsAsync(DeleteSnapshotsOption.IncludeSnapshots);
using (var fileStream = file.OpenReadStream())
{
await blob.UploadAsync(fileStream, new BlobHttpHeaders { ContentType = file.ContentType });
}
var absoluteUrl = blob.Uri.AbsoluteUri.ToString();
Console.WriteLine(absoluteUrl);
return Ok(absoluteUrl);
}
return BadRequest();
}
catch (Exception ex)
{
return StatusCode(500, $"Internal server error: {ex}");
}
}
I have a function in a c# console application, which calls an async function (My aim is to call an azure function via a console application. This function is responsible for converting zip files to csv files and of course I would like to process the zip file in parallel)
Here you can find a section of my code:
Parallel.ForEach(blobs, (currentblob) =>
{
string FileUrl = currentblob.Uri.ToString();
string FileName = currentblob.Uri.Segments.Last();
//string content = "{ \"fileUri\": \""+ currentblob.Uri.ToString()+ "\" , \"fileName\": \""+ currentblob.Uri.Segments.Last()+"\"}";
Console.WriteLine(currentblob.Uri + " #### " + currentblob.Uri.Segments.Last());
var values = new Dictionary<string, string>
{
{ "fileUri", currentblob.Uri.ToString() },
{ "fileName", currentblob.Uri.Segments.Last() }
};
var content = new FormUrlEncodedContent(values);
string baseURL = #"https://<afu>.azurewebsites.net/api/process_zip_files_by_http_trigger?code=45"; ;
//string urlToInvoke = string.Format("{0}&name={1}", baseURL, FileUrl, FileName);
Run(baseURL, content);
});
And I have an async function:
public static async void Run(string i_URL,FormUrlEncodedContent content)
{
HttpClient client = new HttpClient();
HttpResponseMessage response = await client.PostAsync(i_URL,content);
string responseString = await response.Content.ReadAsStringAsync();
Console.WriteLine(responseString);
Console.ReadLine();
}
I can run my code without any errors, but it doesn't process zip files. But after I stop debugging then I it starts to process the files!!!
I think something is wrong with my async function. Do you have any idea why my code doesn’t work correctly? Do I call my async function correctly?
First, your calling an async void method, these methods provide no way of signalling completion and are only intended for event handlers. Second, to process async methods in parallel you use Task.WhenAll with a Select instead of Parallel.ForEach. Parallel.ForEach is only intended for CPU bound operations and not asynchronous tasks. Finally, you should then use async all the way up to the root of your application and await all results, this will keep your process alive until all your blobs have been handled.
class Program
{
private static HttpClient client = new HttpClient();
static async Task Main(string[] args)
{
var blobs = new List<Blob>();
await ProcessBlobs(blobs);
Console.ReadLine();
}
public static async Task ProcessBlobs(IEnumerable<Blob> blobs)
{
var tasks = blobs.Select(currentblob =>
{
string FileUrl = currentblob.Uri.ToString();
string FileName = currentblob.Uri.Segments.Last();
//string content = "{ \"fileUri\": \""+ currentblob.Uri.ToString()+ "\" , \"fileName\": \""+ currentblob.Uri.Segments.Last()+"\"}";
Console.WriteLine(currentblob.Uri + " #### " + currentblob.Uri.Segments.Last());
var values = new Dictionary<string, string>
{
{ "fileUri", currentblob.Uri.ToString() },
{ "fileName", currentblob.Uri.Segments.Last() }
};
var content = new FormUrlEncodedContent(values);
string baseURL = #"https://<afu>.azurewebsites.net/api/process_zip_files_by_http_trigger?code=45"; ;
//string urlToInvoke = string.Format("{0}&name={1}", baseURL, FileUrl, FileName);
return RunAsync(baseURL, content);
});
await Task.WhenAll(tasks);
}
public static async Task RunAsync(string i_URL, FormUrlEncodedContent content)
{
var response = await client.PostAsync(i_URL, content);
var responseString = await response.Content.ReadAsStringAsync();
Console.WriteLine(responseString);
}
}
I design a login form in xamarin Form PCL and I want to call a my webservice that will return JSON. For this, I created two functions for the same but both are n is not returning values.
Can you please tell me what I am doing wrong?
async void OnLoginButtonClick(object sender, EventArgs e)
{
if (usernameEntry.Text != "" && passwordEntry.Text != "")
{
var response = GetLoginDetails(usernameEntry.Text,passwordEntry.Text);
var getData = await getDataFromService(usernameEntry.Text, passwordEntry.Text);
}
}
public static async Task<HttpResponseMessage> GetLoginDetails(string username, string password)
{
try
{
var httpClient = new HttpClient();
HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, "http://mywebserverIP/api/Users?Username=" + username + "&Password=" + password);
var response = await httpClient.SendAsync(request);
return response;
}
catch (Exception ex)
{
throw;
}
}
public static async Task<dynamic> getDataFromService(string username, string password)
{
using (var client = new HttpClient())
{
var responseText = await client.GetStringAsync("http://mywebserverIP/api/Users?Username=" + username + "&Password=" + password);
dynamic data = JsonConvert.DeserializeObject(responseText);
return data;
}
}
Thanks for your comment in Advance.
As you not awaiting the first method , request thread will not wait till it returns the value so , 1st change you have to make is to
var response = await GetLoginDetails()
For the second method
var getData = await getDataFromService()
I do not see any issue. I am not sure how you know that this method is not returning any values. Better to log the response of the both the method call and check.
Use await.
First in the
var response = await GetLoginDetails(...
then maybe in the deserializeobject method too (this one i'm not sure)
dynamic data = await Task.Run(() => JsonConvert.DeserializeObject(responseText));
I am calling the following function to get access token for retrieving Twitter user profile using REST Api.
public async Task<string> GetAccessToken()
{
try
{
var httpClient = new HttpClient();
var request = new HttpRequestMessage(HttpMethod.Post, "https://api.twitter.com/oauth2/token ");
var customerInfo = Convert.ToBase64String(new UTF8Encoding().GetBytes(OAuthConsumerKey + ":" + OAuthConsumerSecret));
request.Headers.Add("Authorization", "Basic " + customerInfo);
request.Content = new StringContent("grant_type=client_credentials", Encoding.UTF8, "application/x-www-form-urlencoded");
//program exits at this point
HttpResponseMessage response = await httpClient.SendAsync(request).ConfigureAwait(false);
string json = await response.Content.ReadAsStringAsync();
var serializer = new JavaScriptSerializer();
dynamic item = serializer.Deserialize<object>(json);
return item["access_token"];
}
catch (Exception ex)
{
MessageBox.Show("In Retrieving access token : " + ex.ToString());
}
}
The program exits/terminates without retrieving a response at the point HttpResponseMessage response = await httpClient.SendAsync(request).ConfigureAwait(false); is called.
This is the parent function which calls GetAccessToken()
public async Task getUserProfile(string userName)
{
try
{
if (accessToken == null)
{
accessToken = await GetAccessToken().ConfigureAwait(false);
}
var request = new HttpRequestMessage(HttpMethod.Get, string.Format(" https://api.twitter.com/1.1/users/show.json?screen_name={0}", userName));
request.Headers.Add("Authorization", "Bearer " + accessToken);
var httpClient = new HttpClient();
HttpResponseMessage response = await httpClient.SendAsync(request).ConfigureAwait(false);
var jsonString = await response.Content.ReadAsStringAsync();
var serializer = new JavaScriptSerializer();
dynamic jsonObj = serializer.Deserialize<object>(jsonString);
}
catch (Exception ex)
{
if (DEBUG)
{
MessageBox.Show("In Retrieving user profile from twitter : " + ex.ToString());
}
}
}
I am unable to catch an exception as to why the program exits at GetAccessToken() or getUserProfile(). But the code executes successfully and retrieves an HttpResponseMessage if getUserProfile() has Task<IEnumerable<string>> as return type. Why does this problem occur? How can the exception be caught?
Your application exits permaturely because you are not waiting for getUserProfile() to be completed. You can mark getTwitterInfo as async similar to the others or tell it to wait for the task to finish
public async Task getTwitterInfo() {
var twitter = new Twitter("consumerKey","consumerSecret");
await twitter.getUserProfile(userName);
}
OR
public void getTwitterInfo() {
var twitter = new Twitter("consumerKey","consumerSecret");
var task = twitter.getUserProfile(userName);
var result = task.WaitAndUnwrapException();
}
Have you tried
HttpResponseMessage response = httpClient.SendAsync(request).Result;
I have the same problem in my own code and this seems to have fixed it, should be equivalent to the original call. I still don't understand the root cause of the crash, though.