简体   繁体   中英

WCF - Return Object With Stream Data

Is it possible to return a stream which is part of a complex object as returned data from a Wcf method?

I have checked most of the msdn references on returing stream data with Wcf; such as this one . All of the examples seem to show how to return stream when the method return type is Stream (or parameter is stream).

What I wanted know is can it return the stream if the data is part of complex object property? For example, can GetData() return the Data which contains a stream as shown below:

[DataContract]
public class Data
{
    [DataMember]
    public string Info { get; set; }

    /// <summary>
    /// This is the file stream that would be returned to client.
    /// </summary>
    [DataMember]
    public Stream File { get; set; }
}

[ServiceContract()]
public interface IService
{           
    [OperationContract]
    Data GetData();
}

From my initial testing, it seems that this doesn't work. I get exception on client side (unexpected socket closure). Result is same regardless of DataContractSerialization or XmlSerialization. I have set the required streaming mode with TransferMode.Streamed .

you can use message contract, design your contract as

[MessageContract]
public class Data 
{ 
    [MessageHeader(MustUnderstand = true)]
    public string Info { get; set; } 

    /// <summary> 
    /// This is the file stream that would be returned to client. 
    /// </summary> 
    [MessageBodyMember(Order = 1)]
    public Stream File { get; set; } 
} 

[ServiceContract()] 
public interface IService 
{            
    [OperationContract] 
    Data GetData(); 
} 

You can't do that, see this documentation

At least one of the types of the parameter and return value must be either Stream, Message, or IXmlSerializable.

So the way you've written it isn't going to work for TransferMode.Streamed however nothing at that link explicitly says a property of type Stream wouldn't be serialized but from experience I would not expect that to work.

Instead you should return a Stream and define the first x bytes as your string Info field.

 [ServiceContract()]
 public interface IService
 {           
     [OperationContract]
     Stream GetData();
 }

thus when writing to the Stream (server side) you would do

 stream.Write(infoStr);//check size and truncate if appropriate
 stream.Write(fileBytes);//write your file here

Then on the other side you need to read from the stream correctly to get your data out of the stream. What I would suggest is writing 2 int to the stream first. The first would be the size of your infoStr field and the second is the size of your file. On the client size you read these off first then you know how many bytes you need to read.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM