4

I have an ASP.NET Core application which needs to cyclically call a web service.

I instantiated a HostedService:

public class MyHostedService : IHostedService
{
    public MyHostedService(IMyWebServiceClient MyWebServiceClient)
    {
      ...
    }

    public Task StartAsync(CancellationToken cancellationToken)
    {
       while (!cancellationToken.IsCancellationRequested)
       {
           var result = await myWebServiceClient.CallSomeWebApi();

           await Task.Delay(5000, cancellationToken);
       }

       return Task.CompletedTask;
    }
}

which calls some function from a WebServiceClient class. The class looks like this

public class MyWebServiceClient: IMyWebServiceClient
{
    private readonly IHttpClientFactory httpClientFactory;

    public MyWebServiceClient(IHttpClientFactory httpClientFactory)
    {
        this.httpClientFactory = httpClientFactory;
    }

    public async Task CallSomeWebApi()
    {
       using (var httpClient = httpClientFactory.CreateClient())
       {
           var requestMessage = new HttpRequestMessage(...);

           var response = await httpClient.SendAsync(requestMessage);
       }
    }
}

The startup code is this:

public void ConfigureServices(IServiceCollection services)
{
    ....
    services.AddHttpClient();
    services.AddSingleton<IMyWebServiceClient, MyWebServiceClient>();
    services.AddHostedService<MyHostedService>();
    ....
}

Can somebody tell me if it is a good practice calling cyclically

var httpClient = httpClientFactory.CreateClient()

(for instance every 5 seconds)?

Could some side effects occur because of this? I am testing with some Web Server and quite often getting an exception

The request was canceled due to the configured HttpClient.Timeout of 100 seconds elapsing

Could this be caused by the implementation above, or is this definitely a server problem?

1 Answer 1

5

The error that you get is because the client API call times out after 100 seconds which is the default timeout so this is probably the server not responding.

It should be fine to create a new HttpClient every five seconds. The HttpClient instance wraps a pooled HttpMessageHandler so it's lightweight (as opposed to the pooled handler). Disposing it doesn't dispose the handler which otherwise could lead to resource exhaustion (client sockets aren't released immediately).

Because the inner handler by default is configured to "refresh itself" at regular intervals to pick up new DNS information you actually don't need to use IHttpClientFactory yourself. You can instead inject HttpClient directly using a typed client as described in Make HTTP requests using IHttpClientFactory in ASP.NET Core. The article Use IHttpClientFactory to implement resilient HTTP requests also explains "best practices" for using HttpClient in .NET.

Sign up to request clarification or add additional context in comments.

5 Comments

Thanks for the links, I will take a look. As far as I understand from your answer, the code is robust enough, also for production. Is it possible to change the 100 seconds httpclient timeout?
@RickyTad Yes, you can set the HttpClient.Timeout property to change the timeout. If you use the typed client approach where HttpClient is injected into your service constructor you can either modify the HttpClient instance in that constructor or when you configure dependency injection by calling AddHttpClient<MyWebServiceClient>(). The details are in the linked documentation.
learn.microsoft.com/en-us/aspnet/core/fundamentals/… I don't think it should use with using according to the doc
@maxisam Yes, you don't have to dispose HttpClient. See HttpClient and lifetime management: HttpClient instances can generally be treated as .NET objects not requiring disposal. Disposal cancels outgoing requests and guarantees the given HttpClient instance can't be used after calling Dispose. IHttpClientFactory tracks and disposes resources used by HttpClient instances. As noted disposal is OK. My suggestion is to inject HttpClient and not dispose.
@MartinLiversage thanks for clarify. It was a bit ambiguous from your answer. It will be great if you can update it with your comment : )

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.