通信对象System.ServiceModel.Channels.ServiceChannel不能用于通信

Inn*_*ova 146 c# wcf

通信对象System.ServiceModel.Channels.ServiceChannel不能用于通信,因为它处于Faulted状态.

什么是这个错误,我将如何解决它?

mar*_*c_s 137

您收到此错误是因为您在服务器端发生了.NET异常,并且您没有捕获并处理它,也没有将其转换为SOAP错误.

现在,由于服务器端"被轰炸",WCF运行时已"故障"通道 - 例如客户端和服务器之间的通信链路无法使用 - 毕竟,它看起来像你的服务器刚刚爆炸,所以你无法与之通信它了.

所以你需要做的是:

  • 始终捕获并处理服务器端错误 - 不要让.NET异常从服务器传递到客户端 - 始终将这些错误包装成可互操作的SOAP错误.查看WCF IErrorHandler接口并在服务器端实现它

  • 如果您要从客户端向您的频道发送第二条消息,请确保该频道未处于故障状态:

    if(client.InnerChannel.State != System.ServiceModel.CommunicationState.Faulted)
    {
       // call service - everything's fine
    }
    else
    {
       // channel faulted - re-create your client and then try again
    }
    
    Run Code Online (Sandbox Code Playgroud)

    如果是,您所能做的只是处理它并再次重新创建客户端代理,然后再试一次

  • 当问题出现在客户端时,似乎也会发生同样的错误:例如,当超过传入消息的消息大小配额时. (10认同)
  • 我该如何重新创建客户端? (4认同)

Ber*_*ndK 29

要防止服务器陷入故障状态,您必须确保不会引发未处理的异常.如果WCF看到意外的异常,则不再接受任何呼叫 - 安全第一.
避免这种行为的两种可能性:

  1. 使用FaultException(这对于WCF来说并不意外,因此WCF知道服务器仍然具有有效状态)
    而不是

    throw new Exception("Error xy in my function")  
    
    Run Code Online (Sandbox Code Playgroud)

    永远使用

    throw new FaultException("Error xy in my function")  
    
    Run Code Online (Sandbox Code Playgroud)

    也许你可以尝试..捕获整个块并在异常的所有情况下抛出FaultException

    try   
    {  
        ... some code here   
    }
    catch (Exception ex)
    {  
        throw new FaultException(ex.Message)   
    }
    
    Run Code Online (Sandbox Code Playgroud)
  2. 告诉WCF使用Errorhandler处理所有异常.这可以通过多种方式完成,我选择了一个使用属性的简单方法:
    我们必须做的更多,就是[SvcErrorHandlerBehaviour]在所需的服务实现上使用该属性

    using System;
    using System.Collections.ObjectModel;
    using System.ServiceModel;
    using System.ServiceModel.Channels;
    using System.ServiceModel.Description;
    using System.ServiceModel.Dispatcher;
    
    namespace MainService.Services
    {
        /// <summary>
        /// Provides FaultExceptions for all Methods Calls of a Service that fails with an Exception
        /// </summary>
        public class SvcErrorHandlerBehaviourAttribute : Attribute, IServiceBehavior
        {
            public void Validate(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
            { } //implementation not needed
    
            public void AddBindingParameters(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase, Collection<ServiceEndpoint> endpoints,
                                             BindingParameterCollection bindingParameters)
            { } //implementation not needed
    
            public void ApplyDispatchBehavior(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
            {
                foreach (ChannelDispatcherBase chanDispBase in serviceHostBase.ChannelDispatchers)
                {
                    ChannelDispatcher channelDispatcher = chanDispBase as ChannelDispatcher;
                    if (channelDispatcher == null)
                        continue;
                    channelDispatcher.ErrorHandlers.Add(new SvcErrorHandler());
                }
            }
        }
    
        public class SvcErrorHandler: IErrorHandler
        {
            public bool HandleError(Exception error)
            {
                //You can log th message if you want.
                return true;
            }
    
            public void ProvideFault(Exception error, MessageVersion version, ref Message msg)
            {
                if (error is FaultException)
                    return;
    
                FaultException faultException = new FaultException(error.Message);
                MessageFault messageFault = faultException.CreateMessageFault();
                msg = Message.CreateMessage(version, messageFault, faultException.Action);
            }
        }
    }
    
    Run Code Online (Sandbox Code Playgroud)

这是一个简单的例子,您可以通过不使用裸体来深入了解IErrorhandler FaultException,但是FaultException<>提供额外信息的类型请参阅IErrorHandler以获取详细示例.


tim*_*4sa 9

事实上,如果在遵循marc_s的建议后不成功,请记住服务器上web.config中服务器绑定配置(或缺少)中的<security>元素可能会导致此异常.例如,服务器期望Message-level安全性,客户端配置为None(或者,如果服务器不是Active Directory域的一部分,但远程客户端主机是).

提示:在这种情况下,客户端应用程序很可能在RDP会话中的管理帐户下直接在服务器计算机上执行时调用Web服务.