WCF Service Generated Proxy Class Exposing Function as ByRef Sub

元气小坏坏 提交于 2020-01-03 18:51:42

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!