Client calling WebAPI stuck in await - c#

I have a httpclient that is calling a WebAPI service. The GET reaches the service and returns the content but the client just keeps waiting...
Client code:
static async Task RunAsyncGet(string baseUri, string uri)
{
using (var client = new HttpClient())
{
client.BaseAddress = new Uri(baseUri);
HttpResponseMessage response = await client.GetAsync(uri); // <-- stuck here
response.EnsureSuccessStatusCode();
if (response.IsSuccessStatusCode)
{
IEnumerable<UserAccountModel> users = await response.Content.ReadAsAsync<IEnumerable<UserAccountModel>>();
//...
}
}
}
WebAPI code:
public class UserAccountController : ApiController
{
private IRepository _repo;
public UserAccountController(IRepository repo)
{
_repo = repo;
}
public HttpResponseMessage Get()
{
var s = _repo.GetAllUserAccounts();
IContentNegotiator negotiator = Configuration.Services.GetContentNegotiator();
ContentNegotiationResult result = negotiator.Negotiate(typeof(AuthResponseModel), Request, Configuration.Formatters);
var bestMatchFormatter = result.Formatter;
var mediaType = result.MediaType.MediaType;
return new HttpResponseMessage()
{
StatusCode = HttpStatusCode.OK,
Content = new ObjectContent<IQueryable<UserAccount>>(s, bestMatchFormatter, mediaType)
};
}
}
Thoughts?

Further up in your client code (whatever ends up calling RunAsyncGet), some code is calling Task.Wait or Task<T>.Result. That will cause a deadlock if called from the UI thread, as I explain on my blog.
The proper solution is to change that Wait/Result to use await.

This is how I ended up calling the WebAPI:
using (HttpClient client = new HttpClient())
{
client.BaseAddress = new Uri("http://localhost:23302");
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
HttpResponseMessage response = client.GetAsync("api/useraccount").Result;
if (response.IsSuccessStatusCode)
{
var t = response.Content.ReadAsAsync<IEnumerable<UserAccount>>().Result;
...
}
else
{
//Something has gone wrong, handle it here
}
}

It seems that your call to EnsureSuccessStatusCode is the likely culprit. That method actually returns a HttpResponseMessage that will have a HTTP status in the 200 range, or will throw an exception. So, you probably want something like:
static async Task RunAsyncGet(string baseUri, string uri)
{
var client = new HttpClient();
client.BaseAddress = new Uri(baseUri);
HttpResponseMessage response = await client.GetAsync(uri);
IEnumerable<UserAccountModel> users = await response.EnsureSuccessStatusCode().Content.ReadAsAsync<IEnumerable<UserAccountModel>>();
// ... the rest ...
}

Related

How would i send a payload with my post request in c#?

I am trying to login to a website and i need to send the credentials as a payload but I don't understand how payloads are sent.
public class LoginClient
{
private readonly HttpClient _client;
public LoginClient()
{
_client = new HttpClient();
}
public async Task Put()
{
using (var request = new HttpRequestMessage(HttpMethod.Post, $"https://accounts.nike.com/challenge/password/v1"))
{
using (var response = await _client.SendAsync(request))
{
}
}
}
}
You are trying to send Json, use PostAsync to set the content
var client = new HttpClient();
var url = $"https://accounts.nike.com/challenge/password/v1";
var data = new System.Net.Http.StringContent(json, Encoding.UTF8, "application/json");
var response = await client.PostAsync(url, data);

How to get a list of households registered to an account with c# and sonos api?

This is my method
static public async Task<string> Get(string token, string url)
{
HttpClient httpclient = new HttpClient();
using (HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, url))
{
request.Headers.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", token);
request.Headers.Host = "api.ws.sonos.com";
var response = await httpclient.SendAsync(request);
response.EnsureSuccessStatusCode();
return await response.Content.ReadAsStringAsync();
}
}
and this is how I call it in my main
namespace ApiTest
{
internal class Program
{
static void Main(string[] args)
{
Console.WriteLine(ApiConnect.Get("My Access Token", "https://api.ws.sonos.com/control/api/v3/households").Result);
I'm try to get the list of households registered to my account but I get a 404 error.
You are not sending your client key or setting the content type to json.

Http Get Request not getting any data

I have my Web Api on a production server online and working well in postman and in Xamarin forms so far until I needed to do a Get Request and does not return any data. Infact it stops at the GetAsStringAsync line and does not continue. Instead, it jumps out of the method and then nothing more.
Does any one know what the problem could be? I have checked and made sure my Internet is working and the Uri too.
This is where I am doing my Get in Xamarin forms:
public async Task<List<OfferModel>> AllOffers()
{
var httpclient = new HttpClient();
httpclient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("bearer", Settings.AccessToken);
//it does not continue after this line, it jumps out of the method instead
var response = await httpclient.GetStringAsync(UrlConstants.offerurl);
var data =JsonConvert.DeserializeObject<List<OfferModel(response);
return data;
}
Solution 1
Can you try access task via awaiter it may be wait until result when responded
public class HttpHelperService
{
public async Task<List<OfferModel>> AllOffers()
{
List<OfferModel> result;
string responseBody;
using (HttpClient client = new HttpClient())
{
try
{
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("bearer", Settings.AccessToken);
HttpResponseMessage response = client.GetStringAsync(new Uri(UrlConstants.offerurl)).GetAwaiter().GetResult();
result = JsonConvert.DeserializeObject<List<OfferModel>>(response);
}
catch (Exception ex)
{
result = null;
}
return result;
}
}
}
Solution 2
public class MyPage : ContentPage
{
//Here is your page constructor
public MyPage()
{
GetServices(); //--> call here without awaiter
}
}
//Here is your awaiter method
private async void GetServices()
{
LoadingPopupService.Show();
var result = await HttpService.AllOffers();
LoadingPopupService.Hide();
}
//Here is your service.
public async Task<List<OfferModel>> AllOffers()
{
var httpclient = new HttpClient();
httpclient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("bearer", Settings.AccessToken);
var response = await httpclient.GetStringAsync(UrlConstants.offerurl);
var data =JsonConvert.DeserializeObject<List<OfferModel(response);
return data;
}

Async call with HttpClient in PCL

I have a PCl in which I want to make a async call usingg HttpClient. I coded like this
public static async Task<string> GetRequest(string url)
{
var httpClient = new HttpClient() { MaxResponseContentBufferSize = int.MaxValue };
HttpResponseMessage response = await httpClient.GetAsync(url);
return response.Content.ReadAsStringAsync().Result;
}
But await is showing error "cannot await System.net.http.httpresponsemessage" like message.
If I use code like this than everything goes well but not in async way
public static string GetRequest(string url)
{
var httpClient = new HttpClient() { MaxResponseContentBufferSize = int.MaxValue };
HttpResponseMessage response = httpClient.GetAsync(url).Result;
return response.Content.ReadAsStringAsync().Result;
}
I just want that this method executes in async way.
This is the screen shot:
Follow the TAP guidelines, don't forget to call EnsureSuccessStatusCode, dispose your resources, and replace all Results with awaits:
public static async Task<string> GetRequestAsync(string url)
{
using (var httpClient = new HttpClient() { MaxResponseContentBufferSize = int.MaxValue })
{
HttpResponseMessage response = await httpClient.GetAsync(url);
response.EnsureSuccessStatusCode();
return await response.Content.ReadAsStringAsync();
}
}
If your code doesn't need to do anything else, HttpClient has a GetStringAsync method that does this for you:
public static async Task<string> GetRequestAsync(string url)
{
using (var httpClient = new HttpClient() { MaxResponseContentBufferSize = int.MaxValue })
return await httpClient.GetStringAsync(url);
}
If you share your HttpClient instances, this can simplify to:
private static readonly HttpClient httpClient =
new HttpClient() { MaxResponseContentBufferSize = int.MaxValue };
public static Task<string> GetRequestAsync(string url)
{
return httpClient.GetStringAsync(url);
}
If you are using a PCL platform that supports .net4 then I suspect you need to install the Microsoft.bcl.Async nuget.

Get data from WebApi in c#

I have webapi and her method:
[HttpPost, HttpGet]
[ActionName("GetData")]
public MyData GetData([FromUri] MyData data)
{
return datamanager.get(data);
}
How do I invoke this method? I.e. how do I send data parameter through query part of URL?
To invoke get method which takes no parameters I use following code:
public static async Task<myClassl> GetData()
{
HttpClient client = new HttpClient();
client.BaseAddress = new Uri("http://sasa.com");
HttpResponseMessage response = await client.GetAsync("api/GetData");
myClassl data = await response.Content.ReadAsAsync<myClassl>();
return data ;
}
Thanks.
Try the following solution:
HttpClient client = new HttpClient();
string baseApiAddress = ConfigurationManager.AppSettings["baseApiAddress"];
client.BaseAddress = new Uri(baseApiAddress);
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
HttpResponseMessage response=client.GetAsync("/api/GetData",data, new JsonMediaTypeFormatter()).Result;
if (response.IsSuccessStatusCode)
{
var mydata = response.Content.ReadAsAsync<MyData>().Result;
}
else
{
Debug.WriteLine(response.ReasonPhrase);
}

Categories

Resources