2011-10-03 54 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")); 
     } 
    }