2012-04-20 25 views
10

Ho un servizio WCF con diversi metodi. Vorrei registrare la richiesta non elaborata ricevuta dal client indipendentemente da come è stata inviata. Un metodo accetta i dati come un querystring (rigorosamente per il supporto legacy), che posso accedere utilizzando:Come registrare la richiesta non elaborata nel servizio WCF

OperationContext.Current.IncomingMessageHeaders.To.AbsoluteUri 

che è sufficiente in questo scenario, ma altri metodi consentono al cliente di inviare i dati in formato XML utilizzando una classe proxy generata di svcutil.exe. In questo scenario ho trovato i dati che voglio nella s: Corpo di:

OperationContext.Current.RequestContext.RequestMessage 

Purtroppo, non importa quello che cerco non riesco a creare una copia tamponata del messaggio prima che venga letta. Ecco un esempio:

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 
    } 

Nella prima riga del SendCustomer, però, ottengo il seguente errore:

Questo messaggio non può supportare l'operazione perché è stato letto.

Questo è il motivo per cui creo la copia bufferizzata, sicuramente? Sto indovinando che sto facendo qualcosa di elementare qui.

Edit:

Ok, quindi il metodo è ora così:

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

mio problema è che non so come ottenere il Cliente e ClientKey inviato come entità separate. Potrei rendere clientKey una proprietà del Cliente (o creare un oggetto personalizzato che sia specifico per il trasferimento dei dati e che contenga Customer e ClientKey come attributi), ma vorrei evitarlo se possibile, poiché si tratta di un aggiornamento di un sistema legacy che funziona già in questo modo

Ho anche problemi con l'uso di svcUtil.exe per creare le mie classi proxy - presumo che avere la firma del metodo sopra significa che il mio servizio non pubblicizzerà più la firma corretta per inviare richieste come? Non sono sicuro se questo è abbastanza chiaro - se il mio unico metodo di input accetta un oggetto Message, come fa il mio cliente a sapere di inviare un Cliente e un ClientKey?

+0

Qualsiasi motivo per cui non è possibile utilizzare la funzionalità di analisi integrata in WCF? http://msdn.microsoft.com/en-us/library/ms733025.aspx – DaveRead

+0

@DaveRead Principalmente che non ero a conoscenza di esso - questo mi consente di salvare i miei registri in un database? – Maloric

+0

Non fuori dalla scatola ma è possibile creare il proprio TraceListener personalizzato, vedere questo articolo per i dettagli: http://msdn.microsoft.com/en-gb/magazine/cc300790.aspx – DaveRead

risposta

19

ho trovato una soluzione che altri potrebbero anche trovare utili. La creazione di un MessageInspector consente di collegare il codice per gli eventi "AfterReceiveRequest" e "BeforeSendReply", secondo il seguente:

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

C'è una full tutorial for setting up message inspectors fo wcf here. Devo dire di fare attenzione a verificare il nome del tuo assembly completo quando aggiungi l'estensione di comportamento al tuo app.config/web.config.

Spero che qualcun altro lo trovi utile.

2

In ordine per voi per raggiungere quanto sopra è necessario cambiare il metodo per come illustrato di seguito:

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

Maggiori informazioni su Using Message Class

+0

Grazie, questo mi ha fatto sulla buona strada, ma ottengo un sacco di errori quando si utilizza svcutil.exe per creare le classi proxy richieste. 'Non è possibile importare wsdl: binding' ' Non è possibile importare wsdl: binding' ... e così via Inoltre, non sono sicuro come recuperare oggetti aggiuntivi dal corpo della richiesta (il mio esempio conteneva un solo oggetto, ma il codice effettivo ha una stringa aggiuntiva che identifica il client). Domani darò un'altra occhiata, ma grazie per il vostro aiuto finora. – Maloric

2

Penso che tu possa usare ...ToString() metodo e quello che faremo è riscrivere il messaggio internamente:

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

sguardo all'interno del metodo ToString() ...;)

0

In VS2015 su un progetto di servizio WCF, è possibile fare clic destro su web .config per modificare la configurazione di WCF. Da qui è possibile abilitare la diagnostica per registrare i messaggi non elaborati.

+0

Puoi approfondire questo aspetto e specificare esattamente come e quali impostazioni? Semplicemente fare questa affermazione non è sufficiente per essere utile. –

Problemi correlati