HttpContent 错误请求 {"error":{"message":"Mandatory parameter missed","error_key":null}}

HttpContent Bad request {"error":{"message":"Mandatory parameter missed","error_key":null}}

我正在尝试使用 HttpClient 做一个简单的 POST,但我在使用 HttpRequestMessage.Content 时遇到了一些问题。 \n 简而言之,如果我在没有 escape character 的情况下对其中一个必需参数进行硬编码,例如:

string value = "lorem ipsum lorem ipsum lorem ipsum lorem ipsum";
request.Content = new StringContent("{\"requiredParameter\":\""+ value +"\}");

一切正常。

但是,如果我按如下方式连接字符串:

string value = "\norem ipsum \n" +
                       "lorem ipsum \n" +
                       "lorem ipsum\n";
or even
//string value = "\nlorem ipsum lorem ipsum lorem ipsum lorem ipsum";
request.Content = new StringContent("{\"requiredParameter\":\""+ value +"\}");

它没有,我收到一个错误的请求:

Status code: BadRequest
{"error":{"message":"Mandatory parameter missed","error_key":null}}

已经尝试过

System.Text.Json.JsonSerializer.Serialize

 var options = new JsonSerializerOptions
 {
           WriteIndented = true,
  };
string json = System.Text.Json.JsonSerializer.Serialize(value, options);

StringBuilder 因为它更适合大量的字符串操作。

string value1 = "\nlorem ipsum \n";
string value2 = "lorem ipsum \n";
string value3 = "lorem ipsum\n";

 stringBuilder.Append(value1);
 stringBuilder.Append(value2);
 stringBuilder.Append(value3);

request.Content = new StringContent("{\"requiredParameter\":\""+ stringBuilder.toString() +"\}");

并且,Encoding.UTF8,“application/json”

request.Content = new StringContent("{\"requiredParameter\":\""+ value +"\", Encoding.UTF8, "application/json");

没有成功。

最小复制:

static async Task<string> postAsync(Uri uri, string postContent)
{
    using (var httpClient = new HttpClient())
    {
        using (var request = new HttpRequestMessage(new HttpMethod("POST"), "https://www.url.com/"))
        {
                   request.Headers.TryAddWithoutValidation("authority", "www.url.com");
                   request.Headers.TryAddWithoutValidation("accept", "application/json, text/plain, */*");
                   request.Headers.TryAddWithoutValidation("x-oauth2-required", "true");                   
                   
                   request.Content = new StringContent("{\"requiredParameter\":\""+ value +"\}");

                   return await response.Content.ReadAsStringAsync();
            }
      }
}                    

static async Task Main(string[] args)
{
    Uri uri = new Uri("www.uri.com");
    var postContent = GenerateDynamicStringContent(List<string> params);
    await PostAsync(uri, postContent);
}

我在这里错过了什么?

不同的是,第二和第三个选项,lorem ipsum之间没有space。

如果您在 concatenate 字符串(每行末尾)中给出空的 spaces 并且在 stringBuilder 中类似,那么它们将与第一个相同。

带连接

string value = "lorem ipsum " +
                       "lorem ipsum " +
                       "lorem ipsum ";

使用 StringBuilder

string value1 = "lorem ipsum ";
string value2 = "lorem ipsum ";
string value3 = "lorem ipsum";

 stringBuilder.Append(value1);
 stringBuilder.Append(value2);
 stringBuilder.Append(value3);

首先,您没有意识到您实际上并不需要任何 string 操作来构建 JSON。 JsonSerializer 会为你做的。

考虑以下示例。

using System.Text.Json;
using System.Net.Http;
public class Program
{
    private static readonly HttpClient client = new HttpClient();

    public async Task Main()
    {
        Dictionary<string, string> values = new Dictionary<string, string>();
        values.Add("lorem1", "ipsum1");
        values.Add("lorem2", "ipsum2");
        values.Add("lorem3", "ipsum3");
        JsonSerializerOptions options = new JsonSerializerOptions
        {
            WriteIndented = true // these Options are not mandatory, just for pretty json formatting for debugging purpose
        };
        string json = JsonSerializer.Serialize(values, options);
        Console.WriteLine(json);
        string result = await PostJsonAsync("https://myapi.url/api", json);
        // handle result here
    }

    private static async Task<string> PostJsonAsync(string url, string json)
    {
        using HttpContent content = new StringContent(json, Encoding.UTF8, "application/json");
        using HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, url);
        request.Content = content;
        using HttpResponseMessage response = await client.SendAsync(request).ConfigureAwait(false);
        return await response.Content.ReadAsStringAsync();
    }
}

输出

{
  "lorem1": "ipsum1",
  "lorem2": "ipsum2",
  "lorem3": "ipsum3"
}

How to serialize and deserialize (marshal and unmarshal) JSON in .NET

更新

我发现发送的数据破坏了 json 结构并导致服务器在 deserealize 过程中失败。

然后创建数据class。它称为数据模型。上面的 link 详细描述了如何做,但我会展示这个例子。不要害怕阅读。我已经完全回答了你的问题,但是你没有弄清楚。

public class MyPostDataClass
{
    [JsonPropertyName("requiredParameter")] // the attribute needed only if Property name differs from the json field name
    public string RequiredParameter { get; set; }
}

那么简单

string postContent = GenerateDynamicStringContent(List<string> params);
MyPostDataClass postData = new MyPostDataClass();
postData.RequiredParameter = postContent;
string json = JsonSerializer.Serialize(postData);
string result = await PostJsonAsync("https://myapi.url/api", json);

使用答案中的 post 方法,删除多余的 Headers 设置,使用我的 StringContent 构造函数。不要设置任何 headers,StringContent 会为您正确设置。不要每个请求实例化new HttpClient,这是错误的,使用上面显示的方式。