Firstly, I wouldn't use HttpClient
directly. It's too easy to make mistakes - particularly in the area of headers. The DefaultHeadersCollection
is not immutable and not thread-safe because other parts of the app can change the headers on you. It's best to set the headers when you make the call. If you are working with an abstraction, and that is recommended because the classes in this area are a bit of a mess, you would want to have a headers collection and put those on your HttpRequestMessage
before you send it. You need to make sure you put the content headers on the content, and not the message.
Code Reference
foreach (var headerName in request.Headers.Names)
{
//"Content-Type"
if (string.Compare(headerName, HeadersExtensions.ContentTypeHeaderName, StringComparison.OrdinalIgnoreCase) == 0)
{
//Note: not sure why this is necessary...
//The HttpClient class seems to differentiate between content headers and request message headers, but this distinction doesn't exist in the real world...
//TODO: Other Content headers
httpContent?.Headers.Add(HeadersExtensions.ContentTypeHeaderName, request.Headers[headerName]);
}
else
{
httpRequestMessage.Headers.Add(headerName, request.Headers[headerName]);
}
}
Here is a data structure that you could use to send the request which includes the headers.
Code Reference
public interface IRequest
{
CancellationToken CancellationToken { get; }
string? CustomHttpRequestMethod { get; }
IHeadersCollection Headers { get; }
HttpRequestMethod HttpRequestMethod { get; }
AbsoluteUrl Uri { get; }
}
public interface IRequest<TBody> : IRequest
{
TBody? BodyData { get; }
}
And, a headers collection:
Code Reference
public sealed class HeadersCollection : IHeadersCollection
{
#region Fields
private readonly IDictionary<string, IEnumerable<string>> dictionary;
#endregion
#region Public Constructors
public HeadersCollection(IDictionary<string, IEnumerable<string>> dictionary) => this.dictionary = dictionary;
public HeadersCollection(string key, string value) : this(ImmutableDictionary.CreateRange(
new List<KeyValuePair<string, IEnumerable<string>>>
{
new(key, ImmutableList.Create(value))
}
))
{
}
#endregion Public Constructors
#region Public Properties
public static HeadersCollection Empty { get; } = new HeadersCollection(ImmutableDictionary.Create<string, IEnumerable<string>>());
public IEnumerable<string> Names => dictionary.Keys;
IEnumerable<string> IHeadersCollection.this[string name] => dictionary[name];
#endregion Public Properties
#region Public Methods
public bool Contains(string name) => dictionary.ContainsKey(name);
public IEnumerator<KeyValuePair<string, IEnumerable<string>>> GetEnumerator() => dictionary.GetEnumerator();
IEnumerator IEnumerable.GetEnumerator() => dictionary.GetEnumerator();
public override string ToString() => string.Join("\r\n", dictionary.Select(kvp => $"{kvp.Key}: {string.Join(", ", kvp.Value)}\r\n"));
#endregion
}
See all the working code and examples here.