Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it possible to set the Default Content-Type to "application/json;v=2.0"

Is it possible to set the Default Content-Type to "application/json;v=2.0". I say default because I'm using a HttpClient class and I use the DefaultRequestHeaders to set my proxies to default values.

I followed this example to create my headers https://stackoverflow.com/a/10679340/196526 but I also use versioning and information about versioning is saved in ContenT-Type

public class BankAccountProxy
{
    public void SetToken()
    {
        Client = new HttpClient();
        Client.BaseAddress = new Uri(System.Configuration.ConfigurationManager.AppSettings["ApiRoute"]);
        Client.DefaultRequestHeaders.Accept.Clear();
        Client.DefaultRequestHeaders.Add("Token", ApiInformations.ApiToken);
        Client.DefaultRequestHeaders
            .Accept
            .Add(new MediaTypeWithQualityHeaderValue($"application/json;v=2.0"));
    }

    public async Task<IEnumerable<BankAccount>> Get()
    {
        HttpResponseMessage response = await Client.GetAsync($"/api/BankAccount/");
        response.EnsureSuccessStatusCode();
        IEnumerable<BankAccount> bankAccount;
        bankAccount = await response.Content.ReadAsAsync<IEnumerable<BankAccount>>();
        return bankAccount;
    }
}

When I run this code I get a

Exception message: The format of value 'application/json;v=2.0' is invalid.

Because of the v=2.0 that is probably not a valid MediaTypeWithQualityHeaderValue.

What I want is to be sure I always send the version information in my Content-Type header value. How can I initialize it? How can I tell my code my default content type is not a quality header but a valid one.

For information here is my query perfectly working on Postman:

enter image description here

like image 201
Bastien Vandamme Avatar asked Apr 12 '19 04:04

Bastien Vandamme


1 Answers

TL;DR

Use this code:

    class Program
    {
        static async Task Main(string[] args)
        {
            try
            {
                var client = new HttpClient { BaseAddress = new Uri("https://contenttypev2.free.beeceptor.com") }; // interceptor
                client.DefaultRequestHeaders.Accept.Clear();
                client.DefaultRequestHeaders.Add("Token", "SOME_TOKEN"); // simplified

                var response = await client.GetJson2Async("/api/BankAccount/");
                response.EnsureSuccessStatusCode();
                var data = await response.Content.ReadAsStringAsync(); // simplified
                Console.WriteLine(data);
            }
            catch (Exception e)
            {
                Console.WriteLine(e);
                throw;
            }
            finally
            {
                Console.ReadLine();
            }
        }
    }

    class Json2Content : StringContent
    {
        public Json2Content(string content) : this(content, Encoding.Default) { }

        public Json2Content(string content, Encoding encoding) : base(content, encoding)
        {
            this.Headers.Clear();
            this.Headers.ContentType = new MediaTypeHeaderValue("application/json");
            this.Headers.ContentType.Parameters.Add(new NameValueHeaderValue("v", "2.0"));
            if (!encoding.Equals(Encoding.Default)) this.Headers.ContentType.CharSet = encoding.HeaderName;
        }
    }

    static class Json2Extensions
    {
        public static Task<HttpResponseMessage> GetJson2Async(this HttpClient client, string requestUri, string content = "", Encoding encoding = default)
        {
            var request = new HttpRequestMessage(HttpMethod.Get, requestUri) { Content = new Json2Content(content, encoding ?? Encoding.Default) };
            return client.SendAsync(request);
        }
    }

And this is the result:

enter image description here

Explanation

As mentioned by carlosfigueira:

The content type is a header of the content, not of the request

So setting the Accept header like you did here:

Client.DefaultRequestHeaders
  .Accept
  .Add(new MediaTypeWithQualityHeaderValue($"application/json;v=2.0"));

will not help your objective.

To simplify use of JSON v2 content type, you can use the wrapper class above as well as the extension method provided.

Note

Are you sure you want to set the Content-Type header? It is very uncommon to have content in a GET request. If you want to signal the server that you wish to receive JSON v2 response, you should do it in the Accept header. Even the API versioning document you have referenced in the comments to the question shows that the version number could be set in the Accept header or the Content-Type header. When there is content you can still, probably, use the 'Accept' header to set the version and you can do that as a default like so:

var client = new HttpClient { BaseAddress = new Uri("https://contenttypev2.free.beeceptor.com") }; // interceptor
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Add("Token", "SOME_TOKEN"); // simplified
client.DefaultRequestHeaders.Accept.Clear();
var json2MediaType = new MediaTypeWithQualityHeaderValue("application/json");
json2MediaType.Parameters.Clear();
json2MediaType.Parameters.Add(new NameValueHeaderValue("v", "2.0"));
client.DefaultRequestHeaders.Accept.Add(json2MediaType);

var response = await client.GetAsync("/api/BankAccount/");
...

resulting with:

enter image description here

like image 81
DoronG Avatar answered Nov 15 '22 21:11

DoronG