通信对象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)
如果是,您所能做的只是处理它并再次重新创建客户端代理,然后再试一次
Ber*_*ndK 29
要防止服务器陷入故障状态,您必须确保不会引发未处理的异常.如果WCF看到意外的异常,则不再接受任何呼叫 - 安全第一.
避免这种行为的两种可能性:
使用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)告诉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以获取详细示例.
事实上,如果在遵循marc_s的建议后不成功,请记住服务器上web.config中服务器绑定配置(或缺少)中的<security>元素可能会导致此异常.例如,服务器期望Message
-level安全性,客户端配置为None
(或者,如果服务器不是Active Directory域的一部分,但远程客户端主机是).
提示:在这种情况下,客户端应用程序很可能在RDP会话中的管理帐户下直接在服务器计算机上执行时调用Web服务.