ASP.NET 核心 3.1 的 JsonHttpContent

JsonHttpContent with ASP.NET Core 3.1

我创建了一个自定义 HttpContent 以使用 System.Text.Json 和 HttpClient 有效地发送对象。遗憾的是,关于如何正确执行此操作的文档很少。以下 class 导致在我的测试端点出现格式错误的 JSON 数据错误。查看 wireshark 中的数据包显示仅传输了一个空的 json 对象 ({})。我还尝试刷新流(相同的结果)或在写入流后将其处置(这导致有关 tring 访问已处置对象的错误)。

using System.IO;
using System.Net;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
using System.Text.Json;
using System.Threading.Tasks;

namespace Common
{
    public sealed class JsonContent : HttpContent
    {
        private readonly object _content;
        private readonly JsonSerializerOptions _options;

        public JsonContent(object content, JsonSerializerOptions options)
        {
            _content = content;
            _options = options;
            Headers.ContentType = new MediaTypeHeaderValue("application/json")
            {
                CharSet = Encoding.UTF8.WebName
            };
        }

        protected override Task SerializeToStreamAsync(Stream stream, TransportContext context)
        {
            return JsonSerializer.SerializeAsync(stream, _content, _options);
        }

        protected override bool TryComputeLength(out long length)
        {
            length = 0;
            return false;
        }
    }
}

整个东西是这样使用的:

public static async Task<HttpResponseMessage> PostAsJsonAsync<T>(this HttpClient client, string url, T content,
    CancellationToken ct = default) where T : class
{
    return await client.PostAsync(url, new JsonContent(content, Json.DefaultSerializerOptions), ct);
}

我在这里错过了什么?

你的对象是否包含字段或属性..System.Text.Json不会序列化字段..

看来,你错过了_content的类型。试试这个:

protected override Task SerializeToStreamAsync(Stream stream, TransportContext context)
{
    return JsonSerializer.SerializeAsync(stream, _content, _content.GetType(), _options);
}

你调用的方法实际上是SerializeAsync<TValue>(...),它使用typeof(TValue)作为序列化的类型。因为你的 _contentobject 的实例,所以 TValue 在这种情况下是 object,因此 _content 被序列化为 object。这就是为什么你只看到 {}.

此修复调用了另一个重载 SerializeAsync(...),它允许您指定要序列化的正确类型。