2016-12-06 1 views
0

Betrachten Sie folgendes:Wie kann man (auf Serverseite) herausfinden, welchen Vertrag ein WCF-Client für die Verbindung verwendet hat (mehrere Verträge)?

Ich habe einen Master-Server und mehrere Server an verschiedenen Standorten, die mit dem Master-Server kommunizieren können. Zusätzlich (GUI) Clients können sich mit jedem Server verbinden. So

Ich habe eine öffentliche Schnittstelle, die von jedermann bekannt ist:

[ServiceContract(SessionMode = SessionMode.Required)] 
public interface IBaseService 
{ 
    [OperationContract] 
    void Subscribe(); 

    [OperationContract] 
    void Unsubscribe(); 
} 

Zusätzlich werden die Server einen Rückruf Vertrag unterstützen, so dass der Master-Server-Anfragen auf den Servern auslösen können mit ihm verbunden.

[ServiceContract(CallbackContract = typeof(ICallback), SessionMode = SessionMode.Required)] 
interface IServerService : IBaseService 
{ 
} 

public interface ICallback 
{ 
    [OperationContract] 
    [FaultContract(typeof(ExceptionDetail))] 
    void TheCallback(); 
} 

Bedeutung der Server hat 2 Verträge implementiert. Also wenn ich alle Teilnehmer iteriere (auf Subscribe ich alle OperationContext zwischenspeichern) auf dem Master-Server und den Callback-Vertrag für Clients aufrufen, kommt es einfach mal raus! Ich hatte eine Art ContractMismatch erwartet. Alles (und sofort!) Aber eine Operation Timeout?!?

Ich versuchte auch, den Vertragsnamen herauszufinden, den der Kunde verwendete, um zu verbinden (OperationContext.Current). Aber das war auch nicht erfolgreich. Es steht IServerService in beiden Fällen in OperationContext.Current.EndpointDispatcher.ContractName.

Gibt es auf der Serverseite eine Möglichkeit herauszufinden, welcher OperationContract vom Client beim Verbindungsaufbau verwendet wurde?

Natürlich könnte ich die Server-Schnittstelle um eine Methode SubscribeServer erweitern, aber das scheint mir ziemlich hässlich.

EDIT:

wie vorgeschlagen, dass ich eine MessageInspector implementieren tat. Aber in der AfterReceiveRequest kann die IClientChannel erfolgreich ICallback

gegossen werden

Was noch komisch ist, dass der Call-Stack enthält bereits 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] 

Bedeutet dies, wenn meine Dienstklasse die IServerService implementiert, die einen Rückruf hat Vertrag definiert, dass alle verbindenden Clients über einen Duplex-Proxy geroutet werden? Egal, welcher Vertrag vom Kunden verwendet (oder implementiert) wurde?

Antwort

0

Auf der Serverseite ist ein anderes Objekt, das ankommende Nachrichtendaten enthält, OperationContext.Current.Host.

Sie können Informationen über die Verträge erhalten. Hier einige Daten zur Verfügung:

Schnittstellenname: OperationContext.Current.Host.ImplementedContracts.FirstOrDefault().Value.Name

Schnittstelle Namespace: OperationContext.Current.Host.ImplementedContracts.FirstOrDefault().Value.Namespace

Voll Vertragsart Name: OperationContext.Current.Host.ImplementedContracts.FirstOrDefault().Value.ContractType.FullName

Sie auch Reflection in OperationContext.Current.Host.Description.ServiceType verwenden können, das ist ein Typ.

Hoffe, das hilft.

+0

Der 'OperationContext.Current.Host' enthält Informationen über den ServiceHost. Ich bin an den Informationen über den Kunden interessiert. Der Vertrag, den der Kunde für die Channel-Erstellung verwendet hat. In den ImplementedContracts auf dem ServiceHost sehe ich den my IServerService und meinen IClientService. Aber keine Angabe, welcher Vertrag vom Kunden verwendet wurde. – toATwork

+0

Vielleicht müssen Sie einen Nachrichteninspektor implementieren. –

+0

Nein, das hat nicht gut getan. Bitte beachten Sie die zusätzlichen Informationen in der Frage. – toATwork

Verwandte Themen