C# HttpClient.PostAsJsonAsync() 失败,即使通过 PostMan 发出完全相同的请求也是如此

MY_*_*Y_G 4 .net c# elasticsearch

我在这里以及Elastic 讨论论坛上都发现了类似的问题,但不幸的是,没有一个答案有帮助。

我目前正在使用ElasticSearch 7.0.

我想向我的 ElasticSearch 服务器发出批量请求。我的 JSON 文件包含如下所示的信息:

{ "index": { "_index": "website", "_id": "link1" }}
{ "label":    "Link1" }
Run Code Online (Sandbox Code Playgroud)

每行都以换行符结束,并且在文档末尾LF还有一个额外的换行符。LF

在 C# 中,以下是我对批量数据发出 POST 请求的方法:

HttpResponseMessage response = await httpClient.PostAsJsonAsync($"http://127.0.0.1:9200/website/_bulk", jsonDocumentContents);

但我仍然看到此错误消息:

{"error":{"root_cause":[{"type":"illegal_argument_exception","reason":"The bulk request must be terminated by a newline [\\n]"}],"type":"illegal_argument_exception","reason":"The bulk request must be terminated by a newline [\\n]"},"status":400}

我该如何修复这个错误?

更新:

关于如何将 JSON 文档内容读入jsonDocumentContents变量的简短描述:JSON 文档存储在压缩文件夹内,因此检索它需要解压缩:

ZipArchive archive = new ZipArchive(zippedFolderStream);
foreach (ZipArchiveEntry entry in archive.Entries)
{
    string jsonDocumentContents = new StreamReader(entry.Open()).ReadToEnd();
    HttpResponseMessage response = await httpClient.PostAsJsonAsync($"http://127.0.0.1:9200/website/_bulk", jsonDocumentContents);
    Console.WriteLine(await response.Content.ReadAsStringAsync());
}
Run Code Online (Sandbox Code Playgroud)

更新:

我刚刚使用 PostMan 发出了内容完全相同的批量请求,并且请求成功。但是,当我使用 C# 在 C# 中发出相同的批量请求时,错误消息仍然存在httpClient.PostAsJsonAsync(...)

MY_*_*Y_G 5

我通过将代码更改为以下内容来使其工作:

ZipArchive archive = new ZipArchive(zippedFolderStream);
foreach (ZipArchiveEntry entry in archive.Entries)
{
    string jsonDocumentContents = new StreamReader(entry.Open()).ReadToEnd();
    StringContent content = new StringContent(jsonDocumentContents, Encoding.ASCII, mediaType: "application/json");
    HttpResponseMessage response = await httpClient.PostAsync($"http://127.0.0.1:9200/website/_bulk", content);
    Console.WriteLine(await response.Content.ReadAsStringAsync());
}
Run Code Online (Sandbox Code Playgroud)

请注意,我使用的HttpClient.PostAsync()HttpClient.PostAsJsonAsync(), 来StringContent指定"application/json"其媒体类型的实例。

我查看了的源代码HttpClient,发现JsonMediaTypeFormatter每次HttpClient.PostAsJsonAsync调用时都会创建一个新实例。

由于我POST通过PostMan发出请求时是成功的,所以问题一定是由如何PostAsJsonAsync()实现引起的。我怀疑(但尚未验证)该问题是由于JsonMediaTypeFormatter类中的默认属性造成的。

为了避免这个问题,我决定使用Http.PostAsync()正确配置的StringContent实例。

你瞧,我现在可以使用 C# 向我的 ElasticSearch 服务器发送批量请求。