Как зарегистрировать необработанный запрос в службе WCF

У меня есть служба WCF с несколькими методами. Я хотел бы зарегистрировать необработанный запрос, который пришел от клиента, независимо от того, как это было отправлено. Один метод принимает данные в виде строки запроса (строго для старой поддержки), которую я могу выполнить с помощью:

OperationContext.Current.IncomingMessageHeaders.To.AbsoluteUri

В этом сценарии этого достаточно, но другие методы позволяют клиенту отправлять данные в формате XML с использованием прокси-класса, сгенерированного svcutil.exe. В этом случае я нашел данные, которые я хочу получить в s: Тело:

OperationContext.Current.RequestContext.RequestMessage

К сожалению, независимо от того, что я пытаюсь, я не могу создать буферную копию сообщения до его чтения. Вот пример:

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
    }

Однако в первой строке SendCustomer появляется следующая ошибка:

Это сообщение не может поддерживать операцию, потому что оно было прочитано.

Это то, что я создаю буферную копию, верно? Я предполагаю, что я делаю что-то элементарно неправильно.

Edit:

Итак, теперь метод выглядит следующим образом:

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

Моя проблема в том, что я не знаю, как отправить Клиента и ClientKey как отдельные объекты. Я мог бы сделать clientKey свойством Клиента (или создать пользовательский объект, который специально предназначен для передачи данных и содержит Customer и ClientKey как атрибуты), но я хотел бы избежать этого, если это возможно, поскольку это обновление устаревшей системы, которая уже работает таким образом.

У меня также возникает проблема с использованием svcUtil.exe для создания моих прокси-классов. Я полагаю, что наличие указанной выше сигнатуры метода означает, что мой сервис больше не будет рекламировать правильную подпись для отправки запросов как? Не уверен, что это достаточно ясно - если мой единственный метод ввода принимает объект Message, как мой клиент знает, чтобы отправить Клиента и ClientKey?

Ответ 1

Я нашел решение, которое другие могут также найти полезным. Создание MessageInspector позволяет присоединить код к событиям "AfterReceiveRequest" и "BeforeSendReply", как показано ниже:

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

Существует полное полное руководство по настройке инспекторов сообщений для wcf здесь. Я скажу, что будьте осторожны, чтобы проверить свое полное имя сборки при добавлении расширения поведения к вашему app.config/web.config.

Надеюсь, что кто-то найдет это полезным.

Ответ 2

Для достижения вышеуказанного вам необходимо изменить свой метод, как показано ниже:

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

Дополнительная информация о Использование класса сообщений

Ответ 3

Я думаю, вы можете использовать... ToString() метод и что он будет делать, это переписать сообщение внутри:

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

Просмотрите метод ToString()...;)

Ответ 4

В VS2015 в проекте службы WCF вы можете щелкнуть правой кнопкой мыши по web.config для редактирования конфигурации WCF. Отсюда вы можете включить диагностику для регистрации сырых сообщений.