Problema con web service: The connection was closed unexpectedly...com...

lunedì 20 ottobre 2008 - 10.22

lukepet Profilo | Junior Member

Ciao a tutti, ho un problema con il trasferimento di alcuni dati da un db ad un altro tramite web service.

Ho creato un servizio web in questo modo:

<WebService(Namespace:="http://tempuri.org/")> _
<WebServiceBinding(ConformsTo:=WsiProfiles.BasicProfile1_1)> _
<Global.Microsoft.VisualBasic.CompilerServices.DesignerGenerated()> _
Public Class GestioneUpdate
Inherits System.Web.Services.WebService

// Web Methods

End Class

richiamo questo servizio dalla mia applicazione inizializzandolo così:

Dim virDirWSWeb As String = DIRVIRTUALE
accountServizioUpdate = New GestioneUpdate.AuthHeaderVB
accountServizioUpdate.Username = NOMEUTENTE
accountServizioUpdate.Password = PASSWORD
p = New GestioneUpdate.GestioneUpdate
If serverWebInternet.IndexOf(HTTP) >= 0 Then
p.Url = serverWebInternet & "/" & virDirWSWeb & "/GestioneUpdate.asmx"
Else
p.Url = HTTP & serverWebInternet & "/" & virDirWSWeb & "/GestioneUpdateOrdiniWeb.asmx"
End If
p.Timeout = TIMEOUT_SERVIZI_WEB
p.AuthHeaderVBValue = accountServizioUpdate


durante il trasferimento a volte però viene visualizzato il seguente errore:

System.Net.WebException: The underlying connection was closed: The connection was closed unexpectedly.
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)...

mi sono documentato un pò in rete e ho visto che è un problema noto (http://weblogs.asp.net/jan/archive/2004/01/28/63771.aspx, http://blog.josh420.com/archives/2008/02/underlying-connection-closed-fix-pesky-aspnet-webexception.aspx), ma ancora devo ben capire il modo per risolverlo.

Da quanto c'è scritto negli articoli dovrei sovrascrivere il metodo GetWebRequest con il seguente codice:

Protected Overrides Function GetWebRequest(ByVal uri As System.Uri) As System.Net.WebRequest
Dim webRequest As HttpWebRequest = DirectCast(MyBase.GetWebRequest(uri), HttpWebRequest)
webRequest.KeepAlive = False

// oppure inserendo webRequest.ConnectionGroupName = Guid.NewGuid().ToString()
// non ho ancora ben capito quale dei due settaggi bisogna usare

Return webRequest
End Function

il mio problema è che se, nel reference.vb del servizio, inserisco questo codice non mi viene riconosciuto, mi dice che il metodo GetWebRequest non appartiene il namespace. Ho provato anche ad inserirlo nella classe da cui richiamo il servizio ma mi dice che il metodo GetWebRequest non può essere sovrascritto.

Non è possibile imposare i parametri della richiesta in altro modo? O in alternativa sapete indicarmi qualche altro tipo di soluzione?

Vi ringrazio in anticipo per ogni informazione.

rossimarko Profilo | Guru

Ciao,

delle due soluzioni quella che ti consente una gestione ottimale secondo me è questa: http://blog.josh420.com/archives/2008/02/underlying-connection-closed-fix-pesky-aspnet-webexception.aspx

In pratica devi creare una nuova classe che eredita dalla classe che rappresenta il tuo webservice, e poi fai l'override del metodo GetWebRequest. In teoria una volta che hai scritto la parola chiave override all'interno della tua classe l'ide di visual studio dovrebbe proporti un elenco di metodi di cui puoi fare l'override.

Se trovi delle difficoltà prova ad inviarci la classe che rappresenta il tuo webservice che ci guardiamo...
-----------------------------------------
Rossi Marco
http://blogs.dotnethell.it/rossimarko

lukepet Profilo | Junior Member

ho provato ad inserire l'override del metodo nella classe del web service...in questo modo:

<WebService(Namespace:="http://tempuri.org/")> _
<WebServiceBinding(ConformsTo:=WsiProfiles.BasicProfile1_1)> _
<Global.Microsoft.VisualBasic.CompilerServices.DesignerGenerated()> _
Public Class GestioneUpdate
Inherits System.Web.Services.WebService

Protected Overrides Function GetWebRequest(ByVal uri As Uri) As System.Net.WebRequest
Dim webRequest As System.Net.HttpWebRequest = MyBase.GetWebRequest(uri)

webRequest.ConnectionGroupName = Guid.NewGuid().ToString()

Return webRequest
End Function
.
.
.
End Class

ma mi viene segnalato questo errore:

Error 112 function 'GetWebRequest' cannot be declared 'Overrides' because it does not override a function in a base class.

Sapete dirmi come mai? Da cosa può dipendere?

rossimarko Profilo | Guru

Penso che il problema sia qui:

>Public Class GestioneUpdate
> Inherits System.Web.Services.WebService

Non devi ereditare da webservice ma dalla classe proxy che è stata creata, quella che useresti per chiamare il webservice...
-----------------------------------------
Rossi Marco
http://blogs.dotnethell.it/rossimarko

lukepet Profilo | Junior Member

Ho inserito il codice nel reference.vb (dovrebbe essere la classe proxy se non sbaglio) del web reference settato nell'applicativo e sembra tutto ok...ora nel reference.vb ho un codice di questo tipo.

Namespace GestioneUpdate

'''<remarks/>
<System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "2.0.50727.1433"), _
System.Diagnostics.DebuggerStepThroughAttribute(), _
System.ComponentModel.DesignerCategoryAttribute("code"), _
System.Web.Services.WebServiceBindingAttribute(Name:="GestioneUpdateSoap", [Namespace]:="http://tempuri.org/"), _
System.Xml.Serialization.XmlIncludeAttribute(GetType(Object()))> _
Partial Public Class GestioneUpdate
Inherits System.Web.Services.Protocols.SoapHttpClientProtocol

Protected Overrides Function GetWebRequest(ByVal uri As System.Uri) As System.Net.WebRequest
Dim webRequest As HttpWebRequest = DirectCast(MyBase.GetWebRequest(uri), HttpWebRequest)
webRequest.KeepAlive = False
webRequest.ConnectionGroupName = Guid.NewGuid().ToString()
Return webRequest
End Function

Private authHeaderVBValueField As AuthHeaderVB

Private GetSizeArchivioOperationCompleted As System.Threading.SendOrPostCallback

.
.
.
End Class

End Namespace

pensi che così possa andar bene?

per quanto riguarda il codice ho inserito entrambi i settaggi segnalati nel post...non dovrei aver problemi in questo modo (credo). Che ne pensate?

rossimarko Profilo | Guru

>pensi che così possa andar bene?

In questo caso il problema si presenta nel momento in cui aggiorni le webreference, perchè se ti viene ricreata la classe perdi il tuo codice.

Secondo me la soluzione migliore è quella di prima, solo che devi ereditare dalla classe GestioneUpdate e quindi il tuo codice diventa:

Public Class GestioneUpdateExt Inherits GestioneUpdate Protected Overrides Function GetWebRequest(ByVal uri As Uri) As System.Net.WebRequest Dim webRequest As System.Net.HttpWebRequest = MyBase.GetWebRequest(uri) webRequest.ConnectionGroupName = Guid.NewGuid().ToString() Return webRequest End Function End Class


Con questo codice crei una classe nuova (nell'esempio l'ho chiamata GestioneUpdateExt, ma puoi mettere il nome che vuoi) che eredita dalla classe del tuo webservice (GestioneUpdate) e fa l'override del metodo che ti interessa. In questo modo se anche rigeneri la classe gestioneupdate la tua modifica non andrà persa. Ovviamente dovrai modificare le chiamate al servizio e usare sempre GestioneUpdateExt

-----------------------------------------
Rossi Marco
http://blogs.dotnethell.it/rossimarko

lukepet Profilo | Junior Member

perfetto grazie mille, ora lo proverò.

ma l'istruzione keepalive=False non è necessaria?

rossimarko Profilo | Guru

Dipende dal tipo di messaggio che ti viene restituito. Il keepalive viene suggerito quando l'errore è:
The underlying connection was closed: A connection that was expected to be kept alive was closed by the server.

quindi penso che non sia il tuo caso
-----------------------------------------
Rossi Marco
http://blogs.dotnethell.it/rossimarko

lukepet Profilo | Junior Member

Ritorno a parlare del problema che avevo segnalato in questo post.

Dunque, la soluzione che stavo cercando di implementare con l'override del metodo GetWebRequest alla fine non si è rivelata efficace.

Però tra una prova e l'altra sono riuscito a capire quale potrebbe essere la causa del problema.

Le inaspettate disconnessioni hanno iniziato a presentarsi dopo che ho cambiato l'isolation level utilizzato dai servizi per connettersi al database.

Inizialmente utilizzavo l'isolation level Serializable e non avevo alcun problema, successivamente per esigenze di concorrenza ho modificato il tipo di connessione abilitando l'isolation level Snapshot.

Da quando ho impostato Snapshot ho notato il presentarsi di queste disconnessioni; in pratica ho implementato un programma per la sincronizzazione di database e quando vengono trasferiti archivi piuttosto corposi a volte capita che si verifichi la disconnessione.

La cosa strana è che questo problema si verifica solo da una particolare postazione in cui è installato WIndows Server 2003; se faccio girere il tutto sulla mia macchina, in cui è installato XP, non ho alcun tipo di errore.

Potrebbe dipendere dalla versione di IIS su cui girano i servizi?

Oppure è più probabile che dipenda dalla stabilità della connessione internet?

Nessuna idea?

Partecipa anche tu! Registrati!
Hai bisogno di aiuto ?
Perchè non ti registri subito?

Dopo esserti registrato potrai chiedere
aiuto sul nostro Forum oppure aiutare gli altri

Consulta le Stanze disponibili.

Registrati ora !
Copyright © dotNetHell.it 2002-2024
Running on Windows Server 2008 R2 Standard, SQL Server 2012 & ASP.NET 3.5