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.

15 Comments

  • i've tried this and got a hang up of iis or wcf =[

    the response just does not come out =[

    i dunno. IIS7 / Vista. WCF .net 3.5

    if you had some problems please, can you contact me by email:

    agornik (at) gmail.com ?

  • A hang up? If you mean that IIS terminates the connection, no I have not seen that. From my testing, this work around worked fine. Maybe some more details about what your particular scenario?

    Cheers

  • Thanks for the tip on the Response Buffer & BufferOutput. This was blocking me as well.

    Also, I found that Mtom will stream but the client will reconstitute the entire buffer so the benefits are lost at the client when stream processing is desired.


  • You are a life-saver. I hit exactly this issue and your work-around solved it. I find it hard to believe this made it through Microsoft QA.

  • aconway:

    I'm quite certain 2GB is all your allowed over http in a browser.

  • Thanks
    It's a simple and elegant description for a HTTPContext in WCF.

  • As a follow up to my earlier post, I ended up hosting the WCF service in a Windows Service, but it still communicates via HTTP, so I got the best of both worlds. By hosting in a Windows Service I did not have to be bound by the 2GB IIS limitation. For security, I applied a SSL certificate to the Windows Service on the port the service communicates on. I streamed a 13GB file across servers in about 5 minutes.

  • Hi Jason, I have problems by hosting my WCF-Service under IIS.

    If I change the transferMode on the Client Side, from "Buffered" to "Streamed", I always get a curiouse Exception:
    The remote server returned an unexpected response: (400) Bad Request.

    If I host my Service in a other host, everything works fine.

    Could you send me a running Solution of a Streamed WCF Service hosted in IIS? If You want I can send you my Solution...

    Thanks Sepp

  • Hi Jason, Your post is similar to issues we have been encountering with our WCF web service. The client is however, Windows 2003 + IIS 6.0. TransferMode is streamed.
    So we have a web page that lists links to PDFs. Each link invokes the web service that streams back the PDF files.
    The PDF files are between 30KB - 1.2 MB.
    The first few calls work just fine. Subsequently however, we stop receiving a response and IIS indicates a "Buffer Overflow". Closing the window and re-trying another link starts the delivery again for the next few links.
    Is the temporary cache mentioned in C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\Temporary ASP.NET Files\MyWCFProject\b1a1a32e\6d915d8a\uploads

    used for all web users. Please note that this website is a secure extranet used for a lot of users.
    I can send the client and service code if reqed. A quick response is very much appreciated.

  • Hi,

    I have tried to implement your solution. but it seems that the streaming is still not working.

    Do you have an example application for this?

    Thanks.

  • Hi Jason,

    Does this work?I am confused as the default service constructor will never be called until we implement an IInstanceprovider!

  • I have a Streaming service under IIS7. The server Streams a large file back to the client.

    The service is working, and appears to be streaming. However I have checked the server memory when the service is called and it appears to be buffering, as the memory usage jumps up by about the same size of the filestream being returned.

    It sounds like the issue described on this page but I've implemented the BufferOutput workaround and it didn't make any difference...I still see high memory usage.

    Am I missing something!?

  • I agree with Paul. It seems that if you add the bufferoutput = false in the class constructor by this time it is too late. The full request has already been sent by the client. At least according to fiddler.

  • This issue was fixed in .NET 3.5 SP1.

  • Any ideas for disabling buffered upload?

    I see the stream being read on the client before i start reading the stream in my service.
    (When setting a breakpoint in the service it is still read to end on the client)

Comments have been disabled for this content.