1

Here is my code:

public class Uploader
{
    private readonly HttpMessageHandler m_httpMessageHandler;

    public Uploader(HttpMessageHandler httpMessageHandler)
    {
         m_httpMessageHandler = httpMessageHandler;
    }

    public async Task<string> Upload(string url, Dictionary<string, string> data)
    {
        HttpResponseMessage result;
        try
        {
            if (somecheck)
            {
                HttpClientHandler handler = (HttpClientHandler)m_httpMessageHandler;
                // error occurs here
                handler.ServerCertificateCustomValidationCallback = delegate { return true; };
            }

            var client = new HttpClient(m_httpMessageHandler);
            result = await client.PostAsync(url, new FormUrlEncodedContent(data));
            if (result.StatusCode != HttpStatusCode.OK)
            {
                return Strings.LabelPrinterNotConfiguredError;
            }
            else
            {
                return null; // Success!
            }
        }
        catch(Exception e) 
        {
            // do some stuff
        }
    }
}

In my Startup.cs

services.AddSingleton<HttpMessageHandler, HttpClientHandler>();

The reason why I have this is because I've created a mock HttpClientHandler used for unit testing the HttpClient. This way I can extend from the abstract class HttpMessageHandler for the mock implementation in my tests.

I am getting this error:

System.InvalidOperationException: This instance has already started one or more requests. Properties can only be modified before sending the first request.

After reading through several other answers on SO, I know that the issue is that the single HttpClientHandler that I have is somehow having its properties modified after starting which the runtime does not like. However, I still can't figure out why that is happening because it does not appear that I am overtly modifying BaseAddress, Timeout, or MaxResponseContentBufferSize.

The answers appear to be to modify the HttpClientHandler after creating it but if so, how do I set the ServerCertificateCustomValidationCallback member variable appropriately?

The follow-up question would be: how would I fix this error while also keeping the ability to mock/test HttpClient?

noblerare
  • 10,277
  • 23
  • 78
  • 140
  • Use an [IHttpClientFactory](https://learn.microsoft.com/en-us/aspnet/core/fundamentals/http-requests). You will still be able to mock it and the framework will manage the pooling for you. In addition, the error you hit is because a HttpMessageHandler is not design to process more than one query at the same time. The basic workaround is to replace the singleton by a functor (factory). – Kalten Jun 14 '19 at 20:05
  • @Kalten Ah, I see that makes sense. Would you mind writing up an answer to this question? I can accept it. – noblerare Jun 14 '19 at 20:47
  • I still recommend you to use IHttpClientFactory, but I'm not sure of my explanation. It sond wrong. In fact the handler should be able to handle many request at the same time. If the issue is the edit of `ServerCertificateCustomValidationCallback` maybe you just need to move it in the singleton registration. Like `services.AddSingleton(serviceProvider => new HttpClientHandler() { ServerCertificateCustomValidationCallback = false});` – Kalten Jun 14 '19 at 21:41

0 Answers0