2009-05-25 15 views
7

Tengo un servicio WCF alojado en IIS/ASP.NET que acepta publicación HTTP (no formada en la publicación) de objetos serializados.Captura de datos HTTP POST sin formato durante la excepción

Si el cliente envía solicitudes mal formadas (p. Ej., No están serializando el objeto correctamente) me gustaría registrar el mensaje enviado.

Ya estamos utilizando ELMAH para capturar excepciones no controladas, por lo que simplemente adjuntar los datos de la publicación sería la opción más fácil.

Puedo obtener el HttpContext actual durante una excepción, sin embargo, esto solo contiene la información del encabezado HTTP.

Mi pregunta es esta: ¿hay alguna forma de capturar el cuerpo original de la solicitud HTTP POST? O, en su defecto, ¿una forma mejor (sin un proxy inverso) de capturar la entrada que causó el error?

Editar: Solo para aclarar, la ejecución a nivel de paquete de captura en todo momento no es realmente adecuada. Estoy buscando una solución que pueda implementar en servidores de Producción, y que tendrá clientes fuera de nuestro control o capacidad para monitorear.

Edición n. ° 2: se hizo una sugerencia para acceder al Request.InputStream; esto no funciona si intenta leer después de que WCF haya leído la solicitud fuera de la transmisión.

Aquí hay una muestra de código para ver cómo he intentado usar esto.

 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(); 

que la salida de log.ToString() es:

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

El "uso" con StreamReader dará como resultado System.Web.Request.InputStream está dispuesto (lo que significa que los datos se pierden). – Jeff

+0

Los datos ya están perdidos. –

Respuesta

3

Cuando llega a su servicio, la solicitud se procesa y no está disponible para usted.

Sin embargo ... podría adjuntar un message inspector. Los inspectores de mensajes le permiten jugar con el mensaje antes de que llegue a las implementaciones de su operación. Puede crear una copia en búfer del mensaje y copiarlo en OperationContext.Current.

Ugly hack por supuesto, y va a significar sobrecarga de memoria ya que ahora dos copias del mensaje están flotando para cada solicitud.

+0

Gracias - no es una solución particularmente buena, pero sacrificar algo de memoria probablemente valga la pena. –

-2

Uso violinista. Gratis de MS. Funciona genial.

+1

Estoy hablando de errores que han sucedido cuando no hay Fiddler, Wireshark o lo que se ejecute para capturarlo. por ejemplo, en un servidor de producción o de etapas donde no es posible ejecutar la captura de paquetes todo el tiempo. –

-1

¿Miraste la propiedad System.Web.Request.InputStream? Debería tener exactamente lo que quieres.

Cómo "rebobinar" la propiedad InputStream.

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

Otra opción que debe buscar en es capturar esta información con un HTTPModule en el caso BeginRequest. Los datos deberían estar allí en el evento BeginRequest porque no creo que WCF recoja la solicitud hasta después de PostAuthenticateEvent.

+1

Miré esa propiedad: desafortunadamente esa transmisión solo contiene datos no leídos. Para cuando se produjo la excepción, la información de entrada ya ha sido leída por WCF. No puede rebobinar/restablecer la posición. –

+0

Ver mi actualización ... Dado que Request.InputStream.CanSeek es verdadero, puede restablecer la posición a 0 utilizando el método Seek. – Jeff

+0

Gracias por la actualización: CanSeek es cierto; sin embargo, todavía no hay nada en la transmisión que leer. Ver el texto actualizado, por ejemplo, de lo que hice para probar y probar esto. –

-1

de debajo de ASP.NET (servicio web ASP en IIS) el siguiente código ayuda a:

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

WCF puede ser diferente (es decir Dispone InputStream después de leerlo)

+0

Esta es la misma respuesta que dio Jeff. Tampoco funciona, ya que la transmisión no es buscable. –