[英]WCF client-side error-handling
我正在消耗一個笨重的WCF服務器,偶爾會拋出各種異常,並且還會將一些錯誤作為string
返回。 我根本無法訪問服務器代碼。
我想覆蓋內部WCF客戶端請求調用方法並處理服務器返回的所有內部異常和硬編碼錯誤,並在發生錯誤時引發Fault
事件,偽:
class MyClient : MyServiceSoapClient
{
protected override OnInvoke()
{
object result;
try
{
result = base.OnInvoke();
if(result == "Error")
{
//raise fault event
}
catch
{
//raise fault event
}
}
}
因此,當我調用myClient.GetHelloWorld()
,它會通過我的重寫方法。
怎么能實現這一目標?
我知道我不必使用生成的客戶端,但我不想再次重新實現所有合同,我想使用生成的ClientBase
子類或至少使用它的通道。
我需要的是控制內部請求調用方法。
更新
我看了這個答案 ,看起來它部分是我正在尋找的,但我想知道是否有辦法將IErrorHandler
僅附加到消費者(客戶端)代碼,我想將它添加到ClientBase<TChannel>
實例不知何故。
更新
這篇文章看起來很有希望,但它不起作用。 應用的屬性似乎沒有生效。 我找不到將IServiceBehavior
添加到客戶端的方法。
更新
我試圖安裝一個IErrorHandler
通過IEndpointBehavior.ApplyClientBehavior
電話:
public void ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime)
{
clientRuntime.CallbackDispatchRuntime.ChannelDispatcher.ErrorHandlers
.Add(new ErrorHandler());
}
( clientRuntime
是一個參數),但仍然會直接跳過異常跳過MyErrorHandler
。
ApplyDispatchBehavior
不調用ApplyDispatchBehavior
。
結論
我需要實現兩個方面:
BaseClient<TChannel>
的生命周期內可能發生的所有異常,並決定是處理它們還是將它們拋出。 這應該照顧所有操作(我正在消耗的服務暴露幾十個) 您可以使用和修改異常處理WCF代理生成器 ,更具體地說,它是使用它的基類。 它的基本思想(檢查此描述 )是通過捕獲連接故障和重試失敗的操作來提供連接彈性。 可以想象,為此目的,它需要能夠捕獲拋出的異常,並且還可以檢查調用的結果。
主要功能由ExceptionHandlingProxyBase<T>
基類提供,您使用它來代替ClientBase<T>
。 這個基類有一個Invoke
方法,如下所示,你需要修改它。
簡化Invoke
:
protected TResult Invoke<TResult>(string operationName, params object[] parameters)
{
this.Open();
MethodInfo methodInfo = GetMethod(operationName);
TResult result = default(TResult);
try
{
this.m_proxyRecreationLock.WaitOne(this.m_proxyRecreationLockWait);
result = (TResult)methodInfo.Invoke(m_channel, parameters);
}
catch (TargetInvocationException targetEx) // Invoke() always throws this type
{
CommunicationException commEx = targetEx.InnerException as CommunicationException;
if (commEx == null)
{
throw targetEx.InnerException; // not a communication exception, throw it
}
FaultException faultEx = commEx as FaultException;
if (faultEx != null)
{
throw targetEx.InnerException; // the service threw a fault, throw it
}
//... Retry logic
}
return result;
}
你需要修改throw targetEx.InnerException;
根據需要處理異常的部分,顯然還要根據您的需要檢查resturn值。 除此之外,如果您不希望出現連接問題,您可以退出重試邏輯或將其丟棄。 Invoke
for void
返回方法還有另一種變體。
哦,順便說一句,它也適用於雙工通道,還有另一個基類。
如果您不想使用生成器(它甚至可能不適用於較新版本的VS),那么您可以從此處獲取基類,並從服務接口生成帶有T4的實際實現類。
如果服務未返回真正的異常,而只返回消息,則可能需要將ClientMessageInspector添加為新的客戶端行為。 請參閱: https : //msdn.microsoft.com/en-us/library/ms733786.aspx
我最終根據這個問題的答案使用了一些東西。
它堅持生成的客戶端代碼,並允許一般調用操作。
代碼不完整,隨意分叉和編輯它。 如果您發現任何錯誤或進行任何更新,請通知我。
它非常笨重,所以我只是分享使用代碼:
using (var proxy = new ClientProxy<MyServiceSoapClientChannel, MyServiceSoapChannel>())
{
client.Exception += (sender, eventArgs) =>
{
//All the exceptions will get here, can be customized by overriding ClientProxy.
Console.WriteLine($@"A '{eventArgs.Exception.GetType()}' occurred
during operation '{eventArgs.Operation.Method.Name}'.");
eventArgs.Handled = true;
};
client.Invoke(client.Client.MyOperation, "arg1", "arg2");
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.