在Silverlight中使用Channel Factory捕获故障异常



我正在尝试从Silverlight客户端使用通道工厂按此链接调用WCF服务。与渠道工厂合作对我来说是一件新的事情,所以请原谅我!

文章中提到的一切都很好。但是现在我正在尝试实现错误异常,以便我可以在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
            );

我在服务和客户端应用程序之间共享datcontract .dll,因此它们引用相同的数据契约类(类别&断层)

请告诉我我做错了什么?

UPDATE:我确实清楚地看到从Fiddler中的服务发送的故障异常。这让我相信我在客户端错过了一些东西。

为了捕捉silverlight中的正常异常,您必须创建"启用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)
    {
    }
}

我们在服务器上使用我们自己的自定义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"));
        }
    }

最新更新