2016-12-06 8 views
0

Учитывайте следующее:Как определить (на стороне сервера), который заключает клиент 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, который имеет функцию обратного вызова контракт, что все соединительные клиенты маршрутизируются через дуплексный прокси? Независимо от того, какой контракт использовался (или реализован) клиентом?

ответ

0

На стороне сервера другой объект, содержащий входящие данные сообщения, - OperationContext.Current.Host.

Вы можете получить информацию о контрактах. Вот некоторые доступные данные:

Имя интерфейса: OperationContext.Current.Host.ImplementedContracts.FirstOrDefault().Value.Name

имен Интерфейс: OperationContext.Current.Host.ImplementedContracts.FirstOrDefault().Value.Namespace

Полный контракт имя типа: OperationContext.Current.Host.ImplementedContracts.FirstOrDefault().Value.ContractType.FullName

Вы также можете использовать Reflection в OperationContext.Current.Host.Description.ServiceType, это тип.

Надеюсь, это поможет.

+0

«OperationContext.Current.Host» содержит информацию о ServiceHost. Меня интересует информация о клиенте. Контракт, используемый клиентом для создания канала. В ImplmentedContracts на ServiceHost я вижу мой IServerService и мой IClientService. Но никаких указаний о том, какой контракт был использован клиентом. – toATwork

+0

Возможно, вам понадобится внедрить Message Inspector. –

+0

Нет, это не помогло. См. Дополнительную информацию в вопросе. – toATwork

 Смежные вопросы

  • Нет связанных вопросов^_^