问题
I have a WCF Service exposing a single contract and operation:
<ServiceContract(Namespace:="ImageSystem")> _
Public Interface IUploadService
<OperationContract()> _
Function UploadFile(ByVal file As ImageUpload) As ImageUpload
End Interface
The function both receives and returns an "ImageUpload" which is defined as such:
<MessageContract()> _
Public Class ImageUpload
<MessageHeader()> _
Public Property ImageID() As Nullable(Of Long)
<MessageHeader()> _
Public Property ImageTypeID() As Long
<MessageHeader()> _
Public Property IncludeInGallery() As Boolean
<MessageHeader()> _
Public Property OriginalFileName() As String
<MessageHeader()> _
Public Property ErrorDescription() As String
<MessageBodyMember()> _
Public Data As System.IO.Stream
End Class
The endpoints are defined as follows (not sure this matters too much but just in case):
Client:
<configuration>
<system.serviceModel>
<bindings>
<netTcpBinding>
<binding name="netTcpStreamBinding" closeTimeout="00:01:00" openTimeout="00:01:00"
receiveTimeout="00:10:00" sendTimeout="00:01:00" transactionFlow="false"
transferMode="Streamed" transactionProtocol="OleTransactions"
hostNameComparisonMode="StrongWildcard" listenBacklog="10" maxBufferPoolSize="524288"
maxBufferSize="20971520" maxConnections="10" maxReceivedMessageSize="20971520">
<readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384"
maxBytesPerRead="4096" maxNameTableCharCount="16384" />
<security mode="None" />
</binding>
</bindings>
<client>
<endpoint address="net.tcp://localhost:809/UploadService" binding="netTcpBinding"
bindingConfiguration="netTcpStreamBinding" contract="UploadService.Local.IUploadService"
name="NetTcpBinding_IUploadService">
<identity>
<dns value="localhost" />
</identity>
</endpoint>
</client>
</system.serviceModel>
</configuration>
Server:
<configuration>
<system.serviceModel>
<bindings>
<netTcpBinding>
<binding name="netTcpStreamBinding" transferMode="StreamedRequest" maxBufferSize="20971520"
maxReceivedMessageSize="20971520" >
<security mode="None"/>
</binding>
</netTcpBinding>
</bindings>
<services>
<service behaviorConfiguration="UploadServiceBehaviour"
name="ImageSystem.SVC.UploadService">
<endpoint address="" binding="netTcpBinding" bindingConfiguration="netTcpStreamBinding"
contract="ImageSystem.SVC.IUploadService">
<identity>
<dns value="localhost" />
</identity>
</endpoint>
<endpoint address="mex" binding="mexTcpBinding" contract="IMetadataExchange" />
<host>
<baseAddresses>
<add baseAddress="net.tcp://localhost:809/UploadService" />
</baseAddresses>
</host>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="UploadServiceBehaviour">
<!-- To avoid disclosing metadata information, set the value below to false and remove the
metadata endpoint above before deployment -->
<serviceMetadata httpGetEnabled="false"/>
<!-- To receive exception details in faults for debugging purposes, set the value below to true.
Set to false before deployment to avoid disclosing exception information -->
<serviceDebug includeExceptionDetailInFaults="true"/>
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
</configuration>
My problem is that the proxy class generated by adding a service reference to the client, is generating a sub (void function) instead of the function I was expecting.
What's more, the generated sub doesn't accept my message contract as in/out parameters, instead it lists the message contracts' members.
I.e, I would expect the auto-generated proxy class to have the following signature:
Public Function UploadFile(ByVal file As ImageUpload) As ImageUpload
Instead, it's generating:
Public Sub UploadFile(ByRef ErrorDescription As String, ByRef ImageID As System.Nullable(Of Long), ByRef ImageTypeID As Long, ByRef IncludeInGallery As Boolean, ByRef OriginalFileName As String, ByRef Data As System.IO.Stream)
Dim inValue As UploadService.Local.ImageUpload = New UploadService.Local.ImageUpload()
inValue.ErrorDescription = ErrorDescription
inValue.ImageID = ImageID
inValue.ImageTypeID = ImageTypeID
inValue.IncludeInGallery = IncludeInGallery
inValue.OriginalFileName = OriginalFileName
inValue.Data = Data
Dim retVal As UploadService.Local.ImageUpload = CType(Me,UploadService.Local.IUploadService).UploadFile(inValue)
ErrorDescription = retVal.ErrorDescription
ImageID = retVal.ImageID
ImageTypeID = retVal.ImageTypeID
IncludeInGallery = retVal.IncludeInGallery
OriginalFileName = retVal.OriginalFileName
Data = retVal.Data
End Sub
This subsequently leads to stream casting issues, because the generated function allows me to pass a memory stream as an input (which works correctly when passed through to the service), but instead of passing me back a new stream for the response, it attempts to cast the MessageBodyStream received from the service into my memory stream.
This is, in some ways similar to other posts but as you can see, there are no enums involved in my contracts - presence of Enums caused strange proxy class generation is marked as the answer in the similar post.
Is there anywhere I configure the proxy behaviour to use the contracts I've specified? Clearly I'm within a dev/test environment currently, but when this eventually goes to production it will be memory and file streams passed to the service, and the returned stream can be in any format to be honest, I intend to treat it as the abstract stream class. The only way round this I can see right now is to change my in stream to be the same as the anticipated out stream, but surely there is a better way?
回答1:
Total idiot. I hadn't checked the box in the service reference configuration for "Always Generate message Contracts".
Once checked my proxy class signatures were changed to the expected signatures in my OP.
Apologies for the hub-bub ^^
来源:https://stackoverflow.com/questions/6095617/wcf-service-generated-proxy-class-exposing-function-as-byref-sub