2010-09-08 31 views
6

我想抓住WCF客戶端上給定的FaultException。我基本上需要從故障類中提取一個內部描述,以便我可以將它包裝在另一個例外中,以供上層做任何事情。FaultException.Detail回來空

我這樣做成功了一些時間,讓他這一次不同的是,故障被聲明爲一個數組,你可以從上拋出異常的方法的頂部聲明服務引用屬性看到:

[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; 
    } 
} 

問題是詳細(這是一個數組)總是回來空中的代碼,即使我可以看到數據(描述字段等)在SOAP respo中來自WCF跟蹤。

所以我需要的東西肯定會回來,但由於某種原因,它不會被反序列化,或者我無法從代碼中得到它。

任何幫助表示讚賞!

UPDATE

與@Darin建議,但沒有運氣,我從XmlReader中提取字符串試圖爲 「/ R/N」:

var sb = new StringBuilder(); 

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

var detail = sb.ToString(); 

貌似細節部分是根本沒有出現!

+0

如果修改代碼(僅用於測試)僅使用FaultClass(不是數組)? – 2010-09-08 18:22:52

+0

已經嘗試過,它根本沒有發現異常 – JohnIdol 2010-09-08 18:58:34

+0

如果沒有示例故障響應或WSDL – 2014-03-19 23:28:09

回答

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 
} 
+1

謝謝,我沒有訪問服務本身(這是一個Java軸服務)。我正在使用WCF客戶端,它確實發現了錯誤,但數組是空的,儘管我可以看到(從跟蹤中)服務響應中有一個項目。 – JohnIdol 2010-09-17 11:08:56

+0

這可能是由於XML名稱空間的差異,它會阻止Fault中的數據被反序列化。您是否將WCF的FaultClass的內容與Java的FaultClass的內容進行了比較? – 2010-09-20 12:24:33

+0

我唯一擁有的是從中生成WCF服務引用的wsdl。我將wsdl的內容與生成的服務參考進行了比較,它看起來很好。如果是這種情況(命名空間問題),我會期望其他類型的反序列化問題,因爲錯誤在同一命名空間中,因爲其他類型的 – JohnIdol 2010-09-21 09:12:31

5

這是很難說的問題出在哪裏,但我懷疑確鑿的證據是不產生標準的消息,這個Axis Web服務。要解決這一種方法是自己解析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. 
    } 
} 
+0

會給它一個鏡頭 - tnx – JohnIdol 2010-09-22 20:48:52

+0

我認爲我們正在接近!問題是我不知道如何形成細節,所以不知道我應該尋找哪些元素/屬性。它會與我從服務中回來的肥皂中看到的反應完全一樣嗎? – JohnIdol 2010-09-23 13:34:33

+0

(由於某種原因,SO不讓我贊成你,說我已經投了票,情況並非如此) – JohnIdol 2010-09-23 13:35:29

1

我曾在試圖將數據與通信的故障類似的情況(特別是堆棧跟蹤)。見this question。我最終通過創建自己的可序列化堆棧跟蹤並將其包含在派生的FaultException類中來解決此問題。

2

花了我很長時間才弄清楚如何從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()似乎得到了整個事情,包括新行,這是我想要的。

+0

我注意到這個效果很好,如果細節是多行字符串,但如果它是一個XML元素層次結構不太好。 – 2016-08-26 10:14:16

4

我發現一個UPS論壇解決方案:

https://developerkitcommunity.ups.com/index.php/Special:AWCforum/st/id371

「。問題是在Visual Studio中並沒有完全映射出ErrorDetail對象右邊的ErrorDetail節點被稱爲‘ErrorDetail’,但生成的類型爲「ErrorDetailType」。我編輯了爲我使用的每個服務生成的reference.cs類,並添加了TypeName:「

+1

我的英雄!:)澄清,他在談論在XmlTypeAttribute中,添加'TypeName =「ErrorDetail」'在那裏,它會工作。 – stroborobo 2017-09-07 10:23:54