Modify request headers per request C# HttpClient PCL - c#

I'm currently using the System.Net.Http.HttpClient for cross platform support.
I read that it is not a good practice to instantiate a HttpClient object for each request and that you should reuse it whenever possible.
Now I have a problem while writing a client library for a service. Some API calls need to have a specific header, some MUST not include this specific header.
It seems that I can only manipulate the "DefaultRequestHeaders" which will be send with each request.
Is there an option when actually making the request with e.g. "client.PostAsync()" to modify the headers only for the specific request?
(Info: Requests can be multi threaded).
Thanks in advance!

Yes, you can create a new HttpRequestMessage, set all the properties you need to, and then pass it to SendAsync.
var request = new HttpRequestMessage() {
RequestUri = new Uri("http://example.org"),
Method = HttpMethod.Post,
Content = new StringContent("Here is my content")
}
request.Headers.Accept.Add(...); // Set whatever headers you need to
var response = await client.SendAsync(request);

Use HttpContent.Headers. Simply create HttpContent instance with required headers and pass it to PostAsync method.

Related

Adding Session Request To API Call

I'm unsure how to add the Session Request to the API call as per the Food Hygiene Instructions. I've copied the relevant code and hope I am close, but unsure where to put this one part.
Reference: https://api.ratings.food.gov.uk/help
Need to add into the API call: Session.Request.Headers.Add("x-api-version", 2);
Partial Code:
readonly string Baseurl = "https://api.ratings.food.gov.uk";
public async Task<ActionResult> Index()
{
List<Authorities> AuthInfo = new List<Authorities>();
using var client = new HttpClient
{
//Passing service base url
BaseAddress = new Uri(Baseurl)
};
client.DefaultRequestHeaders.Clear();
//Define request data format
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
***//Session.Request.Headers.Add("x-api-version", 2);***
//Sending request to find web api REST service resource GETRegions using HttpClient
HttpResponseMessage Res = await client.GetAsync("Authorities/basic");
The documentation you're referring to is misleading/incorrect. When you talk about Session (at least in the .NET world) you talk about the server-side. You're obviously a client of the API, rather than a developer of it, so they asking you to put stuff in the Session is incorrect.
You're a client, passing headers in your requests, so it's just:
client.DefaultRequestHeaders.Add("x-api-version", "2");
Side note, you may want to reuse that HttpClient instance if you are going to make that call often.
Side note 2: you may want to ask them to fix the docs :)

Read GRPC headers

I'm sending data via GRPC to, let's call it, IntegrationApi, calling a method Foo. I need to read header values from the response (the API I'm communicating with sends rate-limiting headers).
I'm using https://www.nuget.org/packages/Grpc.Core/
var metaData = new Metadata();
metadata.Add(new Metadata.Entry("Authorization", $"Bearer {apiKey}"));
var channel = new Channel("url to endpoint", new SslCredentials());
var client = new IntegrationApi(channel);
var callOptions = new CallOptions()
.WithHeaders(metadata)
.WithDeadline(DateTime.UtcNow.AddSeconds(15))
.WithWaitForReady(false);
var response = client.Foo(req, options);
but the response only gives me the properties based on the Foo.proto file.
How do I do this?
You are using the synchronous version of "Foo" method, and that one uses a simplified version of the API (=only allows access to the response and throws RpcExceptions in case of an error).
If you call the asynchronous version of the same method ("FooAsync"), you'll get back a call object that can access all the call details (such as response headers).
https://github.com/grpc/grpc/blob/044a8e29df4c5c2716c7e8250c6b2585e1c425ff/src/csharp/Grpc.Core.Api/AsyncUnaryCall.cs#L73

Is setting the Authorization header in HttpClient safe?

I'm working in a MVC5 ASP.NET project, and learned that to send authenticated requests to a WEB API from the controller I could do the following to add a token to the header(using an example code):
public static class APICaller
{
// Use a single instance for HttpClient to reduce overhead
private static readonly HttpClient client = new HttpClient();
//Set the Authorization Header
public static string SetHeader( string token )
{
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token);
return("Success");
}
}
Is setting the header this way on the HttpClient thread-safe? Will other users have a way to access this same token, given that there is only one instance of this HttpClient?
EDIT:
I'd like to ask one more question to get a better understanding of how it works. Would I need to add the header each time I'm making a request with the same HttpClient object?
With the approach you have, once you've set the default request header on your static instance, it will remain set without you having to keep setting it. This means that if you have multiple requests coming into your server, you could end up in a situation where the header is set for one user and then changed by another request before that first request makes it out the door.
One option to avoid this would be to use SendAsync when using user-specific authorisation headers. This allows you to tie the header to a specific message, rather than setting it as a default for the HttpClient itself.
The code is a bit more verbose, but would look something like this:
using (var httpRequestMessage = new HttpRequestMessage(HttpMethod.Get, "http://path/to/wherever"))
{
httpRequestMessage.Headers.Authorization = new AuthenticationHeaderValue("Bearer", "TheToken");
using (var httpResponseMessage = httpClient.SendAsync(httpRequestMessage))
{
// ...
}
}
As you can see, the header is set specially on each request and therefore the issue of mixing up the headers goes away. The obvious downside is that this syntax is more verbose.
Will other users have a way to access this same token, given that there is only one instance of this HttpClient?
Yes, that is why you need to be careful when setting the default headers.
Would I need to add the header each time I'm making a request with the same HttpClient object?
No, because you set the default header all requests created with that object will have the header.
For things like a Bearer token it is better to not put in the default headers and instead put it in the request header by creating a new HttpRequestMessage object, setting the headers you need there, then using HttpClient.SendAsync( passing in the request message to send the headers along with your request.

Http Put and querystring

I have two problems. I am trying to interact with a Web API that is wanting a HTTP PUT. I am trying to pass the parameters as part of the querystring. Unfortunately, I am not really sure how to do that. Do I include them in with the first parameter of the PutAsync method as shown below?
The other question I have is I am unsure what needs to be coded for the HTTPContent object when using the PutAsync method. I am trying to pass the parameters in the querystring instead of other methods that might be used. Most of the examples that I can find are passing the data as json.
using (var apiManagementSystem = new HttpClient())
{
apiManagementSystem.BaseAddress = new Uri("https://thedomain.com/api/");
apiManagementSystem.DefaultRequestHeaders.Clear();
apiManagementSystem.DefaultRequestHeaders.Add("SessionID", _sessionID);
HttpContent httpContent = new /* What do I do Here? */
responseMessage = apiManagementSystem.PutAsync("Product/someID?available=N", httpContent).Result;
}
My finished url should be something like this.
https://thedomain.com/api/Product/someID?available=N
This API that I am communicating with is a Rest API

Set Content-MD5 in get request

I have the following code:
HttpRequestMessage message = new HttpRequestMessage(HttpMethod.Get, uri);
byte[] md5 = {my hash};
message.Content.Headers.ContentMD5 = md5;
The problem is, message.Content is null.
The client I use is of type System.Net.Http.HttpClient
Now my question, how can I send a HttpContent in a GET request?
My solution is, I created my own header. I planned to use the Content-MD5 for caching, so I just created my own caching header.
Content-MD5 header should only be used when invoking either of the HTTP verbs; PUT or POST. No body is transferred from the client to the server on a GET.

Categories