Montag, 14. April 2008

The underlying connection was closed

System.Net.WebException: The underlying connection was closed: A connection that was expected to be kept alive was closed by the server. at System.Web.Services.Protocols.WebClientProtocol.GetWebResponse(WebRequest request) at System.Web.Services.Protocols.HttpWebClientProtocol.GetWebResponse(WebRequest request) at System.Web.Services.Protocols.SoapHttpClientProtocol.Invoke(String methodName, Object[] parameters) at <my webservice> ....

Das Problem ist meist Serviceseitig zu suchen, durch irgendwelche verkorksten oder properitären, veralteten, etc. Einstellungen. Dummerweise hat man meistens keinen Einflußmöglichkeit auf diesen Service, also muss ein Workaround her.

Als erster Anlaufpunkt kann man versuchen den KeepAlive auf false zu setzen. Denn unter .NET 1.1 war KeepAlive noch defaultmäßig auf false, ab 2.0 auf true. Das steuert ob die WebService Verbindung dauerhaft offen gehalten werden soll, nur dumm wenn der Webserver von alleine irgendwann dicht macht nach einer gewissen Dauer, bzw. idle time.

Funktioniert das nicht, kann man noch versuchen die HttpVersion auf 1.0 runter zu setzen für mehr Kompatibilität.

Desweiteren könnte es noch helfen Expect100Continue auf false zu ändern. Dies bewirkt, dass bei einem Request gleich die Daten mit dem Header geschickt werden. Bei true (Default) wird nur der Header geschickt und die Daten erst, wenn ein "100 Continue" Response vom Server erfolgte.

   1:  namespace MyWebServiceNamespace
   2:  {
   3:      partial class MyWebServices_MyMethod
   4:      {
   5:          protected override System.Net.WebRequest GetWebRequest(Uri uri)
   6:          {
   7:              System.Net.HttpWebRequest request =
   8:                  (System.Net.HttpWebRequest)base.GetWebRequest(uri);
   9:   
  10:              // fix "underlying connection was closed.."
  11:              request.KeepAlive = false;
  12:              request.ProtocolVersion = System.Net.HttpVersion.Version10;
  13:              request.ServicePoint.Expect100Continue = false;
  14:              ...
  15:          }
  16:      }
  17:  }

Anmerkung: Durch das partial class (ab .NET 2.0) kann man das wunderbar in eine eigene Datei verlagern, getrennt vom generierten Proxy und somit unabhängig wenn neu generiert werden muss.

Keine Kommentare: