2011-10-28 22 views
1

今朝私のWCF参照で奇妙な問題に遭遇しました。簡単に言えば、デュプレックスサービスをセットアップして、サーバがデータ契約でオブジェクトを送信してクライアントに通知できるようにします。クライアントが接続すると、サーバー上の関数が実行され、サービスクラスの共有キューにある内容に基づいてList(Of NewItem)が返されます。問題は、クライアントでサービス参照を更新すると、List(Of NewItem)オブジェクトではなく、NewItemオブジェクトが返されることです。私は参照に移動して手動でそれをListオブジェクトに変更することができます。それは正常に転送されます。サービス参照ジェネレータが返すタイプを任意に変更する理由は何ですか?wcfの参照が正しく生成されていない

ここに関連するコードです:

<ServiceContract(
    CallbackContract:=GetType(INotifyCallback), 
    SessionMode:=ServiceModel.SessionMode.Required)> 
Public Interface INotifyService 
    <OperationContract()> 
    Function GetNewServerItems() As List(Of NewItem) 
End Interface 

<DataContract> 
<Serializable> 
Public Class NewItem 
    <DataMember()> 
    Public Property ItemNum As String 

    <DataMember()> 
    Public Property Timestamp As DateTime 
End Class 

<ServiceBehavior(
    ConcurrencyMode:=ServiceModel.ConcurrencyMode.Single, 
    InstanceContextMode:=ServiceModel.InstanceContextMode.Single)> 
Public Class NotifyService 
    Implements INotifyService 

    Shared _server_items As New List(Of NewItem) 

    Public Function GetNewServerItems() As List(Of NewItem) 
     Return _server_items 
    End Function 
End Class 

とReference.vb(簡体字)で:

<System.ServiceModel.OperationContractAttribute(Action:="http://tempuri.org/INotifyService/GetNewServerItems", ReplyAction:="http://tempuri.org/INotifyService/GetNewServerItemsResponse")> _ 
Function GetNewServerItems() As NotifyGateway.NewItem() 
+0

プロジェクトを右クリックし、[サービス参照の追加]を選択して参照を追加しましたか? –

+0

あなたは ''を忘れたのですか? –

+0

@Gabobcat - はい。 – mounty

答えて

3

あなたと私は同じトラップに陥っていました。私たちはプロキシメソッド用に生成されたVB.NETコードを誤って読み込んで単一のアイテムを返すようになりました。実際、配列を返しています。

WSDLは要求と応答の形状を記述するためにXMLスキーマを使用します。 XMLスキーマには、シーケンスの「リスト」という概念はありません。デフォルトでは、一連の項目が表示されると、「サービス参照の追加」によって配列が生成されます。これを変更して、「サービス参照の追加」または「サービス参照の構成」ダイアログの「詳細」タブでコレクションタイプを変更するだけで、「リスト」を生成することができます。

+0

...あなたが正しいです。 'NewItem'は' NewItem() 'と同じではありません。それに気づいたはずです。 – mounty

1

あなたが行った方法を参照を追加するとき、あなたは "コレクションタイプを" に変更する必要がありますが、高度なサービス参照設定(サービス参照の追加ダイアログ)を "system.Collections.Generic.List"に追加します。デフォルトでは、 "System.Array"です。

WCFサービスの設定を制御できなくなり、VSが不要なゴミをたくさん追加してしまい、クライアント/サービスのリンクがより困難になるため、参照の追加方法をお勧めします維持する。

これが役に立ちます。

+0

-1:詳細を記入することなく、このような勧告をしないでください。また、.NET 4.0ではデフォルトを省略してより小さな設定ファイルを作成するため、彼が使用している.NETバージョンを尋ねることなく、 –

+0

答えの最初の部分は、直接の問題を解決するようです。答えの2番目の部分について:「サービス参照の追加」メソッドを使用せずにサービス参照を追加するか、そうでなければ自分の契約を取得するにはどうすればよいでしょうか? (そして、はい。私は.NET 4を使用しています) – mounty

+0

そう、残念です。私は構成ファイルを意味しませんでした。つまり、「Add Service Reference」を使用すると、結果が非​​常に冗長で管理しにくく、構成変更が上書きされる可能性があります。ですから、手動でWCFを設定する(手動または適切なツールを使用して)IMHOを使用するのが最善の方法です。これで私の答えはより明確になり、もう一度申し訳なく思っています。 –

1

あまり知られていませんが、デフォルトのコレクションタイプ設定を使用せずにコレクションタイプを保持するための、より強力なメカニズムがあります。

このメカニズムは、WCFパイプの両側のコードでCollectionDataContractクラスを使用する場合に特に便利です。

解決方法には、WCFサービス参照の一部として生成されたsvcmapを編集し、シリアル化するコレクションの種類ごとに特定のCollectionMappingエントリを追加します。ここで注目すべき主なものはジェネリックスです.WCFが特定のクラスに対して複数の一致を検出した場合、コードの生成を拒否します。

は、実際に変更を加えるには:

1)あなたのWCFサービス参照を含むプロジェクト内のすべてのファイルを表示します。

2)

3)それを編集するReference.svmapファイルをダブルクリックして、あなたのサービス参照を展開します。

4)CollectionMappingsセクションにエントリを追加します(存在しない場合は追加できます)。

例えば、一般的な辞書とリストを転送する、とStringCollectionsを転送するために、次のエントリを持つことができますが:辞書のカテゴリと

<CollectionMappings> 
    <CollectionMapping TypeName="System.Collections.Generic.Dictionary`2" Category="Dictionary" /> 
    <CollectionMapping TypeName="System.Collections.Generic.List`1" Category="List" /> 
    <CollectionMapping TypeName="System.Collections.Specialized.StringCollection" Category="List" /> 
<CollectionMappings> 

最初の項目はデフォルトの辞書のコレクションとして機能しますリストのカテゴリを持つ最初のアイテムがデフォルトのコレクションタイプとして機能します。

SilverlightおよびWindows Formsクライアントにこのように使用する200以上のコレクションクラスがあり、WCFパイプの両側で独自のコードを再利用する方法は非常に効率的です。

重要な注意点:クラスを再利用するには、サービス参照設定の[参照されたアセンブリ内の型を再利用する]フラグがチェックされているか、reference.svmapのGenerateInternalTypesフラグがfalseに設定されていることを確認する必要がありますこれらは同じものです)。

関連する問題