如何将带有自定义标头的任意 JSON 数据发送到 REST 服务器?

Posted

技术标签:

【中文标题】如何将带有自定义标头的任意 JSON 数据发送到 REST 服务器?【英文标题】:How do I send arbitrary JSON data, with a custom header, to a REST server? 【发布时间】:2014-01-11 01:19:23 【问题描述】:

TL;DR -- 如何将 JSON 字符串发送到带有 auth 标头的 REST 主机?我尝试了 3 种不同的方法,找到了一种适用于匿名类型的方法。为什么我不能使用匿名类型?我需要设置一个名为“Group-Name”的变量,连字符不是有效的 C# 标识符。

背景

我需要 POST JSON,但无法正确获取正文和内容类型

功能 #1 - 适用于匿名类型

内容类型和数据是正确的,但我不想使用匿名类型。我想用一个字符串

  static void PostData(string restURLBase, string RESTUrl, string AuthToken, string postBody)
    
        HttpClient client = new HttpClient();
        client.BaseAddress = new Uri(restURLBase);
        client.DefaultRequestHeaders.Add("Auth-Token", AuthToken);
        client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));

        // StringContent content = new StringContent(postBody);

        var test1 = "data1";
        var test2 = "data2";
        var test3 = "data3";

        var response = client.PostAsJsonAsync(RESTUrl, new  test1, test2, test3).Result;  // Blocking call!
        if (!response.IsSuccessStatusCode)
        
            Console.WriteLine("0 (1)", (int)response.StatusCode, response.ReasonPhrase);
            return;
         
    

输出 #1

使用 AnonymousTypes + PostAsJsonAsync 时内容类型和数据正确,但我不想使用匿名类型。

POST https://api.dynect.net/REST/Zone/ABCqqqqqqqqqqqqYYYYYtes3ss.com HTTP/1.1
Auth-Token: --- REDACTED -----
Accept: application/json
Content-Type: application/json; charset=utf-8
Host: api.dynect.net
Content-Length: 49
Expect: 100-continue

"test1":"data1","test2":"data2","test3":"data3"

功能 #2 - 无法按预期工作

获取一个字符串并将其放入一个 StringContent 对象中。这会产生改变内容类型的副作用。

  static void PostData(string restURLBase, string RESTUrl, string AuthToken, string postBody)
    
        HttpClient client = new HttpClient();
        client.BaseAddress = new Uri(restURLBase);
        client.DefaultRequestHeaders.Add("Auth-Token", AuthToken);
        client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));

        StringContent content = new StringContent(postBody);

        var response = client.PostAsync(RESTUrl, content).Result;  // Blocking call!
        if (!response.IsSuccessStatusCode)
        
            Console.WriteLine("0 (1)", (int)response.StatusCode, response.ReasonPhrase);
            return;
         
    

输出 #2

使用 StringContent + PostAsync 时内容类型错误

POST https://api.dynect.net/REST/Zone/ABCqqqqqqqqqqqqYYYYYtes3ss.com HTTP/1.1
Auth-Token: ---- REDACTED -------
Accept: application/json                      // CORRECT
Content-Type: text/plain; charset=utf-8       // WRONG!!!
Host: api.dynect.net
Content-Length: 100
Expect: 100-continue

"rdata" : ["rname" : "dynect.nfp.com", "zone" : "ABCqqqqqqqqqqqqYYYYYtes3ss.com"], "ttl" : "43200"
        // ^^ THIS IS CORRECT

功能 #3 - 无法按预期工作

因为我知道PostAsJsonAsync 正确设置了 contentType,所以让我们使用该方法。 (不工作)

    static void PostData(string restURLBase, string RESTUrl, string AuthToken, string postBody)
    
        HttpClient client = new HttpClient();
        client.BaseAddress = new Uri(restURLBase);
        client.DefaultRequestHeaders.Add("Auth-Token", AuthToken);
        client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));

        StringContent content = new StringContent(postBody);

        var response = client.PostAsJsonAsync(RESTUrl, content).Result;  // Blocking call!
        if (!response.IsSuccessStatusCode)
        
            Console.WriteLine("0 (1)", (int)response.StatusCode, response.ReasonPhrase);
            return;
         
    

输出#3

内容类型正确,使用 StringContent + PostAsJsonAsync 时 POST 正文错误

POST https://api.dynect.net/REST/Zone/ABCqqqqqqqqqqqqYYYYYtes3ss.com HTTP/1.1
Auth-Token: -- REDACTED ---
Accept: application/json
Content-Type: application/json; charset=utf-8
Host: api.dynect.net
Content-Length: 74
Expect: 100-continue

"Headers":["Key":"Content-Type","Value":["text/plain; charset=utf-8"]]

问题

我要做的就是将 JSON 作为字符串或在运行时定义的动态对象发送到服务器,HTTP 内容类型正确,并带有特殊的“Auth-Token”标头。

任何示例,如果不使用 WebAPI,例如 servicestack 或其他任何东西,都很酷。

【问题讨论】:

你能显示你得到的错误吗? @G.Stoynev 本身没有错误,但是如何在 PostAsync 中使用“HttpContent”? 【参考方案1】:
/// <summary>
    /// Creates a new instance of the <see cref="T:System.Net.Http.StringContent"/> class.
    /// </summary>
    /// <param name="content">The content used to initialize the <see cref="T:System.Net.Http.StringContent"/>.</param><param name="encoding">The encoding to use for the content.</param><param name="mediaType">The media type to use for the content.</param>
    [__DynamicallyInvokable]
    public StringContent(string content, Encoding encoding, string mediaType)
      : base(StringContent.GetContentByteArray(content, encoding))
    
      this.Headers.ContentType = new MediaTypeHeaderValue(mediaType == null ? "text/plain" : mediaType)
      
        CharSet = encoding == null ? HttpContent.DefaultStringEncoding.WebName : encoding.WebName
      ;
    

它是 StringContent 的构造函数。看起来你应该指定适当的编码和媒体类型

【讨论】:

【参考方案2】:

您不能直接设置 HttpContent 的实例,因为它是一个抽象类。您需要使用其中一个子类,具体取决于您的需要。最有可能是 StringContent,它允许您在构造函数中设置响应的字符串值、编码和媒体类型:http://msdn.microsoft.com/en-us/library/system.net.http.stringcontent.aspx

How do I set up HttpContent for my HttpClient PostAsync second parameter?的回答

【讨论】:

感谢这帮助我想出了上面列出的输出。 +1

以上是关于如何将带有自定义标头的任意 JSON 数据发送到 REST 服务器?的主要内容,如果未能解决你的问题,请参考以下文章

带有自定义标头的 C# HttpClient POST 请求发送不正确的 Content-Type 标头字段

带有自定义标头的 Ajax 请求发送到启用 CORS 的 Web API 服务器

如何发送带有自定义标题的表单

使用flash发送带有自定义标头的POST请求

如何将自定义标头从 mvc 项目发送到 Web api 项目?

HttpClient postasync,带有自定义标头和应用程序/json,用于正文 C#