WCF Streaming Issue Under IIS
Recently, I've been doing a lot of work with streaming under an IIS hosted WCF service (using the BasicHttpBinding). I ran into a rather strange issue, that appears to be an oversight deep inside the internals of WCF. Enabling streaming on a binding is typically set when you anticipate sending large objects across the wire, and do not want to buffer up the entire message prior to sending. When streaming mode is enabled, the headers of the message are buffered and the body is exposed as a stream and sent across the wire. When you host your service inside a console app or windows service, everything works as expected (the body is indeed streamed no buffering at all). Now comes the issue...
When you host your service under IIS, no matter if you enable streaming or not, your service will buffer the entire message prior to sending it. The reason for this, is that it appears as though WCF does not set the Response.BufferOutput to "false" (default is true), when streaming is enabled on a service. This seems to be an oversight in my opinion, that could be rectified in the framework code. So the good news is, there is a way around this issue:
Since we want to somehow set that Response.BufferOutput to false, we need to get at the HttpContext. The flexibility of WCF comes to our aid here with the ability to enable AspNet Compatibility Mode, there are 3 changes we need to make to the service, to work around this issue.
1) Add the following attribute to your service: [AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
2) Inside the default constructor for your service, or wherever you want to set the bufferoutput property paste this code:
HttpContext httpContext = HttpContext.Current;
if (httpContext != null)
{
httpContext.Response.BufferOutput = false;
}
3) Inside <system.serviceModel> place the following tag
<serviceHostingEnvironment aspNetCompatibilityEnabled="true"/>
What we've done here is get access to the HttpContext and manually set the flag, which isn't wonderful, but works around the problem.