All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.sonar.plugins.csharp.S6962.html Maven / Gradle / Ivy

There is a newer version: 10.2.0.105762
Show newest version

In frequently used code paths, such as controller actions, you should avoid using the HttpClient directly and opt for one of the IHttpClientFactory-based mechanisms instead. This way, you avoid wasting resources and creating performance overhead.

Why is this an issue?

If a code path that creates and disposes of HttpClient objects is frequently used, then the following issues can occur:

  • Under heavy load, there’s the risk of running out of available sockets, leading to SocketException errors. This is because each HttpClient instance uses a separate network connection, and there’s a limit to the number of connections that can be opened simultaneously. Note that even after you dispose of an HttpClient its sockets are not immediately freed up.
  • Each HttpClient has its own set of resources (like headers, base address, timeout, etc.) that must be managed. Creating a new HttpClient for every request means these resources are not being reused, leading to resource waste.
  • You introduce a significant performance overhead when creating a new HttpClient for every HTTP request.

How to fix it

The IHttpClientFactory was introduced in ASP.NET Core 2.1 to solve these problems. It handles pooling HTTP connections to optimize performance and reliability.

There are several ways that you can use IHttpClientFactory in your application:

Alternatively, you may cache the HttpClient in a singleton or a static field. You should be aware that by default, the HttpClient doesn’t respect the DNS’s Time To Live (TTL) settings. If the IP address associated with a domain name changes, HttpClient might still use the old, cached IP address, leading to failed requests.

Code examples

Noncompliant code example

[ApiController]
[Route("controller")]
public class FooController : Controller
{
    [HttpGet]
    public async Task<string> Foo()
    {
        using var client = new HttpClient();  // Noncompliant
        return await client.GetStringAsync(_url);
    }
}

Compliant solution

// File: Startup.cs
public class Startup
{
    public void ConfigureServices(IServiceCollection services)
    {
        services.AddHttpClient();
        // ...
    }
}

[ApiController]
[Route("controller")]
public class FooController : Controller
{
    private readonly IHttpClientFactory _clientFactory;

    public FooController(IHttpClientFactory clientFactory)
    {
        _clientFactory = clientFactory;
    }

    [HttpGet]
    public async Task<string> Foo()
    {
        using var client = _clientFactory.CreateClient(); // Compliant (Basic usage)
        return await client.GetStringAsync(_url);
    }
}

Resources

Documentation





© 2015 - 2024 Weber Informatics LLC | Privacy Policy