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?
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.