10

WCF クライアントで特定の FaultException をキャッチしようとしています。基本的に、障害クラスから内部記述を抽出する必要があります。これにより、上位層が何でもできるように別の例外にパッケージ化できます。

私は何度もこれを成功させてきましたが、今回の違いは、例外をスローするメソッドの上で宣言されたサービス参照属性からわかるように、fault が配列として宣言されていることです。

[System.ServiceModel.FaultContractAttribute(typeof(FaultClass[]), Action = "http://whatever/", Name = "whateverBusinessFault")] 

これは私のコードです:

try
{
  // call service here
}
catch (FaultException<FaultClass[]> ex)
{
  if (ex.Detail != null && ex.Detail.Length > 0)
  {
    throw new CustomException(ex.Detail[0].description);
  }
  else
  {
    throw;
  }
}

問題は、WCF トレースからの SOAP 応答でデータ (説明フィールドなど) を確認できても、コード内の詳細 (配列) が常に空になることです。

したがって、必要なものは間違いなく戻ってきますが、何らかの理由で逆シリアル化されないか、コードからアクセスできません。

どんな助けでも大歓迎です!

更新

@Darin の提案を試してみましたが、うまくいきませんでした。XmlReader から抽出している文字列は "/r/n" です。

var sb = new StringBuilder();

using (XmlReader reader = fault.GetReaderAtDetailContents())
{
  while (reader.Read())
     sb.AppendLine(reader.ReadOuterXml()); 
}

var detail = sb.ToString();

詳細セクションがまったく表示されないようです。

4

5 に答える 5

5

問題がどこにあるのかを特定するのは困難ですが、私は、この軸 Web サービスが標準メッセージを生成していないことが決定的な原因ではないかと考えています。これを回避する 1 つの方法は、XML を自分で解析することです。

try
{
    proxy.CallSomeMethod();
}
catch (FaultException ex)
{
    var fault = ex.CreateMessageFault();
    using (XmlReader reader = fault.GetReaderAtDetailContents())
    {
        // TODO: read the XML fault and extract the necessary information.
    }
}
于 2010-09-22T18:36:44.690 に答える
3

から完全な詳細メッセージを文字列として取得する方法を理解するのに何年もかかりましたFaultException。私は最終的にそれを理解し、この拡張メソッドを書きました:

public static string GetDetail(this FaultException faultException)
{
    if (faultException == null)
        throw new ArgumentNullException(nameof(faultException));

    MessageFault messageFault = faultException.CreateMessageFault();
    if (messageFault.HasDetail) {
        using (XmlDictionaryReader reader = messageFault.GetReaderAtDetailContents()) {
            return reader.ReadContentAsString();
        }
    }
    return null;
}

もともと私は使用してreader.Valueいましたが、複数行の詳細メッセージの最初の行を返すようにしか見えませんでした。reader.ReadContentAsString()新しい行を含めて、すべてを取得しているように見えます。これが私が望んでいたものです。

于 2016-08-24T16:07:12.797 に答える
2

できる限り簡単なテストケースを思いつきました。お役に立てば幸いです。サーバ側:

[ServiceContract]
public interface IService1
{
    [OperationContract]
    [FaultContract(typeof(FaultClass[]))]
    string Crash();
}

public class Service1 : IService1
{
    public string Crash()
    {
        var exception = new FaultException<FaultClass[]>(new FaultClass[] { new FaultClass { Data = "TEST" } }, new FaultReason("Boom"));

        throw exception;
    }
}

[DataContract]
public class FaultClass
{
    [DataMember]
    public string Data { get; set; }
}

クライアント側:

try
{
    using (var client = new Service1Client())
    {
        client.Crash();
    }
}
catch(FaultException<FaultClass[]> e)
{
    //Break here
}
于 2010-09-17T06:00:39.190 に答える
1

障害のあるデータ (具体的にはスタック トレース) を通信しようとすると、同様の状況が発生しました。この質問を参照してください。独自のシリアル化可能なスタック トレースを作成し、それを派生した FaultException クラスに含めることで、最終的に解決しました。

于 2011-04-25T03:59:00.143 に答える