2009-05-25 11 views
7

Ho un servizio WCF ospitato in IIS/ASP.NET che accetta post HTTP (non modulo post) di oggetti serializzati.Acquisizione di dati POST HTTP non elaborati durante l'eccezione

Se il client invia richieste malformate (ad esempio non serializzano correttamente l'oggetto), desidero registrare il messaggio inviato.

Stiamo già utilizzando ELMAH per catturare le eccezioni non gestite, quindi semplicemente allegare i dati del post sarebbe l'opzione più semplice.

È possibile ottenere HttpContext corrente durante un'eccezione, tuttavia questo contiene solo le informazioni dell'intestazione HTTP.

La mia domanda è questa: esiste un modo per acquisire il corpo della richiesta HTTP POST originale? Oppure, in caso contrario - un modo migliore (senza un proxy inverso) di catturare l'input che ha causato l'errore?

Modifica: Giusto per chiarire, eseguire l'acquisizione a livello di pacchetto in ogni momento non è proprio adatto. Sto cercando una soluzione che posso distribuire sui server di produzione e che avrà clienti fuori dal nostro controllo o capacità di monitoraggio.

Modifica # 2: È stato suggerito di accedere a Request.InputStream. Questo non funziona se si sta tentando di leggere dopo che WCF ha letto la richiesta dallo stream.

Un esempio di codice per vedere come ho provato a utilizzare questo è qui.

 StringBuilder log = new StringBuilder(); 

     var request = HttpContext.Current.Request; 

     if (request.InputStream != null) 
     { 
      log.AppendLine(string.Format("request.InputStream.Position = \"{0}\"", request.InputStream.Position)); 
      if (request.InputStream.Position != 0) 
      { 
       request.InputStream.Seek(0, System.IO.SeekOrigin.Begin); 
      } 

      using (StreamReader sr = new StreamReader(request.InputStream)) 
      { 
       log.AppendLine(string.Format("Original Input: \"{0}\"", sr.ReadToEnd())); 
      } 
     } 
     else 
     { 
      log.AppendLine("request.Inputstream = null"); 
     } 


     log.ToString(); 

L'ouput di log.ToString() è:

 
    request.InputStream.Position = "0" 
    Original Input: "" 
+1

Il "usando" con StreamReader risulterà nel System.Web.Request.InputStream in fase di eliminazione (il che significa che i dati vengono persi). – Jeff

+0

I dati sono già persi. –

risposta

3

Nel momento in cui arriva al tuo servizio la richiesta viene elaborata e non disponibile.

Tuttavia ... è possibile allegare un message inspector. Gli ispettori dei messaggi ti permettono di armeggiare con il messaggio prima che raggiunga le tue implementazioni operative. È possibile creare una copia bufferizzata del messaggio e copiarlo in OperationContext.Current.

Ugly hack, naturalmente, e significherà sovraccarico di memoria come ora due copie del messaggio stanno fluttuando per ogni richiesta.

+0

Grazie - non è una soluzione particolarmente valida, ma probabilmente ne varrà la pena sacrificare un po 'di memoria. –

-2

utilizzare Fiddler. Libero da MS. Funziona alla grande.

+1

Sto parlando di errori che si sono verificati in assenza di Fiddler, Wireshark o di qualsiasi altra esecuzione per acquisirla. ad esempio su un server di produzione o di gestione temporanea in cui non è possibile eseguire l'acquisizione di pacchetti ininterrottamente. –

-1

Hai guardato la proprietà System.Web.Request.InputStream? Dovrebbe avere esattamente quello che vuoi.

Come "riavvolgere" la proprietà InputStream.

if (Request.InputStream.Position != 0) 
    { 
     Request.InputStream.Seek(0, System.IO.SeekOrigin.Begin); 
    } 

Un'altra opzione si dovrebbe guardare in è catturare queste informazioni con un HttpModule sull'evento BeginRequest. I dati dovrebbero essere lì all'evento BeginRequest perché non credo che WCF prelevi la richiesta fino a dopo PostAuthenticateEvent.

+1

Ho dato un'occhiata a quella proprietà - sfortunatamente quel flusso contiene solo dati non letti. Nel momento in cui si è verificata l'eccezione, i dati di input sono già stati letti da WCF. Non è possibile riavvolgere/ripristinare la posizione. –

+0

Vedere il mio aggiornamento ... Poiché Request.InputStream.CanSeek è true, è possibile reimpostare la posizione su 0 utilizzando il metodo Seek. – Jeff

+0

Grazie per l'aggiornamento - CanSeek è vero, tuttavia non c'è ancora nulla nello stream da leggere. Vedere il testo aggiornato per esempio di ciò che ho fatto per provare e testarlo. –

-1

da sotto ASP.NET (servizio Web ASP in IIS) il seguente codice aiuta:

if (request.InputStream.Position != 0) 
{ 
    request.InputStream.Seek(0, System.IO.SeekOrigin.Begin); 
} 

WCF forse differente (cioè Dispone InputStream dopo averlo letto)

+0

Questa è la stessa risposta che Jeff ha dato. Inoltre non funziona in quanto il flusso non è ricercabile. –