2010-08-24 126 views
2

我已經實現了異步模式服務:WCF異步模式不會引發故障異常

[OperationContract(AsyncPattern = true)] 
IAsyncResult BeginLoadDocument(Byte[] value, AsyncCallback callback, object state); 

Boolean EndLoadDocument(IAsyncResult asyncResult); 

的「BeginLoadDocument」使用線程池運行在服務端的私有方法「回調」:

public IAsyncResult BeginLoadDocument(string id, AsyncCallback callback, object state) 
    { 
      PendingAsyncResult<string> asyncResult = 
      new PendingAsyncResult<string>(id, callback, state); 
      ThreadPool.QueueUserWorkItem(new WaitCallback(Callback), asyncResult); 
      return asyncResult; 
    } 

回調方法加載文檔並設置「EndLoadDocument」的結果。

到目前爲止好,但我如何處理例外?

如果我在服務器端拋出exceling,我得到一個FaultedException'1沒有處理。 我確實嘗試使用屬性[FaultContract(typeof(InforError))],其中「InfoError」是我的Custum DataMember,但它不起作用。

我使用SvcUtil工具構建代理/一個http:...

回答

1

您可以捕捉異常的客戶端如下:

try { 
    MyClient.MyCall(); 
} 

catch (FaultException<IOException> exc) { 
    // Log and handle exception 
} 

凡真正拋出的異常是,在這個例子是一個IOException

您還需要一個FaultContract,因爲你表明你是在服務接口,因爲這樣的:

[ServiceContract] 
public interface IMyService { 

    [OperationContract] 
    [FaultContract(typeof(IOException))] 
    void MyCall();  
} 


**** ****編輯

我M於東西你寫了一個有點模糊:

[FaultContract(typeof運算(InforError))],其中 「InfoError」 是我俗數據成員

'DataMember'是什麼意思? InfoError的定義是什麼?

[FaultContract]應該在服務接口方法上定義......在你的文章中,你聽起來像是試圖將它添加到客戶端;這是不正確的。如果我修改你的示例代碼,它看起來像:

[ServiceContract] 
public interface IMyService { 

    [OperationContract(AsyncPattern = true)] 
    [FaultContract(typeof(InfoErrorException))] 
    IAsyncResult BeginLoadDocument(Byte[] value, AsyncCallback callback, object state); 

    string EndLoadDocument(IAsyncResult asyncResult); 

如果你的服務接口被裝飾成這樣,客戶端應該能夠當你調用EndLoadDocument接收FaultException S(前提是拋出的異常是一個InfoErrorException例外)。

在服務器端,你必須捕獲異常,然後在FaultException包裝他們,因爲這樣:

catch (IOException exp) { 
    InfoErrorException myException = new InfoErrorException(); 
    myException.Reason = "I failed: " + exp.Message; 
    throw new FaultException<InfoErrorException>(myException); 
} 

相信(但必須要仔細檢查),您還可以趕上一個FaultException在客戶端沒有指定類型...類似於捕獲通用System.Exception

try...catchFaultException應該在你的回調,周圍的語句來調用EndLoadDocument()

+0

我的接口作爲異步簽名: [的ServiceContract] 公共接口IMyService { [OperationContract的(AsyncPattern =真)] IAsyncResult的BeginLoadDocument(字節[]值,AsyncCallback的回調,對象的狀態); Boolean EndLoadDocument(IAsyncResult asyncResult); } 我確實在客戶端使用Try-Catch,問題出現在服務器端,expect沒有處理它。如果我在服務器端使用Try-Catch,客戶端永遠不會知道異常,如果我不使用try-catch錯誤停止服務並且客戶端沒有收到任何東西。 – user429715 2010-08-24 16:18:35

+0

兩個客戶端都知道IServiceInterface,因此他們應該知道您將寫入的ServiceFault。把它放在「常用」或任何你把IServiceInterface放在哪裏.. – ilansch 2013-03-28 06:27:48

1

看起來像你使用的是Silverlight。 問題是WCF服務返回的HTTP狀態與200不同,所以瀏覽器不提供有關Silverlight運行時響應的附加數據。

的解決方案是使用自定義的ErrorHandler提供必要的HTTP代碼:

/// <summary>Sets the HTTP code to 200 for faults.</summary> 
public class HttpStatusCode200ErrorHandler : IErrorHandler 
{ 
    public Type ServiceType { get; set; } 

    public HttpStatusCode200ErrorHandler(Type serviceType) 
    { 
     ServiceType = serviceType; 
    } 

    public bool HandleError(Exception error) 
    { 
     return false; 
    } 

    public virtual void ProvideFault(Exception error, MessageVersion version, ref Message fault) 
    { 
     fault.Properties[HttpResponseMessageProperty.Name] = 
     new HttpResponseMessageProperty { StatusCode = System.Net.HttpStatusCode.OK }; 
    } 
} 

您可以將其連接到使用以下ServiceBehavior屬性爲您服務:

/// <summary>Applies HttpStatusCode200ErrorHandler.</summary> 
[AttributeUsage(AttributeTargets.Class)] 
public class HttpStatusCode200BehaviorAttribute : Attribute, IServiceBehavior 
{ 
    public void AddBindingParameters(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase, System.Collections.ObjectModel.Collection<ServiceEndpoint> endpoints, System.ServiceModel.Channels.BindingParameterCollection bindingParameters) 
    { 
    } 

    public void ApplyDispatchBehavior(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase) 
    { 
     foreach (ChannelDispatcher dispatcher in serviceHostBase.ChannelDispatchers) 
     { 
      dispatcher.ErrorHandlers.Add(new HttpStatusCode200ErrorHandler(serviceDescription.ServiceType)); 
     } 
    } 

    public void Validate(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase) 
    { 
    } 
} 

欲瞭解更多詳細看Understanding WCF Faults in Silverlight