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

时间:2010-05-04 07:39:21

标签: c# wcf

  

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

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

17 个答案:

答案 0 :(得分:132)

您收到此错误是因为您在服务器端发生了.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
    }
    

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

答案 1 :(得分:27)

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

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

    throw new Exception("Error xy in my function")  
    

    始终使用

    throw new FaultException("Error xy in my function")  
    

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

    try   
    {  
        ... some code here   
    }
    catch (Exception ex)
    {  
        throw new FaultException(ex.Message)   
    }
    
  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);
            }
        }
    }
    
  3. 这是一个简单的示例,您可以通过不使用裸FaultException深入IErrorhandler,但使用提供其他信息类型的FaultException<> 有关详细示例,请参阅IErrorHandler

答案 2 :(得分:7)

附加到the faulted event以找出错误发生的原因和时间。

编辑:如果您发布了一些有关您正在做的事情的更多信息,也会有所帮助。

答案 3 :(得分:7)

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

  

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

答案 4 :(得分:2)

要诊断此问题,请在Visual Studio调试器下运行该服务。使用菜单:Debug | Exceptions并指示在抛出异常时要中断。

抛出的原始异常将会出现比#34更好的错误消息。它处于故障状态。&#34;

例如,我从ServiceHost.Open()获取此异常,但是当我在抛出它时捕获到原始异常时,错误消息是:

  

服务&#39; MyServiceName&#39;零应用(非基础设施)   端点。这可能是因为找不到配置文件   为您的应用程序,或因为没有匹配的服务元素   服务名称可以在配置文件中找到,或者因为没有   端点是在服务元素中定义的。

修复App.config中的拼写错误解决了这个问题。

答案 5 :(得分:2)

我有一个通过WCF连接到Windows服务的Web客户端。 我的网络应用程序抛出相同的错误

通信对象System.ServiceModel.Channels.ServiceChannel不能用于通信,因为它处于Faulted状态 我启用了WCF跟踪,这没有多大帮助。 终于重新启动Windows服务解决了它,我仍然有 不知道原因。 故障排除应始终从简单开始。这是 一个很好的例子。如果有人有类似的问题,请尝试重新启动 服务。

答案 6 :(得分:1)

我有另一个问题,我认为在其他答案中没有提及。

我必须在相同的tcp地址和端口上为端点提供服务。在app.config中,我忘记添加两个端点,因此服务在正确的端口上运行,但服务接口错误。

答案 7 :(得分:1)

如果在Visual Studio的Debug中看到此消息,则解决方案包含WCF项目。 然后打开此WCF项目设置 - &gt;转到&#34; WCF选项&#34;标签 - &gt;关闭&#34;调试时启动WCF服务主机...&#34;选项

答案 8 :(得分:1)

我在尝试使用http asmx服务中的net.tcp wcf服务端点时遇到了相同的问题。

正如我所见,没有人写出具体的答案,为什么会出现此问题,而只是如何正确处理。

我已经连续几天苦苦挣扎,最后我发现问题出在哪里。

最初,我认为当您引用服务时,配置文件的安全标记的配置方式将与源代码中的配置方式相同,但事实并非如此,我应该手动进行处理。 就我而言,只有

<netTcpBinding>
    <binding name="NetTcpBinding_IAuthenticationLoggerService"
    </binding>
</netTcpBinding>`

后来我看到安全部分丢失了,看起来应该像这样

<netTcpBinding>
    <binding name="NetTcpBinding_IAuthenticationLoggerService" transferMode="Buffered">
      <security mode="None">
        <transport clientCredentialType="None"/>
      </security>
    </binding>
  </netTcpBinding>

在我的案例中,第二个问题是我在源WCF服务上使用transferMode="Streamed",而在客户端中我对此没有任何具体说明,这很糟糕,因为默认的transferMode是{{ 1}},在地方源和客户端上以相同的方式进行配置很重要。

答案 9 :(得分:0)

在我的情况下,原因是某些错误的证书无法加载。我在系统:

下的事件查看器中发现了它
  

尝试访问TLS服务器时发生致命错误   凭证私钥。加密返回的错误代码   模块是0x8009030D。内部错误状态为10001。

答案 10 :(得分:0)

此错误也可以由您自己的计算机触发,而不仅仅是未处理的异常。如果您的服务器/计算机的时钟时间过多,则许多.NET Web服务将拒绝您的请求,并显示未处理的错误。它是从他们的角度处理的,但是从你的观点来看未得到处理。检查以确保您的接收服务器的时钟时间正确。如果需要修复,您必须重新启动服务或重新启动频道重新启动。

我在服务器上遇到此问题,防火墙阻止了Internet时间更新,服务器由于某种原因关闭了时间。所有第三方.NET Web服务都因为拒绝任何Web服务请求而出现故障。深入了解事件查看器有助于识别问题,但调整时钟解决了问题。即使我们收到了Faulted State错误消息以供将来的Web服务调用,但错误仍然存​​在。

答案 11 :(得分:0)

服务器将自动中止在其等于接收超时的持续时间内没有收到任何消息的连接(默认值为10分钟)。这是一个DoS缓解措施,可以防止客户端强制服务器无限期地打开连接。

由于服务器由于已变为空闲状态而中止了连接,因此客户端会收到此异常。

通过在服务器绑定上配置接收超时,可以控制服务器允许连接空闲多长时间后才中止连接。 图片来源:T.R。Vishwanath-MSFT

答案 12 :(得分:0)

我知道这是一篇较旧的文章,但是当您无法更改安全性时要注意的一件事是确保设置了用户名和密码。

我有一个身份验证模式为UserNameOverTransport的服务,当未为服务客户端设置用户名和密码时,会出现此错误。

答案 13 :(得分:0)

对我来说,这是一个负载平衡器/ URL问题。负载均衡器后面的Web服务使用完整的URL调用同一负载均衡器后面的另一个服务,例如:loadbalancer.mycompany.com。我改为使用localhost.mycompany.com来调用第二个服务时将其更改为绕过负载平衡器。

我认为负载均衡器正在发生某种循环引用问题。

答案 14 :(得分:0)

对我来说,问题是由导入WSDL自动生成的配置文件引起的。我将绑定从basicHttpBinding更新为customBinding。添加其他异常处理无助于指出这一点。

之前

<basicHttpBinding>
            <binding name="ServiceName">
                <security mode="Transport" />
            </binding>
        </basicHttpBinding>`

之后

<customBinding>
        <binding name="ServiceName">
          <textMessageEncoding messageVersion="Soap12" />
          <httpsTransport />
        </binding>
      </customBinding>`

答案 15 :(得分:0)

我们在系统中使用 MSMQ,此错误消息来了。原因是我们的队列已满,我们没有正确处理错误日志记录机制,所以我们得到了上述异常而不是 msmq ful。我们清除了消息然后它工作正常。

答案 16 :(得分:-1)

不是此问题的解决方案,但如果您在使用Ektron eSync时遇到上述错误,则可能是您的数据库磁盘空间不足。

编辑:事实上,这并非仅仅是Ektron eSync问题。这可能发生在任何查询完整数据库的服务上。

编辑:磁盘空间不足或阻止访问您需要的目录会导致此问题。

相关问题