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
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?
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
Vielleicht müssen Sie einen Nachrichteninspektor implementieren. –
Nein, das hat nicht gut getan. Bitte beachten Sie die zusätzlichen Informationen in der Frage. – toATwork