System.Net.WebException: The underlying connection was closed: An unexpected error occurred on a receive.
Na semana passada estávamos mexendo em uma aplicação desenvolvida em .NET 2.0. O objetivo era incluir uma nova funcionalidade que dependia de um Web Service SOAP de terceiros.
Para fazer a nova implementação o mais rápido possível, utilizamos o recurso “Add Web Reference…” do Visual Studio 2005 para criar um proxy para o Web Service que queríamos consumir.

Fazendo isso, o Visual Studio 2005 gera algumas classes no arquivo Reference.cs (para visualizá-lo é preciso estar com a opção “Show all files” habilitada na janela Solution Explorer).

A partir dessas classes você pode fazer a comunicação com o Web Service através de simples chamadas de métodos.
CalcPrecoPrazoWS proxy = new CalcPrecoPrazoWS();
Resultado resultado = proxy.Calcular("03478010", "13500313", "0,456");
O problema
Até aqui tudo certo, mas quando testamos a aplicação fazendo a chamada do Web Service, aconteceu o seguinte erro:
System.Net.WebException: The underlying connection was closed: An unexpected error occurred on a receive.
at System.Web.Services.Protocols.WebClientProtocol.Ge tWebResponse(WebRequest request)
at System.Web.Services.Protocols.HttpWebClientProtocol.GetWebResponse(WebRequest request)
at System.Web.Services.Protocols.SoapHttpClientProtocol.Invoke(String methodName, Object[] parameters)
Depois de pesquisarmos um pouco, descobrimos que as possíveis causas desse problema são:
- Quando o servidor do Web Service inesperadamente fecha a conexão
- O time out do servidor do Web Service é muito baixo
- O servidor do Web Service “reseta” a conexão inesperadamente, algo como uma exceção não tratada
A solução
Quando você chama um método da classe proxy, no exemplo acima a classe CalcPrecoPrazoWS, internamente a classe SoapHttpClientProtocol, que é a classe base do nosso proxy, aciona seu método protegido GetWebRequest, que irá fazer um requisição Web através da classe WebRequest.
Para não mantermos a “conexão viva” na requisição Web, sobrescrevemos o método GetWebRequest da classe SoapHttpClientProtocol, convertendo um objeto WebRequest em um objeto HttpWebRequest e configurando a propriedade KeepAlive para false antes de acionar a requisição.
protected override WebRequest GetWebRequest(Uri uri)
{
HttpWebRequest webRequest = (HttpWebRequest)base.GetWebRequest(uri);
webRequest.KeepAlive = false;
webRequest.ProtocolVersion = HttpVersion.Version10;
return webRequest;
}
Isso pode ser feito no próprio arquivo Reference.cs, dentro da classe proxy que foi gerada pelo Visual Studio 2005. Mas qualquer alteração na referência Web, o Visual Studio 2005 irá gerar novamente o código do arquivo Reference.cs e seu código será apagado.
Então a melhor maneira de fazer isso é utilizar os recursos de classes parciais do .NET e separar seu código em um arquivo separado, como mostrado no exemplo abaixo:
public partial class CalcPrecoPrazoWS
{
protected override WebRequest GetWebRequest(Uri uri)
{
HttpWebRequest webRequest = (HttpWebRequest)base.GetWebRequest(uri);
webRequest.KeepAlive = false;
webRequest.ProtocolVersion = HttpVersion.Version10;
return webRequest;
}
}
Mas não é só isso
Há também um série de outras causas para esse problema, bem como outras possíveis soluções, inclusive quando você está usando WCF no .NET 3.5.
A solução que apresentei funcionou no meu caso. Se ela não resolver seu problema, vale a pena investigar nesse artigo do suporte da Microsoft que lista possíveis causas e soluções:
You receive one or more error messages when you try to make an HTTP request in an application that is built on the .NET Framework 1.1 Service Pack 1
http://support.microsoft.com/kb/915599
Esse artigo é um tanto confuso e mal organizado, mas já é um bom começo.



Por conta disso, procurei pela 




Comentários