更新:在进一步调查过程中,我意识到错误不是我原先想到的自定义ServiceHostFactory,而是我在内部包装OperationContext的方式。我今天晚些时候要更新这个问题。
我最近在我的IIS托管的WCF Web服务中添加了一个自定义ServiceHostFactory,试图将Ninject的依赖注入用于我的服务构造函数。出于某种原因,每当我尝试访问属于OperationContext.Current
的属性时,都会抛出以下异常跟踪:
2015-05-08 10:30:39.5718 MyErrorHandler System.ObjectDisposedException: Message is closed.
at System.ServiceModel.Channels.BufferedMessage.get_Headers()
at System.ServiceModel.Channels.DelegatingMessage.get_Headers()
at System.ServiceModel.OperationContext.get_IncomingMessageHeaders()
... (my code here)
at SyncInvokeFindCurves(Object , Object[] , Object[] )
at System.ServiceModel.Dispatcher.SyncMethodInvoker.Invoke(Object instance, Object[] inputs, Object[]& outputs)
at System.ServiceModel.Dispatcher.DispatchOperationRuntime.InvokeBegin(MessageRpc& rpc)
at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage5(MessageRpc& rpc)
at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage41(MessageRpc& rpc)
at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage4(MessageRpc& rpc)
at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage31(MessageRpc& rpc)
at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage3(MessageRpc& rpc)
at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage2(MessageRpc& rpc)
at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage11(MessageRpc& rpc)
at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage1(MessageRpc& rpc)
at System.ServiceModel.Dispatcher.MessageRpc.Process(Boolean isOperationContextSet)
2015-05-08 10:31:51.2459 MyErrorHandler System.TimeoutException: The service's security session did not receive a 'close' message from the client within the configured timeout (00:00:10).
at System.ServiceModel.Security.SecuritySessionServerSettings.ServerSecuritySimplexSessionChannel.OnClose(TimeSpan timeout)
at System.ServiceModel.Channels.CommunicationObject.Close(TimeSpan timeout)
at System.ServiceModel.Channels.ServiceChannel.OnClose(TimeSpan timeout)
at System.ServiceModel.Channels.CommunicationObject.Close(TimeSpan timeout)
at System.ServiceModel.Dispatcher.MessageRpc.CloseChannel()
在调试器中,我注意到ObjectDisposedException不仅针对OperationContext.IncomingMessageHeaders
抛出,也针对OperationContext.ServiceSecurityContext
和其他许多抛出。
我尝试了几种不同的服务主机工厂实现,包括:
ServiceHostFactory
并返回带有自定义ServiceHost
的{{1}} IInstanceProvider
。但无济于事,因为所有人都有同样的问题。我也试过插入NinjectServiceHostFactory
,但它仍然没有解决这个问题的根本原因。我也试过谷歌搜索这个错误信息以及可能失败的组件,但我还没有找到类似于我的情况。
以下是我可以用来说明问题的最简单的代码:
IErrorHandler
我的配置包括:
public class WorkingServiceHostFactoryWithNinject : NinjectServiceHostFactory
{
// ReSharper disable once PrivateFieldCanBeConvertedToLocalVariable
// ReSharper disable once FieldCanBeMadeReadOnly.Local
private IKernel _kernel;
/// <summary>
/// Initializes the factory.
/// </summary>
public WorkingServiceHostFactoryWithNinject()
{
_kernel = new StandardKernel();
_kernel.Bind<IDummyDependency>().To<DummyDependency>();
...
SetKernel(_kernel);
}
}
和
<wsHttpBinding>
<binding name="ServiceBinding"
maxBufferPoolSize="4000000000"
maxReceivedMessageSize="2000000000"
allowCookies="true">
<readerQuotas maxDepth="32"
maxBytesPerRead="2000000000"
maxStringContentLength="2000000000"
maxArrayLength="2000000000" />
<security mode="TransportWithMessageCredential">
<transport clientCredentialType="Basic" proxyCredentialType="None" realm="" />
<message clientCredentialType="UserName" />
</security>
</binding>
</wsHttpBinding>
我确切知道的是<serviceBehaviors>
<behavior name="ServiceBehavior">
<serviceCredentials>
<serviceCertificate findValue="**redacted**" storeLocation="LocalMachine" storeName="My" x509FindType="FindBySubjectName" />
<userNameAuthentication userNamePasswordValidationMode="Custom" customUserNamePasswordValidatorType="CustomUserNamePasswordValidator, MyAssembly" />
</serviceCredentials>
<serviceDebug includeExceptionDetailInFaults="true" />
<serviceMetadata httpGetEnabled="true" httpsGetEnabled="true" />
<serviceSecurityAudit
auditLogLocation="Application"
serviceAuthorizationAuditLevel="Failure"
messageAuthenticationAuditLevel="Failure"
suppressAuditFailure="true"/>
</behavior>
</serviceBehaviors>
在我编写自己的ServiceHostFactory之前没有这样做。看起来好像垃圾收集器太早处理了这个消息......