TCP Streaming is Broke in Beta 2
The release notes document for Beta 2 lists the following known issue with WCF Stream types and operations:
4.1 When Using WCF Steam Types and Operations, May Get QuotaExceededException When Using Binary Encoding
When using types that derive from System.IO.Stream as input or output parameters in service operations, QuotaExceededException may be thrown if the binary encoding is being used, even though no quotas have actually been exceeded. This encoding is the default for several standard bindings, such as NetTcpBinding.
To work around this problem, set the MaxBytesPerRead quota to the value 4200 (or some other number that is divisible by 8 but not by 16) instead of the default value of 4096. You can do this by changing the setting in your application’s configuration file. MaxBytesPerRead is contained in the ReaderQuotas subsection of the binding configuration section.The problem I see with the stated work-around is that it cannot be applied to a streamed TCP binding. To set the transfer mode for a TCP binding to Streamed in a config file, we must use the CustomBinding/Binding elements. But, the readerQuotas element is not a valid child element of CustomBinding/Binding (or their tcpTransport child element). So, in practice, there is no way to implement this work-around and therefore Beta 2 has broken TCP streamed services!
(I really hope I'm wrong about this!)
BTW, whatever happened to the TransferMode attribute for the netTcpBinding element? In the earlier pre-releases, the NetProfileTcp binding had a TransferMode attribute. Why are we forced to use CustomBinding to switch to Streamed mode?
Answers
I received a lot of helpful response from the WCF team on this via e-mail and so I thought I'd post it here for anyone interested.
When using a CustomBinding element in a config file to create a streamed TCP binding, use the readerQuotas child element of the binaryMessageEncoding element to accomplish the work-around. Here is a sample:
<customBinding>
<binding name="NetTcpStreamedBinding">
<binaryMessageEncoding>
<!-- The maxBytesPerRead is being set to a value divisible by 8 but not by 16 as a work-around
for the "Stream Types" Known Issue mentioned in the WinFX Runtime Beta 2 Notes. -->
<readerQuotas maxBytesPerRead="4200" />
</binaryMessageEncoding>
<tcpTransport transferMode="Streamed" />
</binding>
</customBinding>If you're using the programmatic approach rather than the config file approach, you may use the following (taken from a self-hosted service host program):
Uri baseAddress = new Uri(ConfigurationManager.AppSettings["baseAddress"]);
using (ServiceHost host = new ServiceHost(typeof(MyServiceLib), baseAddress))
{
NetTcpBinding myTcpBinding = new NetTcpBinding();
myTcpBinding.ReaderQuotas.MaxBytesPerRead = 4200
BindingElementCollection elements = myTcpBinding.CreateBindingElements();
TcpTransportBindingElement transport = elements.Find<TcpTransportBindingElement>();
transport.TransferMode = TransferMode.Streamed;
CustomBinding myCustomBinding = new CustomBinding(elements);
host.AddServiceEndpoint(typeof(IWinFxImagingServiceLib), myCustomBinding, baseAddress);
host.Open();
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1());
host.Close();
}This may seem a bit circuitous, but as it was explained to me: "Once the binding elements are created, modifications don't affect the original binding. The solution is just to put those elements back into a new binding (myCustomBinding above)." So here we are starting with a standard netTcpBinding, altering its readerQuotas element, making a copy of its binding elements, altering the TransferMode property of the TcpTransportBindingElement for Streamed, and finally creating a new CustomBinding from the resultant binding elements.
All Replies
I received a lot of helpful response from the WCF team on this via e-mail and so I thought I'd post it here for anyone interested.
When using a CustomBinding element in a config file to create a streamed TCP binding, use the readerQuotas child element of the binaryMessageEncoding element to accomplish the work-around. Here is a sample:
<customBinding>
<binding name="NetTcpStreamedBinding">
<binaryMessageEncoding>
<!-- The maxBytesPerRead is being set to a value divisible by 8 but not by 16 as a work-around
for the "Stream Types" Known Issue mentioned in the WinFX Runtime Beta 2 Notes. -->
<readerQuotas maxBytesPerRead="4200" />
</binaryMessageEncoding>
<tcpTransport transferMode="Streamed" />
</binding>
</customBinding>If you're using the programmatic approach rather than the config file approach, you may use the following (taken from a self-hosted service host program):
Uri baseAddress = new Uri(ConfigurationManager.AppSettings["baseAddress"]);
using (ServiceHost host = new ServiceHost(typeof(MyServiceLib), baseAddress))
{
NetTcpBinding myTcpBinding = new NetTcpBinding();
myTcpBinding.ReaderQuotas.MaxBytesPerRead = 4200
BindingElementCollection elements = myTcpBinding.CreateBindingElements();
TcpTransportBindingElement transport = elements.Find<TcpTransportBindingElement>();
transport.TransferMode = TransferMode.Streamed;
CustomBinding myCustomBinding = new CustomBinding(elements);
host.AddServiceEndpoint(typeof(IWinFxImagingServiceLib), myCustomBinding, baseAddress);
host.Open();
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1());
host.Close();
}This may seem a bit circuitous, but as it was explained to me: "Once the binding elements are created, modifications don't affect the original binding. The solution is just to put those elements back into a new binding (myCustomBinding above)." So here we are starting with a standard netTcpBinding, altering its readerQuotas element, making a copy of its binding elements, altering the TransferMode property of the TcpTransportBindingElement for Streamed, and finally creating a new CustomBinding from the resultant binding elements.
And as for my last question regarding the missing TransferMode attribute of netTcpBinding, here is what the WCF team told me:
"NetTcpBinding got a TransferMode knob several months ago but it hasn’t made it into the public releases yet."

