Im making some automatic surveillance for an Rest API im running and i need to retrieve the response body from the HttpResponseMessage object.
Im using Flurl Http: https://flurl.dev/docs/fluent-http/
I know how to retrieve the responsebody by adding ".RecieveSomeForm()" at the end of the http request, but i also need to get the response headers, as the error code from the Rest API is sent back as a header. My problem is that - to my knowledge and what i tried - its only the HttpResponseMessage object that i can retrieve the headers from. So the question is:
How do i get the responsebody out of the HttpResponseMessage while still being able to retrieve the headers for error logging?
using (var cli = new FlurlClient(URL).EnableCookies())
{
//get response body - var is set to string and has only response body
var AsyncResponse = await cli.WithHeader("some header").Request("some end point").AllowAnyHttpStatus().PostJsonAsync(some body).ReceiveString();
Console.WriteLine(AsyncResponse);
//get headers - var is set to HttpResponseMessage
var AsyncResponse = await cli.WithHeader("some header").Request("some end point").AllowAnyHttpStatus().PostJsonAsync(some body);
Console.WriteLine(AsyncResponse.Headers);
}
If I've understood correctly, you want Headers + Response body from a HTTP response.
var response = await cli.WithHeader("some header").Request("some end point").AllowAnyHttpStatus().PostJsonAsync("some body");
var headers = response.Headers; //do your stuff
var responseBody = response.Content != null ? await response.Content.ReadAsStringAsync() : null;
Another option which I personally don't like:
var responseTask = cli.WithHeader("some header", "haha").Request("some end point").AllowAnyHttpStatus().PostJsonAsync("some body");
var headers = (await responseTask).Headers; //do your stuff
var responseBody = await responseTask.ReceiveString();
Unfortunately, Flurl's extension methods can be used on Task, not on HttpResponseMessage. (that's why you have to avoid awaiting in the first line of code)
Related
I'm trying to call a Tableau endpoint to get the list of project.
It is in 2 steps:
Call the signIn endpoint to get a token that allow to call others endpoint
Call the list projects endpoint with my signed In token
By using insomnia, this is working like a charm, but in csharp code, the first step is working well, but the second always returning me a 401 error.
Tableau list projects documentation
public async Task<string> ListProjectAsync()
{
var signIn = await SignInAsync(); // Working
var endPoint = $"https://myTableauSite.com/api/3.17/sites/{signIn.SiteId}/projects";
var acceptedCodes = new List<HttpStatusCode>();
acceptedCodes.Add(HttpStatusCode.OK);
var client = new HttpClient();
client.DefaultRequestHeaders.Add("X-Tableau-Auth", signIn.Token);
HttpResponseMessage response = await client.GetAsync(endPoint); // 401
response.EnsureSuccessStatusCode();
string responseString = await response.Content.ReadAsStringAsync();
return responseString;
}
Edit: The problem was from the JWT generated token that had a missing permission, my bad
The only difference I could find between your code's request and insomnia is that you forgot to set the content-type
public async Task<string> ListProjectAsync()
{
var signIn = await SignInAsync(); // Working
var endPoint = $"https://myTableauSite.com/api/3.17/sites/{signIn.SiteId}/projects";
var client = new HttpClient();
client.DefaultRequestHeaders.Add("Content-Type", "application/xml");
client.DefaultRequestHeaders.Add("X-Tableau-Auth", signIn.Token);
HttpResponseMessage response = await client.GetAsync(endPoint); // Should be working
response.EnsureSuccessStatusCode();
return await response.Content.ReadAsStringAsync();
}
I am doing a post request and reading the response as given
var response = client.PostAsync(uriBuilder.Uri.ToString(), Content).Result;
var value = response.Content.ReadAsStreamAsync().Result;
if the result is a proper json string, it populates that in 'value' variable
otherwise it returns empty.
but if run the same in postman or fiddler i get this as response
Is there a way to get this response too?
ReadAsStreamAsync() returns a Task<System.IO.Stream> and not a Task<string>. The json string that you see is probably the debugger showing you the content of the stream.
Consider using ReadAsStringAsync() to get the HTML content :
var response = await client.PostAsync(uriBuilder.Uri.ToString(), Content);
var result = await response.Content.ReadAsStringAsync();
I am trying to read the contents of a HttpResponseMessage message as a string. However, it appears to be being returned as unicode.
This is my code that I am using to make the request with HttpClient
var responseMsg = await httpClient
.SendAsync(requestMsg, HttpCompletionOption.ResponseContentRead)
.ConfigureAwait(false);
return await BuildResponse(responseMsg, cookieContainer.GetAllCookies().ToList()).ConfigureAwait(false);
And here is my code for BuildResponse
private static async Task<IResponse> BuildResponse(HttpResponseMessage responseMsg, List<Cookie> cookies)
{
Ensure.ArgumentNotNull(responseMsg, nameof(responseMsg));
// We only support text stuff for now
using var content = responseMsg.Content;
var headers = responseMsg.Headers.ToDictionary(header => header.Key, header => header.Value.First());
var body = await responseMsg.Content.ReadAsStringAsync().ConfigureAwait(false);
var contentType = content.Headers?.ContentType?.MediaType;
return new Response(headers)
{
ContentType = contentType,
StatusCode = responseMsg.StatusCode,
Body = body,
CookieCollection = cookies
};
}
I know that the API call is working correctly, as I can see the exact request in fiddler return the JSON I am expecting:
What am I doing wrong? I should get the JSON returned as shown in screenshot 2.
try to check your response data:
var body = await responseMsg.Content.ReadAsStringAsync();
var data= JsonConvert.DeserializeObject<your response data class>(body);
Used the Flurl to Get response from API.
var response = await url.WithClient(fc)
.WithHeader("Authorization", requestDto.ApiKey)
.GetJsonAsync<T>();
dynamic httpResponse = response.Result;
But I cant able to access httpResponse.Headers
How to access response headers while using GetJsonAsync .
You can't get a header from GetJsonAsync<T> because it returns Task<T> instead of raw response. You can call GetAsync and deserialize your payload at next step:
HttpResponseMessage response = await url.GetAsync();
HttpResponseHeaders headers = response.Headers;
FooPayload payload = await response.ReadFromJsonAsync<FooPayload>();
ReadFromJsonAsync is an extention method:
public static async Task<TBody> ReadFromJsonAsync<TBody>(this HttpResponseMessage response)
{
if (response.Content == null) return default(TBody);
string content = await response.Content.ReadAsStringAsync();
return JsonConvert.DeserializeObject<TBody>(content);
}
P.S. This is why I prefer and recommend to use raw HttpClient instead of any third-party high-level client like RestSharp or Flurl.
You could also await for the HttpResponseMessage, pick off the .Headers object, then send the completed task to ReceiveJson<T> for deserialization. Here's how to do it without an extension method:
var task = url.GetAsync();
HttpResponseMessage response = await task;
HttpResponseHeaders headers = response.Headers;
//Get what I need now from headers, .ReceiveJson<T>() will dispose
//response object above.
T obj = await task.ReceiveJson<T>();
If a caller adds HttpContent:
using (var content = new MultipartFormDataContent())
{
HttpContent additionalContent = StringContent("just a test");
content.Add(additionalContent);
Which is then POST'ed, how does the receiver retrieve this additional content?
I've seen examples where people call Request.Content. However, HttpContent.Current.Request doesn't have a Content object.
The receiver is an [HttpPost] WebAPI.
Use ReadAsMultipartAsync extension method for getting content parts and then ReadAsStringAsync for parsing string content:
var provider = await Request.Content.ReadAsMultipartAsync();
var content = provider.Contents.FirstOrDefault(); //assumed single content part has been sent
if (content != null)
{
var result = await content.ReadAsStringAsync();
}
I think the body of your request is nothing but content of request.
Please cross check using F12 developers tools->Network-> Request's response section or body section.