У меня есть Служба WCF, выставляющая один контракт и операцию:
<ServiceContract(Namespace:="ImageSystem")> _
Public Interface IUploadService
<OperationContract()> _
Function UploadFile(ByVal file As ImageUpload) As ImageUpload
End Interface
Функция получает и возвращает «ImageUpload», который определен так:
<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
Конечные точки определены следующим образом (не уверен, что это имеет большое значение, но на всякий случай):
Клиент:
<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>
Сервер:
<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>
Моя проблема в том, что прокси-класс, сгенерированный путем добавления ссылки на службу к клиенту, генерирует подпрограмму (функцию void) вместо функции, которую я ожидал.
Более того, сгенерированная подпрограмма не принимает мой контракт сообщений в качестве параметров ввода / вывода, вместо этого в нем перечислены участники контрактов сообщений.
То есть, я ожидаю, что автоматически сгенерированный прокси-класс будет иметь следующую подпись:
Public Function UploadFile(ByVal file As ImageUpload) As ImageUpload
Вместо этого он генерирует:
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
Это впоследствии приводит к проблемам приведения потоков, потому что сгенерированная функция позволяет мне передавать поток памяти в качестве входных данных (который работает правильно при передаче в службу), но вместо того, чтобы передавать мне новый поток для ответа, он пытается преобразовать MessageBodyStream, полученный от службы, в поток моей памяти.
Это в некотором роде похоже на другие посты , но, как вы можете видеть, в моих контрактах нет перечислений, связанных с перечислением - присутствие Enums, вызвавшее генерацию прокси-класса странного типа, помечается как ответ в подобном почта.
Есть ли где-нибудь, где я настраиваю поведение прокси для использования указанных контрактов? Ясно, что в настоящее время я нахожусь в среде dev / test, но когда это в конечном итоге пойдет в производство, это будет память и потоки файлов, передаваемые службе, и возвращаемый поток может быть в любом формате, если честно, я намерен рассматривать его как класс абстрактного потока. Единственный способ обойти это прямо сейчас - это изменить мой в потоке так, чтобы он совпадал с ожидаемым out , но, конечно, есть лучший способ?