Search code examples
asp.netvb.netwcfweb-servicesdatacontract

IO.FileStream fails when MessageContract changed to DataContract


I have a very basic WCF service that receives uploaded documents. When defined like, it works perfectly:

<ServiceContract()>
Public Interface ITransferService

    <OperationContract()>
    <FaultContractAttribute(GetType(MyProcessingFault))>
    Function UploadFile(ByVal request As RemoteFileInfo) As MyWebMethodResult

End Interface

<MessageContract()>
Public Class RemoteFileInfo
    Implements IDisposable

    <MessageHeader(MustUnderstand:=True)>
    Public FileName As String

    <MessageHeader(MustUnderstand:=True)>
    Public Length As Long

    <MessageBodyMember()>
    Public FileByteStream As System.IO.Stream

    Public Sub Dispose() Implements IDisposable.Dispose
        If FileByteStream IsNot Nothing Then
            FileByteStream.Close()
            FileByteStream = Nothing
        End If
    End Sub

End Class

However, I was a bit confused about using MessageContractAttribute, and most authors suggest keeping things simple with a DataContract instead. When I change the above to the following however, like this...

<ServiceContract()>
Public Interface ITransferService

    <OperationContract()>
    <FaultContractAttribute(GetType(MyProcessingFault))>
    Function UploadFile(ByVal request As RemoteFileInfo) As MyWebMethodResult

End Interface

<DataContract()>
Public Class RemoteFileInfo
    Implements IDisposable

    <DataMember>
    Public FileName As String

    <DataMember>
    Public Length As Long

    <DataMember()>
    Public FileByteStream As System.IO.Stream

    Public Sub Dispose() Implements IDisposable.Dispose
        If FileByteStream IsNot Nothing Then
            FileByteStream.Close()
            FileByteStream = Nothing
        End If
    End Sub

End Class

I get the following WCF exception when I try to upload to the service:

Type 'System.IO.FileStream' with data contract name 'FileStream:http://schemas.datacontract.org/2004/07/System.IO' is not expected

Researching this, I read that streams cannot be serialized, however, surely this must be incorrect for the first example to work? Is it possible to use a FileStream with a DataContract, or should I not bother even attempting this approach?


Solution

  • DataContract messages serialize in a different way than MessageContract messages. Having a Stream member (thus allowing streaming) must be done using MessageContract, wcf then understands it is inteded for streaming and does not try to perform standard serialization.

    See http://msdn.microsoft.com/en-us/library/ms733742.aspx for more info:

    You should not be using System.IO.Stream derived types inside of data contracts. Stream data should be communicated using the streaming model, explained in the following "Streaming Data" section.