Paul Williams
Paul Williams

Reputation: 17020

Are WCF data streaming restrictions enforced?

We have been seeing random OutOfMemoryExceptions and InsufficientMemoryExceptions at customer sites. We use the GZipMessageEncoder to compress messages. (I am aware of the IIS 7.x compression option and other problems with buffering and/or the GZipMessageEncoder.)

I wanted to try to enable WCF streaming. Our WCF services have contracts like the following:

[OperationContract]     
DataSet GetDataSet(Guid someGUID, string someName, DataSet parameters);

According to this article on MSDN:

Operations that occur across a streamed transport can have a contract with at most one input or output parameter

Obviously, our contract violates the WCF streaming restrictions. This contract has 3 input parameters.

However, out of curiosity, I decied to try enabling streaming anyway. I edited the web.config file and MyCSharpClient.config file and inserted the following attribute into the transport section of the binding:

<httpTransport ... transferMode="Streamed">

To my surprise, everything seems to work anyway! There are no exceptions thrown. I can break into the GZipMessageEncoder and verify that the stream methods are being called instead of the buffer methods.

So, my question: why was I able to setup streaming transport on an operation context that violates the WCF restriction on input parameters? Given the strong wording of the MSDN streaming article, I assume this is just an implementation detail, and that I must not rely on this behavior.

Upvotes: 2

Views: 361

Answers (1)

carlosfigueira
carlosfigueira

Reputation: 87228

What is going on currently is the following: you enabled streaming on the HTTP transport, so the transport isn't buffering anything - the transport receives a Message object, and writes it out to the transport stream (wrapped in an XML writer) directly. However, the parameters to the operation are buffered before they're serialized so you're "paying" the memory usage which you would were the transfer mode set to 'Buffered'. On the wire, the difference is that the response from this service, instead of having a Content-Length header, will be chunked (i.e., it'll have a Transfer-Encoded: chunked header, and the body will be formatted accordingly. But it will work just as well.

I'd say that the article in MSDN could have chosen better words. In order for an operation to take advantage of streaming, it needs to have one single parameter, often of type Stream, Message or some type which implements IXmlSerializable. But a simple contract (i.e., [OperationContract] int Add(int x, int y)) will work just as well. And I'd imagine that it'll continue working like that, since it's perfectly valid for one single contract to have "normal" operations, and operations which take advantage of streaming, and since the transfer mode needs to be set per endpoint (and not per operation), it has to work for "simple" operations as well.

Upvotes: 2

Related Questions