(Подобный this вопрос, однако в конечном итоге не нужно в этом случае)WCF IErrorHandler Получить сообщение запроса
Я использую реализацию IErrorHandler - создание FaultException так, чтобы клиенты к службе получить «довольно 'ошибки в случае необработанных исключений.
Я бы хотел использовать элемент в сообщении и вернуть его обратно в исключение FaultException, и я не выигрываю.
я могу получить доступ к OperationContext.Current.RequestContext.RequestMessage
, и может видеть полный конверт (в том числе имущества «идентификатор сообщения» Я хочу FaultResponse содержать), используя его ToString()
, однако я хотел бы либо «вручную» десериализации запрос сообщение, или даже просто прочитать тело как XML, чтобы извлечь свойство запроса, которое я ищу.
Однако я не в состоянии прочитать из сообщения, так как (я предполагаю) Послание уже где-то читал предыдущий в WCF трубопровода:
«Сообщение не может поддерживать операцию, так как это было скопировал»
Вот мой ProvideFault()
реализации (я знаю XElement разбор не может работать даже в таком виде - я не сосредотачиваясь на том, что в настоящее время):
public void ProvideFault(Exception error, MessageVersion version, ref Message fault) {
if (error is FaultException)
{
// Let WCF handle
}
else
{
// Extract the 'messageID' element from the request message
var req = OperationContext.Current.RequestContext.RequestMessage;
// Throws the 'has been copied' exception
XElement body = XElement.Parse(XElement.ReadFrom(req.GetReaderAtBodyContents()).ToString());
var msgId = (string)body.Descendants("messageID").FirstOrDefault();
var err = new FaultException<Foo>(new Foo
{
MessageID = msgId
}, "Server error");
var msgFault = err.CreateMessageFault();
fault = Message.CreateMessage(
version,
msgFault,
null);
} }
что т он лучший способ сделать это?
EDIT: Это не выглядит, как это можно прочитать в OperationContext в сообщение запроса во время событий IErrorHandler - предположительно, потому что это уже было прочитано ранее в конвейере WCF (создавая таким образом копию сообщения с помощью MessageBuffer не будет работать). Обходной путь к проблеме описан в принятом ответе.
Я думаю, ваша проблема в том, что вы читаете объект ошибки до того, как сделать копию. Это поток ref, поэтому, если вы читаете его содержимое, это вызывает ошибку «Сообщение не может поддерживать операцию, потому что оно было скопировано». Сначала попробуйте скопировать его, например: MessageBuffer buffer = fault.CreateBufferedCopy (Int32.MaxValue); fault = buffer.CreateMessage(); Сообщение сообщениеFault = буфер.Создать сообщение(); И использовать объект messageFault вместо –
Я вообще не читаю Fault (хотя в моей реальной реализации я регистрирую его) - это сообщение с запросом, которое я пытаюсь получить. Вызов CreateBufferedMessage() в сообщении Request также приводит к тому, что исключение «уже скопировано» было поднято. – Ive
У меня есть. Когда точно происходит ошибка? –