简体   繁体   中英

Has HttpContent.ReadAsAsync<T> method been superceded in .NET Core?

The following refers to a .NET Core application with dependencies as follows...

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

At Microsoft.com is the document Call a Web API From a .NET Client (C#) from 2017 November.

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

Within the document is this client side invocation of 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;
    }

The value response.Content refers to an HttpContent object. As of 2020 July HttpContent has no instance method with the signature ReadAsAsync<T>() , at least according to the following document. However, this instance method works.

Reference link to where there is no instance method with the signature ReadAsAsync<T>() ... https://docs.microsoft.com/en-us/dotnet/api/system.net.http.httpcontent?view=netcore-3.1

There is a static method HttpContentExtensions.ReadAsAsync<T>(myContent) where myContent refers to an HttpContent object. This static method also works.

Reference link... https://docs.microsoft.com/en-us/previous-versions/aspnet/hh834253(v=vs.118)

For example one documented signature has the...

static icon followed by ReadAsAsync<T>(HttpContent)

and a description that says it will return Task<T> . This static method is probably the behind the scenes implementation of the instance method.

However there is information at the top of the static method webpage that indicates... " We're no longer updating this content regularly. Check the Microsoft Product Lifecycle for information about how this product, service, technology, or API is supported. "

Has HttpContent.ReadAsAsync<T>() of both forms, instance and static, been superceded in .NET Core 3.1?

I can't tell from the code if it ever was an instance method but it probably was.

The links you included alternate between .net 4.x and .net core , it's not clear if you are aware of this. Labelling them with dates suggests a linear progression but we have a fork in the road.

And that is all, it was 'demoted' to residing in an additional package because it will be used less. In .net core we now have similar extensionmethods acting on HttpClient directly.


In order to use this with .net core 3.x you may have to add the System.Net.Http.Json nuget package. The extensions only work with System.Text.Json , for Newtonsoft you will have to use the traditional code patterns.


HttpClientJsonExtensions appears to be absent from .NET Core 3.1 online documentation as of 2020 July.

The other answers are not correct.

The method ReadAsAsync is part of the System.Net.Http.Formatting.dll

Which in turn is part of the nuget: Microsoft.AspNet.WebApi.Client

I just created a new Console project.Net Core 3.1 and added 2 nugets

  1. Newtonsoft
  2. Microsoft.AspNet.WebApi.Client

I created a project with .NET Core 3.1 here are some pictures: 在此处输入图像描述

Here is my project file: 在此处输入图像描述

Here is the code I just wrote which compiles just fine:

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

UPDATE:

To clear some confusion about the dependecies for package Microsoft.AspNet.WebApi.Client

Here is a picture of the dependecies showing as of 2020-10-27 the dependencies which clearly shows it depends on Newtonsoft JSON 10 or higher. As of today there is no replacement of ReadAsAsync using System.Text.Json... So you can use ApiClient + Newtonsoft Json or create your own using System.Text.Json

在此处输入图像描述

Something I used recently, I had to install Newtonsoft.Json

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

I actually found this in Microsoft documents on how to consume a REST API, and it worked. Your code is ok on the get part, assuming it has the right Uri,

Also something to not is my code wasn't static

If you don't want to install third party nuget packages, it's not too difficult to implement an extension method for this.

For example, using System.Text.Json :

using System.Net.Http;
using System.Text.Json;
using System.Threading.Tasks;
public static async Task<T> ReadAsAsync<T>(this HttpContent content) {
    string contentString = await content.ReadAsStringAsync();
    JsonSerializerOptions options = new JsonSerializerOptions {
        PropertyNamingPolicy = JsonNamingPolicy.CamelCase
    };
    return (T)JsonSerializer.Deserialize(contentString, typeof(T), options);
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM