【问题标题】:Is it possible to set the Default Content-Type to "application/json;v=2.0"是否可以将默认内容类型设置为“application/json;v=2.0”
【发布时间】:2019-09-02 19:28:51
【问题描述】:

是否可以将默认内容类型设置为“application/json;v=2.0”。我说默认是因为我使用的是 HttpClient 类,并且我使用 DefaultRequestHeaders 将我的代理设置为默认值。

我按照这个示例创建了我的标题https://stackoverflow.com/a/10679340/196526,但我也使用了版本控制,有关版本控制的信息保存在 ContentT-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;
    }
}

当我运行这段代码时,我得到一个

异常消息:值'application/json;v=2.0'的格式是 无效。

因为 v=2.0 可能不是有效的 MediaTypeWithQualityHeaderValue。

我想要确保始终在我的 Content-Type 标头值中发送版本信息。我怎样才能初始化它?如何告诉我的代码我的默认内容类型不是质量标头而是有效标头。

这里的信息是我在 Postman 上完美运行的查询:

【问题讨论】:

  • 可以试试,Client.DefaultRequestHeaders.Add("Accept", "application/json;v=2.0");
  • 我认为它有效,但我需要的是“Content-Type”,当我添加 Client.DefaultRequestHeaders.Add("Content-Type", "application/json;v=2.0");行我得到一个'误用的标题名称。确保请求标头与 HttpRequestMessage 一起使用,响应标头与 HttpResponseMessage 一起使用,内容标头与 HttpContent 对象一起使用。例外。
  • 关于版本控制 API 的文档在这里 github.com/Microsoft/aspnet-api-versioning/wiki/… 我不明白为什么他们有时使用 Content-Type 有时使用 Accept 标头参数。

标签: c# rest http-headers asp.net-web-api2


【解决方案1】:

TL;DR

使用此代码:

    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);
        }
    }

结果如下:

说明

正如carlosfigueira所说:

内容类型是内容的头部,而不是请求的头部

所以像你在这里做的那样设置Accept 标头:

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

不会帮助你实现目标。

为了简化 JSON v2 内容类型的使用,您可以使用上面的包装类以及提供的扩展方法。

注意

您确定要设置Content-Type 标头吗?在 GET 请求中包含内容是非常少见的。 如果您想向服务器发送您希望接收 JSON v2 响应的信号,您应该在Accept 标头中执行此操作。即使您在问题的 cmets 中引用的 API versioning document 也表明可以在 Accept 标头 Content-Type 标头中设置版本号。当有内容时,您可能仍然可以使用“接受”标题来设置版本,您可以将其作为默认设置,如下所示:

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/");
...

结果:

【讨论】:

  • 我确实测试过,是的,这就是答案。
猜你喜欢
  • 2012-02-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-01-04
  • 2015-10-09
  • 2023-03-06
  • 2020-01-05
  • 2019-03-01
相关资源
最近更新 更多