2016-08-18 48 views
1

我正在使用幾個WCF調用執行過程的項目。第一次呼叫返回一個唯一的ID(Guid),以下所有呼叫必須提供。在服務器端,每個呼叫都與該唯一ID一起記錄,以便可以觀察單個過程的過程(假設客戶端可以同時開始其中幾個過程並且它們是線程安全的)如何捕獲WCF中的所有異常但包含自定義數據?

一個客戶端的例子是類似以下內容:

string clientName = GetClientName(); 
Guid uniqueId = wcfClient.Begin(clientName); 
object data = wcfClient.GetData(clientName, uniqueId); 

object processedData = ProcessDataLocally(data); 

bool success = wcfClient.confirmDataValidity(clientName, uniqueId, processedData); 

// ... 

wcfClient.End(clientName, uniqueId); 

如果出現錯誤,在服務器端,我想,要使用UNIQUEID給予通話記錄爲好,那出問題了。爲此,我做了所有的服務方法使用如下的功能:

private T DoProcess<T>(Guid uniqueId, Func<T> process) 
{ 
    try 
    { 
     return process(); 
    } 
    catch(Exception ex) 
    { 
     Log(ex, uniqueId); 

     throw; // or throw the same thing every time, if the client 
       // shouldn't know the details 
    } 
} 

public object GetData(string clientName, Guid uniqueId) 
{ 
    return DoProcess(uniqueId,() => 
    { 
     object data; 

     // Generate data 

     return data; 
    }); 
} 

然而,似乎這樣做沒有捕捉到所有可能出現的錯誤(例如,如果連接超時) 。

我閱讀了關於實現IErrorHandler接口並將其附加到服務。雖然這似乎捕捉到了所有的錯誤,但除了異常之外,似乎沒有辦法將信息傳遞給它,例如uniqueId。因此無法記錄該ID。

是否有可能捕獲所有異常幷包含已傳遞給拋出異常的方法的數據?

+0

https://開頭計算器。 com/questions/3666516/is-there-a-way-to-catch-all-unhandled-exceptions-throw-by-a-given-class –

回答

2

連接超時等異常未到達該服務,因此無法在服務端捕獲該異常。

就是說,你可以使用IExtension向當前的OperationContext添加額外的信息。對於基本的模式是這樣的:

public class OperationContextExtension : IExtension<OperationContext> 
{ 
    private readonly Dictionary<string, object> extraInfo; 

    public OperationContextExtension() 
    { 
     extraInfo = new Dictionary<string, object>(); 
    } 

    public static OperationContextExtension Current 
    { 
     get 
     { 
      OperationContextExtension c = OperationContext.Current.Extensions.Find<OperationContextExtension>(); 
      if (c == null) 
      { 
       c = new OperationContextExtension(); 
       OperationContext.Current.Extensions.Add(c); 
      } 
      return c; 
     } 
    } 

    public Dictionary<string, object> Extras 
    { 
     get { return extraInfo; } 
    } 

    public void Attach(OperationContext owner) { } 

    public void Detach(OperationContext owner) { } 
} 

,然後使用類的IErrorHandler實現:

class FaultErrorHandler : IErrorHandler 
{ 
    public bool HandleError(Exception error) 
    { 
     return false; 
    } 

    public void ProvideFault(Exception error, MessageVersion version, ref Message fault) 
    { 
     Guid ID = OperationContextExtension.Current.Extras["uniqueId"] as Guid; 

     LogIt(error.ToString() + ID); 
    } 
} 

然後在的GetData

public object GetData(string clientName, Guid uniqueId) 
{ 
    OperationContextExtension.Current.Extras["uniqueId"] = uniqueId; 
    return DoProcess(uniqueId,() => 
    { 
     object data; 

     // Generate data 

     return data; 
    }); 
} 
+0

'Current'是一個靜態字段;可以安全地使用它,而同時可以發生多個呼叫? –

+1

是的這些類型的環境值在WCF中很常見。每個線程獲得不同的值(如果您配置了PerCall或PerSession) – Laurijssen