例外狀況可用來在服務或客戶端實作中傳達錯誤訊息。 另一方面,錯誤可用來跨服務界限通訊錯誤,例如從伺服器到用戶端,反之亦然。 除了故障之外,傳輸通道通常會使用專屬於傳輸的機制來告知傳輸層級的錯誤。 例如,HTTP 傳輸會使用 404 之類的狀態代碼來通訊非現有的端點 URL(沒有端點可傳回錯誤)。 本文由三部分構成,提供自訂頻道作者的指引。 第一節提供何時以及如何定義和擲回例外狀況的指引。 第二節提供關於生成和處理故障的指導。 第三節說明如何提供追蹤資訊,以協助自定義通道的使用者針對執行中的應用程式進行疑難解答。
例外狀況
擲回例外狀況時,請記住兩件事:首先,它必須是一種類型,可讓使用者撰寫可適當地回應例外狀況的正確程序代碼。 其次,它必須提供足夠的資訊,讓使用者了解發生錯誤的原因、失敗影響,以及如何修正它。 下列各節提供 Windows Communication Foundation (WCF) 信道例外狀況類型和訊息的指引。 在 [例外狀況的設計指導方針] 檔中,也會提供 .NET 中例外狀況的一般指引。
例外狀況類型
通道擲回的所有例外狀況都必須是 System.TimeoutException、 System.ServiceModel.CommunicationException或 衍生自 CommunicationException的類型。 (例如的 ObjectDisposedException 例外狀況也可能擲回,但只會指出呼叫端程式代碼已誤用通道。如果通道已正確使用,則它只能擲回指定的例外狀況。WCF 提供衍生自 CommunicationException 的七種例外狀況類型,並設計成供通道使用。 有其他 CommunicationException衍生的例外狀況設計為供系統其他部分使用。 這些例外狀況類型包括:
例外狀況類型 | 意義 | 內部例外狀況內容 | 復原策略 |
---|---|---|---|
AddressAlreadyInUseException | 為接聽指定的端點位址已在使用中。 | 如果存在,請提供造成此例外狀況之傳輸錯誤的詳細數據。 例如。 PipeException、HttpListenerException 或 SocketException。 | 請嘗試不同的位址。 |
AddressAccessDeniedException | 進程不允許存取為接聽所指定的端點位址。 | 如果存在,請提供造成此例外狀況之傳輸錯誤的詳細數據。 例如,PipeException 或 HttpListenerException。 | 嘗試使用不同的認證。 |
CommunicationObjectFaultedException | ICommunicationObject所使用的 是處於錯誤狀態(如需詳細資訊,請參閱瞭解狀態變更)。 請注意,當具有多個暫止呼叫的物件轉換為 Faulted 狀態時,只有一個呼叫會擲回與失敗相關的例外狀況,而其餘的呼叫會擲回 CommunicationObjectFaultedException。 此例外狀況通常會引發,因為應用程式忽略了一些例外狀況,並嘗試使用已發生錯誤的物件,可能在不同於攔截原始例外的線程中。 | 如果存在,則提供內部例外狀況的詳細數據。 | 建立新的物件。 請注意,根據最初導致 ICommunicationObject 發生故障的原因,可能需要執行其他工作才能復原。 |
CommunicationObjectAbortedException | 使用中的ICommunicationObject已被中止(如需詳細資訊,請參閱瞭解狀態變更)。 類似於 CommunicationObjectFaultedException,這個例外狀況表示應用程式已在 物件上呼叫 Abort ,可能來自另一個線程,而且該對象無法再基於這個原因使用。 | 如果存在,則提供內部例外狀況的詳細數據。 | 建立新的物件。 請注意,取決於導致ICommunicationObject最初中止的原因,可能需要執行其他工作才能復原。 |
EndpointNotFoundException | 目標遠端端點未接聽。 這可能會導致端點位址的任何部分不正確、無法復原或端點關閉。 範例包括 DNS 錯誤、無法使用佇列管理員,以及服務未執行。 | 內部例外狀況提供詳細數據,通常是來自基礎傳輸。 | 請嘗試不同的位址。 或者,如果服務關閉,寄件者可能會等候一段時間,然後再試一次 |
ProtocolException | 如端點原則所述,通訊協定在端點之間不一致。 例如,框架內容類型不符或超過訊息大小上限。 | 如果存在,則提供特定通訊協定錯誤的詳細資訊。 例如,當錯誤原因超過 MaxReceivedMessageSize 時, QuotaExceededException 是內部例外狀況。 | 復原:確定傳送者和接收的通訊協議設定相符。 若要這樣做,其中一個方法是重新匯入服務端點的元數據(原則),並使用產生的系結重新建立通道。 |
ServerTooBusyException | 遠端端端點正在接聽,但尚未準備好處理訊息。 | 如果存在,內部例外狀況會提供SOAP錯誤或傳輸層級錯誤詳細數據。 | 復原:稍後等候並重試作業。 |
TimeoutException | 作業無法在逾時期間內完成。 | 可能會提供有關逾時的詳細資訊。 | 請稍候,稍後再重試作業。 |
只有當該類型對應到與所有現有例外狀況類型不同的特定復原策略時,才定義新的例外狀況類型。 如果您確實定義新的例外狀況類型,它必須衍生自 CommunicationException 或其其中一個衍生類別。
例外狀況訊息
例外狀況訊息是以使用者而非程式為目標,因此應該提供足夠的資訊來協助使用者瞭解並解決問題。 良好例外狀況訊息的三個重要部分如下:
發生了什麼事。 使用與用戶體驗相關的詞彙,提供問題的清楚描述。 例如,不正確的例外狀況訊息會是「無效的組態區段」。 這讓使用者想知道哪個組態區段不正確,以及其不正確的原因。 改善的訊息會是「無效的組態區段 <customBinding>」。 更好的訊息是「無法將名為 myTransport 的傳輸新增至名為 myBinding 的系結,因為系結已經有名為 myTransport 的傳輸」。 這是一個非常特定的訊息,使用使用者可以輕鬆地在應用程式的組態檔中識別的詞彙和名稱。 不過,仍有一些主要元件遺失。
錯誤的重要性。 除非訊息清楚指出錯誤的意義,否則使用者可能會懷疑它是否為嚴重錯誤,或是否可以忽略錯誤。 一般而言,訊息應該先說明錯誤的意義或重要性。 若要改善上述範例,訊息可能是「ServiceHost 因為設定錯誤而無法開啟:無法將名為 myTransport 的傳輸新增至名為 myBinding 的系結,因為系結已經有名為 myTransport 的傳輸」。
用戶應該如何更正問題。 訊息最重要的部分是協助使用者修正問題。 訊息應包含一些有關要檢查或修正以解決問題的指引或提示。 例如,「ServiceHost 因為設定錯誤而無法開啟:無法將名為 myTransport 的傳輸新增至名為 myBinding 的系結,因為系結已經有名為 myTransport 的傳輸。 請確定綁定中只有一個傳輸。
通訊錯誤
SOAP 1.1 和 SOAP 1.2 都會定義錯誤的特定結構。 這兩個規範之間有一些差異,但一般而言,Message 和 MessageFault 類型用於建立和處理錯誤。
SOAP 1.2 錯誤 (左) 和 SOAP 1.1 錯誤 (右)。 在SOAP 1.1中,只有Fault元素符合命名空間。
SOAP 將錯誤訊息定義為只包含錯誤元素(名稱為 <env:Fault>
的元件)的訊息,這個錯誤元素作為 <env:Body>
的子元素。 錯誤元素的內容在 SOAP 1.1 和 SOAP 1.2 之間稍有不同,如圖 1 所示。 不過,類別會將 System.ServiceModel.Channels.MessageFault 這些差異正規化為一個物件模型:
public abstract class MessageFault
{
protected MessageFault();
public virtual string Actor { get; }
public virtual string Node { get; }
public static string DefaultAction { get; }
public abstract FaultCode Code { get; }
public abstract bool HasDetail { get; }
public abstract FaultReason Reason { get; }
public T GetDetail<T>();
public T GetDetail<T>( XmlObjectSerializer serializer);
public System.Xml.XmlDictionaryReader GetReaderAtDetailContents();
// other methods omitted
}
屬性 Code
會對應至 env:Code
(或在 faultCode
SOAP 1.1中),並識別錯誤的類型。 SOAP 1.2 定義五個 faultCode
允許的值(例如 Sender 和 Receiver),並定義一個 Subcode
元素,可包含任何子代碼值。 (如需允許的錯誤碼及其意義清單,請參閱 SOAP 1.2 規格 。SOAP 1.1 具有稍微不同的機制:它會定義四 faultCode
個值(例如 Client 和 Server),其可藉由定義全新的值,或使用點表示法來建立更具體的 faultCodes
,例如 Client.Authentication。
當您使用 MessageFault 來設計錯誤時,FaultCode.Name 和 FaultCode.Namespace 會對應至 SOAP 1.2 env:Code
或 SOAP 1.1 faultCode
的名稱和命名空間。 FaultCode.SubCode 會對應至 env:Subcode
SOAP 1.2,而 SOAP 1.1 則為 Null。
如果以程式化方式區分錯誤是有趣的,您應該建立新的錯誤子碼(如果使用SOAP 1.1,則建立新的錯誤碼)。 這類似於建立新的例外狀況類型。 您應避免在使用 SOAP 1.1 錯誤碼時使用點符號。 ( WS-I 基本配置檔 也不建議使用錯誤碼點表示法。
public class FaultCode
{
public FaultCode(string name);
public FaultCode(string name, FaultCode subCode);
public FaultCode(string name, string ns);
public FaultCode(string name, string ns, FaultCode subCode);
public bool IsPredefinedFault { get; }
public bool IsReceiverFault { get; }
public bool IsSenderFault { get; }
public string Name { get; }
public string Namespace { get; }
public FaultCode SubCode { get; }
// methods omitted
}
Reason
屬性對應至 env:Reason
(或在 SOAP 1.1 中為 faultString
),這是類似於例外情況訊息的人類可讀錯誤狀況描述。 類別 FaultReason
(和 SOAP env:Reason/faultString
)內建支援多種語言翻譯以促進全球化。
public class FaultReason
{
public FaultReason(FaultReasonText translation);
public FaultReason(IEnumerable<FaultReasonText> translations);
public FaultReason(string text);
public SynchronizedReadOnlyCollection<FaultReasonText> Translations
{
get;
}
}
錯誤詳細數據內容會在 MessageFault 上使用各種方法公開,包括 GetDetail
<T> 和 GetReaderAtDetailContents
()。 錯誤詳細資訊是一個不可讀的元素,用於攜帶有關錯誤的其他詳細資訊。 如果有一些您想要攜帶故障的任意結構化的詳細資訊,這會很有用。
產生錯誤
本節說明產生錯誤的程式,以回應通道或通道所建立之訊息屬性中偵測到的錯誤狀況。 典型的範例是返回錯誤訊息,以回應包含無效資料的要求訊息。
產生錯誤時,自定義通道不應該直接傳送錯誤,而是應該擲回例外狀況,並讓上述層決定是否將該例外狀況轉換成錯誤,以及如何傳送錯誤。 為了協助進行這項轉換,通道應該提供實 FaultConverter
作,可將自定義通道擲回的例外狀況轉換成適當的錯誤。
FaultConverter
定義為:
public class FaultConverter
{
public static FaultConverter GetDefaultFaultConverter(
MessageVersion version);
protected abstract bool OnTryCreateFaultMessage(
Exception exception,
out Message message);
public bool TryCreateFaultMessage(
Exception exception,
out Message message);
}
產生自定義錯誤的每個通道都必須實作FaultConverter
,並在對GetProperty<FaultConverter>
的呼叫中傳回它。 自訂 OnTryCreateFaultMessage
實作必須將例外狀況轉換成錯誤,或委派給內部通道的 FaultConverter
進行處理。 如果通道是傳輸,則必須將例外狀況轉換或委派給編碼器的 FaultConverter
或 WCF 中提供的預設 FaultConverter
。 預設值 FaultConverter
會轉換與 WS-Addressing 和SOAP所指定的錯誤訊息對應的錯誤。 以下是範例 OnTryCreateFaultMessage
實作。
public override bool OnTryCreateFaultMessage(Exception exception,
out Message message)
{
if (exception is ...)
{
message = ...;
return true;
}
#if IMPLEMENTING_TRANSPORT_CHANNEL
FaultConverter encoderConverter =
this.encoder.GetProperty<FaultConverter>();
if ((encoderConverter != null) &&
(encoderConverter.TryCreateFaultMessage(
exception, out message)))
{
return true;
}
FaultConverter defaultConverter =
FaultConverter.GetDefaultFaultConverter(
this.channel.messageVersion);
return defaultConverter.TryCreateFaultMessage(
exception,
out message);
#else
FaultConverter inner =
this.innerChannel.GetProperty<FaultConverter>();
if (inner != null)
{
return inner.TryCreateFaultMessage(exception, out message);
}
else
{
message = null;
return false;
}
#endif
}
此模式的含意在於,針對需要引發故障的錯誤狀況,層之間擲回的例外狀況必須包含足夠的資訊,以便對應的故障生成器能夠建立正確的故障。 身為自定義通道作者,如果這類例外狀況不存在,您可以定義對應至不同錯誤狀況的例外狀況類型。 請注意,橫跨通道層的例外狀況應該會傳達錯誤狀況,而不是模糊的錯誤數據。
錯誤類別
錯誤通常有三種類別:
整個堆疊中普遍存在的故障。 這些錯誤可能會在通道堆疊中的任何層發生,例如 InvalidCardinalityAddressingException。
在堆疊中某一層上方可能發生的錯誤,例如,與流動交易或安全性角色相關的某些錯誤。
指向堆疊中單一層的錯誤,例如 WS-RM 序號錯誤。
類別1。 錯誤通常是 WS-Addressing 和 SOAP 錯誤。 WCF 提供的基礎 FaultConverter
類將錯誤轉換為由 WS-Addressing 和 SOAP 所指定的錯誤訊息,因此您無需自行處理這些例外狀況的轉換。
類別 2. 當某層將屬性新增至訊息,而未完全取用該層相關的訊息內容時,就會發生錯誤。 當較高層要求訊息屬性進一步處理訊息資訊時,可能會偵測錯誤。 這類通道應該實施先前指定的GetProperty
,以便讓較高層能夠傳回正確的錯誤。 其中一個範例是 TransactionMessageProperty。 這個屬性會新增至訊息,而不需完整驗證標頭中的所有數據(這樣做可能涉及連絡分散式交易協調器 (DTC)。
類別 3. 錯誤只會由處理器中的單一層產生和傳送。 因此,所有例外狀況都包含在圖層內。 若要改善通道之間的一致性並簡化維護,您的自定義通道應該使用先前指定的模式來產生錯誤訊息,即使是內部錯誤也一樣。
解譯收到的錯誤
本節提供在收到錯誤訊息時產生適當例外狀況的指引。 在堆疊中每一層處理訊息的判定樹如下所示:
如果圖層認為訊息無效,圖層應該執行其「無效訊息」處理。 這類處理是特定於層的,但可能包括丟棄訊息、追蹤或擲回轉換成錯誤的例外。 範例包括安全部門收到未正確保護的訊息,或 RM 收到具有錯誤序號的訊息。
否則,如果訊息是特別套用至圖層的錯誤訊息,而且訊息在圖層互動之外沒有意義,則該層應該處理錯誤狀況。 其中一個範例是 RM 序列拒絕錯誤,對 RM 通道上方的層級毫無意義,這表示發生 RM 通道錯誤,並從擱置作業擲回。
否則,應該從 Request() 或 Receive() 傳回訊息。 這包括層可辨識錯誤的情況,但錯誤只會指出要求失敗,而且並不表示通道發生錯誤,而且不會從擱置的作業擲回。 若要改善這類案例的可用性,層應該實現
GetProperty<FaultConverter>
,並傳回一個可藉由覆寫FaultConverter
將錯誤轉換成例外狀況的OnTryCreateException
衍生類別。
下列物件模型支援將訊息轉換成例外狀況:
public class FaultConverter
{
public static FaultConverter GetDefaultFaultConverter(
MessageVersion version);
protected abstract bool OnTryCreateException(
Message message,
MessageFault fault,
out Exception exception);
public bool TryCreateException(
Message message,
MessageFault fault,
out Exception exception);
}
通道層可以實 GetProperty<FaultConverter>
作以支援將錯誤訊息轉換成例外狀況。 為此,請覆寫 OnTryCreateException
並檢查錯誤訊息。 如果已辨識,請執行轉換,否則請要求內部通道進行轉換。 傳輸通道應該委派給FaultConverter.GetDefaultFaultConverter
,以取得預設SOAP/WS-Addressing FaultConverter。
一般實作看起來像這樣:
public override bool OnTryCreateException(
Message message,
MessageFault fault,
out Exception exception)
{
if (message.Action == "...")
{
exception = ...;
return true;
}
// OR
if ((fault.Code.Name == "...") && (fault.Code.Namespace == "..."))
{
exception = ...;
return true;
}
if (fault.IsMustUnderstand)
{
if (fault.WasHeaderNotUnderstood(
message.Headers, "...", "..."))
{
exception = new ProtocolException(...);
return true;
}
}
#if IMPLEMENTING_TRANSPORT_CHANNEL
FaultConverter encoderConverter =
this.encoder.GetProperty<FaultConverter>();
if ((encoderConverter != null) &&
(encoderConverter.TryCreateException(
message, fault, out exception)))
{
return true;
}
FaultConverter defaultConverter =
FaultConverter.GetDefaultFaultConverter(
this.channel.messageVersion);
return defaultConverter.TryCreateException(
message, fault, out exception);
#else
FaultConverter inner =
this.innerChannel.GetProperty<FaultConverter>();
if (inner != null)
{
return inner.TryCreateException(message, fault, out exception);
}
else
{
exception = null;
return false;
}
#endif
}
針對具有不同復原案例的特定錯誤狀況,請考慮定義ProtocolException
的衍生類別。
MustUnderstand 處理
SOAP 定義了一個通用錯誤,用於指示接收者不理解所需的標頭。 這個錯誤稱為 mustUnderstand
錯誤。 在 WCF 中,自定義通道永遠不會產生 mustUnderstand
錯誤。 在此情況下,位於 WCF 通訊堆疊頂端的 WCF 調度器會檢查基礎堆疊是否已理解所有標示為 MustUnderstand=true 的標頭。 如果有任何未被理解,則在該時間點會產生 mustUnderstand
故障。 (使用者可以選擇關閉此 mustUnderstand
處理,並讓應用程式接收所有訊息標頭。在此情況下,應用程式會負責執行 mustUnderstand
處理。產生的錯誤包含 NotUnderstood 標頭,其中包含未瞭解之 MustUnderstand=true 的所有標頭名稱。
如果您的通訊協定通道傳送具有 MustUnderstand=true 的自定義標頭,並收到 mustUnderstand
錯誤,則必須找出該錯誤是否因為其傳送的標頭所造成。
MessageFault
類別有兩個成員可用於此用途:
public class MessageFault
{
...
public bool IsMustUnderstandFault { get; }
public static bool WasHeaderNotUnderstood(MessageHeaders headers,
string name, string ns) { }
...
}
IsMustUnderstandFault
如果錯誤是true
錯誤,則傳mustUnderstand
回 。
WasHeaderNotUnderstood
true
如果具有指定名稱和命名空間的標頭包含在錯誤中,則會傳回 NotUnderstood 標頭。 否則會傳回 false
。
如果通道發出標示為 MustUnderstand = true 的標頭,則該層也應該實作例外狀況產生 API 模式,而且應該將該標頭所造成的錯誤轉換成 mustUnderstand
更有用的例外狀況,如先前所述。
追踪
.NET Framework 提供一種機制來追蹤程式執行,以協助診斷生產環境下的應用程式或間歇性問題,當無法直接附加除錯器並逐步執行程式碼時。 此機制的核心元件位於 命名空間中 System.Diagnostics ,且包含:
System.Diagnostics.TraceSource,這是要寫入的追蹤資訊來源,這是特定接聽程式的抽象基類, System.Diagnostics.TraceListener可接收要從 TraceSource 追蹤的資訊,並將它輸出至接聽程式特定目的地。 例如, XmlWriterTraceListener 將追蹤信息輸出至 XML 檔案。 最後,System.Diagnostics.TraceSwitch 讓應用程式使用者可以控制追蹤詳細程度,而且通常會在設定檔中指定。
除了核心元件之外,您還可以使用 服務追蹤查看器工具 (SvcTraceViewer.exe) 來檢視和搜尋 WCF 追蹤。 此工具專為 WCF 所產生的追蹤檔案所設計,並使用 XmlWriterTraceListener寫出。 下圖顯示追蹤所涉及的各種元件。
從自訂通道追蹤
自定義通道應該寫出追蹤訊息,以協助診斷無法將調試程式附加至執行中的應用程式時的問題。 這牽涉到兩個高階工作:實例化 TraceSource ,並呼叫其方法來寫入追蹤記錄。
具現化 TraceSource時,您指定的字串會變成該來源的名稱。 此名稱可用來設定追蹤來源(啟用/停用/設定追蹤層級)。 它也會出現在追蹤輸出本身中。 自定義通道應該使用唯一的來源名稱,協助追蹤輸出的讀取器瞭解追蹤資訊的來源。 使用正在寫入資訊的組件名稱作為追蹤來源名稱是常見的做法。 例如,WCF 會使用 System.ServiceModel 作為從 System.ServiceModel 元件寫入資訊的追蹤來源。
擁有追蹤來源之後,您可以呼叫其 TraceData、TraceEvent 或 TraceInformation 方法,將追蹤項目寫入追蹤監聽器。 針對您撰寫的每個追蹤項目,您需要將事件類型分類為TraceEventType所定義的事件類型之一。 此分類和設定中的追蹤層級設定決定是否將追蹤項目輸出到接聽程式。 例如,將組態中的追蹤層級設定為 Warning
,允許寫入 Warning
、Error
和 Critical
追蹤條目,但會封鎖 Information 和 Verbose 條目。 以下是具現化追蹤來源並在資訊層級寫出專案的範例:
using System.Diagnostics;
//...
TraceSource udpSource = new TraceSource("Microsoft.Samples.Udp");
//...
udpsource.TraceInformation("UdpInputChannel received a message");
這很重要
強烈建議您指定自定義通道唯一的追蹤來源名稱,以協助追蹤輸出讀取器了解輸出的來源。
與Trace Viewer整合
您的通道所產生的追蹤可以使用 作為追蹤接聽器,以 System.Diagnostics.XmlWriterTraceListener 可讀取的格式輸出。 這不是您作為通道開發人員需要執行的動作。 而是應用程式使用者(或應用程式疑難解答人員)需要在應用程式的組態檔中設定此追蹤接聽程式。 例如,下列組態會將 追蹤資訊從 System.ServiceModel 和 Microsoft.Samples.Udp
輸出至名為 TraceEventsFile.e2e
的檔案:
<configuration>
<system.diagnostics>
<sources>
<!-- configure System.ServiceModel trace source -->
<source name="System.ServiceModel" switchValue="Verbose"
propagateActivity="true">
<listeners>
<add name="e2e" />
</listeners>
</source>
<!-- configure Microsoft.Samples.Udp trace source -->
<source name="Microsoft.Samples.Udp" switchValue="Verbose" >
<listeners>
<add name="e2e" />
</listeners>
</source>
</sources>
<!--
Define a shared trace listener that outputs to TraceFile.e2e
The listener name is e2e
-->
<sharedListeners>
<add name="e2e" type="System.Diagnostics.XmlWriterTraceListener"
initializeData=".\TraceFile.e2e"/>
</sharedListeners>
<trace autoflush="true" />
</system.diagnostics>
</configuration>
追蹤結構化數據
System.Diagnostics.TraceSource中有一個TraceData方法,它接受要包含在追蹤輸入中的一個或多個物件。 一般而言,會在每個物件上呼叫 Object.ToString 方法,然後將產生的字串寫入追蹤條目的其中一部分。 使用 System.Diagnostics.XmlWriterTraceListener 輸出追蹤時,您可以將 System.Xml.XPath.IXPathNavigable 作為資料物件傳遞至 TraceData。 產生的追蹤記錄包含System.Xml.XPath.XPathNavigator所提供的XML內容。 以下是一個 XML 應用資料的範例項目:
<E2ETraceEvent xmlns="http://schemas.microsoft.com/2004/06/E2ETraceEvent">
<System xmlns="...">
<EventID>12</EventID>
<Type>3</Type>
<SubType Name="Information">0</SubType>
<Level>8</Level>
<TimeCreated SystemTime="2006-01-13T22:58:03.0654832Z" />
<Source Name="Microsoft.ServiceModel.Samples.Udp" />
<Correlation ActivityID="{00000000-0000-0000-0000-000000000000}" />
<Execution ProcessName="UdpTestConsole"
ProcessID="3348" ThreadID="4" />
<Channel />
<Computer>COMPUTER-LT01</Computer>
</System>
<!-- XML application data -->
<ApplicationData>
<TraceData>
<DataItem>
<TraceRecord
Severity="Information"
xmlns="…">
<TraceIdentifier>some trace id</TraceIdentifier>
<Description>EndReceive called</Description>
<AppDomain>UdpTestConsole.exe</AppDomain>
<Source>UdpInputChannel</Source>
</TraceRecord>
</DataItem>
</TraceData>
</ApplicationData>
</E2ETraceEvent>
WCF 追蹤查看器會瞭解先前顯示的元素架構 TraceRecord
,並從其子元素擷取數據,並以表格式格式顯示它。 追蹤結構化應用程式數據時,您的通道應該使用此架構,以協助 Svctraceviewer.exe 使用者讀取數據。