Używając Message Inspector możemy modyfikować wiadomości przychodzące i wychodzące zarówno po stronie serwera jak i klienta. Wystarczy zaimplementować dwa interfejsy: IClientMessageInspector oraz IDispatchMessageInspector. Ich definicja wygląda następująco:
public interface IClientMessageInspector { void AfterReceiveReply(ref Message reply, object correlationState); object BeforeSendRequest(ref Message request, IClientChannel channel); } public interface IDispatchMessageInspector { object AfterReceiveRequest(ref Message request, IClientChannel channel, InstanceContext instanceContext); void BeforeSendReply(ref Message reply, object correlationState); }
Pierwszy z nich służy do tworzenia filtrów po stronie klienta a drugi po stronie usługi. Każda z metod wywoływana jest w momencie odebrania odpowiedzi lub wysłania zapytania. Warto zwrócić uwagę, że wiadomości przekazywane są przez referencję(REF). Oznacza to, że możemy tworzyć całkowicie nowy obiekt (wiadomość) przez operator new.
Wartość zwrócona w BeforeSendRequest jest potem przekazywana w parametrze correlationState AfterReceiveReply. Spróbujmy napisać prosty filtr, który wyświetli wiadomość w momencie wysyłki i odbioru:
public class SampleMessageInspector : IDispatchMessageInspector { public object AfterReceiveRequest(ref Message request, IClientChannel channel, InstanceContext instanceContext) { MessageBuffer buffer = request.CreateBufferedCopy(Int32.MaxValue); request = buffer.CreateMessage(); Console.WriteLine(buffer.CreateMessage().ToString()); return null; } public void BeforeSendReply(ref Message reply, object correlationState) { MessageBuffer buffer = reply.CreateBufferedCopy(Int32.MaxValue); reply = buffer.CreateMessage(); Console.WriteLine(buffer.CreateMessage().ToString()); } }
Innym przykładem jest wyświetlenie wszystkich nagłówków SOAP:
public class MessageInspectorExample2 : IDispatchMessageInspector { public object AfterReceiveRequest(ref Message request, IClientChannel channel, InstanceContext instanceContext) { MessageBuffer buffer = request.CreateBufferedCopy(Int32.MaxValue); request = buffer.CreateMessage(); Message originalMessage = buffer.CreateMessage(); foreach (MessageHeader header in originalMessage.Headers) { Console.WriteLine("\n{0}\n", header); } return null; } public void BeforeSendReply(ref Message reply, object correlationState) { MessageBuffer buffer = reply.CreateBufferedCopy(Int32.MaxValue); reply = buffer.CreateMessage(); Message originalMessage = buffer.CreateMessage(); foreach (MessageHeader header in originalMessage.Headers) { Console.WriteLine("\n{0}\n", header); } } }
Analogicznie wygląda sytuacja w przypadku klienta. W prawdziwym przypadku oczywiście w metodach umieścilibyśmy bardziej zaawansowaną logikę (np. walidacja luz wykonywanie logów). W następnej części przedstawię w jaki sposób można podłączyć Message Inspector do klienta lub usługi.
One thought on “WCF Message Inspector–implementacja (część I)”