2012-04-20 13 views
10

Tengo un servicio WCF con varios métodos. Me gustaría registrar la solicitud sin procesar que vino del cliente, independientemente de cómo se envió. Un método acepta los datos como una cadena de consulta (estrictamente para el soporte de legado), que puedo abrir una sesión usando:Cómo registrar la solicitud sin procesar en el servicio WCF

OperationContext.Current.IncomingMessageHeaders.To.AbsoluteUri 

que es suficiente en ese escenario, pero otros métodos permiten que el cliente envíe datos como XML usando una clase de proxy generada por svcutil.exe. En este escenario he encontrado los datos que yo quiero en el s: Cuerpo de:

OperationContext.Current.RequestContext.RequestMessage 

Desafortunadamente, no importa lo que intento no puedo crear una copia del mensaje tamponada antes de que se lee. He aquí un ejemplo:

public CascadeResponse SendCustomer(Customer c) 
    { 
     Message msg = OperationContext.Current.RequestContext.RequestMessage.CreateBufferedCopy(Int32.MaxValue).CreateMessage(); 
     LogMessage(msg); 
     // Now that the request is logged, get on with the rest 
    } 

En la primera línea de SendCustomer, sin embargo, me sale el siguiente error:

Este mensaje no puede soportar la operación, ya que se ha leído.

Este es el punto de la creación de la copia en búfer, ¿no? Supongo que estoy haciendo algo incorrecto aquí.

Editar:

Ok, por lo que el método es ahora así:

public CascadeResponse SendCustomer(Message requestMessage) 
    { 
     Message msg = OperationContext.Current.RequestContext.RequestMessage.CreateBufferedCopy(Int32.MaxValue).CreateMessage(); 
     LogMessage(msg); 
     // Now that the request is logged, get on with the rest   
     Customer c = msg.GetBody<Customer>(); 
     string clientKey = "1111"; // This should be the clientKey string passed to the function along with the customer 
     return SendLead(c, clientKey); 
    } 

Mi problema es que no sé cómo sacar el Cliente y ClientKey enviado como entidades separadas. Podría hacer clientKey una propiedad del Cliente (o crear un objeto personalizado que sea específicamente para pasar datos y que contenga Customer y ClientKey como atributos), pero me gustaría evitar eso si es posible, ya que esta es una actualización de un sistema heredado que ya funciona de esta manera.

También estoy teniendo problemas para usar svcUtil.exe para crear mis clases proxy - Supongo que tener la firma del método anterior significa que mi servicio ya no anunciará la firma correcta para enviar las solicitudes como? No estoy seguro si eso es lo suficientemente claro: si mi único método de entrada acepta un objeto Message, ¿cómo sabe mi cliente enviar un Cliente y una ClientKey?

+0

¿Alguna razón por la que no puede usar la función de seguimiento incorporada en WCF? http://msdn.microsoft.com/en-us/library/ms733025.aspx – DaveRead

+0

@DaveRead Principalmente, no lo sabía, ¿esto me permite guardar mis registros en una base de datos? – Maloric

+0

No está deshabilitado, pero puede crear su propio TraceListener personalizado, consulte este artículo para obtener más información: http://msdn.microsoft.com/en-gb/magazine/cc300790.aspx – DaveRead

Respuesta

19

he encontrado una solución que otros también podrían serle de utilidad. La creación de un MessageInspector le permite adjuntar código a los eventos "AfterReceiveRequest" y "BeforeSendReply", según el siguiente:

public class MessageInspector : IDispatchMessageInspector 
{ 
    public object AfterReceiveRequest(ref Message request, IClientChannel channel, InstanceContext instanceContext) 
    { 
     MessageBuffer buffer = request.CreateBufferedCopy(Int32.MaxValue); 
     request = buffer.CreateMessage(); 
     LogMessage("Received:\n{0}", buffer.CreateMessage().ToString()); 
     return null; 
    } 

    public void BeforeSendReply(ref Message reply, object correlationState) 
    { 
     MessageBuffer buffer = reply.CreateBufferedCopy(Int32.MaxValue); 
     reply = buffer.CreateMessage(); 
     LogMessage("Sending:\n{0}", buffer.CreateMessage().ToString()); 
    } 
} 

Hay una full tutorial for setting up message inspectors fo wcf here. Diré que tenga cuidado de verificar el nombre completo de su ensamblaje cuando agregue la extensión de comportamiento a su app.config/web.config.

Espero que alguien más lo encuentre útil.

2

Para que usted pueda lograr lo anterior se necesita cambiar su método como se muestra a continuación:

public CascadeResponse SendCustomer(Message requestMessage) 
    { 
     Message msg = OperationContext.Current.RequestContext.RequestMessage.CreateBufferedCopy(Int32.MaxValue).CreateMessage(); 
     LogMessage(msg); 
     // Now that the request is logged, get on with the rest   
     Customer c = msg.GetBody<Customer>(); 
    } 

Más información sobre Using Message Class

+0

Gracias, esto me puso en el camino correcto, pero tengo un montón de errores al usar svcutil.exe para crear las clases de proxy requeridas. 'No se puede importar WSDL: binding' ' No se puede importar WSDL: binding' ... y así sucesivamente Además, no estoy seguro de cómo recuperar objetos adicionales desde el cuerpo de la petición (mi ejemplo sólo contenía un objeto, pero el código real tiene una cadena adicional que identifica al cliente). Echaré otro vistazo el lunes, pero gracias por su ayuda hasta ahora. – Maloric

2

Creo que puedes usar ...ToString() método y lo que vamos a hacer es volver a escribir el mensaje interno:

string soap = OperationContext.Current.RequestContext.RequestMessage.ToString(); 

observar el interior del método ToString() ...;)

0

En VS2015 en un proyecto de servicio WCF, puede haga clic en Web .config para editar la configuración de WCF. Desde aquí puede habilitar los diagnósticos para registrar los mensajes sin procesar.

+0

¿Puede explicar esto y especificar exactamente cómo y qué configuraciones? Simplemente hacer esta declaración no es suficiente para ser útil. –

Cuestiones relacionadas