HttpClient request header customisation - c#

Is it possible to set the request ACCEPT header of the HttpClient in .Net/Web Api to include "application/json;odata=verbose"?
I know how to set the request media type
HttpClient client = new HttpClient(handler);
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
But how do I set the odata=verbose part? I cannot seem to find any solutions online to do that.
Do I have to use HttpWebRequest instead? Basically I need to call sharepoint 2013 rest api, and that odata=verbose part is required.

MediaTypeWithQualityHeaderValue has a property called Parameters to which you can add 'odata=verbose' parameter.
Other easy way is to call MediaTypeWithQualityHeaderValue's Parse/TryParse methods to which you can supply the whole "application/json;odata=verbose" media type string.
Here is an example using Parse
using (HttpClient httpClient = new HttpClient())
{
//Setup Accept Header
MediaTypeWithQualityHeaderValue acceptHeader = MediaTypeWithQualityHeaderValue.Parse("application/json;odata=verbose");
httpClient.DefaultRequestHeaders.Accept.Add(acceptHeader);
//... do other stuff
}

Related

Load a json url from Webclient

I want to get data from this json url.
https://viabilita.autostrade.it/traffico-fasce-orarie-cantieri-liguria/all2.json
This data is used from this page:
https://viabilita.autostrade.it/traffico-fasce-orarie-cantieri-liguria/index.html
using (var httpClient = new HttpClient())
{
var json = await httpClient.GetStringAsync("https://viabilita.autostrade.it/traffico-fasce-orarie-cantieri-liguria/all2.json");
// Now parse with JSON.Net
}
If I try to get from webclient I get a totally different string from when I use the browser to get it.
Is perhaps the "strict-origin-when-cross-origin" that cause this? Is it some other header to add to my request?
Thank you
Per default HttpClient won't send any User-Agent and this will make quite a few sites suspious. I tried the same request without setting an User-Agent header and it returned an HTML document instead.
So you need to add a User-Agent header and it will probably work (and to be a good sport, add a user-agent that identifies your application).
using (var httpClient = new HttpClient())
{
httpClient.DefaultRequestHeaders.Add("User-Agent", "MyApp/1.0");
var json = await httpClient.GetStringAsync("https://viabilita.autostrade.it/traffico-fasce-orarie-cantieri-liguria/all2.json");
// Now parse with JSON.Net
}

C# How to pass on a cookie using a shared HttpClient

I have the following set up:
JS client -> Web Api -> Web Api
I need to send the auth cookie all the way down. My problem is sending it from one web api to another. Because of integration with an older system, that uses FormsAuthentication, I have to pass on the auth cookie.
For performance reasons I share a list of HttpClients (one for each web api) in the following dictionary:
private static ConcurrentDictionary<ApiIdentifier, HttpClient> _clients = new ConcurrentDictionary<ApiIdentifier, HttpClient>();
So given an identifier I can grab the corresponding HttpClient.
The following works, but I'm pretty sure this is bad code:
HttpClient client = _clients[identifier];
var callerRequest = HttpContext.Current.Items["MS_HttpRequestMessage"] as HttpRequestMessage;
string authCookieValue = GetAuthCookieValue(callerRequest);
if (authCookieValue != null)
{
client.DefaultRequestHeaders.Remove("Cookie");
client.DefaultRequestHeaders.Add("Cookie", ".ASPXAUTH=" + authCookieValue);
}
HttpResponseMessage response = await client.PutAsJsonAsync(methodName, dataToSend);
// Handle response...
Whats wrong about this is that 1) it seems wrong to manipulate DefaultRequestHeaders in a request and 2) potentially two simultanious requests may mess up the cookies, as the HttpClient is shared.
I've been searching for a while without finding a solution, as most having a matching problem instantiates the HttpClient for every request, hence being able to set the required headers, which I'm trying to avoid.
At one point I had get requests working using a HttpResponseMessage. Perhaps that can be of inspiration to a solution.
So my question is: is there a way to set cookies for a single request using a HttpClient, that will be safe from other clients using the same instance?
Instead of calling PutAsJsonAsync() you can use HttpRequestMessage and SendAsync():
Uri requestUri = ...;
HttpMethod method = HttpMethod.Get /*Put, Post, Delete, etc.*/;
var request = new HttpRequestMessage(method, requestUri);
request.Headers.TryAddWithoutValidation("Cookie", ".ASPXAUTH=" + authCookieValue);
request.Content = new StringContent(jsonDataToSend, Encoding.UTF8, "application/json");
var response = await client.SendAsync(request);
UPDATE:
To make sure that your HTTP client does not store any cookies from a response you need to do this:
var httpClient = new HttpClient(new HttpClientHandler() { UseCookies = false; });
Otherwise you might get unexpected behavior by using one client and sharing other cookies.

HttpRequestMessage multiple custom headers overwriting each other

I am struggling to understand how to add MULTIPLE headers to the HttpRequestMessage. I mean I get the basics and if I do one header it works but multiple headers and the last one is what sticks and all others are overwritten?
So for example the Accept header will be overwritten but the authorization header will stick.
HttpRequestMessage httpreqmsg = new HttpRequestMessage();
httpreqmsg.Headers.Add("Accept", "CustomAccept");
httpreqmsg.Headers.Add("Authorization", "asdfas#%fwqerq#werfds...");
Now HttpRequestMessage has an overload with the signature
.Add(string, List<string>)
and that is fine if you have ONE name with multiple values but how do you do multiple headers. TryAddWithoutValidation has the same overloads as above?
TIA
Great...so I kinda made a mistake in my post. I didn't think it mattered but it does. I am unit testing a controller and therefore there is no HttpClient object created.
It seems the "Accept" header is reserved. No matter what value I tried to assign to it a FormatException was thrown.
If you change your code to this you get both headers back.
HttpRequestMessage httpreqmsg = new HttpRequestMessage();
httpreqmsg.Headers.Add("Lolz", "CustomAccept");
httpreqmsg.Headers.Add("Authorization", "SomeValue");
foreach (var item in httpreqmsg.Headers)
{
Console.WriteLine(item.Key + " : " + item.Value);
}
Also the value of 'Authorization' in your example was invalid, but I'm guessing that was just random key mashing :)
Not sure about the context of your code, but you could use HttpClient (WebApi NuGet) instead, which lets you add "Accept" and "Authorization" headers:
using (var client = new HttpClient())
{
client.BaseAddress = new Uri();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/x-www-form-urlencoded"));
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("scheme", "param");
//client.PostAsJsonAsync or something else
}
Building on #sidjames's post. It seems you're looking for the Accept and Authorization headers. If that's the case, then set it in HttpClient, instead of the HttpRequestMessage:
httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("some accept"));
httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", "your parameters");
There are a bunch of examples for accept and authorization on the StackOverflow.

Set HTTP protocol version in HttpClient

I need to make a request to a webservice that uses HTTP version 1.0. Im using HttpClient , But I cant see any option to set HTTP version.
Where can i set the request version?
In order to set the version you'll have to create an instance of HttpRequestMessage and set its Version property which you pass to HttpClient.SendAsync. You can use the helper HttpVersion utility class:
var requestMessage = new HttpRequestMessage
{
Version = HttpVersion.Version10
};
var client = new HttpClient();
var response = await client.SendAsync(requestMessage);
HTTP version is sent as a header in every request, so it is set in the message sent by System.Net.Http.HttpClient: see the ProtocolVersion property of the HttpWebRequest class.

HttpClient.GetAsync with network credentials

I'm currently using HttpWebRequest to get a website. I'd like to use the await pattern, which is not given for HttpWebRequests. I found the class HttpClient, which seems to be the new Http worker class. I'm using HttpClient.GetAsync(...) to query my webpage. But I'm missing the option to add ClientCredentials like HttpWebRequest.Credentials. Is there any way to give the HttpClient authentication information?
You can pass an instance of the HttpClientHandler Class with the credentials to the HttpClient Constructor:
using (var handler = new HttpClientHandler { Credentials = ... })
using (var client = new HttpClient(handler))
{
var result = await client.GetAsync(...);
}
You shouldn't dispose of the HttpClient every time, but use it (or a small pool of clients) for a longer period (lifetime of application. You also don't need the handler for it, but instead you can change the default headers.
After creating the client, you can set its Default Request Headers for Authentication. Here is an example for Basic authentication:
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", "username:password".ToBase64());
ToBase64() represents a helper function that transforms the string to a base64 encoding.

Categories

Resources