Accessing contents of HttpResponseMessage - c#

I'd like to print the contents of a HTTPResponseMessage.
class Requests
{
public static async Task SendRequest(int port, string path, KVPairs kvPairs)
{
using (var client = new HttpClient())
{
client.BaseAddress = new Uri(BASE_ADDRESS + port);
var request = new HttpRequestMessage(HttpMethod.Put, path);
request.Content = new FormUrlEncodedContent(kvPairs);
ProcessResponse(await client.SendAsync(request));
}
}
public static void ProcessResponse (HttpResponseMessage response)
{
Console.WriteLine(response.Content.ReadAsStringAsync());
}
}
SendRequest works perfectly. But ProcessResponse() prints System.Threading.Tasks.Task\`1[System.String]
How can I access and print the contents of the response? Thank you!

You need to await the task returned by response.Content.ReadAsStringAsync(), which in turn means you need to make ProcessResponse an async method, and await on that too. Otherwise, you are printing out the task object itself, which is not what you want.
Notice the 3 changes below (see comments):
public static async Task SendRequest(int port, string path, KVPairs kvPairs)
{
using (var client = new HttpClient())
{
client.BaseAddress = new Uri(BASE_ADDRESS + port);
var request = new HttpRequestMessage(HttpMethod.Put, path);
request.Content = new FormUrlEncodedContent(kvPairs);
await ProcessResponse(await client.SendAsync(request)); // added await here
}
}
public static async Task ProcessResponse (HttpResponseMessage response) // added async Task here
{
Console.WriteLine(await response.Content.ReadAsStringAsync()); // added await here
}

This solution should work for you. Deserialize JSON to Array or List with HTTPClient .ReadAsAsync using .NET 4.0 Task pattern
You should use await or wait() to get the response and then process it like this:
var jsonString = response.Content.ReadAsStringAsync();
jsonString.Wait();
model = JsonConvert.DeserializeObject<List<Job>>(jsonString.Result);

Related

Prepare controller and http request to preocess request without returning value

I have following method to get collection of cars:
public async Task<IEnumerable<Car>> GetCars(object car, CancellationToken ct)
{
var uri = new Uri($"{_webApiUrl}Car/GetCars");
using (var httpClient = new HttpClient())
{
HttpContent content = new StringContent(JsonConvert.SerializeObject(car), Encoding.UTF8, "application/json");
var req = await httpClient.PostAsync(uri, content, ct);
var response = await req.Content.ReadAsStringAsync();
return JsonConvert.DeserializeObject<IEnumerable<Car>>(response);
}
}
In my service api in controller i have this to get it:
[HttpPost]
[Route("api/[controller]/[action]")]
public IActionResult GetBottleTypeById(Car car)
{
return Ok(_carQuery.GetCars(car));
}
Both things works great - no issues.
Now i need to save the Car and i don't need to return something (eventually i could return true or false whether it was succesfull or not). The problem is i am not sure how controller's method should look like, if i do this way it says: not all code path returns value:
[HttpPost]
[Route("api/[controller]/[action]")]
public IActionResult UpdateOperation(Car car)
{
_carRepository.UpdateOperation(car) //UpdateOperation is void with try/catch - throw;
}
Same thing with request, how this should be accomplished?
public async Task UpdateCar(Car selectedCar, CancellationToken ct)
{
var uri = new Uri($"{_webApiUrl}Car/UpdateOperation");
using (var httpClient = new HttpClient())
{
HttpContent content = new StringContent(JsonConvert.SerializeObject(selectedCar), Encoding.UTF8, "application/json");
var req = await httpClient.PostAsync(uri, content, ct);
var response = await req.Content.ReadAsStringAsync();
return JsonConvert.DeserializeObject<IEnumerable<Car>>(response);
}
}
How could i prepare both things to make it work?
Just change your code to return void. ASP.NET is smart enough to just send 200 OK if no exceptions were thrown out of a void method.
[HttpPost]
[Route("api/[controller]/[action]")]
public void UpdateOperation(Car car)
{
_carRepository.UpdateOperation(car) //UpdateOperation is void with try/catch - throw;
}
To make your calling code work, you don't need to receive anything but the HTTP response message from the server. Even if your method returns void, HTTP servers still send a status code (200, 500, etc.) and some headers for you to inspect.
Try this:
public async Task UpdateCar(Car selectedCar, CancellationToken ct)
{
var uri = new Uri($"{_webApiUrl}Car/UpdateOperation");
using (var httpClient = new HttpClient())
{
HttpContent content = new StringContent(JsonConvert.SerializeObject(selectedCar), Encoding.UTF8, "application/json");
var response = await httpClient.PostAsync(uri, content, ct);
if (response.IsSuccessStatusCode)
{
return;
}
else
{
// handle error
}
}
}

HttpClient GetAsync with query string

I am using Google's GeoCoding API. I have two methods where one works and the other doesn't and I can't seem to figure out why:
string address = "1400,Copenhagen,DK";
string GoogleMapsAPIurl = "https://maps.googleapis.com/maps/api/geocode/json?address={0}&key={1}";
string GoogleMapsAPIkey = "MYSECRETAPIKEY";
string requestUri = string.Format(GoogleMapsAPIurl, address.Trim(), GoogleMapsAPIkey);
// Works fine
using (var client = new HttpClient())
{
using (HttpResponseMessage response = await client.GetAsync(requestUri))
{
var responseContent = response.Content.ReadAsStringAsync().Result;
response.EnsureSuccessStatusCode();
}
}
// Doesn't work
using (HttpClient client = new HttpClient())
{
client.BaseAddress = new Uri("https://maps.googleapis.com/maps/api/", UriKind.Absolute);
client.DefaultRequestHeaders.Add("key", GoogleMapsAPIkey);
using (HttpResponseMessage response = await client.GetAsync("geocode/json?address=1400,Copenhagen,DK"))
{
var responseContent = response.Content.ReadAsStringAsync().Result;
response.EnsureSuccessStatusCode();
}
}
My last method with GetAsync where I am sending a query string doesn't work and I am in doubt why it is so. When I introduce BaseAddress on the client the GetAsync somehow doesn't send to the correct URL.
I don't suggest adding API key into globals. Maybe you'll need to send some HTTP request outside of the API and the key will be leaked.
Here's the example that works.
using Newtonsoft.Json;
public class Program
{
private static readonly HttpClient client = new HttpClient();
private const string GoogleMapsAPIkey = "MYSECRETAPIKEY";
static async Task Main(string[] args)
{
client.BaseAddress = new Uri("https://maps.googleapis.com/maps/api/");
try
{
Dictionary<string, string> query = new Dictionary<string, string>();
query.Add("address", "1400,Copenhagen,DK");
dynamic response = await GetAPIResponseAsync<dynamic>("geocode/json", query);
Console.WriteLine(response.ToString());
}
catch (Exception ex)
{
Console.WriteLine(ex);
}
Console.ReadKey();
}
private static async Task<string> ParamsToStringAsync(Dictionary<string, string> urlParams)
{
using (HttpContent content = new FormUrlEncodedContent(urlParams))
return await content.ReadAsStringAsync();
}
private static async Task<T> GetAPIResponseAsync<T>(string path, Dictionary<string, string> urlParams)
{
urlParams.Add("key", GoogleMapsAPIkey);
string query = await ParamsToStringAsync(urlParams);
using (HttpResponseMessage response = await client.GetAsync(path + "?" + query, HttpCompletionOption.ResponseHeadersRead))
{
response.EnsureSuccessStatusCode();
string responseText = await response.Content.ReadAsStringAsync();
return JsonConvert.DeserializeObject<T>(responseText);
}
}
}
Ciao, the problem is related with key parameter on URL. Change your code like this:
using (HttpClient client = new HttpClient())
{
client.BaseAddress = new Uri("https://maps.googleapis.com/maps/api/");
using (HttpResponseMessage response = await client.GetAsync("geocode/json?address=1400,Copenhagen,DK&key=" + GoogleMapsAPIkey))
{
var responseContent = response.Content.ReadAsStringAsync().Result;
response.EnsureSuccessStatusCode();
}
}
As google sheets said:
After you have an API key, your application can append the query parameter key=yourAPIKey to all request URLs. The API key is safe for embedding in URLs; it doesn't need any encoding.

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

Windows Phone 8.1 Runtime HttpClient async with the same result

I'm working with Windows Phone Runtime API.
I declare a timer, which every 2 seconds does async http connection in Listen method.
Timer t = new Timer(Listen, null, 0, 2000);
Listen method:
private async void Listen(object state)
{
string url = "http://www.mywebpage.com?data=my_data";
string responseBodyAsText = null;
var response = new HttpResponseMessage();
var httpClient = new HttpClient();
try
{
response = await httpClient.GetAsync(new Uri(url));
responseBodyAsText = await response.Content.ReadAsStringAsync();
}
catch
{
//...
}
Debug.WriteLine(responseBodyAsText);
httpClient.Dispose();
}
My problem is that responseBodyAsText contains always the same data (given the same uri) and not as I would expect different data according to my external actions (modifying web page or different results with the same uri).
Does HttpClient remembers content during liftime of application? How can I solve this problem?
HttpClient does have caching on by default. You can turn it off by passing it an HttpBaseProtocolFilter:
var filter = new HttpBaseProtocolFilter
{
CacheControl.ReadBehavior = HttpCacheReadBehavior.MostRecent,
CacheControl.WriteBehavior = HttpCacheWriteBehavior.NoCache;
}
Side note: You could also, instead of a Timer, use Task.Delay to achieve the timer behavior (it internally uses one):
private async Task ListenAsync()
{
while (someCondition)
{
string url = "http://www.mywebpage.com?data=my_data";
string responseBodyAsText = null;
var response = new HttpResponseMessage();
using (var httpClient = new HttpClient())
{
try
{
response = await httpClient.GetAsync(new Uri(url));
responseBodyAsText = await response.Content.ReadAsStringAsync();
}
catch
{
//...
}
Debug.WriteLine(responseBodyAsText);
await Task.Delay(2000);
}
}

C# HttpClient async POST request Task not returning a value

I'm executing an async POST request using a HttpClient in C#/Xamarin:
private async Task<string> ServicePostRequest (string url, string parameters)
{
string result = String.Empty;
using (var client = new HttpClient()) {
HttpContent content = new StringContent (parameters);
content.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue ("application/x-www-form-urlencoded");
client.Timeout = new TimeSpan (0, 0, 15);
using(var response = await client.PostAsync(url, content)){
using (var responseContent = response.Content) {
result = await responseContent.ReadAsStringAsync ();
Console.WriteLine (result);
return result;
}
}
}
}
When I execute the following code, the expected result (JSON) is being logged correctly in the terminal:
Task<string> result = ServicePostRequest("http://www.url.com", "parameters");
Now, I would like to get this result into a variable to be able to parse it. However, when I use the following code, no result is being logged at all and the application is frozen:
Task<string> result = ServicePostRequest("http://www.url.com", "parameters");
string myResult = result.Result;
Also when I use the result.Wait() method, the application doesn't respond at all.
Any help would be highly appreciated.
Since ServicePostRequest is an awaitable method, change this:
Task<string> result = ServicePostRequest("http://www.url.com", "parameters");
string myResult = result.Result;
To:
string result = await ServicePostRequest("http://www.url.com", "parameters");
Side Note: Make sure the calling method is an Asynchronous method.

Categories

Resources