This is the first time i've tried making a call to an API and I'm struggling a little. I keep getting back my error message, I plan on using the json response to populate my object. The OMDB api instructions are here (not helpful though): http://www.omdbapi.com/
private static async Task RunAsync()
{
using (var client = new HttpClient())
{
client.BaseAddress = new Uri("http://www.omdbapi.com/?");
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
HttpResponseMessage response = client.GetAsync("t=Captain+Phillips&r=json").Result;
if (response.IsSuccessStatusCode)
{
Console.WriteLine("Success");
}
else
{
Console.WriteLine("Error with feed");
}
}
}
You have placed the question mark (?) on the wrong place. Try like this:
private static async Task RunAsync()
{
using (var client = new HttpClient())
{
client.BaseAddress = new Uri("http://www.omdbapi.com");
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
HttpResponseMessage response = await client.GetAsync("?t=Captain+Phillips&r=json");
if (response.IsSuccessStatusCode)
{
Console.WriteLine("Success");
}
else
{
Console.WriteLine("Error with feed");
}
}
}
Notice that the question mark is here:
HttpResponseMessage response = await client.GetAsync("?t=Captain+Phillips&r=json");
and not on the base url as you placed it.
Also in order to properly write your asynchronous method you need to await on it inside and not be eagerly calling the .Result property which of course is a blocking operation.
Related
I am getting this error when I call add "await" keyword and getting output when I remove "await" keyword
Code:
public class ApiHelper : IApiHelper
{
private const int APiRetryCount = 4;
private static HttpClient client = new HttpClient();
public async Task<string> PostAsync<T>(T payload, string apiEndpoint)
{
for (int i = 0; i < APiRetryCount; i++)
{
client.DefaultRequestHeaders.Accept.Clear();
client.BaseAddress = new Uri("http://app-et-csswrapperapi-dev.azurewebsites.net/");
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
client.DefaultRequestHeaders.TryAddWithoutValidation("Authorization", "Bearer " + token.AccessToken);
var content = new StringContent(JsonConvert.SerializeObject(payload), Encoding.UTF8, "application/json");
var response = **await** client.PostAsync(apiEndpoint, content);
}
// if we got here, we have maxed out retry count and got transient failures or are not authorized
// log warning
return default(string);
}
}
I am getting exception:
Sys.WebForms.PageRequestManagerTimeoutException: Sys.WebForms.PageRequestManagerTimeoutException: The server request timed out
But when I replace the line
var response = **await** client.PostAsync(apiEndpoint, content);
with below code, its working fine:
var response = client.PostAsync(apiEndpoint, content).Result;
My doubt is what its making a big difference between await and .Result() ??
There is nothing wrong with your code. This is the way to go var response = await client.PostAsync(apiEndpoint, content);. I suspect you are running into a deadlock in the code outside the method PostAsync. Make sure you use await when you call it: await PostAsync<SomeClass>(instance,"/api/endpoint"); and that you use async/await all the way up to the controller.
Edit: you can check this answer too: https://stackoverflow.com/a/15022170/1817574
I am facing an issue regarding not getting response from GetAsync API of HttpClient in MVC Applications(Target Framework - .Net Framework 4.7) whereas getting response in web services and console applications with same snippet. Here I have attached code snippet which I am trying to execute.
public void Get()
{
var response = Gettasks().Result;
}
public static async Task<HttpResponseMessage> GetTasks()
{
var response = new HttpResponseMessage();
try
{
using (var client = new HttpClient())
{
response = await client.GetAsync("https://www.google.com");
}
}
catch (Exception exception)
{
Console.WriteLine(exception.Message);
}
return response;
}
I am getting stuck on response = await client.GetAsync("https://www.google.com"); this line and not getting any response after executing this statement.
If anyone can please suggest solution for this or provide fix/solution which works for you.
You're seeing a deadlock because the code is blocking on an asynchronous method.
The best fix is to remove the blocking:
public async Task Get()
{
var response = await Gettasks();
}
This deadlock happens because await captures a context, and ASP.NET (pre-Core) has a context that only allows one thread at a time, and the code blocks a thread (.Result) in that context, which prevents GetTasks from completing.
Both the context and the blocking are necessary to see this kind of deadlock. In the other scenarios, there is no context, so that is why the deadlock does not occur. Since ASP.NET (pre-Core) has a context, the proper solution here is to remove the blocking.
Not sure whether you have tried following which is working for me.
using (HttpClient client = new HttpClient())
{
client.BaseAddress = new Uri(Environment.GetEnvironmentVariable("BaseAddress"));
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
var requestUri = Environment.GetEnvironmentVariable("Uri");
HttpResponseMessage response = await client.GetAsync(requestUri);
if (response.IsSuccessStatusCode)
{
var data = await response.Content.ReadAsStringAsync();
}
}
I'm trying to get a response from a HTTP request but i seem to be unable to. I have tried the following:
public Form1() {
HttpClient client = new HttpClient();
client.BaseAddress = new Uri("someUrl");
string content = "someJsonString";
HttpRequestMessage sendRequest = new HttpRequestMessage(HttpMethod.Post, client.BaseAddress);
sendRequest.Content = new StringContent(content,
Encoding.UTF8,
"application/json");
Send message with:
...
client.SendAsync(sendRequest).ContinueWith(responseTask =>
{
Console.WriteLine("Response: {0}", responseTask.Result);
});
} // end public Form1()
With this code, i get back the status code and some header info, but i do not get back the response itself. I have tried also:
HttpResponseMessage response = await client.SendAsync(sendRequest);
but I'm then told to create a async method like the following to make it work
private async Task<string> send(HttpClient client, HttpRequestMessage msg)
{
HttpResponseMessage response = await client.SendAsync(msg);
string rep = await response.Content.ReadAsStringAsync();
}
Is this the preferred way to send a 'HttpRequest', obtain and print the response? I'm unsure what method is the right one.
here is a way to use HttpClient, and this should read the response of the request, in case the request return status 200, (the request is not BadRequest or NotAuthorized)
string url = 'your url here';
// usually you create on HttpClient per Application (it is the best practice)
HttpClient client = new HttpClient();
using (HttpResponseMessage response = client.GetAsync(url).GetAwaiter().GetResult())
{
using (HttpContent content = response.Content)
{
var json = content.ReadAsStringAsync().GetAwaiter().GetResult();
}
}
and for full details and to see how to use async/await with HttpClient you could read the details of this answer
I have a functioning async Task that calls a web service:
private async Task GetResult()
{
using (var client = new HttpClient())
{
client.BaseAddress = new Uri(_baseAddress);
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(
new MediaTypeWithQualityHeaderValue("application/json"));
client.DefaultRequestHeaders.Add("Username", _username);
client.DefaultRequestHeaders.Add("Action", "GET");
/* etc */
var response = await client.GetAsync(client.BaseAddress);
}
}
I would like to separate out the creation of the HttpClient object so it can be parameterized and reused:
private async Task GetResult()
{
using (var client = GetClient(_baseAddress, _username))
{
var response = await client.GetAsync(client.BaseAddress);
}
}
private static HttpClient GetClient(string Address, string Username)
{
using (var client = new HttpClient())
{
client.BaseAddress = new Uri(Address);
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(
new MediaTypeWithQualityHeaderValue("application/json"));
client.DefaultRequestHeaders.Add("Username", Username);
client.DefaultRequestHeaders.Add("Action", "GET");
/* etc */
return client;
}
}
While this appears functionally identical to me, the latter throws an AggregateException error with inner exception
Cannot Access a disposed object. Object name: 'System.Net.Http.HttpClient'.
Perhaps there is some async subtlety that I don't understand?
Get rid of the using inside of GetClient. You only use using for things that remain "in your ownership", you are "giving up ownership to the caller" when you return client;.
It is now the caller's resposability to use a using statement (which you do already correctly do in GetResult).
This has nothing to do with asnyc and is simply standard IDisposable behavior.
I am calling a test REST web service that basically takes a string as input, and echoes it back to the caller. I have the following code, in a C# console app:
static async Task RunAsync()
{
using (var client = new HttpClient())
{
string baseAddress =
"http://xxx.xxx.xxx.xxx/Services/OnyxCloudSyncService.svc/pingSync";
client.BaseAddress = new Uri(baseAddress);
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new
MediaTypeWithQualityHeaderValue("application/json"));
HttpResponseMessage response = await
client.GetAsync("?sampleJson={SAMPLEJSON}");
if (response.IsSuccessStatusCode)
{
string txtBlock = await response.Content.ReadAsStringAsync();
Console.WriteLine(txtBlock);
Console.ReadKey();
}
}
}
This code runs perfectly. But when I essentially copy the same code into the code-behind for an ASP.NET page, I timeout on the call to the service:
using (var SyncClient = new HttpClient())
{
string baseAddress = "http://xxx.xxx.xxx.xxx/Services/OnyxCloudSyncService.svc/pingSync";
SyncClient.DefaultRequestHeaders.Accept.Clear();
SyncClient.DefaultRequestHeaders.Accept.Add(new
MediaTypeWithQualityHeaderValue("application/json"));
HttpResponseMessage response = await
SyncClient.GetAsync("?sampleJson={SAMPLEJSON}");
if (response.IsSuccessStatusCode)
{
string txtBlock = await response.Content.ReadAsStringAsync();
Response.Write(txtBlock);
Response.End();
}
else
{
Response.Write("Error Calling service");
Response.End();
}
}
The error I get from this page is:
System.Net.Sockets.SocketException: A connection attempt failed because
the connected party did not properly respond after a period of time, or
established connection failed because connected host has failed to respond
xxx.xxx.xxx.xxx:80.
Would there be some type of setup or option I need to set on the WebClient to make it work in the ASP page like it does in the Console App? I am at a loss as to why this would work in a console app and not in an ASP.NET web page.
You might be having a problem because the result is not being waited for, the solution might be found on: http://www.hanselman.com/blog/TheMagicOfUsingAsynchronousMethodsInASPNET45PlusAnImportantGotcha.aspx
I assume you're using .NET 4.5.
Edit method to be instance, not static since you won't be able to reach Response object:
async Task RunAsync()
{
using (var client = new HttpClient())
{
string baseAddress =
"http://74.120.219.166/Services/OnyxCloudSyncService.svc/pingSync";
client.BaseAddress = new Uri(baseAddress);
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new
MediaTypeWithQualityHeaderValue("application/json"));
HttpResponseMessage response = await
client.GetAsync("?sampleJson={SAMPLEJSON}");
if (response.IsSuccessStatusCode)
{
string txtBlock = await response.Content.ReadAsStringAsync();
Response.Write(txtBlock);
Response.End();
}
else
{
Response.Write("Error Calling service");
Response.End();
}
}
}
Run method like: RegisterAsyncTask(new PageAsyncTask(RunAsync));
Put Async="true" in Page directive of your .aspx page.
I tried this approach and it worked as expected.