Search code examples
c#httpclientdotnet-httpclientc#-9.0

HttpClient null warning in C# 9+


I've just migrated an .NET3.1 application to .NET6 (I am using VS 2022) and I noticed that they've introduced some constraints related to nullable types. I fixed all my code to follow best practices, but not sure how to go about this issue:

When creating a new HttpClient instance it returns a nullable HttpClient type (code is executed inside a Polly retry policy):

   public async Task<List<InterestedParty>> GetInterestedPartiesAsync()
    {
        return await _retryPolicy.ExecuteAsync(async () =>
        {
            using var client = new HttpClient()
            const string endpoint = "my-endpoint";
            var url = $"{endpoint}/test";

            var response = await client.GetAsync(url);
            response.EnsureSuccessStatusCode();

            var jsonString = await response.Content.ReadAsStringAsync();
            return JsonConvert.DeserializeObject<List<InterestedParty>>(jsonString);
        });
    }

enter image description here

The compiler is complaining about a possible null reference return. I know I could suppress the warning by using:

#pragma warning disable CS8603 // Possible null reference return.

but I don't think it's the best solution.

Any other suggestions? Thank you.


Solution

  • The issue itself it's not related to HttpClient as I thought in the beginning.

    The return type of the method it's Task<List> and inside the using statement I was returning

    JsonConvert.DeserializeObject<List<InterestedParty>>(jsonString); Indeed, the deserialized object can be null, so one solution would be add the "null forgiving" operator (!) at the end:

       public async Task<List<InterestedParty>> GetInterestedPartiesAsync()
        {
            return await _retryPolicy.ExecuteAsync(async () =>
            {
                using var client = new HttpClient();
                const string endpoint = "my-endpoint";
                var url = $"{endpoint}/test";
    
                var response = await client.GetAsync(url);
                response.EnsureSuccessStatusCode();
    
                var jsonString = await response.Content.ReadAsStringAsync();
                return JsonConvert.DeserializeObject<List<InterestedParty>>(jsonString)!;
            });
        }
    

    Another better suggestion would be :

      public async Task<IEnumerable<InterestedParty>> GetInterestedPartiesAsync()
    {
        return await _retryPolicy.ExecuteAsync(async () =>
        {
            using var client = new HttpClient();
            const string endpoint = "my-endpoint";
            var url = $"{endpoint}/test";
    
            var response = await client.GetAsync(url);
            response.EnsureSuccessStatusCode();
    
            var jsonString = await response.Content.ReadAsStringAsync();
            return JsonConvert.DeserializeObject<List<InterestedParty>>(jsonString) ??
                   Enumerable.Empty<InterestedParty>();
        });
    }
    

    Thanks @JeroenMostert and @DavidG for your suggestion.