2015-04-28 1 views
0

У меня есть приложение ASP.NET MVC с контроллером, который использует службу WCF. Веб-приложение аутентифицируется службой WCF с использованием WIF и службы маркеров безопасности (STS). Это требует, чтобы служба WCF имела отпечаток сертификата STS в своем web.config (<system.identityModel>). Если метод WCF услуги называются и служба WCF настроена с неправильным отпечатком метод сервиса генерирует исключение:Замок Виндзор бросает CommunicationObjectFaultedException при удалении клиента WCF, который создал MessageSecurityException

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 цепляемы какие-либо исключения, брошенных службами, так как мы хотим, чтобы вернуть ответ даже если существует проблема с услугой:

try { 
    service.Hello(); 
} 
catch (Exception e) { 
    log.Error("Service error", e); 
} 

метод контроллер возвращает ViewResult и замок Виндзор начинает очистку контроллера и его зависимости. Однако, когда Виндзор располагает клиент WCF, что повергло MessageSecurityException я получаю это исключение:

[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:\work\16de7b8c88ab14af\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(); называется и кидаю новую Exception («тест») затем 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 или ошибкой конфигурации.

ответ

0

попробуйте добавить оператор прерывания:

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

Успехов,

Marwijn.

+0

Привет, i'am знает о проблеме клиента Indisposable WCF.Замок Виндзор уже обрабатывает сбитых клиентов ('Castle.Facilities.WcfIntegration.Internal.WcfUtils'). Если служба выдает исключение, она будет находиться в состоянии сбоя, и Windsor сможет правильно распоряжаться клиентом. Проблема в том, что служба бросила вызов MessageSecurityException. Виндзор не может правильно распоряжаться клиентом. Я мог бы добавить сервис '((IClientChannel)) .Abort();' в блоке catch, но он кажется немного взломанным. Я хочу, чтобы Castle Windsor справлялся с образом жизни объектов. – aquaUrge

1

Вы можете добавить прерывани заявление о событии OnDestroy:

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(); 
      })); 
    } 
} 
0

Корневая причина ошибки была регрессия ошибка в Виндзорском замке ФОС объекта. Исправлена ​​ошибка в версии 4.1.0 пакета nuget Castle.WcfIntegrationFacility.

Порядок отчетности по очистке была изменена, подробнее см https://github.com/castleproject/Windsor/issues/104