Should we use singletons for clients derived from Microsoft.Rest.ServiceClient in C #?

When working with Azure.NET SDKs generated from swagger specifications (for example, related to Azure Resource Manager), the resulting libraries use the Microsoft AutoRest Client Runtime, and the various Clients all inherit from the ServiceClient.

We work with DocumentDB Client and read a lot about the problems of using native HttpClient in .NET. Microsoft suggests using singleton templates for both of these clients because of the way they work internally, despite known issues with the singleton template. In these cases, it is necessary.

As a result, we have developed a strategy for using and managing singlons for these cases, so we want to know if we should use the same strategy for Azure REST clients sourced from ServiceClient. If it is using HttpClient it makes sense.

Note. This question is not a question requiring general developer advice about singlons or clients, but rather a specific question for Microsoft dev teams related to AutoRest client runtime based on knowledge of its internal operations.

+3


source to share


3 answers


Yes and no. :-) You do not need to use the Singleton design pattern, but it is advisable to share ServiceClient

-derived instances where possible, since each one encapsulates HttpClient

.



For some azure libraries, sharing the same client is not always possible. For example, the SearchIndexClient

Azure Search Library can only target one index at a time, so if your application uses multiple indexes, you need to merge them somehow. Here is a related question on the subject that has links to other discussions elsewhere.

+1


source


I tried to solve this same problem. I am using several Autoload clients, but they need to re-instantiate each request to pass the client's custom credentials. As of Microsoft.Rest.ClientRuntime 2.3.6, you can instantiate the ServiceClient using your own HttpClient. This allows a temporary ServiceClient to be used with a single point HttpClient. I just added a new constructor to the generated autoload client.

public partial class MyClient : ServiceClient<IMyClient>, IMyClient
{

    public MyClient(Uri baseUri, ServiceClientCredentials credentials, HttpClient client) : base(client)
    {
        if (baseUri == null)
        {
            throw new ArgumentNullException("baseUri");
        }
        if (credentials == null)
        {
            throw new ArgumentNullException("credentials");
        }

        this.Initialize();
        this.Credentials = credentials;
        Credentials?.InitializeServiceClient(this);
        this.BaseUri = baseUri;

    }
    [...]
}

      

This, however, will throw an ObjectDisposedException after the first request. This is because ServiceClient exposes HttpClients, whether you passed it in or not. method

protected virtual void Dispose(bool disposing)
{
    if (!_disposed)
    {
        _disposed = true;

        // Dispose the client
        HttpClient.Dispose();
        HttpClient = null;
        FirstMessageHandler = null;
        HttpClientHandler = null;
    }
}

      



I simply override the Dispose method in "MyClient" so that it does nothing, since the only object available is the HttpClient.

protected override void Dispose(bool disposing) { }

      

I didn't notice any implications from this as the FirstMessageHandler and HttpClientHandler are only created when the ServiceClient creates the HttpClient for you. This approach allowed me to use a single HttpClient for multiple ServiceRell-generated AutoRest requests with custom user credentials on each request.

I would be interested to know if anyone sees a departure from this approach.

+2


source


You can now exchange HttpClient instances with ServiceClient instances, so there is no longer any reason to use the singleton pattern

+1


source







All Articles