Как зарегистрировать необработанный запрос в службе 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. Отсюда вы можете включить диагностику для регистрации сырых сообщений.