c# - ObjectContent 不起作用,但 StringContent 起作用
问题描述
我正在尝试编写一个HttpClient.PutAsJsonAsync<T>
允许在每个请求上设置标头的重载。查看该方法的源代码,它在ObjectContent<T>
内部创建了一个,我试图在下面进行模拟。
[FromBody] Form form
但是,我的目标服务器在绑定(使用)时总是收到一个空正文。
如果我将请求更改为 aStringContent
并手动序列化正文,则请求成功!两种实现之间可能有什么区别?
更奇怪的是,如果我await content.ReadAsStringAsync()
之前 SendAsync
打电话,它也有效!
我的想法是它可能是:
- JSON 的序列化方式不同(但我没有在任何地方配置任何 Json.NET 全局变量。)明显的问题是大小写不同,但据我所知,JSON.net 在解析时不区分大小写,我的服务器将是使用 JSON.net
- 我不是在等待什么,而是在完全序列化之前发送内容。不过,我无法在我的代码中发现任何未等待的任务,并且入口点是标准的
async Main()
我的环境是:
- 客户端是一个简单的
netcoreapp2.1
exe,在microsoft/dotnet:2.1-sdk-alpine
docker 镜像中运行。 - 服务器是一个 .NET 框架 MVC5 WebApi,有许多类似的 API,其他客户端可以很好地调用
下面的代码是我的客户调用的精简版本。
public static class UserUpdater
{
public static async Task UpdateAsync(List<string> users)
{
using (var client = new HttpClient())
{
var form = new { Users = users };
var headers = new Dictionary<string, string>
{
["Authorization"] = "Bearer " // Real JWT here
};
var response = await client.PutAsJsonAsync(new Uri("http://localhost/api/app/v1/gateway-users"), form, headers);
if (!response.IsSuccessStatusCode)
{
throw new InvalidOperationException("Response status code does not indicate success: " +
response.StatusCode + "\n\n" +
await response.Content.ReadAsStringAsync());
}
}
}
public static async Task<HttpResponseMessage> PutAsJsonAsync<T>(this HttpClient client, Uri requestUri, T value,
IEnumerable<KeyValuePair<string, string>> headers, CancellationToken cancellationToken = default)
{
var content = new ObjectContent<T>(value, new JsonMediaTypeFormatter(), (MediaTypeHeaderValue)null);
////var content = new StringContent(JsonConvert.SerializeObject(value), Encoding.UTF8, "application/json"); // This works fine
var message = MakeRequestMessage(HttpMethod.Put, requestUri, headers, content);
return await client.SendAsync(message, cancellationToken);
}
private static HttpRequestMessage MakeRequestMessage(
[NotNull] HttpMethod method,
[NotNull] Uri requestUri,
[CanBeNull] IEnumerable<KeyValuePair<string, string>> headers,
[CanBeNull] HttpContent content = null)
{
var message = new HttpRequestMessage(method, requestUri);
if (headers != null)
{
foreach (var header in headers)
{
message.Headers.Add(header.Key, header.Value);
}
}
if (content != null)
{
message.Content = content;
}
return message;
}
如果有帮助,这是服务器端(MVC5 WebApi):
[Route("")]
[ValidateModel]
public IHttpActionResult Put([Required] [FromBody] GatewayUserCollectionForm form)
{
Ensure.NotNull(form, nameof(form)); // This throws since form is null
this.manager.UpdateGatewayUsers(form.Users.ToList());
return this.Ok();
}
public class GatewayUserCollectionForm
{
[Required]
public List<string> Users { get; set; }
}
解决方案
推荐阅读
- python - 将树节点的路径打印为列表
- perl - eval 不打印“Hello World”并且仍然输出到 stderr
- css - 将 flexbox 元素粘贴到容器的每一侧(一个元素在左侧,另一个在右侧)
- c - 如何逐位获取任意十进制数
- python - 无法通过 Windows 终端导入 django
- node.js - 如何删除猫鼬nodejs中id的所有引用?
- python - 条件结构——“if”和“elif”——没有显示正确的结果
- docker - 除非明确调用构建,否则从远程映像中拉取
- java - 将 jar 部署到 unix 服务器
- ruby - 如果 Ruby 中的程序创建散列并将这些散列保存在另一个文件中,它会是什么样子?