How to get HttpContent from Request object? - c#

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.

Related

I am not able to get the response content from API call

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

HttpResponseMessage content is being returned as unicode

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

Get response body from Flurl HttpResponseMessage

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)

"Message body is malformed. Unable to map into expected format" response with 400 Bad request when update controller service

I have a problem when try to update a controller-service at nifi instance. I try to make a "put" request to nifi instance and disable the controller-service.
this is my logic:
get a specific controller-service (controller-services/{id})
parse response message to ControllerServiceEntity object
update state of service like --> currentService.Component.State = "DISABLED"; (All part of entity same with first time i just update State poperty)
serialize modified service instance
request nifi-api put for update service (controller-services/{id})
and i get the Badrequest response with "Message body is malformed. Unable to map into expected format." message.
This is my method for put request:
public async Task<T> Put<T>(Uri url,T data) where T:IBaseEntitty
{
T resultEntity = default(T);
using (var client = new HttpClient())
{
var jsonSerializerSettings = new JsonSerializerSettings
{
ContractResolver = new CamelCasePropertyNamesContractResolver()
};
var requestContent = new StringContent(JsonConvert.SerializeObject(data,jsonSerializerSettings), Encoding.UTF8, "application/json");
var response = client.PutAsync(url,requestContent);
var content = response.Result.Content;
using (var reader = new StreamReader(await content.ReadAsStreamAsync()))
{
var result = await reader.ReadToEndAsync();
if (response.Result.StatusCode == HttpStatusCode.OK)
{
var template = Newtonsoft.Json.JsonConvert.DeserializeObject(result, typeof(T));
if (template != null)
{
resultEntity = (T)template;
}
}
}
}
return resultEntity;
}
Any idea please ?
The response body should contain a message indicating why the request failed. Additionally, the <NIFI_HOME>/logs/nifi-user.log and <NIFI_HOME>/logs/nifi-app.log may contain more details.
Also, I would suggest opening the Developer Tools in your web browser to see these requests in action. The UI uses the REST API exclusively for all of it's functionality.
As i understand the request message should be short; my bad was sending whole entity back. I opened the Developer Tools on browser and checked the nifi instance's own requests and compared with mine: than i noticed the request is just include properties that will be update, not whole entity.
The request body must include just state and revision information. This is the request body that sending by nifi-instance when it disables controller-services:
{"revision":{"clientId":"644bf345-015d-1000-e82d-047f6a9f9432","version":15},"component":{"id":"015b1030-a099-13d3-812c-77772afcaeb0","state":"DISABLED"}}
I changed my codes according this informations. This is my sample code that set controll-service for disabling:
var controllerService = new ControllerServiceEntity();
controllerService.Id = existingService.Id;
controllerService.Revision = existingService.Revision;
var component = new ControllerServiceDTO();
component.Id = existingService.Component.Id;
component.State = "DISABLED";
controllerService.Component = component;
After i send the new control-service instance instead of existing one than it worked as i expected.

Getting response header

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

Categories