Учитывайте следующее:Как определить (на стороне сервера), который заключает клиент WCF, используемый для подключения (несколько контрактов)?
У меня есть один главный сервер и несколько серверов в разных местах, которые могут связываться с главным сервером. Кроме того, клиенты (GUI) могут подключаться к каждому серверу.
Так у меня есть открытый интерфейс, который известен всеми:
[ServiceContract(SessionMode = SessionMode.Required)]
public interface IBaseService
{
[OperationContract]
void Subscribe();
[OperationContract]
void Unsubscribe();
}
Дополнительно серверы поддерживают контракт обратного вызова так, что главный сервер может инициировать запросы на серверах, подключенных к нему.
[ServiceContract(CallbackContract = typeof(ICallback), SessionMode = SessionMode.Required)]
interface IServerService : IBaseService
{
}
public interface ICallback
{
[OperationContract]
[FaultContract(typeof(ExceptionDetail))]
void TheCallback();
}
У сервера есть 2 реализованных контракта. Итак, когда я перебираю всех подписчиков (на Subscribe
, я кэширую все OperationContext
) на главном сервере и звоню в callback-контракт для клиентов, он просто отключается! Я ожидал какого-то контракта. Все (и сразу!), Но время ожидания операции?!?
Я также попытался выяснить название контракта, которое клиент использовал для подключения (OperationContext.Current
). Но это тоже не удалось. Он говорит IServerService
в обоих случаях в OperationContext.Current.EndpointDispatcher.ContractName
.
Есть ли возможность на стороне сервера выяснить, какой OperationContract
был использован клиентом при подключении?
Конечно, я мог бы расширить интерфейс сервера по методу SubscribeServer
, но это кажется довольно уродливым для меня.
EDIT:
, как предложил я реализовать MessageInspector
. Но в AfterReceiveRequest
IClientChannel может быть успешно отлиты в ICallback
Что еще более странно, что стек вызовов содержит уже ReliableDuplexSessionChannel
:
> XYZ.exe!XYZ.AfterReceiveRequest(ref System.ServiceModel.Channels.Message request, System.ServiceModel.IClientChannel channel, System.ServiceModel.InstanceContext instanceContext) Line 99 C#
System.ServiceModel.dll!System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.AfterReceiveRequestCore(ref System.ServiceModel.Dispatcher.MessageRpc rpc) + 0x86 bytes
System.ServiceModel.dll!System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage2(ref System.ServiceModel.Dispatcher.MessageRpc rpc) + 0x37 bytes
System.ServiceModel.dll!System.ServiceModel.Dispatcher.MessageRpc.Process(bool isOperationContextSet) + 0x151 bytes
System.ServiceModel.dll!System.ServiceModel.Dispatcher.ChannelHandler.DispatchAndReleasePump(System.ServiceModel.Channels.RequestContext request, bool cleanThread, System.ServiceModel.OperationContext currentOperationContext) + 0x644 bytes
System.ServiceModel.dll!System.ServiceModel.Dispatcher.ChannelHandler.HandleRequest(System.ServiceModel.Channels.RequestContext request, System.ServiceModel.OperationContext currentOperationContext) + 0x1d2 bytes
System.ServiceModel.dll!System.ServiceModel.Dispatcher.ChannelHandler.AsyncMessagePump(System.IAsyncResult result) + 0x4b bytes
System.Runtime.DurableInstancing.dll!System.Runtime.Fx.AsyncThunk.UnhandledExceptionFrame(System.IAsyncResult result) + 0x32 bytes
System.Runtime.DurableInstancing.dll!System.Runtime.AsyncResult.Complete(bool completedSynchronously) + 0x16b bytes
System.Runtime.DurableInstancing.dll!System.Runtime.InputQueue<System.ServiceModel.Channels.Message>.AsyncQueueReader.Set(System.Runtime.InputQueue<System.ServiceModel.Channels.Message>.Item item) + 0x41 bytes
System.Runtime.DurableInstancing.dll!System.Runtime.InputQueue<System.ServiceModel.Channels.Message>.Dispatch() + 0x320 bytes
System.ServiceModel.dll!System.ServiceModel.Channels.ReliableDuplexSessionChannel.ProcessDuplexMessage(System.ServiceModel.Channels.WsrmMessageInfo info) + 0x7cb bytes
System.ServiceModel.dll!System.ServiceModel.Channels.ServerReliableDuplexSessionChannel.ProcessMessage(System.ServiceModel.Channels.WsrmMessageInfo info) + 0x2a7 bytes
System.ServiceModel.dll!System.ServiceModel.Channels.ReliableDuplexSessionChannel.HandleReceiveComplete(System.IAsyncResult result) + 0x1fa bytes
System.ServiceModel.dll!System.ServiceModel.Channels.ReliableDuplexSessionChannel.OnReceiveCompletedStatic(System.IAsyncResult result) + 0x86 bytes
System.Runtime.DurableInstancing.dll!System.Runtime.Fx.AsyncThunk.UnhandledExceptionFrame(System.IAsyncResult result) + 0x32 bytes
System.Runtime.DurableInstancing.dll!System.Runtime.AsyncResult.Complete(bool completedSynchronously) + 0x16b bytes
System.ServiceModel.dll!System.ServiceModel.Channels.ReliableChannelBinder<System.__Canon>.InputAsyncResult<System.__Canon>.OnInputComplete(System.IAsyncResult result) + 0x7a bytes
System.Runtime.DurableInstancing.dll!System.Runtime.Fx.AsyncThunk.UnhandledExceptionFrame(System.IAsyncResult result) + 0x32 bytes
System.Runtime.DurableInstancing.dll!System.Runtime.AsyncResult.Complete(bool completedSynchronously) + 0x16b bytes
System.ServiceModel.dll!System.ServiceModel.Channels.FramingDuplexSessionChannel.TryReceiveAsyncResult.OnReceive(System.IAsyncResult result) + 0xa9 bytes
System.Runtime.DurableInstancing.dll!System.Runtime.Fx.AsyncThunk.UnhandledExceptionFrame(System.IAsyncResult result) + 0x32 bytes
System.Runtime.DurableInstancing.dll!System.Runtime.AsyncResult.Complete(bool completedSynchronously) + 0x16b bytes
System.ServiceModel.dll!System.ServiceModel.Channels.SynchronizedMessageSource.ReceiveAsyncResult.OnReceiveComplete(object state) + 0x82 bytes
System.ServiceModel.dll!System.ServiceModel.Channels.SessionConnectionReader.OnAsyncReadComplete(object state) + 0x175 bytes
System.Runtime.DurableInstancing.dll!System.Runtime.Fx.AsyncThunk.UnhandledExceptionFrame(System.IAsyncResult result) + 0x32 bytes
System.dll!System.Net.LazyAsyncResult.Complete(System.IntPtr userToken) + 0xc5 bytes
System.dll!System.Net.Security.NegotiateStream.ProcessFrameBody(int readBytes, byte[] buffer, int offset, int count, System.Net.AsyncProtocolRequest asyncRequest) + 0x126 bytes
System.dll!System.Net.Security.NegotiateStream.ReadCallback(System.Net.AsyncProtocolRequest asyncRequest) + 0xea bytes
System.dll!System.Net.FixedSizeReader.CheckCompletionBeforeNextRead(int bytes) + 0x32 bytes
System.dll!System.Net.FixedSizeReader.ReadCallback(System.IAsyncResult transportResult) + 0x9c bytes
System.Runtime.DurableInstancing.dll!System.Runtime.AsyncResult.Complete(bool completedSynchronously) + 0x16b bytes
System.ServiceModel.dll!System.ServiceModel.Channels.ConnectionStream.ReadAsyncResult.OnAsyncReadComplete(object state) + 0xa2 bytes
System.ServiceModel.dll!System.ServiceModel.Channels.SocketConnection.AsyncReadCallback(bool haveResult, int error, int bytesRead) + 0x19b bytes
System.Runtime.DurableInstancing.dll!System.Runtime.Fx.IOCompletionThunk.UnhandledExceptionFrame(uint error, uint bytesRead, System.Threading.NativeOverlapped* nativeOverlapped) + 0x40 bytes
mscorlib.dll!System.Threading._IOCompletionCallback.PerformIOCompletionCallback(uint errorCode, uint numBytes, System.Threading.NativeOverlapped* pOVERLAP) + 0x96 bytes
[Native to Managed Transition]
Означает ли это, если мой класс обслуживания реализует IServerService
, который имеет функцию обратного вызова контракт, что все соединительные клиенты маршрутизируются через дуплексный прокси? Независимо от того, какой контракт использовался (или реализован) клиентом?
«OperationContext.Current.Host» содержит информацию о ServiceHost. Меня интересует информация о клиенте. Контракт, используемый клиентом для создания канала. В ImplmentedContracts на ServiceHost я вижу мой IServerService и мой IClientService. Но никаких указаний о том, какой контракт был использован клиентом. – toATwork
Возможно, вам понадобится внедрить Message Inspector. –
Нет, это не помогло. См. Дополнительную информацию в вопросе. – toATwork