Here
I have talked about various encoding options and their impact on the message size
(byte stream produced by WCF). The question is how you can measure the size of
the byte stream produced by WCF?
Size of the byte stream depends on the encoder being used
and different encoder produced byte stream of different sizes.
I have written a MessageInspector, which does message/stream
rewriting to calculate the size of the final byte stream. Once you have
configured this inspector in your client it will print the difference in the size
of message created by text encoder vs your configured encoder (MTOM, Binary or
GZip). Send method of Inspector looks like following:
public object
BeforeSendRequest(ref
System.ServiceModel.Channels.Message
request, IClientChannel channel)
{
var
mb = request.CreateBufferedCopy(int.MaxValue);
request = mb.CreateMessage();
var
ms = new MemoryStream();
// Dump
message size based on text encoder.
using
(var memWriter = XmlDictionaryWriter.CreateTextWriter(ms))
{
mb.CreateMessage().WriteMessage(memWriter);
memWriter.Flush();
Console.WriteLine("Message
size using text encoder {0}", ms.Position);
}
ms = new
MemoryStream();
if
(gzipEncoding != null)
{// GZip
Special case
var encoder =
gzipEncoding.CreateMessageEncoderFactory().CreateSessionEncoder();
encoder.WriteMessage(mb.CreateMessage(), ms);
Console.WriteLine("GZip
encoded size {0}", ms.Position);
return null;
}
// just
wrap the message - and wrapper will do the trick.
request = new WrappingMessage(request);
return
null;
}
public class WrappingMessage : Message
{
Message
innerMsg;
MessageBuffer
msgBuffer;
public
WrappingMessage(Message inner)
{
this.innerMsg = inner;
msgBuffer
= innerMsg.CreateBufferedCopy(int.MaxValue);
innerMsg
= msgBuffer.CreateMessage();
}
public
override MessageHeaders
Headers
{
get { return
innerMsg.Headers; }
}
protected
override void
OnWriteBodyContents(XmlDictionaryWriter
writer)
{
innerMsg.WriteBodyContents(writer);
}
public
override MessageProperties
Properties
{
get { return
innerMsg.Properties; }
}
public
override MessageVersion
Version
{
get { return
innerMsg.Version; }
}
protected
override void
OnWriteMessage(XmlDictionaryWriter writer)
{
// write message to the actual stream using encoder..
base.OnWriteMessage(writer);
writer.Flush();
// write message to MemoryStream (using encoder) to get
it's size.
var copy = msgBuffer.CreateMessage();
DumpEncoderSize(writer, copy);
}
private
static void
DumpEncoderSize(System.Xml.XmlDictionaryWriter
writer, Message copy)
{
var ms = new MemoryStream();
string configuredEncoder = string.Empty;
if (writer is IXmlTextWriterInitializer)
{
var w = (IXmlTextWriterInitializer)writer;
w.SetOutput(ms, Encoding.UTF8, true);
configuredEncoder = "Text";
}
else if (writer is IXmlMtomWriterInitializer)
{
var w = (IXmlMtomWriterInitializer)writer;
w.SetOutput(ms, Encoding.UTF8, int.MaxValue,
"", null,
null, true, false);
configuredEncoder = "MTOM";
}
else if (writer is IXmlBinaryWriterInitializer)
{
var w = (IXmlBinaryWriterInitializer)writer;
w.SetOutput(ms, null, null,
false);
configuredEncoder = "Binary";
}
copy.WriteMessage(writer);
writer.Flush();
var size = ms.Position;
Console.WriteLine("Message
size using configured ({1}) encoder {0}",
size,configuredEncoder);
}
}
I have attached complete solution with this post.