HttpClient.SendAsync() 未将 JSON 作为字符串发送

Posted

技术标签:

【中文标题】HttpClient.SendAsync() 未将 JSON 作为字符串发送【英文标题】:HttpClient.SendAsync() is not sending JSON as string 【发布时间】:2017-09-29 18:29:46 【问题描述】:

我无法弄清楚 HttpClient 脚本出了什么问题。

当我使用 Fiddler 时,它可以工作,而且 AspNetCore MVC 不会抛出错误。

 http://localhost:6004/api/XUnitExamplesTest/JsonStringMethod

 Http-Get

 User-Agent: Fiddler
 Accept: text/json
 Content-Type: text/json
 Host: localhost:6004
 Content-Length: 24

 "\"Color\": \"Green\""

但 HttpClient 脚本会导致 AspNetCore MVC 问题。

var sampleData = new XUnitSampleData()  Color = "Red" ;
var contentType = "text/json";
var httpMethod = HttpMethod.Get;
var uriPath = "JsonStringMethod";
var jsonData = JsonConvert.SerializeObject(_sampleData, Formatting.None).ToString();  // JSON String.  --> " \"Vin\" : \"foo\", \"Color\" : \"foo\" "
var jsonRequest = string.Format("\"0\"", jsonData);

var result = await XUnitWebClient.GetAsync3(contentType, httpMethod, uriPath, jsonRequest, CancellationToken.None);


public static async Task<string> GetAsync3(string contentType, HttpMethod httpMethod, string uriPath, string request, CancellationToken cancellationToken)

    using (var httpClient = new HttpClient())  
    
        using (var httpRequestMessage = new HttpRequestMessage(httpMethod, string.Format("01", _uri, uriPath)))
        
            httpClient.BaseAddress = new Uri(string.Format("0", _baseAddress));

            //httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue(contentType));  // "Accept" Header.

            //httpClient.DefaultRequestHeaders.Remove("Content-Type");
            //httpClient.DefaultRequestHeaders.Add("Content-Type", contentType);

            httpRequestMessage.Content = new StringContent(request, Encoding.UTF8, contentType);  // "Content-Type" Header.

            var response = await httpClient.SendAsync(httpRequestMessage);

            return await response.Content.ReadAsStringAsync();
        
    

AspNetCore MVC 得到的 JSON 值为""

由于我使用的是 text/json,所以我如何告诉 HttpClient 发送带有开头引号和结尾引号的 json 字符串,而不是去掉它?

或者我在这里对 JsonConvert.SerializeObject() 做错了什么?

【问题讨论】:

客户端还是服务器端? JSON 字符串两端的双引号,当我通过 freeformatter.com/json-validator.html 运行它时,它表示它是有效的 JSON 字符串。因此,当发送到服务器端(AspNetCore MVC)时,它应该在客户端(HttpClient)上工作。如果 text/json 两端没有双引号,AspNetCore MVC 将不会接受它 回答您关于 Fiddler 示例的问题。如果两端没有双引号,则会导致 AspNetCore MVC 异常,其中 Newtonsoft.Json.JsonInputFormatter & Newtonsoft.Json.JsonReaderException 遇到错误。但是在两端加上双引号就可以了。 我的立场是正确的 - 从技术上讲,JSON string 本身就是有效的 JSON。尽管如此,要求客户端对 JSON 进行刺痛,而不是直接发送它是非常尴尬的。我会尝试回答。 另一个观察结果 - 在 GET 请求中发送 JSON 正文(或任何正文)并不常见。 color: green 是列表过滤器还是类似的东西?将其作为查询字符串参数传递更为常见。 我的手被绑了。必须遵守陷入自身集成混乱的第 3 方提供商。不过它的很多客户都在使用它。 【参考方案1】:

直接回答问题...

您没有转义 JSON 字符串中的引号。试试这个:

var jsonRequest = string.Format("\"0\"", jsonData.Replace("\"", "\\\""));

但是...

我质疑您是如何解决这个问题的。您在 cmets 中提到,如果您不在客户端对 JSON 进行字符串化,则会在服务器端(在您的 MVC 代码中)出现错误。但是,要求客户这样做是非常尴尬和不标准的。我会:

    将内容类型从 text/json 更改为 application/json。这不能解决问题,但这是标准。

    去掉上面那行,直接发送jsonData。即不要将 JSON 字符串化。

    提出一个关于如何解决您遇到的服务器端错误的新问题,并发布相关的 MVC 代码。

【讨论】:

Replace() 对象中怎么会有双斜线?它有什么作用? 转义转义字符。 C# 中的"\\" 将按字面意思呈现为 \,这就是您想要在这里结束的内容。你实际上是双重转义,这就是它看起来很奇怪的原因。 实际上,我刚刚更新了它 - 你需要 3 个反斜杠。第一个转义第二个,第三个转义引用。够迷惑吗? :) 感谢您的编辑。第 3 方提供者需要 text/json。 :-/ 所以,我正在构建客户端以发出 3rd 方提供程序,作为 xUnit 测试的一部分,因此我们在未来升级时不会破坏任何东西。 :-/

以上是关于HttpClient.SendAsync() 未将 JSON 作为字符串发送的主要内容,如果未能解决你的问题,请参考以下文章

HttpClient.SendAsync 不发送请求正文

HttpClient.SendAsync 方法退出而不抛出异常

HttpClient SendAsync

模拟 HttpClient.SendAsync 以返回内容不为空的响应

如何从 Httpclient.SendAsync 调用中获取和打印响应

HttpClient.SendAsync:500 - Windows 服务应用程序中的内部服务器错误