2010-08-24 127 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