WCF Message Inspector–implementacja (część I)

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)”

Leave a Reply

Your email address will not be published.