I'm having custom IClientMessageFormatter, that currently adds attribute to specified xml element in a message:
public class GetOrdersMessageFormatter : IClientMessageFormatter
{
readonly IClientMessageFormatter original;
public GetOrdersMessageFormatter(IClientMessageFormatter actual)
{
original = actual;
}
public void AddArrayNamespace(XmlNode node)
{
if (node != null)
{
var attribute = node.OwnerDocument.CreateAttribute("test");
attribute.Value = "test";
node.Attributes.Append(attribute);
}
}
public object DeserializeReply(Message message, object[] parameters)
{
return original.DeserializeReply(message, parameters);
}
public Message SerializeRequest(MessageVersion messageVersion, object[] parameters)
{
Message newMessage = null;
var message = original.SerializeRequest(messageVersion, parameters);
if (message.Headers.Action == "urn:Mage_Api_Model_Server_HandlerAction")
{
var doc = new XmlDocument();
using (var reader = message.GetReaderAtBodyContents())
{
doc.Load(reader);
}
if (doc.DocumentElement != null)
{
switch (doc.DocumentElement.LocalName)
{
case "call":
AddArrayNamespace(doc.SelectSingleNode("//args"));
break;
}
}
using (var ms = new MemoryStream())
{
using (var xw = XmlWriter.Create(ms))
{
doc.Save(xw);
ms.Position = 0;
using (var xr = XmlReader.Create(ms))
{
newMessage = Message.CreateMessage(message.Version, null, xr);
newMessage.Headers.CopyHeadersFrom(message);
newMessage.Properties.CopyProperties(message.Properties);
}
}
}
}
return newMessage;
}
}
It gives exception
System.ArgumentException : The XmlReader used for the body of the message must be positioned on an element. Parameter name: reader
Server stack trace: at System.ServiceModel.Channels.XmlReaderBodyWriter.OnWriteBodyContents(XmlDictionaryWriter writer) at System.ServiceModel.Channels.BodyWriter.WriteBodyContents(XmlDictionaryWriter writer) at System.ServiceModel.Channels.BodyWriterMessage.OnWriteBodyContents(XmlDictionaryWriter writer) at System.ServiceModel.Channels.Message.OnWriteMessage(XmlDictionaryWriter writer) at System.ServiceModel.Channels.Message.WriteMessage(XmlDictionaryWriter writer) at System.ServiceModel.Channels.BufferedMessageWriter.WriteMessage(Message message, BufferManager bufferManager, Int32 initialOffset, Int32 maxSizeQuota) at System.ServiceModel.Channels.TextMessageEncoderFactory.TextMessageEncoder.WriteMessage(Message message, Int32 maxMessageSize, BufferManager bufferManager, Int32 messageOffset) at System.ServiceModel.Channels.HttpOutput.SerializeBufferedMessage(Message message) at System.ServiceModel.Channels.HttpOutput.Send(TimeSpan timeout) at System.ServiceModel.Channels.HttpChannelFactory.HttpRequestChannel.HttpChannelRequest.SendRequest(Message message, TimeSpan timeout) at System.ServiceModel.Channels.RequestChannel.Request(Message message, TimeSpan timeout) at System.ServiceModel.Dispatcher.RequestChannelBinder.Request(Message message, TimeSpan timeout) at System.ServiceModel.Channels.ServiceChannel.Call(String action, Boolean oneway, ProxyOperationRuntime operation, Object[] ins, Object[] outs, TimeSpan timeout) at System.ServiceModel.Channels.ServiceChannelProxy.InvokeService(IMethodCallMessage methodCall, ProxyOperationRuntime operation) at System.ServiceModel.Channels.ServiceChannelProxy.Invoke(IMessage message)
I thought, that may be I need to create message copy using message.CreateBufferedCopy() and use that copy to load XmlDocument, but that didn't worked either. May be someone knows what I'm doing wrong, or knows example, which is doing pretty much same thing (I mean affecting message xml before sending it).