HttpClient.SendAsync method exits without throwing exception - c#

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.

Related

How to have an API call working? Currently my call to client is not working

I have an API in .net 5 that runs locally. One of the endpoints is https://localhost:44362/User
Now, I created a console app that will consume the API and defined a method to call the get User.
public async Task<bool> CallAPI()
{
using (var client = new HttpClient())
{
client.BaseAddress = new Uri("http://localhost:44362/");
using (HttpResponseMessage response = await client.GetAsync("User"))
{
var resContent = response.Content.ReadAsStringAsync().Result;
return true;
}
}
}
Here is the code in the API
[HttpGet]
public IEnumerable<User> Get()
{
using (var context = new ohabartContext())
{
return context.Users.ToList();
}
}
But when the code using (HttpResponseMessage response = await client.GetAsync("User")) is executed nothing happens. I don't receive any error or whatsoever. I search the net and all other codes look the same in consuming or calling an API.
What seems to be the problem?
ReadAsStringAsync() Serialize the HTTP content to a string as an asynchronous operation. This operation will not block. The returned Task object will complete after all of the content has been written as a string.
HttpResponseMessage response= await client.GetAsync(u);
var resContent = await response.Content.ReadAsStringAsync().Result;
Once the operation completes, the Result property on the returned task object contains the string with the HTTP content.
public async Task<bool> CallAPI()
{
try
{
using (var client = new HttpClient())
{
client.BaseAddress = new Uri("http://localhost:44362/");
HttpResponseMessage response = await client.GetAsync(u);
var resContent = awit response.Content.ReadAsStringAsync().Result;
return true;
}
}
catch (HttpRequestException e)
{
Console.WriteLine("\nException Caught!");
Console.WriteLine("Message :{0} " , e.Message);
return false;
}
}
https://learn.microsoft.com/en-us/dotnet/api/system.net.http.httpclient?view=net-6.0
https://learn.microsoft.com/en-us/dotnet/api/system.net.http.httpclient.getasync?view=net-6.0

httpClient Does not give Response

i am trying to call the Zoom Api for Access token. It work Perfectly fine when i am trying to post with postman .
but from code it does not respond
ZoomApiLink_StepNo2
below are the following details
public static async Task<String> PostTogetToken<T>(string requestUrl, string client_Secretkey) {
ZoomToken hello = new ZoomToken();
var EncodedURl = ApiService.Base64Encode(client_Secretkey);
using (var _httpClient = new HttpClient()) {
if (!string.IsNullOrEmpty(requestUrl))
_httpClient.DefaultRequestHeaders.TryAddWithoutValidation("Authorization", "Basic " + EncodedURl);
var httpContent = new StringContent("", System.Text.Encoding.UTF8, "application/x-www-form-urlencoded");
var httpRequestMessage = new HttpRequestMessage(HttpMethod.Post, new Uri(requestUrl)) {
Version = HttpVersion.Version11,
Content = httpContent
};
using (var response = await _httpClient.SendAsync(httpRequestMessage)) {
if (response.IsSuccessStatusCode) {
response.EnsureSuccessStatusCode();
return await response.Content.ReadAsStringAsync();
} else {
return await response.Content.ReadAsStringAsync();
}
}
}
}
You're seeing a common deadlock problem because code further up the stack is using Result, blocking on asynchronous code.
To fix, change the Result to await and use async all the way.

Getting Bad Request when requesting JWT in web API from Xamarin Forms

So I made a web API that authenticates with JSON Web Tokens, however, I haven't been able to authenticate using the HttpClient from my xamarin forms application. The odd thing is that I can connect without any problem on a console application that I made for testing, and both the console application and the xamarin forms app use almost exactly the same code.
The code in the console app is like this:
public static async Task<AutenticacionModel> PostCredentialsAsync(string UserName, string Password)
{
HttpClient cliente = new HttpClient();
cliente.BaseAddress = new Uri("http://172.25.1.53:9891");
HttpResponseMessage response = new HttpResponseMessage();
string _result = String.Empty;
try
{
string Path = cliente.BaseAddress + "oauth/secreto";
HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, Path);
string autenticacion = "username=" + UserName + "&password=" + Password + "&grant_type=password";
request.Content = new StringContent(autenticacion, Encoding.UTF8, "application/x-www-form-urlencoded");
response = await cliente.SendAsync(request);
response.EnsureSuccessStatusCode();
_result = await response.Content.ReadAsStringAsync();
}
catch (Exception ex)
{
// something to do
}
return response.Content != null ? JsonConvert.DeserializeObject<AutenticacionModel>(_result) : new AutenticacionModel();
}
And the code in the Xamarin Forms:
public async Task<AutenticacionDTO> GetUsuario(string email, string clave)
{
string JSONAutenticacion;
HttpResponseMessage response = new HttpResponseMessage();
try
{
var client = new HttpClient();
client.BaseAddress = new Uri(GlobalSetting.UrlWebApi);
string Path = client.BaseAddress + "oauth/secreto";
HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, Path);
string autenticacion = "username=" + email + "&password=" + clave + "&grant_type=password";
request.Content = new StringContent(autenticacion, Encoding.UTF8, "application/x-www-form-urlencoded");
response = await client.SendAsync(request);
response.EnsureSuccessStatusCode();
JSONAutenticacion = await response.Content.ReadAsStringAsync();
}
catch (Exception ex)
{
string sss = ex.ToString();
return null;
}
return response.Content != null ? JsonConvert.DeserializeObject<AutenticacionDTO>(JSONAutenticacion) : new AutenticacionDTO();
}
When I use postman to connect to the web API that I have hosted in my local IIS, there's no problem, same with the console application. But whenever I try to connect with the Xamarin Forms App I get a 400 Bad Request response.
The code that makes the Jwt work goes like this:
public override async Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context)
{
var allowedOrigin = "*";
context.Response.Headers.Add("Access-Control-Allow-Origin", new[] { allowedOrigin });
Seguridad _Seguridad = new fovissste.bll.Seguridad();
LoginDTO Usuario = _Seguridad.Login(context.UserName, context.Password).FirstOrDefault();
if (Usuario == null)
{
context.SetError("invalid_grant", "Usuario o contraseƱa incorrectos");
return;
}
ClaimsIdentity oauthIdentity = new ClaimsIdentity(new ApplicationUser(context.UserName, "JWT"), new[] { new Claim(ClaimTypes.Role, "Publico") });
var ticket = await Task.Run(() => new AuthenticationTicket(oauthIdentity, null));
context.Validated(ticket);
}
Can anybody help? Is this an issue with Xamarin Forms? I truly require some comments because I honestly can't see what I'm missing. I've read other posts in this site that suggest that it can be an issue of enabling remote requests on IIS or a CORS issue but I think that's handled in this line: context.Response.Headers.Add("Access-Control-Allow-Origin", new[] { allowedOrigin });
Try the following code:
using (var client = new HttpClient())
{
client.BaseAddress = new Uri("http://172.25.1.53:9891");
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
string autenticacion = "?username=" + email + "&password=" + clave + "&grant_type=password";
HttpResponseMessage response = await client.PostAsync(client.BaseAddress + "oauth/secreto", new StringContent(autenticacion, Encoding.UTF8, "application/x-www-form-urlencoded"));
response.EnsureSuccessStatusCode();
string JSONAutenticacion = await response.Content.ReadAsStringAsync();
}
What is the value of Path after this line?
string Path = client.BaseAddress + "oauth/secreto";
Also try to add this line before using (var client... :
System.Net.ServicePointManager.ServerCertificateValidationCallback += (sender, certificate, chain, sslPolicyErrors) => true;
Edit
Changed
HttpResponseMessage response = await client.PostAsync(client.BaseAddress + autenticacion, new StringContent(autenticacion));
to
HttpResponseMessage response = await client.PostAsync(client.BaseAddress + "oauth/secreto", new StringContent(autenticacion, Encoding.UTF8, "application/x-www-form-urlencoded"));

Quickbooks Online sandbox returns Waiting for Activation, i have realmId, accesstoken aswell

My Code is as follow:-
i have no idea why i am receiving this message, please help. Right now
i am using sandbox account to test this. I have generated the data i.e. sample data from API explorer and i am passing it as a parameter as Json.
public bool GeneratePayment(string JsonData)
{
var principal = User as ClaimsPrincipal;
Session["realmId"] = "XXXXXX";
if (Session["realmId"] != null)
{
string realmId = Session["realmId"].ToString();
string qboBaseUrl = ConfigurationManager.AppSettings["QBOBaseUrl"];
//add qbobase url and query
string uri = string.Format("{0}/v3/company/{1}/invoice", qboBaseUrl, realmId);
try
{
var client = new HttpClient();
client.DefaultRequestHeaders.Add("Accept", "application/json;charset=UTF-8");
client.DefaultRequestHeaders.Add("ContentType", "application/json;charset=UTF-8");
client.DefaultRequestHeaders.Add("Authorization", "Bearer " + "XXXX");
//Here i am getting waiting for activation
var result = client.PostAsync(uri, new StringContent(JsonData, System.Text.Encoding.UTF8, "application/json"));
return true;
}
catch (Exception ex)
{
return false;
}
}
else
return false;
}
Has to do with the Task associated with PostAsync.
The GeneratePayment method needs to be made async and client.PostAsync needs to be awaited as well
public async Task<bool> GeneratePayment(string JsonData) {
var principal = User as ClaimsPrincipal;
Session["realmId"] = "XXXXXX";
if (Session["realmId"] != null) {
string realmId = Session["realmId"].ToString();
string qboBaseUrl = ConfigurationManager.AppSettings["QBOBaseUrl"];
//add qbobase url and query
string uri = string.Format("{0}/v3/company/{1}/invoice", qboBaseUrl, realmId);
try {
var client = http.Value; //singleton http client
var result = await client.PostAsync(uri, new StringContent(JsonData, System.Text.Encoding.UTF8, "application/json"));
return true;
} catch (Exception ex) {
return false;
}
}
else
return false;
}
//Singleton lazy loaded HttpClieny
static Lazy<HttpClient> http = new Lazy<HttpClient>(() => {
var client = new HttpClient();
client.DefaultRequestHeaders.Add("Accept", "application/json;charset=UTF-8");
client.DefaultRequestHeaders.Add("ContentType", "application/json;charset=UTF-8");
client.DefaultRequestHeaders.Add("Authorization", "Bearer " + "XXXX");
return client;
});

call REST API in xamarin

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));

Categories