2013-10-21 12 views
7

WCFはオブジェクトを正常にシリアル化できます。WCF一覧<string >シリアライズ/デシリアライズエラー

Message=The formatter threw an exception while trying to deserialize the message: 
There was an error while trying to deserialize parameter http://tempuri.org/:GetDataResult. 
The InnerException message was 'Error in line 1 position 990. 
    Element 'http://schemas.microsoft.com/2003/10/Serialization/Arrays:Value' contains data from a type 
    that maps to the name 'http://schemas.microsoft.com/2003/10/Serialization/Arrays:ArrayOfstring'. 
    The deserializer has no knowledge of any type that maps to this name. 
    Consider using a DataContractResolver or add the type corresponding to 'ArrayOfstring' 
    to the list of known types - for example, by using the KnownTypeAttribute attribute or 
    by adding it to the list of known types passed to DataContractSerializer.'. 

私もKnownType属性を追加しようとしました:Response.Data辞書の値の型がリスト<文字列>である場合にデータをitreceivedし、それをデシリアライズしようとしたときには、クライアントは次の例外がスローされましたServiceContractとDataContractは次のようになります。

[ServiceContract] 
[ServiceKnownType(typeof(List<string>))] 
[ServiceKnownType(typeof(Dictionary<string, string>))] 
[ServiceKnownType(typeof(Dictionary<string, List<string>>))] 
public interface IWcfService 
{ 
    [OperationContract] 
    [ServiceKnownType(typeof(List<string>))] 
    [ServiceKnownType(typeof(Dictionary<string, string>))] 
    [ServiceKnownType(typeof(Dictionary<string, List<string>>))] 
    Response GetData(); 
} 

[DataContract] 
[ServiceKnownType(typeof(List<string>))] 
[ServiceKnownType(typeof(Dictionary<string, string>))] 
[ServiceKnownType(typeof(Dictionary<string, List<string>>))] 
[KnownType(typeof(List<string>))] 
[KnownType(typeof(Dictionary<string, string>))] 
[KnownType(typeof(Dictionary<string, List<string>>))] 
public class Response 
{ 
    [DataMember] 
    public Dictionary<string, object> Data { get; set; } 
} 

しかし、これは役に立ちませんでした。誰もがこれに関するアイデアを持っていますか? サーバーがクライアントに「動的」の辞書を送信する必要があります:

Data = new new DIctionary<string, object> 
     { 
      {"_id", 12344}, 
      {"names", new List<string>{ "John", "Peter", "Jack"}}, 
      {"time", DateTime.Now} 
     } 

私たちは辞書<文字列、オブジェクト>を使用した理由を:データは次のようになり

を更新しました

データは、int、List、DataTimeなどとすることができます。これは辞書を使用してこの問題を解決するのに役立ちますが、元の型情報も失います。たとえば、クライアントはListを必要とし、コレクションを表示するためにデータバインディングを行うため、List.ToString()はこの場合役に立ちません。

+2

辞書の値の1つが 'string []'または 'List 'でしょうか?私は言う必要があります: 'オブジェクト'を使用する***任意のポイントで***データの契約ではすぐに警鐘をオフに設定する必要があります。 'object' *は契約ではありません* - 契約の合計*不在*です。しかしながら! ([KnownType(typeof(string [])) '/' [ServiceKnownType(typeof(string [])) '(注:ランダム属性を追加するのは何かを "修正"する最良の方法ではありません) –

+0

辞書の値がList である場合、問題が発生します。また、[KnownType(typeof(string []))]/[ServiceKnownType(typeof(string []))]を使用しようとしましたが、役に立たなかった – wd113

+0

サービスリファレンスの追加を使用して、サービス? –

答えて

1

皆様のご意見ありがとうございます。私はシリアライザとしてNetDataContractSerializer(デフォルトはDataContractSerializer)を使用するようにWCFを設定することで問題を解決しました。 NetDataContractSerializerには、パフォーマンスの低下(シリアル化時間の約2倍)がありますが、シリアル化を行うときにCLRの型情報がより多く含まれます。

+0

チップをありがとう!私はそれを使用して、クライアントからログにサーバーへの例外を送信する方法の長年の問題を解決しました。ここで私はそれをしました(http://stackoverflow.com/a/28737527/722393)。再度、感謝します。 – InteXX

1

デフォルトでは、System.ObjectSerializableではないと思います。あなたは余分な情報を送る必要がありますが、それでもベストプラクティスではありません。辞書を使用する前に、別のタイプを定義することをお勧めします。

以下を参照してください:あなたのデータ契約がワイヤ上の文字列の中に連載されます念頭に置いて

WCF service returning an array of dictionary

WCF System.Object Serialization

Serializing IDictionary in WCF

1

ベアので、あなたが渡す任意のオブジェクトoverは直列化可能でなければなりません(objectはありません)。

問題は、サービス指向のコンテキストでオブジェクト指向のパターンを使用していることです。ディクショナリ値で渡したすべてがobjectに多相的であることが必要です。私はここに似た "匂い"を持った質問に答えました:https://stackoverflow.com/a/19445875/2382536

この問題は、WCFがサービスの基盤となるチャネルを抽象化することで非常に優れていることに起因しています。現在、「サービスオリエンテッド」のコンテキストで作業していることを忘れてしまいます(KnownTypesはハッキングOOの幻想)。データコントラクトはサービスの「公開」APIの一部を形成するため、サービスが公開するデータを明示的に表現する必要があります。 「動的」データを返すデータ構造を持つことは、この重要なルールに違反します。

クライアントは戻ってくるデータを知る必要があるので、「動的」応答を実装する場合は、応答のバリエーションにさまざまなメソッド/エンドポイント/サービスを実装する必要があります。あなたのサービスの中で、多形性を使ってコードを単純化することはできませんが、公共サービス/データ契約に漏れてはいけません。

関連する問題