【问题标题】:Catch Fault Exception in Silverlight with Channel Factory使用 Channel Factory 在 Silverlight 中捕获故障异常
【发布时间】:2023-03-05 15:51:01
【问题描述】:

我正在尝试按照 link 使用通道工厂从 Silverlight 客户端调用 WCF 服务。与渠道工厂合作对我来说是新事物,所以请多多包涵!

文章中提到的一切都很好。但现在我正在尝试实现错误异常,以便我可以在 Silverlight 端捕获实际异常。但由于某种原因,我总是最终捕获 CommunicationException 这不符合我的目的。

这是我的服务合同:

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

服务的捕获块:

    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
            );

我在服务和客户端应用程序之间共享 DataContract .dll,因此它们指的是相同的数据协定类(类别和故障)

请告诉我我做错了什么?

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

【问题讨论】:

    标签: silverlight wcf silverlight-4.0 channelfactory


    【解决方案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)
        {
        }
    }
    

    【讨论】:

    • 我不想捕捉正常的异常。我只想捕获服务引发的错误异常。我认为如果没有启用 Silverlight 的 WCF 服务,这是可能的。如果我错了,请纠正我。
    • 好吧,我错了!这似乎是唯一的方法。谢谢安德里斯。下面的文章对我很有用:codeproject.com/KB/silverlight/SilverlightWCFService.aspx
    【解决方案2】:

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2023-03-21
      • 1970-01-01
      • 2018-06-22
      • 1970-01-01
      • 1970-01-01
      • 2013-10-14
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多