2011-02-08 16 views
9

Sto tentando di eseguire il debug di a specific issue with my ASP.NET application. Il client esegue il seguente codice:Posso riutilizzare HttpWebRequest senza disconnetterti dal server?

void uploadFile(string serverUrl, string filePath) 
{ 
    HttpWebRequest request = (HttpWebRequest)HttpWebRequest. 
     Create(serverUrl); 
    CredentialCache cache = new CredentialCache(); 
    cache.Add(new Uri(serverUrl), "Basic", new NetworkCredential("User", "pass")); 
    request.Credentials = cache; 
    request.Method = "POST"; 
    request.ContentType = "application/octet-stream"; 
    request.Timeout = 60000; 
    request.KeepAlive = true; 

    using(BinaryReader reader = new BinaryReader( 
     File.OpenRead(filePath))) { 

     request.ContentLength = reader.BaseStream.Length; 
     using(Stream stream = request.GetRequestStream()) { 
      byte[] buffer = new byte[1024]; 
      while(true) { 
       int bytesRead = reader.Read(buffer, 0, buffer.Length); 
       if(bytesRead == 0) { 
        break; 
       } 
       stream.Write(buffer, 0, bytesRead); 
      } 
     } 
    } 

    HttpWebResponse result = (HttpWebResponse)request.GetResponse(); 
    //handle result - not relevant 
} 

e Write() genera un'eccezione con "Impossibile scrivere i dati sul collegamento nazionale: una connessione stabilita è stata interrotta dal software del computer host." testo. Ho usato System.Net tracing e ho scoperto che qualcosa va storto quando invio la richiesta con il set Content-Length.

In particolare se Tralascio tutto ciò che è dentro using dichiarazione nel codice sopra il server prontamente risponde con WWW-Authenticate e quindi il client ristampato la richiesta con WWW-Authenticate e tutto va bene, tranne il file in non caricato e la richiesta fallisce molto più tardi.

Mi piacerebbe fare quanto segue: inviare una richiesta senza dati, attendere WWW-Authenticate, quindi ripetere con WWW-Authenticate e dati. Così ho provato a modificare il codice sopra: prima di tutto impostare tutti i parametri, quindi chiamare GetResponse(), quindi inviare, ma quando provo a impostare la proprietà ContentLength viene lanciata un'eccezione con testo "Questa proprietà non può essere impostata dopo aver scritto".

Quindi HttpWebRequest sembra non riutilizzabile.

Come posso riutilizzarlo per inviare nuovamente la richiesta senza chiudere la connessione?

+0

Ho anche lo stesso problema. Se hai la soluzione, ti preghiamo di fornire o visualizzare il nuovo codice modificato, che mi aiuterà. – Herin

+0

@Herin: nessuna soluzione se si utilizza l'autenticazione con nonce. Se usi qualcosa come l'autenticazione di base puoi semplicemente impostare le intestazioni di "Autorizzazione" in modo che non ci sia la fase "Autenticazione WWW". – sharptooth

+0

Ma sto ottenendo errore alla riga 'stream.Write (buffer, 0, bytesRead)' allora qual è la soluzione per quello. Potete fornire il vostro codice modificato, in modo che io possa capire meglio. Grazie – Herin

risposta

16

Non riutilizzare una richiesta, come suggerisce il nome, è una richiesta. Tuttavia, se si eseguono più richieste per lo stesso host, .NET riutilizzerà la connessione di rete sottostante per impostazione predefinita.

Si noti che è fai necessità di smaltire il WebResponse restituito da request.GetResponse - altrimenti l'infrastruttura sottostante non saprà che si sta effettivamente finito con esso, e non sarà in grado di riutilizzare la connessione.

(Per inciso, perché stai usando BinaryReader? Basta usare il flusso restituito direttamente File.OpenRead.)

+0

Posso garantire l'eliminazione di WebResponse. Non ho eliminato WebResponse in una delle mie applicazioni e ha causato una perdita di memoria sgradevole perché stavo creando una serie di HttpWebRequests. – jlafay

+0

Giusto, ma quale altro meccanismo potrei usare per risolvere il mio problema - in particolare che ho bisogno di essere autenticato e quindi riutilizzare lo stesso 'WWW-Authenticate'? – sharptooth

+0

@sharptooth: non è chiaro il motivo per cui non puoi semplicemente prendere l'intestazione dalla risposta e usarla nella prossima richiesta. Perché pensi di dover riutilizzare lo stesso oggetto? –

2

Oltre alla risposta di Jon Skeet, non è necessario impostare manualmente la proprietà ContentLength. HttpWebRequest calcola e popola automaticamente tale proprietà.

Problemi correlati