I have a WCF service which has one method returning a stream.
[ServiceContract]
public interface IService1
{
[OperationContract]
MyMessage Test();
}
Now, MyMessage is defined like this:
[MessageContract]
public class MyMessage
{
public MyMessage(string file)
{
this.Stream = File.OpenRead(file);
this.Length = Stream.Length;
}
[MessageHeader]
public long Length;
[MessageBodyMember]
public Stream Stream;
}
Peachy.
The service has a streamed response, using basicHttpBinding. This is the binding configuration:
<basicHttpBinding>
<binding name="BasicStreaming"
maxReceivedMessageSize="67108864" maxBufferSize="65536" transferMode="StreamedResponse" />
</basicHttpBinding>
Now this is where things start to get interesting. When calling this service, the last byte is lost if i read the stream in a particular way. Here is the code illustrating the two different approaches:
Service1Client client = new Service1Client();
//this way the last byte is lost
Stream stream1;
var length = client.Test(out stream1);
var buffer1 = new byte[length];
stream1.Read(buffer1, 0, (int)length);
File.WriteAllBytes("test1.txt", buffer1);
stream1.Close();
//here i receive all bytes
Stream stream2;
length = client.Test(out stream2);
var buffer2 = new byte[length];
int c = 0, b;
while ((b = stream2.ReadByte()) != -1)
{
buffer2[c++] = (byte)b;
}
File.WriteAllBytes("test2.txt", buffer2);
stream2.Close();
I am sure I’m missing something, but can anyone point out to me exactly why this is happening? The biggest problem is that in another service, whichever way i read the stream, i lose the last byte, but maybe by identifying the problem here I can solve that one too.
Technical details:
- IIS 7.0
- .NET 3.5
- Basic HTTP Binding
- Streamed response mode
Note: I have uploaded the project isolating the problem, so anyone can try it out: mediafire
I don’t have an exact answer as to why this works (my brain isn’t fully engaged at the moment), however this DOES work:
(and, yes, you end up with a buffer that’s too large. It’s just a starting point for further thinking)
In testing I found +1 isn’t large enough, but +2 is.