【问题标题】:Has HttpContent.ReadAsAsync<T> method been superceded in .NET Core?.NET Core 中是否已取代 HttpContent.ReadAsAsync<T> 方法?
【发布时间】:2021-09-29 14:56:36
【问题描述】:

以下指的是一个.NET Core应用,依赖如下...

Microsoft.NETCore.App
Microsoft.AspNet.WepApi.Client (5.2.7)

在 Microsoft.com 上是 2017 年 11 月的文档 Call a Web API From a .NET Client (C#)

链接...https://docs.microsoft.com/en-us/aspnet/web-api/overview/advanced/calling-a-web-api-from-a-net-client

在文档中是 HTTP GET 的客户端调用。

    static HttpClient client = new HttpClient();
    static async Task<Product> GetProductAsync(string path)
    {
        Product product = null;
        HttpResponseMessage response = await client.GetAsync(path);
        if (response.IsSuccessStatusCode)
        {
            product = await response.Content.ReadAsAsync<Product>();
        }
        return product;
    }

response.Content 指的是HttpContent 对象。截至 2020 年 7 月,HttpContent 没有签名为ReadAsAsync&lt;T&gt;() 的实例方法,至少根据以下文档。但是,此实例方法有效。

没有带有签名ReadAsAsync&lt;T&gt;()的实例方法的参考链接... https://docs.microsoft.com/en-us/dotnet/api/system.net.http.httpcontent?view=netcore-3.1

有一个静态方法HttpContentExtensions.ReadAsAsync&lt;T&gt;(myContent),其中myContent 指的是HttpContent 对象。这种静态方法也有效。

参考链接... https://docs.microsoft.com/en-us/previous-versions/aspnet/hh834253(v=vs.118)

例如,一个记录在案的签名具有...

静态图标后跟ReadAsAsync&lt;T&gt;(HttpContent)

还有一个说明它将返回Task&lt;T&gt;。这个静态方法很可能是实例方法的幕后实现。

但是,静态方法网页顶部的信息表明... "我们不再定期更新此内容。请查看 Microsoft 产品生命周期,了解有关如何支持此产品、服务、技术或 API 的信息。"

HttpContent.ReadAsAsync&lt;T&gt;() 两种形式(实例和静态)是否已在 .NET Core 3.1 中被取代?

【问题讨论】:

  • 虽然文档令人困惑,并且不能保证 2017 年 11 月应该可以工作,但我决定接受它作为 .NET Core 项目的“足够好”示例。
  • 这个链接可能会在 2020 年 7 月 28 日引起人们的兴趣。visualstudiomagazine.com/articles/2020/07/28/… 引用它...“但是请注意,NuGet 并不能说明整个故事,因为 System.Text.Json 库包含在 .NET Core 3.0 共享框架中,而对于其他目标框架,开发者需要安装 System.Text.Json NuGet 包。”
  • 截至今天,在 .Net Core 3.1 中仍然没有替代 ReadAsAsync...。您必须创建自己的...或继续使用 ApiClient 版本 5.2.7,这很明显依赖于 Newtonsoft JSON

标签: c# asp.net-core httpresponse


【解决方案1】:

其他答案不正确。

方法 ReadAsAsync 是 System.Net.Http.Formatting.dll 的一部分

这又是 nuget 的一部分:Microsoft.AspNet.WebApi.Client

我刚刚创建了一个新的控制台项目 .Net Core 3.1 并添加了 2 个 nugets

  1. 牛顿软件
  2. Microsoft.AspNet.WebApi.Client

我使用 .NET Core 3.1 创建了一个项目,这里有一些图片:

这是我的项目文件:

这是我刚刚编写的代码,编译得很好:

using System;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Threading.Tasks;

namespace Custom.ApiClient
{
    internal static class WebApiManager
    {
        //private const string _requestHeaderBearer = "Bearer";
        private const string _responseFormat = "application/json";

        private static readonly HttpClient _client;

        static WebApiManager()
        {

            // Setup the client.
            _client = new HttpClient { BaseAddress = new Uri("api url goes here"), Timeout = new TimeSpan(0, 0, 0, 0, -1) };

            _client.DefaultRequestHeaders.Accept.Clear();
            _client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue(_responseFormat));

            // Add the API Bearer token identifier for this application.
            //_client.DefaultRequestHeaders.Add(RequestHeaderBearer, ConfigHelper.ApiBearerToken);       
        }

        public static async Task<T> Get<T>()
        {
            var response = _client.GetAsync("api extra path and query params go here");

            return await ProcessResponse<T>(response);
        }

        private static async Task<T> ProcessResponse<T>(Task<HttpResponseMessage> responseTask)
        {
            var httpResponse = await responseTask;

            if(!httpResponse.IsSuccessStatusCode)
                throw new HttpRequestException(httpResponse.ToString());

            var dataResult = await httpResponse.Content.ReadAsAsync<T>();

            return dataResult;
        }
    
    }
}

更新:

为了消除对包 Microsoft.AspNet.WebApi.Client 的依赖项的一些混淆

这是显示截至 2020 年 10 月 27 日的依赖项的图片,这些依赖项清楚地表明它依赖于 Newtonsoft JSON 10 或更高版本。到今天为止,没有使用 System.Text.Json 替代 ReadAsAsync... 所以您可以使用 ApiClient + Newtonsoft Json 或使用 System.Text.Json 创建自己的

【讨论】:

  • 好的,这适用于 NewtonSoft。您可能需要它来实现一些向后兼容性,但 System.Text.Json 是前进的方向,通常速度快 20%。
  • @HenkHolterman 如果您看到 Microsoft.AspNet.WebApi.Client 依赖于 Newtonsoft 的图片,它是他根据问题安装的软件包。至于“更快”,它适用于某些场景......但对于很多事情 System.Text.Json 还没有完成......我不会在生产中使用它。它仍然有很多粗糙的边缘。到目前为止,最稳定的 .net json 序列化器是 Newtonsoft,下载量超过 5 亿次。
  • 您的代码依赖于与我相同的对象。您的代码使用HttpClient.GetAsync()HttpConent.ReadAsAsync&lt;T&gt;()。我的代码在没有 Newtonsoft 的情况下也可以工作,因此您的代码很可能不需要 Newtonsoft。
  • @H2ONaCl 你错了。包 Microsoft.AspNet.WebApi.Client 确实依赖于 Newtonsoft JSON .....只需查看依赖列表..... ReadAsAsync 依赖于 Newtonsoft JSON,截至今天,使用 System. Text.Json...您必须创建自己的。
  • @H2ONaCl 此外,当您安装软件包 Microsoft.AspNet.WebApi.Client 5.2.7 时,它会自动安装 Newtonsoft JSON 版本 10 作为依赖...我建议您手动将 Newtonsoft JSON 升级到最新版本
【解决方案2】:

我无法从代码中判断它是否曾经是实例方法,但它可能是。

您包含的链接在 .net 4.x.net core 之间交替出现,不清楚您是否知道这一点。用日期标记它们表明线性进展,但我们有一个岔路口。

仅此而已,它被“降级”为驻留在额外的包中,因为它将被使用得更少。在 .net 核心中,我们现在有类似的扩展方法直接作用于 HttpClient。


为了在 .net core 3.x 中使用它,您可能需要添加 System.Net.Http.Json nuget 包。扩展仅适用于System.Text.Json,对于 Newtonsoft,您将不得不使用传统的代码模式。

【讨论】:

  • 很高兴知道这一点。但是,在 HttpClientExtensions 中我没有看到 GET 方法。它们都是 POST 和 PUT。 docs.microsoft.com/en-us/previous-versions/aspnet/…
  • 你必须清楚想要 4.x 或核心。还有一个与 NewtonSoft vs System.Text.Json 的纠葛。
  • 在 .net 核心中我们有 HttpClientJsonExtensions 和 GetFromJsonAsync&lt;&gt;()
  • 我想要核心。不幸的是,并非所有文档页面都有一个下拉列表来仅选择核心文档。我会研究 HttpClientJsonExtensions,谢谢。
  • HttpClientJsonExtensions 似乎在 2020 年 7 月没有出现在 .NET Core 中。
【解决方案3】:

如果你不想安装第三方的nuget包,为此实现一个扩展方法并不难。

例如,使用System.Text.Json:

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

public static class HttpContentExtensions {

    private static readonly JsonSerializerOptions defaultOptions = new JsonSerializerOptions {
        PropertyNameCaseInsensitive = true,
        PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
    };

    public static async Task<T> ReadAsAsync<T>(this HttpContent content, JsonSerializerOptions options = null) {
        using(Stream contentStream = await content.ReadAsStreamAsync()) {
            return await JsonSerializer.DeserializeAsync<T>(contentStream, options ?? defaultOptions);
        }
    }

}

【讨论】:

    【解决方案4】:

    最近用的东西,必须安装Newtonsoft.Json

    string responseContent = await response.Content.ReadAsStringAsync();
    var productResult = JsonConverter.DeserializeObject<Product>(responseContent);
    

    我实际上是在有关如何使用 REST API 的 Microsoft 文档中找到它,并且它确实有效。你的代码在 get 部分没问题,假设它有正确的 Uri,

    还有一点是我的代码不是静态的

    【讨论】:

    • 阅读此答案的任何人只需 2 美分。这可行,但考虑到它分配的字符串是不必要的步骤。
    • product = JsonConverter.DeserialzeObject(await response.Content.ReadAsStringAsync());
    • 仍在分配字符串
    • Read as string 会将内容读取为字符串,然后将该字符串反序列化为对象。支持将流直接读取到对象,因此不需要先读取字符串的中间步骤
    • 你可以在这里阅读它以获得 newtonsoft 的支持:newtonsoft.com/json/help/html/Performance.htm
    猜你喜欢
    • 2016-12-04
    • 2020-10-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-01-22
    • 2019-05-25
    相关资源
    最近更新 更多