首页 > 解决方案 > ObjectContent 不起作用,但 StringContent 起作用

问题描述

我正在尝试编写一个HttpClient.PutAsJsonAsync<T>允许在每个请求上设置标头的重载。查看该方法的源代码,它在ObjectContent<T>内部创建了一个,我试图在下面进行模拟。

[FromBody] Form form但是,我的目标服务器在绑定(使用)时总是收到一个空正文。

如果我将请求更改为 aStringContent并手动序列化正文,则请求成功!两种实现之间可能有什么区别?

更奇怪的是,如果我await content.ReadAsStringAsync() 之前 SendAsync打电话,它也有效!

我的想法是它可能是:

我的环境是:

下面的代码是我的客户调用的精简版本。

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; }
    }

标签: c#dotnet-httpclient

解决方案


推荐阅读