WCF discovery with service hosts using net.tcp: //0.0.0.0: 0 / blah declares net.tcp: //0.0.0.0: 0 / blah

I need a discovery service that will listen on all interfaces and publish discovery announcements for each interface. I was hoping that I could eventually configure this in the configuration file using tcp: //0.0.0.0: 0 / blah as the service endpoint. But when I run the code below, the ads it sends use tcp: //0.0.0.0: 0 / blah as an EndpointAddress, which is useless to clients.

I want to receive announcements for each endpoint obtained from tcp: //0.0.0.0: 0 / blah, and I would prefer to use a configuration file rather than a host program setting, as shown below. Any ideas for a workaround?

[TestFixtureSetUp] public void SetUp() { service1 = new MyContract(); EndpointDiscoveryBehavior discoveryBehavior = new EndpointDiscoveryBehavior(); ServiceDiscoveryBehavior serviceDiscoveryBehavior = new ServiceDiscoveryBehavior(discoveryUri); serviceDiscoveryBehavior.AnnouncementEndpoints.Add(new UdpAnnouncementEndpoint(announcementUri)); serviceHost1 = new ServiceHost(service1, new Uri[] {new Uri("net.pipe://localhost"), new Uri("net.tcp://0.0.0.0:0")}); ServiceEndpoint localEndpoint1 = serviceHost1.AddServiceEndpoint(typeof (IContract), new NetNamedPipeBinding(), "/Pipe"); ServiceEndpoint localEndpoint2 = serviceHost1.AddServiceEndpoint(typeof (IContract), new NetTcpBinding(), "/Tcp"); localEndpoint2.Behaviors.Add(discoveryBehavior); serviceHost1.Description.Behaviors.Add(serviceDiscoveryBehavior); serviceHost1.AddServiceEndpoint(new UdpDiscoveryEndpoint(discoveryUri)); serviceHost1.Open(); } 
+4
source share
1 answer

Although my solution cannot be β€œright”, strictly speaking (it really should be fixed in the WCF itself, if you ask me), it works and is sufficient for my purposes.

First declare a new endpoint behavior, for example:

 public class WcfDiscoveryAddressFixEndpointBehavior : IEndpointBehavior, IDispatchMessageInspector { public void ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime) { // Attach ourselves to the MessageInspectors of reply messages clientRuntime.CallbackDispatchRuntime.MessageInspectors.Add(this); } public object AfterReceiveRequest(ref Message request, IClientChannel channel, InstanceContext instanceContext) { object messageProperty; if (!OperationContext.Current.IncomingMessageProperties.TryGetValue(RemoteEndpointMessageProperty.Name, out messageProperty)) return null; var remoteEndpointProperty = messageProperty as RemoteEndpointMessageProperty; if (remoteEndpointProperty == null) return null; // Extract message body string messageBody; using (var oldMessageStream = new MemoryStream()) { using (var xw = XmlWriter.Create(oldMessageStream)) { request.WriteMessage(xw); xw.Flush(); messageBody = Encoding.UTF8.GetString(oldMessageStream.ToArray()); } } // Replace instances of 0.0.0.0 with actual remote endpoint address messageBody = messageBody.Replace("0.0.0.0", remoteEndpointProperty.Address); // NOTE: Do not close or dispose of this MemoryStream. It will be used by WCF down the line. var newMessageStream = new MemoryStream(Encoding.UTF8.GetBytes(messageBody)); XmlDictionaryReader xdr = XmlDictionaryReader.CreateTextReader(newMessageStream, new XmlDictionaryReaderQuotas()); // Create a new message with our modified endpoint address and // copy over existing properties and headers Message newMessage = Message.CreateMessage(xdr, int.MaxValue, request.Version); newMessage.Properties.CopyProperties(request.Properties); newMessage.Headers.CopyHeadersFrom(request.Headers); request = newMessage; return null; } public void BeforeSendReply(ref Message reply, object correlationState) { } public void Validate(ServiceEndpoint endpoint) { } public void AddBindingParameters(ServiceEndpoint endpoint, BindingParameterCollection bindingParameters) { } public void ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher) { } } 

This endpoint behavior replaces the original WCF response response message with a copy in which the 0.0.0.0 instances were replaced with the address from which the message was received, available in the RemoteEndpointMessageProperty Address property.

To use it, simply add the new endpoint behavior to the UdpDiscoveryEndpoint when you create the DiscoveryClient :

 var udpDiscoveryEndpoint = new UdpDiscoveryEndpoint(); udpDiscoveryEndpoint.EndpointBehaviors.Add(new WcfDiscoveryAddressFixEndpointBehavior()); _discoveryClient = new DiscoveryClient(udpDiscoveryEndpoint); // Proceed as usual. 
+2
source

Source: https://habr.com/ru/post/1484703/


All Articles