Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C# HttpClient and Windows Authentication: Cannot access a closed Stream

I'm using the native C# HTTP client with a handler to process Windows Authentication and I'm having ObjectDisposedException.

using (var httpClientHandler = new HttpClientHandler { Credentials = CredentialCache.DefaultNetworkCredentials })
{
    bool disposeHandler = true; //Setting true or false does not fix the problem
    using (var httpClient = new HttpClient(httpClientHandler, disposeHandler))
    {
        using (var content = new ByteArrayContent(Encoding.UTF8.GetBytes("Hello")))
        {
            // Commenting/uncommenting the line below does not fix the problem
            // httpRequestMessage.Headers.Connection.Add("Keep-Alive");

            using (var httpResponseMessage = await httpClient.PostAsync("http://SomeUrl", content)) // This line throws an ObjectDisposedException
            {

            }
        }
    }
}

Any idea?

like image 402
Kino101 Avatar asked Apr 10 '19 11:04

Kino101


1 Answers

After some new investigations, I think/fear there it is a Microsoft bug in HttpClientHandler (or HttpClient):

If instead of using the PostAsync method I use the SendAsync method, I can compose my request with more options and especially change the HTTP version from 1.1 (by default) to 1.0. Then in this case the real exception was revealed (and it was not anymore hidden/overridden by the ObjectDisposedException exception). For your information, my real exception was the following:

--> System.Net.WebException: The remote server returned an error: (401) Unauthorized.

--> System.ComponentModel.Win32Exception: The target principal name is incorrect

(Still for your information, this exception was due to a bad configuration of an SPN of a user in the Active Directory)

using (var httpClientHandler = new HttpClientHandler { Credentials = CredentialCache.DefaultNetworkCredentials })
{
    bool disposeHandler = true; //Setting true or false does not fix the problem
    using (var httpClient = new HttpClient(httpClientHandler, disposeHandler))
    {
        using (var content = new ByteArrayContent(Encoding.UTF8.GetBytes("Hello")))
        {
            // Commenting/uncommenting the line below does not fix the problem
            // httpRequestMessage.Headers.Connection.Add("Keep-Alive");

            var httpRequestMessage = new HttpRequestMessage(HttpMethod.Post, "http://SomeUrl")
            {
                Content = content,
                Version = HttpVersion.Version10
            };

            using (var httpResponseMessage = await httpClient.SendAsync(httpRequestMessage)) // This line still throws but with the real exception (and not the ObjectDisposedException)
            {

            }
        }
    }
}

Beware: downgrading the HTTP version is just a hack to get the real exception message, HTTP 1.0 is getting very old.

Any experts analysis would be really appreciated. Hope this will help others.

like image 103
Kino101 Avatar answered Nov 05 '22 07:11

Kino101