Unable to read data from the transport connection: The connection was closed

By FoxLearn 1/9/2025 2:23:09 AM   32
If you get an error when attempting to retrieve an image via a WebRequest, the error message is shown below.
Exception: System.IO.IOException 
Message: Unable to read data from the transport connection: The connection was closed.
Source: System
at System.Net.ConnectStream.Read(Byte[] buffer, Int32 offset, Int32 size)

After some research, I found a few potential causes for this issue:

  1. IIS Keep-Alive Settings: If IIS has "Keep-Alive" enabled, it can cause issues with WCF and .NET. Apparently, in IIS 7.5, the Keep-Alive feature was enabled by default after an update.

  2. Remote Server Closing Connection: Sometimes, the remote server closes the connection before the data is fully transferred. Changing the HttpVersion to 1.0 might resolve this.

  3. Missing Content-Length Header: If the remote server doesn't specify the "Content-Length" header when sending data, this can cause issues after upgrading to .NET 4.0.

The solution that worked for me was switching from a WebRequest to an HttpWebRequest.

This gave me more control over important settings like:

  • KeepAlive: Whether or not to keep the connection open.
  • ProtocolVersion: Allows switching between HTTP/1.0 and HTTP/1.1.
  • ConnectionLimit: Specifies the maximum number of connections allowed to a service point.

Here’s the code that resolved the issue for me:

private Byte[] RetrieveAsset(Uri uri, out string contentType)
{
  try
  {
    Byte[] bytes;
    HttpWebRequest webRequest = (HttpWebRequest) WebRequest.Create(uri);
    webRequest.KeepAlive = true; // Set KeepAlive as needed
    webRequest.ProtocolVersion = HttpVersion.Version10; // Use HTTP/1.0 to fix the issue
    webRequest.ServicePoint.ConnectionLimit = 24; // Adjust connection limit
    webRequest.Headers.Add("UserAgent", "Pentia; MSI");
    
    using (WebResponse webResponse = webRequest.GetResponse())
    {
      contentType = webResponse.ContentType;
      using (Stream stream = webResponse.GetResponseStream())
      {
        using (MemoryStream memoryStream = new MemoryStream())
        {
          // Stream the response to a MemoryStream
          Byte[] buffer = new Byte[0x1000];
          Int32 bytesRead;
          while ((bytesRead = stream.Read(buffer, 0, buffer.Length)) > 0)
          {
            memoryStream.Write(buffer, 0, bytesRead);
          }
          bytes = memoryStream.ToArray();
        }
      }
    }
    return bytes;
  }
  catch (Exception ex)
  {
    throw new Exception("Failed to retrieve asset from '" + uri + "': " + ex.Message, ex);
  }
}

In my case, simply setting the ProtocolVersion to 1.0 resolved the issue.

However, different scenarios might require adjustments to other settings such as KeepAlive or ConnectionLimit.

Therefore, you should consider setting these properties (KeepAlive, ProtocolVersion, and ConnectionLimit) dynamically based on the specific needs of your scenario.