Getting issue while using HttpClient/HttpClientFactory in .net core

949 Views Asked by At

We have implemented IHttpClientFactory to make the third party calls using HttpClient in .NET Core. However, we are still getting the below errors.

System.IO.IOException: Unable to read data from the transport connection: The I/O operation has been aborted because of either a thread exit or an application request.

System.Net.Sockets.SocketException (995): The I/O operation has been aborted because of either a thread exit or an application request

System.Net.Http.HttpRequestException: An error occurred while sending the request.   ---> System.IO.IOException: The response ended prematurely

This is the code in which we have configured the things:

Startup.cs

builder.Services
       .AddHttpClient<IRequestHandler, RequestHandler>()
       .SetHandlerLifetime(TimeSpan.FromMinutes(5))
       .ConfigurePrimaryHttpMessageHandler(_ => new HttpClientHandler
       {
           SslProtocols = SslProtocols.Tls12 | SslProtocols.Tls13
       })
       .AddPolicyHandler(retryPolicyHttp);

services.AddTransient<IRequestHandler, RequestHandler>();

RequestHandler.cs

public class RequestHandler: IRequestHandler
{
    private readonly IHttpClientFactory _httpClientFactory;

    public RequestHandler(IHttpClientFactory httpClientFactory)
    {
        _httpClientFactory = httpClientFactory;
    }

    public virtual HttpResponseMessage ExecuteThirdPartyServices(HttpMethod httpMethod, string 
                           postData, RequestModel requestModel)
    {
        using HttpRequestMessage request = new(httpMethod, requestModel.RequestUri);
        
        HttpResponseMessage httpMessageResponse;

        using (var httpClient = _httpClientFactory.CreateClient())
        {
            httpClient.Timeout = TimeSpan.FromMinutes(5);
            httpMessageResponse = httpClient.SendAsync(request).Result;
        }

        return httpMessageResponse;
    }
}

I have tried all sort of options to resolve these errors but still we are not able to pass these errors and we keep on getting these errors.

Any help on this is appreciated!

2

There are 2 best solutions below

0
Mustafa Özçetin On

Not sure about the actual reason of the errors but I suspect the line (because of using Result)

httpClient.SendAsync(request).Result;

What about changing this method to async and awaiting the SendAsync() line?

await httpClient.SendAsync(request);
3
Angel Yordanov On

First about your Startup.cs. You have two registrations for the same service .AddHttpClient<IRequestHandler, RequestHandler>() and .AddTransient<IRequestHandler, RequestHandler>();. The second one is the one being used if you try to inject an IRequestHandler. Which means your setup for the SSL is not being used and may be the reason for the error.

I would suggest you remove the second registration and use the first one. I also doubt you need this SetHandlerLifetime and would suggest that you should remove it.

Than there is the .Result blocking in your code. Generally you should never use .Result or .Wait() and do async all the way, but if you really want a blocking call you better do GetAwaiter().GetResult(), check Stephen Cleary's writings on the matter, he should be your go-to guide on all things async.

// Startup.cs

services
    .AddHttpClient<IRequestHandler, RequestHandler>(httpClient =>
    {  
        httpClient.Timeout = TimeSpan.FromMinutes(5);
    })
    .ConfigurePrimaryHttpMessageHandler(_ =>
        new HttpClientHandler
        {
            SslProtocols = SslProtocols.Tls12 | SslProtocols.Tls13
        })
    .AddPolicyHandler(retryPolicyHttp);
// RequestHandler.cs

public class RequestHandler: IRequestHandler
{
    private readonly HttpClient _httpClient;

    public RequestHandler(HttpClient httpClient)
    {
        _httpClient = httpClient;
    }

    public virtual HttpResponseMessage ExecuteThirdPartyServices(
        HttpMethod httpMethod,
        string postData,
        RequestModel requestModel)
    {
        using HttpRequestMessage request = new(httpMethod, requestModel.RequestUri);
        
        return _httpClient.SendAsync(request).GetAwaiter().GetResult();
    }
}