(类似于这问题,但在这种情况下最终不需要它)
我正在使用一个IErrorHandler实现--创建一个FaultException,以便服务的客户端在发生未处理异常时接收“漂亮”错误。
现在,我想在请求消息中使用一个元素,并在FaultException中将其弹出,但我没有获胜。
我可以访问OperationContext.Current.RequestContext.RequestMessage,并且可以使用它的ToString()看到完整的信封(包括我希望FaultResponse包含的'message‘属性),但是我想要’手动‘反序列化请求消息,或者甚至只是将主体读取为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);
} }做这件事最好的方法是什么?
编辑:看上去不可能在IErrorHandler事件期间读取OperationContext的请求消息--大概是因为它已经在IErrorHandler管道中被读取了(因此使用MessageBuffer创建消息副本将无法工作)。这个问题的“解决办法”在公认的答案中描述了。
发布于 2016-03-17 19:17:22
一种可能的方法是使用IDispatchMessageInspector从请求消息中读取所需的值,并将它们存储在OperationContext中,直到需要访问它们为止。
用于IDispatchMessageInspector的MSDN文档是笔直的。只需记住在读取消息之前先创建消息的缓冲副本。
public object AfterReceiveRequest(ref System.ServiceModel.Channels.Message request, IClientChannel channel, InstanceContext instanceContext)
{
var bufferedCopy = request.CreateBufferedCopy(2000000); // choose a suitable buffer size
request = bufferedCopy.CreateMessage();// Message for continued processing
var messageToRead = bufferedCopy.CreateMessage(); // message to read properties from
return null;
}有关如何将属性附加到问题上,请参阅此OperationContext。
发布于 2016-03-17 17:11:16
您应该复制原始消息的缓冲区:
// Read orignal messagem
var originalMessage = OperationContext.Current.RequestContext.RequestMessage;
// Copy message
MessageBuffer buffer = originalMessage.CreateBufferedCopy(Int32.MaxValue);
//OperationContext.Current.RequestContext.RequestMessage = buffer.CreateMessage();
var req = buffer.CreateMessage();
XElement body = XElement.Parse(XElement.ReadFrom(req.GetReaderAtBodyContents()).ToString());希望能帮上忙。
发布于 2016-03-17 13:58:58
您应该自定义异常并使用它的属性来保持Id。
public void ProvideFault(Exception error, MessageVersion version, ref Message fault)
{
var myException = error as MyException;
if (myException == null)
{
return;
}
var err = new FaultException<Foo>(new Foo
{
MessageID = myException.MsgId
}, "Server error");
var msgFault = err.CreateMessageFault();
fault = Message.CreateMessage(
version,
msgFault,
null);
} https://stackoverflow.com/questions/36062138
复制相似问题