2011-10-03 23 views
0

我正嘗試使用通道工廠根據此link從Silverlight客戶端調用WCF服務。與渠道工廠合作對我來說是新事物,請耐心等待!通道工廠在Silverlight中捕獲錯誤異常

在文章中提到的一切都很好。但是現在我試圖實現Fault異常,以便能夠捕獲Silverlight端的實際異常。但由於某種原因,我總是最終捕獲CommunicationException,這不符合我的目的。

這裏是我的服務合同:服務的

[OperationContract] 
[FaultContract(typeof(Fault))] 
IList<Category> GetCategories(); 

Catch塊:與異步模式的客戶端

catch (Exception ex) 
    { 
     Fault fault = new Fault(ex.Message); 
     throw new FaultException<Fault>(fault, "Error occured in the GetCategories service"); 
    } 

服務合同:

[OperationContract(AsyncPattern = true)] 
[FaultContract(typeof(Fault))] 
IAsyncResult BeginGetCategories(AsyncCallback callback, object state); 

IList<Category> EndGetCategories(IAsyncResult result); 

這裏是服務呼叫來自客戶:

 ICommonServices channel = ChannelProviderFactory.CreateFactory<ICommonServices>(COMMONSERVICE_URL, false); 
     var result = channel.BeginGetCategories(
      (asyncResult) => 
      { 
       try 
       { 
        var returnval = channel.EndGetCategories(asyncResult); 
        Deployment.Current.Dispatcher.BeginInvoke(() => 
        { 
         CategoryCollection = new ObservableCollection<Category>(returnval); 
        }); 
       } 
       catch (FaultException<Fault> serviceFault) 
       { 
        MessageBox.Show(serviceFault.Message); 
       } 
       catch (CommunicationException cex) 
       { 
        MessageBox.Show("Unknown Communications exception occured."); 
       } 
      }, null 
      ); 

我.dll文件共享DataContract無論是服務和客戶端應用程序,因此,他們指的是相同的數據合同類(A類&故障)

請告訴我,我在做什麼錯之間?

UPDATE:我清楚地看到從Fiddler服務發送的故障異常。這使我相信我在客戶端丟失了一些東西。

回答

1

爲捕捉sivleright中的正常異常,您必須創建「支持Silverlight的WCF服務」(添加 - >新建項目 - >啓用Silverlight的WCF服務)。 如果您已經創建了標準的WCF服務,您可以手動添加屬性[SilverlightFaultBehavior]到您的服務。 默認實現這個屬性是:

public class SilverlightFaultBehavior : Attribute, IServiceBehavior 
{ 
    private class SilverlightFaultEndpointBehavior : IEndpointBehavior 
    { 
     public void AddBindingParameters(ServiceEndpoint endpoint, BindingParameterCollection bindingParameters) 
     { 
     } 

     public void ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime) 
     { 
     } 

     public void ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher) 
     { 
      endpointDispatcher.DispatchRuntime.MessageInspectors.Add(new SilverlightFaultMessageInspector()); 
     } 

     public void Validate(ServiceEndpoint endpoint) 
     { 
     } 

     private class SilverlightFaultMessageInspector : IDispatchMessageInspector 
     { 
      public object AfterReceiveRequest(ref Message request, IClientChannel channel, InstanceContext instanceContext) 
      { 
       return null; 
      } 

      public void BeforeSendReply(ref Message reply, object correlationState) 
      { 
       if ((reply != null) && reply.IsFault) 
       { 
        HttpResponseMessageProperty property = new HttpResponseMessageProperty(); 
        property.StatusCode = HttpStatusCode.OK; 
        reply.Properties[HttpResponseMessageProperty.Name] = property; 
       } 
      } 
     } 
    } 

    public void AddBindingParameters(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase, Collection<ServiceEndpoint> endpoints, BindingParameterCollection bindingParameters) 
    { 
    } 

    public void ApplyDispatchBehavior(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase) 
    { 
     foreach (ServiceEndpoint endpoint in serviceDescription.Endpoints) 
     { 
      endpoint.Behaviors.Add(new SilverlightFaultEndpointBehavior()); 
     } 
    } 

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

我不我想要捕捉正常的例外情況。我只想捕捉服務引發的故障異常。我認爲沒有啓用Silverlight的WCF服務是可能的。如果我錯了,請糾正我。 – Vinod

+0

好吧,我錯了!這似乎是唯一的方法。謝謝Andris。下面的文章派上用場: http://www.codeproject.com/KB/silverlight/SilverlightWCFService.aspx – Vinod

0

我們如使用我們自己的自定義ServiceException類的服務器上

[Serializable] 
public class ServiceException : Exception 
{ 
    public ServiceException() 
    { 

    } 

    public ServiceException(string message, Exception innerException) 
     : base(message, innerException) 
    { 

    } 

    public ServiceException(Exception innerException) 
     : base("Service Exception Occurred", innerException) 
    { 

    } 

    public ServiceException(string message) 
     : base(message) 
    { 

    } 
} 

然後在我們的服務器端服務的方法,我們使用的錯誤處理是這樣的:

 try 
     { 
     ...... 
     } 
     catch (Exception ex) 
     { 
      Logger.GetLog(Logger.ServiceLog).Error("MyErrorMessage", ex); 
      throw new ServiceException("MyErrorMessage", ex); 
     } 

然後,使用一個通用的方法爲所有Web服務調用:

/// <summary> 
    /// Runs the given functon in a try catch block to wrap service exception. 
    /// Returns the result of the function. 
    /// </summary> 
    /// <param name="action">function to run</param> 
    /// <typeparam name="T">Return type of the function.</typeparam> 
    /// <returns>The result of the function</returns> 
    protected T Run<T>(Func<T> action) 
    { 
     try 
     { 
      return action(); 
     } 
     catch (ServiceException ex) 
     { 
      ServiceLogger.Error(ex); 
      throw new FaultException(ex.Message, new FaultCode("ServiceError")); 
     } 
     catch (Exception ex) 
     { 
      ServiceLogger.Error(ex); 
      throw new FaultException(GenericErrorMessage, new FaultCode("ServiceError")); 
     } 
    }