解決一個通過 WebReference 調用 WCF 時自定義 DataContract 類參數提交的問題

先看一下VS2013自動創建默認的IService1.vb,注意自定義的數據契約 CompositeType

' 注意: 使用上下文菜單上的“重命名”命令可以同時更改代碼和配置文件中的接口名“IService1”。
<ServiceContract()>
Public Interface IService1

    <OperationContract()>
    Function GetData(ByVal value As Integer) As String

    <OperationContract()>
    Function GetDataUsingDataContract(ByVal composite As CompositeType) As CompositeType

    ' TODO: 在此添加您的服務操作

End Interface

' 使用下面示例中說明的數據約定將複合類型添加到服務操作。

<DataContract()>
Public Class CompositeType

    <DataMember()>
    Public Property BoolValue() As Boolean

    <DataMember()>
    Public Property StringValue() As String

End Class

通過添加 WebReference 引用後的客戶端代碼

Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
    Dim wrClient As New localhost.Service1
    Dim data As New localhost.CompositeType
    data.BoolValue = True
    'data.BoolValueSpecified = True
    data.StringValue = "Hello world"

    Dim result As localhost.CompositeType = wrClient.GetDataUsingDataContract(data)
    MessageBox.Show(result.StringValue)
End Sub

注意被註釋掉的那一行,在沒有顯式地指定 data.BoolValueSpecified = True 的情況下,BoolValue 的值不會被客戶端提交到服務端,服務端接收到的 data 參數中BoolValue 將賦值爲其默認值(false)。

類似的還有服務契約中的參數如果不是String類型,則必須指定 [參數名]Specified = True,該參數纔會被執行提交,如

  <OperationContract()>
   Function GetDataUsingBoolValue(ByVal boolValue As Boolean, ByVal StringValue As String) As String

對應的客戶端調用代碼

MessageBox.Show(wrClient.GetDataUsingBoolean(True, True, "Hello World"))

如果你打算客戶端省點功夫,不想總是顯式地設置 Specified = True, 那麼在聲明服務契約和數據契約時,就要多做一點工作

<ServiceContract()>
Public Interface IService1

    <OperationContract()>
    Function GetData(ByVal value As Integer) As String

    <OperationContract()>
    Function GetDataUsingDataContract(ByVal composite As CompositeType) As CompositeType

    ' TODO: 在此添加您的服務操作

    ''' <summary>
    ''' 存在非String類參數的方法
    ''' </summary>
    ''' <param name="boolValue"></param>
    ''' <param name="StringValue"></param>
    ''' <returns></returns>
    ''' <remarks>
    ''' 注意:DataContractFormat(Style:=OperationFormatStyle.Rpc)
    ''' 如果沒有設置此屬性,非String類的參數默認不會被提交,是否被提交將由 [非String類參數名]Specified 的取值決定
    ''' </remarks>
    <OperationContract(), DataContractFormat(Style:=OperationFormatStyle.Rpc)>
    Function GetDataUsingBoolValue(ByVal boolValue As Boolean, ByVal StringValue As String) As String
End Interface

' 使用下面示例中說明的數據約定將複合類型添加到服務操作。

<DataContract()>
Public Class CompositeType

    ''' <summary>
    ''' 非String類的參數
    ''' </summary>
    ''' <value></value>
    ''' <returns></returns>
    ''' <remarks>
    ''' 注意:IsRequired:=True
    ''' 如果沒有設置此屬性,該參數默認不會被提交,是否被提交將由 BoolValueSpecified 的取值決定
    ''' </remarks>
    <DataMember(IsRequired:=True)>
    Public Property BoolValue() As Boolean

    <DataMember()>
    Public Property StringValue() As String

End Class

具體的解釋,可以參見這裏

今天爲這個問題折騰了老半天,尤其是 DataContract 裏面的 DataMember(IsRequired:=True) 藏得比較深,特別是在客戶端通過 ServiceReference 引用的時候沒有這個問題,到了用 WebReference 引用的時候,發現非String類型(如 Integer, Double, Single, DateTime等,不過 Byte數組除外)的參數死活提交不上去了。

立此存照,希望能幫到不小心掉進這個坑裏的同行,:)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章