3

私はWCFサービスに取り組んでいます。

OperationContractsの1つは、パラメーターの1つとして複合型を必要とします(具体的にはSystem.Exception)。

新しい例外を作成した場合にクライアントがプロキシを呼び出すとき。

 System.Exception toNewException = new Exception();

そしてそれを送ってください...それはかなりうまく機能します。

しかし、タイプ'System.Web.HttpUnhandledException'の例外を送信しようとすると。不明なタイプでサービスに障害が発生しました。(以下のエラーを参照)

パラメータ http://tempuri.org/:Exceptionをシリアル化しようとしたときにエラーが発生しました。InnerExceptionメッセージは「タイプ」「System.Web.HttpUnhandledException」であり、データコントラクト名は「HttpUnhandledException:http://schemas.datacontract.org/2004/07/System.Web」ではありません。静的に不明なタイプを既知のタイプのリストに追加します。たとえば、KnownTypeAttribute属性を使用するか、DataContractSerializerに渡される既知のタイプのリストにそれらを追加します。詳細については、InnerExceptionを参照してください。

既知のtypes属性を調査しましたが、これまでのところ、役立つ例やドキュメントは見つかりませんでした。

どんな種類の例外でも受け入れ/動作するようにクライアント/サーバーを変更する方法についての良い情報源を知っている人はいますか?

私の質問をもう少し詳しく説明すると...エラーは次のように述べています。「静的に不明なタイプを既知のタイプのリストに追加します」。これが、system.exceptionのような複雑な.netオブジェクトに対して具体的に行う方法を知りたいことです。

アップデート

次の変更を試みました。

[OperationContract]
[ServiceKnownType(typeof(HttpUnhandledException))]
void LogError(Exception Exception, Boolean LogInternalFlag, int UserId, int ApplicationId, int SeverityId);

そして、私は別のエラーを受け取ることになりました!

パラメータ http://tempuri.org/:Exceptionをシリアル化しようとしたときにエラーが発生しました。InnerExceptionメッセージは「タイプ」「System.Collections.ListDictionaryInternal」で、データコントラクト名は「ArrayOfKeyValueOfanyTypeanyType:http://schemas.microsoft.com/2003/10/Serialization/Arrays」ではありません。静的に不明なタイプを既知のタイプのリストに追加します。たとえば、KnownTypeAttribute属性を使用するか、DataContractSerializerに渡される既知のタイプのリストにそれらを追加します。詳細については、InnerExceptionを参照してください。

少なくとも例外を除いたエラーは理にかなっています...これが何を意味するのかまったくわかりません。


また、例外をxmlとしてシリアル化し、文字列として渡すことも試みました...残念ながら、それは思ったほど単純ではなく、シリアル化を考慮に入れるための多くの考慮事項があります。例外と内部例外の。

4

3 に答える 3

2

あなたの問題は、型が複雑であることではありません。あなたの問題は、契約が基本クラス (Exception) で宣言され、子クラス (HttpUnhandledException) に渡されたことです。子が基本定義に追加したものの型情報をコントラクト シリアライザーに提供しませんでした。その追加情報は、KnownTypes を通じて提供します。

MSDN の KnowTypes で私が見た中で最も優れたドキュメントはhereです。

検索で見逃しているのは、OperationContract しかない (DataContract がない) ため、実際に使用する属性はServiceKnownTypeであるということです。

[ServiceContract]
public interface IContract
{
   [OperationContract]
   [ServiceKnownType(typeof(HttpUnhandledException))]
   void PassException(Exception c);
}

属性は、メソッドのみまたはインターフェイス全体に配置できます。

コンパイル時に可能なすべての子 (例外) 型がわからない場合、実行時メソッドを取る ServiceKnownType (および KnowTypes) のバージョンがあることに注意してください。

于 2012-06-22T18:37:35.903 に答える
1

ErnieL は正しい技術的な答えを持っています。ただし、実用的には、1) 例外の一部を分割してそれらのみを渡すか、2) 独自のカスタム ErrorLog タイプを作成して送信する傾向があります。

これにより、例外オブジェクトのサブクラス化を処理する必要がなくなり、操作するための一貫したインターフェイスが提供されます。おそらく、例外からいくつかのメンバー (エラー メッセージ、内部例外エラー メッセージ、およびスタック トレース) だけが必要です。

内部例外の場合は、メッセージをループしてそれらを連結するメソッドを作成するだけです。それらは本当に別々に保管する必要がありますか?

于 2012-06-22T20:02:02.260 に答える
1

例外をバイト配列としてシリアル化し、サーバー側で逆シリアル化することで、これを回避できます。

クライアント側では、次を使用します。

    try { /* Do something that generates an exception here. */ }
    catch(System.Exception exception)
    {
        using (MemoryStream ms = new MemoryStream())
        {
            BinaryFormatter bf = new BinaryFormatter();
            bf.Serialize(ms, exception);
            YourWCFMethodHere(ms.ToArray());
        }
     }

次に、サーバー側で:

    public void YourWCFMethodHere(byte[] exception)
    {
        using (MemoryStream ms = new MemoryStream(exception, false))
        {
            BinaryFormatter bf = new BinaryFormatter();
            Exception ex = (Exception)bf.Deserialize(ms);
            // Do something with the exception here
        }
    }

もちろん、渡された byte[] が実際には例外ではない場合に備えて、何らかのエラー チェックを配置する必要があります。

于 2013-04-05T19:54:01.263 に答える