I have a requirement for a WCF service operation that accepts a large Stream, processes it and returns that stream.
I used an MSDN article on Large Data Streaming as a reference to what I need. I followed the advice in that article.
Asking the question in advance:
I would like to know why the generated service operation does not have a return type when I specified it in the contract?
If that is expected behaviour, how should I get it to pass on a stream and return a processed stream?
Details:
Because I need to accompany both the input and return streams with MetaData, I decorated the classes with MessageContract attributes, as is required.
Here is a brief run-down of my implementation:
Message Contracts:
[MessageContract]
public class InputStreamMessage
{
[MessageHeader]
public InputStreamHeader Header { get; set; }
[MessageBodyMember(Order = 1)]
public Stream Data { get; set; }
}
[MessageContract]
public class OutputStreamMessage
{
[MessageHeader]
public OutputStreamHeader Header { get; set; }
[MessageBodyMember(Order = 1)]
public Stream Data { get; set; }
}
Service Contract:
[ServiceContract]
public interface IStreamService
{
[OperationContract]
OutputStreamMessage ProcessStream(InputStreamMessage input);
}
Service Implementation:
public OutputStreamMessage DoStreamOperation(InputStreamMessage input)
{
//Some logic that assigns re
OutputStreamMessage output = DoSomeNonBufferedProcessing(input);
return output;
}
Client-side:
On the client-side, I then generate the service reference, and call the service as below:
private void PerformStreamOperation()
{
try
{
//
StreamServiceReference.StreamServiceClient client = new StreamServiceReference.StreamServiceReferenceClient();
client.Open();
//Set Header and Parameters
InputMessageHeader header = new InputMessageHeader();
//...
//... initialize header data here
//...
//... do some operation to get input stream
var inputstream = SomeOperationToGetInputStream();
//Perform Service stream action
// ____ [ Why does the generated method have the following signature, retuning void?]
// | [ If this is expected, how do I use it? ]
// |
// V
client.DoStreamOperation(header, ref inputstream);
//...
//... Do what you wish with data
//...
}
catch (Exception ex)
{
MessageBox.Show(ex.Message.ToString(), "Stream Processing Error");
}
}
The MSDN article uses the exact same contract that exists in the official WCF samples.
Stream EchoStream(Stream data)
But no example of an equivalent MessageContract implementation. The sample version does an expected return.
Update
- I noticed that the service reference has Task/Asynchronous methods that are generated with the expected method signature. Maybe that means when using MessageContract with a Stream property, returning a similarly structured object, then you will have to call it Asynchronously. I have not seen it documented anywhere. Will try using the methods - Did not work as we want synchronous operations.
I have also tried using the
ChannelFactory
as an alternative to the generated proxy client:EndpointAddress endpoint = new EndpointAddress("net.tcp://localhost:9910/StreamService"); channelFactory = new ChannelFactory<IStreamService>("netTcpStreamedEndPoint"); channelFactory.Endpoint.Contract.SessionMode = SessionMode.Allowed; IStreamService service = channelFactory.CreateChannel();