Search code examples
c#asp.net-core-webapi.net-6.0dotnet-httpclient

.NET Core HttpClient exception


I am using .NET 6 to develop the core Web API, I have a abstract class AdminApiClient inherit ApiClientBase class like below:

public abstract class AdminApiClient : ApiClientBase
{
    protected static HttpClient? client;

    public AdminApiClient()
    {
        client = client ?? new HttpClient
        {
            BaseAddress = new Uri("http://localhost:44355/")
        };
    }

    protected override HttpClient GetHttpClient()
    {
        return client;
    }
}

Below is my ApiClientBase class, When I call the Test method, declare new httpClient inside method is working fine, but when calling GetHttpClient() throw exception.

public abstract class ApiClientBase
{
    protected abstract HttpClient GetHttpClient();

    protected async Task<TResult> Test<TResult>()
    {
        var apiName = "api/users/GetTest";

        var httpClient = new HttpClient();

        httpClient.BaseAddress = new Uri("https://localhost:44355/");

        //working fine
        var response1 = await httpClient.GetAsync(apiName);

        //throw error exception
        var response2 = await GetHttpClient().GetAsync(apiName);
    }
}

I am not sure why using code below is fine.

 var response1 = await httpClient.GetAsync(apiName);

But throw exception when using code below:

var response2 = await GetHttpClient().GetAsync(apiName);

Exception message:

"System.Net.Http.HttpRequestException: An error occurred while sending the request.\r\n ---> System.IO.IOException: Unable to read data from the transport connection: An existing connection was forcibly closed by the remote host..\r\n ---> System.Net.Sockets.SocketException (10054): An existing connection was forcibly closed by the remote host.\r\n --- End of inner exception stack trace ---\r\n at System.Net.Sockets.Socket.AwaitableSocketAsyncEventArgs.ThrowException(SocketError error, CancellationToken cancellationToken)\r\n at System.Net.Sockets.Socket.AwaitableSocketAsyncEventArgs.System.Threading.Tasks.Sources.IValueTaskSource<System.Int32>.GetResult(Int16 token)\r\n at System.Net.Http.HttpConnection.InitialFillAsync(Boolean async)\r\n
at System.Net.Http.HttpConnection.SendAsyncCore(HttpRequestMessage request, Boolean async, CancellationToken cancellationToken)\r\n --- End of inner exception stack trace ---\r\n at System.Net.Http.HttpConnection.SendAsyncCore(HttpRequestMessage request, Boolea n async, CancellationToken cancellationToken)\r\n at System.Net.Http.HttpConnectionPool.SendWithVersionDetectionAndRetryAsync(HttpRequestMessage request, Boolean async, Boolean doRequestAuth, CancellationToken cancellationToken)\r\n at System.Net.Http.DiagnosticsHandler.SendAsyncCore(HttpRequestMessage request, Boolean async, CancellationToken cancellationToken)\r\n at System.Net.Http.RedirectHandler.SendAsync(HttpRequestMessage request, Boolean async, CancellationToken cancellationToken)\r\n at System.Net.Http.HttpClient.g__Core|83_0(HttpRequestMessage request, HttpCompletionOption completionOption, CancellationTokenSource cts, Boolean disposeCts, CancellationTokenSource pendingRequestsCts, CancellationToken originalCancellationToken)\r\n at Web.Core.ApiClientBase.Test() in C:\Web.Core\ApiClientBase.cs:line 76"


Solution

  • Behaviour is different because the addresses are different:

    http://localhost:44355/
    https://localhost:44355/
    

    It looks like the API you're connecting to is http only (despite using the https-ish port 44355).

    Please note that you should be able to reproduce the issue in your browser by trying to go to both addresses.