Get response in JSON from API - c#

I am using HttpClient to consume an external API from an ASP.NET Web API controller. I am not using authentication, just a token, so I have:
using (var httpClient = new HttpClient()) {
httpClient.DefaultRequestHeaders.Accept.Clear();
httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
HttpResponseMessage response = await httpClient.GetAsync(endpoint);
}
I am getting the response always in XML format but I am sending header with "application/json".
Am I missing something it this is a problem with the external API?
What else can I try to get the response in JSON?

It's up to the API developer(s) to respect the media type (application/json). It is possible for a developer to explicitly return XML when a client requests JSON (if they feel like trolling), though in this case it is probably just giving you the default format because they don't check the header value.
Check the docs or contact them directly to confirm they return data in JSON format and how to format the request to get JSON.

You should set Accept: application/json as well as Content-Type: application/json.

Related

Replicate POSTMAN GET request in C#/VB.net with Authorization

I've been here for 2 days now driving me nuts.
All I want to do it call a webservice at:
https://use-land-property-data.service.gov.uk/api/v1/datasets
Which returns some JSON object.
It requires the "Authorization" header to be set with an API Key that I have.
I've tried it in POSTMAN and it works.
However trying to get a Webclient or Httpclient version working is currently beyond me. I've tried countless examples here on SO. None return the same responses as POSTMAN. All return "Request Rejected"
e.g.
Using client = New HttpClient()
client.DefaultRequestHeaders.Add("Authorization", "MYKEY")
Dim response = Await client.GetStringAsync("https://use-land-property-data.service.gov.uk/api/v1/datasets")
Return response
End Using
what is the equivalent in httpclient to replicate the postman Authorization header?
Try:
httpClient.DefaultRequestHeaders.Authorization = New AuthenticationHeaderValue("Bearer", "Your Key")

Add content-type header to httpclient GET request

I am trying to add Content-Type header to HttpClient GET request, here my code:
HttpClient client=new ....
bool added = client.DefaultRequestHeaders.TryAddWithoutValidation("Content-Type", "application/x-www-form-urlencoded");
var response = await client.GetAsync(...
but the added variable is false, i.e it failed to add the header.
How can I add this header?
NOTE:
This post deals with POST request, I asked about GET
If you look at the Http/1.1 specification:
A sender that generates a message containing a payload body SHOULD
generate a Content-Type header field in that message unless the
intended media type of the enclosed representation is unknown to the
sender. If a Content-Type header field is not present, the recipient
MAY either assume a media type of "application/octet-stream"
([RFC2046], Section 4.5.1) or examine the data to determine its type.
Check also the MDN on get requests
The HTTP GET method requests a representation of the specified resource. Requests using GET should only retrieve data.
Sending body/payload in a GET request may cause some existing implementations to reject the request — while not prohibited by the specification, the semantics are undefined. It is better to just avoid sending payloads in GET requests.
Effectively, that means that wether you send or not the header, it's going to be ignored and/or rejected.
When setting the content type, it's better to set it from the content itself: How do you set the Content-Type header for an HttpClient request?
Im currently working on a project, where I call an api using a POST request.
This might help in your case. Its how its done in an official Microsoft Documentation.
using (var content = new ByteArrayContent(byteData))
{
// This example uses the "application/octet-stream" content type.
// The other content types you can use are "application/json"
// and "multipart/form-data".
content.Headers.ContentType = new mediaTypeHeaderValue("application/octet-stream");
response = await client.PostAsync(uriBase, content);
}

Unsupported Media Type with HttpClient / .NET Core

I am working with a RESTful API that supports POST requests in JSON format. The API's own Swagger documentation shows that this is a valid call to one of its endpoints:
curl -X POST --header 'Content-Type: application/json' --header 'Accept: application/json' -d '<JSON>' '<URL>'
Where <JSON> and <URL> are the valid JSON message and the endpoint's URL. From this Swagger documentation I gather that any posts to this endpoint must include both a Content-Type and Accept headers set to application/json.
I am writing a C# method that will use .NET Core's HttpClient class to post to this endpoint. However, upon posting my message I receive an HTTP 415 error code back, for Unsupported Media Type. From what I've learned so far, the Content-Type header must be set in your content (I am using the StringContent class) and the Accept header can only be set in the HttpClient headers. Here is my particular example:
var httpContent = new StringContent("<JSON>", Encoding.UTF32, "application/json");
var httpClient = new HttpClient();
httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
var responseMessage = httpClient.PostAsync("<URL>", httpContent);
var result = responseMessage.Result;
Once again, where <JSON> and <URL> are the valid JSON message and the endpoints's URL. It would seem to me that the third line, on which I reference httpCllient.DefaultRequestHeaders, is not adding the Accept: application/json header to my request. If I manually add the header to the httpContent.Headers collection, I get a run-time error that tells me that Accept is not a header I can add to the httpContent. That's why I am hoping to add it to the httpClient instead.
I have validated the URL and my JSON with Swagger, so I know those are correct. Also, the request is done over HTTPS, so I can't use Fiddler to validate that the Accept header is being included. And while I could enable decryption in Fiddler, that's a whole other ball of wax. I don't want to add their root certificate to my system, especially if I'm missing something fairly simple, which this seems to be.
Any pointers will be appreciated. Thanks.
what about if you try:
var httpContent = new StringContent(jsonData, Encoding.UTF8, "application/json");
You shouldn't need to add an Accept header.

How do I not exclude charset in Content-Type when using HttpClient?

I am attempting to use HttpClient in a .net core project to make a GET request to a REST service that accepts/returns JSON. I don't control the external service.
No matter how I try, I can't figure out to set the Content-Type header to application/json only.
When I use
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
it sends in the HTTP GET request:
Content-Type: application/json; charset=utf-8
However, this particular service does not work with this. It will only work if the header is:
Content-Type: application/json
I've tried setting headers without validation, and all the approaches I've found on the web/SO doesn't apply to .net core. All the other the approaches to sending HTTP requests aren't available in .net core, so I need to figure this out. How can I exclude the charset in content-type?
EDIT with workaround
As mentioned in the answers, the service should be using the Accept header. The workaround (as Shaun Luttin has in his answer) is to add an empty content to the GET (what? GETs don't have content! yeah...). It's not pretty, but it does work.
You're setting the Accept header. You need to set the ContentType header instead, which is only canonical for a POST.
var client = new HttpClient();
var content = new StringContent("myJson");
content.Headers.ContentType = MediaTypeHeaderValue.Parse("application/json");
var result = client.PostAsync("http://bigfont.ca", content).Result;
If you really want to set it for a GET, you can do this:
var client = new HttpClient();
var message = new HttpRequestMessage(HttpMethod.Get, "http://www.bigfont.ca");
message.Content = new StringContent(string.Empty);
message.Content.Headers.Clear();
message.Content.Headers.Add("Content-Type", "application/json");
var result = client.SendAsync(message).Result;
If you are the client and you perform a GET request how can you specify the Content-Type? Isn't it supposed to say what your are able to Accept ? According to this 7.2.1 Type you can only set Content-Type when there is Body.

Why I cannot set 'Allow' in HTTP response header?

I've written a RESTful API using ASP.NET Web Api. Now I'm trying to make it returns the allowed verbs for a controller. I'm trying to do it with the following code:
[AcceptVerbs("OPTIONS")]
public HttpResponseMessage Options()
{
var response = new HttpResponseMessage(HttpStatusCode.OK);
response.Headers.Add("Access-Control-Allow-Origin", "*");
response.Headers.Add("Access-Control-Allow-Methods", "POST");
response.Headers.Add("Allow", "POST");
return response;
}
But instead of getting a Allow Header on my response, I'm getting a 500 Internal Server Error. While debugging I receive the following error:
{"Misused header name. Make sure request headers are used with HttpRequestMessage, response headers with HttpResponseMessage, and content headers with HttpContent objects."}
Is that possible to set that header?
As the error message says, you must use content headers with HttpContent objects.
response.Content.Headers.Add("Allow", "POST");
Must admit this is kinda weird API...
Allow is a content header.
response.Content.Headers.Allow.Add("POST");

Categories