I have an application that submits a large amount of data to a WCF web service. Since the data can be large I wanted to use the Streamed TransportMode so I can process the data as its coming in instead of buffering it all.
When Im debugging the application, the streaming works as expected. Once I actually publish the service to my IIS server, the streaming no longer works and the data seems to just be getting buffered.
I tested it by putting a throw new Exception
at the beginning of the web service function and changed the source stream to provide "infinite data".
Here is the Server source code:
[ServiceContract]
public class Service1
{
[OperationContract]
public void SubmitData(Stream stream)
{
throw new Exception("Test");
using (var reader = new StreamReader(stream))
{
string line = reader.ReadLine();
// Do Something...
}
}
}
Here is the client code:
Service1Client client = new Service1Client();
client.Endpoint.Address = new EndpointAddress(address);
client.Open();
using (var stream = new InfiniteDataStream())
client.SubmitData(stream);
client.Close();
.
class InifiteDataStream : Stream
{
...
public override int Read(byte[] buffer, offset, count)
{
// Create random data...
return count;
}
...
}
Server Web.Config:
<system.serviceModel>
<bindings>
<basicHttpsBinding>
<binding transferMode="Streamed" maxReceivedMessageSize="2147483647">
<security mode="TransportWithMessageCredential">
<message clientCredentialType="UserName" />
</security>
</basicHttpsBinding>
</bindings>
<behaviors>
<serviceBehaviors>
<behavior>
<serviceMetadata httpGetEnabled="true" httpsGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="true" />
</behavior>
</serviceBehaviors>
</behaviors>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" />
<protocolMapping>
<add binding="basicHttpsBinding" scheme="https" />
</protocolMapping>
</system.serviceModel>
Client App.Config:
<system.serviceModel>
<bindings>
<basicHttpsBinding>
<binding name="BasicHttpsBinding_Service1" transferMode="Streamed" >
<security mode="TransportWithMessageCredential" />
</binding>
</basicHttpsBinding>
</bindings>
<client>
<endpoint address="https://localhost:56297/WebService/Service1.svc"
binding="basicHttpsBinding" bindingConfiguration="BasicHttpsBinding_Service1"
contract="WebService.Service1" name="BasicHttpsBinding_Service1" />
</client>
Like I said this code works exactly how it should when Im debugging in VS (w/ IIS Express), when I run the client it gives the exception instantly. When I run the client pointed to the web server it just sits there, until it eventually gets a receive timeout exception. Which would be expected from a buffered transport since it will never be done buffering. And if I debug the client application while its pointed at the web server, I can see that the Read function is being called in the stream.
Is there some kind of configuration in IIS that needs to be changed? I looked through the settings and didn't see anything apparent.
Update:
I found this Microsoft forums thread post https://social.msdn.microsoft.com/Forums/vstudio/en-US/cfe625b2-1890-471b-a4bd-94373daedd39/streamedrequest-possible-under-iis?forum=wcf
The last comment indicates this was a bug that was fixed in .Net 4.5 but Im builiding with 4.6.1
Also, my server is running IIS 8.5 so I decided to try the same test on my local Win10 machine which has IIS 10, still doing the same thing.
Using Wireshark I was able to confirm that the data is being streamed to the server, its just not getting processed by the server.
I also tried changing transferMode="Streamed"
to transferMode="StreamedRequest"
, no luck.