处理已引发 MessageSecurityException 的 WCF 客户端时,Castle Windsor 引发 CommunicationObjectFaultedException
Castle Windsor throws a CommunicationObjectFaultedException when disposing a WCF client that has thrown a MessageSecurityException
我有一个 ASP.NET MVC 应用程序,其控制器使用 WCF 服务。 Web 应用程序由 WCF 服务使用 WIF 和安全令牌服务 (STS) 进行身份验证。这要求 WCF 服务在其 web.config () 中具有 STS 证书指纹。当调用 WCF 服务方法并且 WCF 服务配置有错误的指纹时,服务方法将引发异常:
System.AggregateException: One or more errors occurred. ---> System.ServiceModel.Security.MessageSecurityException: An unsecured or incorrectly secured fault was received from the other party. See the inner FaultException for the fault code and detail. ---> System.ServiceModel.FaultException: An error occurred when processing the security tokens in the message. --- End of inner exception stack trace --- at
System.Runtime.AsyncResult.End[TAsyncResult](IAsyncResult result) at
System.ServiceModel.Channels.ServiceChannel.SendAsyncResult.End(SendAsyncResult result) at
System.ServiceModel.Channels.ServiceChannel.EndCall(String action, Object[] outs, IAsyncResult result) at
System.ServiceModel.Channels.ServiceChannelProxy.TaskCreator.<>c__DisplayClass5`1.<CreateGenericTask>b__4(IAsyncResult asyncResult) at
System.Threading.Tasks.TaskFactory`1.FromAsyncCoreLogic(IAsyncResult iar, Func`2 endFunction, Action`1 endAction, Task`1 promise, Boolean requiresSynchronization) --- End of inner exception stack trace --- at
System.Threading.Tasks.Task`1.GetResultCore(Boolean waitCompletionNotification) at
Helper.GetMessages(String func) in xxx ---> (Inner Exception #0) System.ServiceModel.Security.MessageSecurityException: An unsecured or incorrectly secured fault was received from the other party. See the inner FaultException for the fault code and detail. ---> System.ServiceModel.FaultException: An error occurred when processing the security tokens in the message. --- End of inner exception stack trace --- at
System.Runtime.AsyncResult.End[TAsyncResult](IAsyncResult result) at
System.ServiceModel.Channels.ServiceChannel.SendAsyncResult.End(SendAsyncResult result) at
System.ServiceModel.Channels.ServiceChannel.EndCall(String action, Object[] outs, IAsyncResult result) at
System.ServiceModel.Channels.ServiceChannelProxy.TaskCreator.<>c__DisplayClass5`1.<CreateGenericTask>b__4(IAsyncResult asyncResult) at
System.Threading.Tasks.TaskFactory`1.FromAsyncCoreLogic(IAsyncResult iar, Func`2 endFunction, Action`1 endAction, Task`1 promise, Boolean requiresSynchronization)<---
在 MVC 控制器中,我们捕获服务抛出的任何异常,因为我们想要 return 响应,即使服务出现问题也是如此:
try {
service.Hello();
}
catch (Exception e) {
log.Error("Service error", e);
}
控制器方法 returns ViewResult 和 Castle Windsor 开始清理控制器及其依赖项。但是,当 Windsor 处理抛出 MessageSecurityException 的 WCF 客户端时,我得到了这个异常:
[CommunicationObjectFaultedException: The communication object, System.ServiceModel.Channels.ServiceChannel, cannot be used for communication because it is in the Faulted state.]
System.Runtime.Remoting.Proxies.RealProxy.HandleReturnMessage(IMessage reqMsg, IMessage retMsg) +14579646
System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(MessageData& msgData, Int32 type) +622
System.IDisposable.Dispose() +0
Castle.MicroKernel.LifecycleConcerns.DisposalConcern.Apply(ComponentModel model, Object component) in c:\Downloads\Windsor-3.3\Windsor-3.3\src\Castle.Windsor\MicroKernel\LifecycleConcerns\DisposalConcern.cs:47
Castle.MicroKernel.ComponentActivator.AbstractComponentActivator.ApplyConcerns(IEnumerable`1 steps, Object instance) in c:\Downloads\Windsor-3.3\Windsor-3.3\src\Castle.Windsor\MicroKernel\ComponentActivator\AbstractComponentActivator.cs:120
Castle.MicroKernel.ComponentActivator.AbstractComponentActivator.ApplyDecommissionConcerns(Object instance) in c:\Downloads\Windsor-3.3\Windsor-3.3\src\Castle.Windsor\MicroKernel\ComponentActivator\AbstractComponentActivator.cs:132
Castle.Facilities.WcfIntegration.WcfClientActivator.ApplyDecommissionConcerns(Object instance) in c:\Downloads\Windsor-3.3\Windsor-3.3\src\Castle.Facilities.WcfIntegration\Client\WcfClientActivator.cs:64
Castle.MicroKernel.ComponentActivator.DefaultComponentActivator.InternalDestroy(Object instance) in c:\Downloads\Windsor-3.3\Windsor-3.3\src\Castle.Windsor\MicroKernel\ComponentActivator\DefaultComponentActivator.cs:74
Castle.MicroKernel.ComponentActivator.AbstractComponentActivator.Destroy(Object instance) in c:\Downloads\Windsor-3.3\Windsor-3.3\src\Castle.Windsor\MicroKernel\ComponentActivator\AbstractComponentActivator.cs:87
Castle.MicroKernel.Lifestyle.AbstractLifestyleManager.Release(Object instance) in c:\Downloads\Windsor-3.3\Windsor-3.3\src\Castle.Windsor\MicroKernel\Lifestyle\AbstractLifestyleManager.cs:64
Castle.MicroKernel.Handlers.DefaultHandler.ReleaseCore(Burden burden) in c:\Downloads\Windsor-3.3\Windsor-3.3\src\Castle.Windsor\MicroKernel\Handlers\DefaultHandler.cs:65
Castle.MicroKernel.Handlers.AbstractHandler.Release(Burden burden) in c:\Downloads\Windsor-3.3\Windsor-3.3\src\Castle.Windsor\MicroKernel\Handlers\AbstractHandler.cs:170
Castle.MicroKernel.Burden.Release() in c:\Downloads\Windsor-3.3\Windsor-3.3\src\Castle.Windsor\MicroKernel\Burden.cs:119
Castle.MicroKernel.Lifestyle.Scoped.ScopeCache.<Dispose>b__0(Burden b) in c:\Downloads\Windsor-3.3\Windsor-3.3\src\Castle.Windsor\MicroKernel\Lifestyle\Scoped\ScopeCache.cs:65
Castle.Core.Internal.CollectionExtensions.ForEach(IEnumerable`1 items, Action`1 action) in d:\workde7b8c88ab14af\src\Castle.Core\Core\Internal\CollectionExtensions.cs:44
Castle.MicroKernel.Lifestyle.Scoped.ScopeCache.Dispose() in c:\Downloads\Windsor-3.3\Windsor-3.3\src\Castle.Windsor\MicroKernel\Lifestyle\Scoped\ScopeCache.cs:65
Castle.MicroKernel.Lifestyle.Scoped.DefaultLifetimeScope.Dispose() in c:\Downloads\Windsor-3.3\Windsor-3.3\src\Castle.Windsor\MicroKernel\Lifestyle\Scoped\DefaultLifetimeScope.cs:38
Castle.MicroKernel.Lifestyle.PerWebRequestLifestyleModule.Application_EndRequest(Object sender, EventArgs e) in c:\Downloads\Windsor-3.3\Windsor-3.3\src\Castle.Windsor\MicroKernel\Lifestyle\PerWebRequestLifestyleModule.cs:47
System.Web.SyncEventExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() +92
System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) +165
抛出异常的代码为:
AbstractComponentActivator.ApplyConcerns(IEnumerable<IDecommissionConcern> steps, object instance)
DisposalConcern.Apply(ComponentModel model, object component)
在调试时我注意到以下区别:
当service.Hello();被调用并且 frameowrk 抛出 MessageSecurityException
然后 object component = {System.ServiceModel.Channels.ServiceChannelProxy}
在 DisposalConcern.Apply(ComponentModel model, object component)
这会抛出 CommunicationObjectFaultedException
当service.Hello();被调用,我抛出新的异常("test")
然后 object component = {System.Runtime.Remoting.Proxies.__TransparentProxy}
在 DisposalConcern.Apply(ComponentModel model, object component)
这不会引发异常
该服务在网络应用程序中注册如下:
public class MeldingssystemServiceInstaller : IWindsorInstaller
{
public void Install(IWindsorContainer container, IConfigurationStore store)
{
container.Register(Component.For<IMeldingssystemService>()
.AsWcfClient(new DefaultClientModel(WcfEndpoint.FromConfiguration("MeldingssystemService")))
.LifeStyle.PerWebRequest);
}
}
我想弄清楚这是 Castle Windsor 中的 bug/limitation 还是配置错误。
尝试添加中止语句:
try {
service.Hello();
}
catch (Exception e) {
service.abort();
log.Error("Service error", e);
}
查看以下内容:http://www.codeproject.com/Articles/74129/The-Proper-Use-and-Disposal-of-WCF-Channels-or-Com
祝你好运,
马尔维恩.
您可以在 OnDestroy 事件上添加 abort 语句:
public class MeldingssystemServiceInstaller : IWindsorInstaller
{
public void Install(IWindsorContainer container, IConfigurationStore store)
{
container.Register(Component.For<IMeldingssystemService>()
.AsWcfClient(new DefaultClientModel(WcfEndpoint.FromConfiguration("MeldingssystemService")))
.LifeStyle.PerWebRequest.OnDestroy(service =>
{
var channel = (IClientChannel) service;
if (channel.State == CommunicationState.Faulted)
channel.Abort();
}));
}
}
错误的根本原因是 castle windsor wcf 工具中的回归错误。该错误已在 nuget 包 Castle.WcfIntegrationFacility 的 4.1.0 版中修复。
清理语句的顺序已更改,详情请参阅https://github.com/castleproject/Windsor/issues/104
我有一个 ASP.NET MVC 应用程序,其控制器使用 WCF 服务。 Web 应用程序由 WCF 服务使用 WIF 和安全令牌服务 (STS) 进行身份验证。这要求 WCF 服务在其 web.config (
System.AggregateException: One or more errors occurred. ---> System.ServiceModel.Security.MessageSecurityException: An unsecured or incorrectly secured fault was received from the other party. See the inner FaultException for the fault code and detail. ---> System.ServiceModel.FaultException: An error occurred when processing the security tokens in the message. --- End of inner exception stack trace --- at
System.Runtime.AsyncResult.End[TAsyncResult](IAsyncResult result) at
System.ServiceModel.Channels.ServiceChannel.SendAsyncResult.End(SendAsyncResult result) at
System.ServiceModel.Channels.ServiceChannel.EndCall(String action, Object[] outs, IAsyncResult result) at
System.ServiceModel.Channels.ServiceChannelProxy.TaskCreator.<>c__DisplayClass5`1.<CreateGenericTask>b__4(IAsyncResult asyncResult) at
System.Threading.Tasks.TaskFactory`1.FromAsyncCoreLogic(IAsyncResult iar, Func`2 endFunction, Action`1 endAction, Task`1 promise, Boolean requiresSynchronization) --- End of inner exception stack trace --- at
System.Threading.Tasks.Task`1.GetResultCore(Boolean waitCompletionNotification) at
Helper.GetMessages(String func) in xxx ---> (Inner Exception #0) System.ServiceModel.Security.MessageSecurityException: An unsecured or incorrectly secured fault was received from the other party. See the inner FaultException for the fault code and detail. ---> System.ServiceModel.FaultException: An error occurred when processing the security tokens in the message. --- End of inner exception stack trace --- at
System.Runtime.AsyncResult.End[TAsyncResult](IAsyncResult result) at
System.ServiceModel.Channels.ServiceChannel.SendAsyncResult.End(SendAsyncResult result) at
System.ServiceModel.Channels.ServiceChannel.EndCall(String action, Object[] outs, IAsyncResult result) at
System.ServiceModel.Channels.ServiceChannelProxy.TaskCreator.<>c__DisplayClass5`1.<CreateGenericTask>b__4(IAsyncResult asyncResult) at
System.Threading.Tasks.TaskFactory`1.FromAsyncCoreLogic(IAsyncResult iar, Func`2 endFunction, Action`1 endAction, Task`1 promise, Boolean requiresSynchronization)<---
在 MVC 控制器中,我们捕获服务抛出的任何异常,因为我们想要 return 响应,即使服务出现问题也是如此:
try {
service.Hello();
}
catch (Exception e) {
log.Error("Service error", e);
}
控制器方法 returns ViewResult 和 Castle Windsor 开始清理控制器及其依赖项。但是,当 Windsor 处理抛出 MessageSecurityException 的 WCF 客户端时,我得到了这个异常:
[CommunicationObjectFaultedException: The communication object, System.ServiceModel.Channels.ServiceChannel, cannot be used for communication because it is in the Faulted state.]
System.Runtime.Remoting.Proxies.RealProxy.HandleReturnMessage(IMessage reqMsg, IMessage retMsg) +14579646
System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(MessageData& msgData, Int32 type) +622
System.IDisposable.Dispose() +0
Castle.MicroKernel.LifecycleConcerns.DisposalConcern.Apply(ComponentModel model, Object component) in c:\Downloads\Windsor-3.3\Windsor-3.3\src\Castle.Windsor\MicroKernel\LifecycleConcerns\DisposalConcern.cs:47
Castle.MicroKernel.ComponentActivator.AbstractComponentActivator.ApplyConcerns(IEnumerable`1 steps, Object instance) in c:\Downloads\Windsor-3.3\Windsor-3.3\src\Castle.Windsor\MicroKernel\ComponentActivator\AbstractComponentActivator.cs:120
Castle.MicroKernel.ComponentActivator.AbstractComponentActivator.ApplyDecommissionConcerns(Object instance) in c:\Downloads\Windsor-3.3\Windsor-3.3\src\Castle.Windsor\MicroKernel\ComponentActivator\AbstractComponentActivator.cs:132
Castle.Facilities.WcfIntegration.WcfClientActivator.ApplyDecommissionConcerns(Object instance) in c:\Downloads\Windsor-3.3\Windsor-3.3\src\Castle.Facilities.WcfIntegration\Client\WcfClientActivator.cs:64
Castle.MicroKernel.ComponentActivator.DefaultComponentActivator.InternalDestroy(Object instance) in c:\Downloads\Windsor-3.3\Windsor-3.3\src\Castle.Windsor\MicroKernel\ComponentActivator\DefaultComponentActivator.cs:74
Castle.MicroKernel.ComponentActivator.AbstractComponentActivator.Destroy(Object instance) in c:\Downloads\Windsor-3.3\Windsor-3.3\src\Castle.Windsor\MicroKernel\ComponentActivator\AbstractComponentActivator.cs:87
Castle.MicroKernel.Lifestyle.AbstractLifestyleManager.Release(Object instance) in c:\Downloads\Windsor-3.3\Windsor-3.3\src\Castle.Windsor\MicroKernel\Lifestyle\AbstractLifestyleManager.cs:64
Castle.MicroKernel.Handlers.DefaultHandler.ReleaseCore(Burden burden) in c:\Downloads\Windsor-3.3\Windsor-3.3\src\Castle.Windsor\MicroKernel\Handlers\DefaultHandler.cs:65
Castle.MicroKernel.Handlers.AbstractHandler.Release(Burden burden) in c:\Downloads\Windsor-3.3\Windsor-3.3\src\Castle.Windsor\MicroKernel\Handlers\AbstractHandler.cs:170
Castle.MicroKernel.Burden.Release() in c:\Downloads\Windsor-3.3\Windsor-3.3\src\Castle.Windsor\MicroKernel\Burden.cs:119
Castle.MicroKernel.Lifestyle.Scoped.ScopeCache.<Dispose>b__0(Burden b) in c:\Downloads\Windsor-3.3\Windsor-3.3\src\Castle.Windsor\MicroKernel\Lifestyle\Scoped\ScopeCache.cs:65
Castle.Core.Internal.CollectionExtensions.ForEach(IEnumerable`1 items, Action`1 action) in d:\workde7b8c88ab14af\src\Castle.Core\Core\Internal\CollectionExtensions.cs:44
Castle.MicroKernel.Lifestyle.Scoped.ScopeCache.Dispose() in c:\Downloads\Windsor-3.3\Windsor-3.3\src\Castle.Windsor\MicroKernel\Lifestyle\Scoped\ScopeCache.cs:65
Castle.MicroKernel.Lifestyle.Scoped.DefaultLifetimeScope.Dispose() in c:\Downloads\Windsor-3.3\Windsor-3.3\src\Castle.Windsor\MicroKernel\Lifestyle\Scoped\DefaultLifetimeScope.cs:38
Castle.MicroKernel.Lifestyle.PerWebRequestLifestyleModule.Application_EndRequest(Object sender, EventArgs e) in c:\Downloads\Windsor-3.3\Windsor-3.3\src\Castle.Windsor\MicroKernel\Lifestyle\PerWebRequestLifestyleModule.cs:47
System.Web.SyncEventExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() +92
System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) +165
抛出异常的代码为:
AbstractComponentActivator.ApplyConcerns(IEnumerable<IDecommissionConcern> steps, object instance)
DisposalConcern.Apply(ComponentModel model, object component)
在调试时我注意到以下区别:
当service.Hello();被调用并且 frameowrk 抛出 MessageSecurityException
然后 object component = {System.ServiceModel.Channels.ServiceChannelProxy}
在 DisposalConcern.Apply(ComponentModel model, object component)
这会抛出 CommunicationObjectFaultedException
当service.Hello();被调用,我抛出新的异常("test")
然后 object component = {System.Runtime.Remoting.Proxies.__TransparentProxy}
在 DisposalConcern.Apply(ComponentModel model, object component)
这不会引发异常
该服务在网络应用程序中注册如下:
public class MeldingssystemServiceInstaller : IWindsorInstaller
{
public void Install(IWindsorContainer container, IConfigurationStore store)
{
container.Register(Component.For<IMeldingssystemService>()
.AsWcfClient(new DefaultClientModel(WcfEndpoint.FromConfiguration("MeldingssystemService")))
.LifeStyle.PerWebRequest);
}
}
我想弄清楚这是 Castle Windsor 中的 bug/limitation 还是配置错误。
尝试添加中止语句:
try {
service.Hello();
}
catch (Exception e) {
service.abort();
log.Error("Service error", e);
}
查看以下内容:http://www.codeproject.com/Articles/74129/The-Proper-Use-and-Disposal-of-WCF-Channels-or-Com
祝你好运,
马尔维恩.
您可以在 OnDestroy 事件上添加 abort 语句:
public class MeldingssystemServiceInstaller : IWindsorInstaller
{
public void Install(IWindsorContainer container, IConfigurationStore store)
{
container.Register(Component.For<IMeldingssystemService>()
.AsWcfClient(new DefaultClientModel(WcfEndpoint.FromConfiguration("MeldingssystemService")))
.LifeStyle.PerWebRequest.OnDestroy(service =>
{
var channel = (IClientChannel) service;
if (channel.State == CommunicationState.Faulted)
channel.Abort();
}));
}
}
错误的根本原因是 castle windsor wcf 工具中的回归错误。该错误已在 nuget 包 Castle.WcfIntegrationFacility 的 4.1.0 版中修复。
清理语句的顺序已更改,详情请参阅https://github.com/castleproject/Windsor/issues/104