WCF4 contains support for the WS-Discovery protocol, which allows the discovery of services on a network. WS-Discovery was originally developed as joint venture between BEA Systems, Canon, Intel, Microsoft, and WebMethods, and is famously used in Windows Vista to provide the "people near me" functionality. For more information on WS-Discovery, please refer to http://schemas.xmlsoap.org/ws/2004/10/discovery/ws-discovery.pdf.
WS-Discovery is a great way of easing deployment of your applications, and perhaps even making them more robust by discovering alternative endpoints to use in the event of failure.
WCF4 implements WS-Discovery via a new behavior called ServiceDiscoveryBehavior, which tells WCF to make a service discoverable. WCF then creates an UdpAnnouncementEndpoint to listen for discovery requests. WS-Discovery can operate in two different modes: managed and ad hoc.
In managed mode, a list of services is held in a central location (called the discovery proxy). When services start up, they inform the discovery proxy of their location. Managed mode is more complex to implement than ad hoc, but it creates much less network traffic and is more suitable for use in larger networks. It does, however, have the drawback that if your discovery proxy goes down, there will be no more service discovery (single point of failure).
Services operating in ad hoc mode broadcast their location over the network, which generates much more network traffic but has no central point of failure. Ad hoc mode is also restricted to the current subnet. Let's look into how to use WS-Discovery ad hoc mode now (note that the WCF samples contain an example of managed mode).
We will create a simple service that capitalizes a string and makes it discoverable, and then we'll find and invoke it.
Now add references to the System.ServiceModel and System.ServiceModel.Discovery assemblies and replace Program.cs with the following code:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.ServiceModel; using System.ServiceModel.Discovery; using System.ServiceModel.Description; namespace Chapter7.WCFDiscovery { public class Program { static void Main(string[] args) { ServiceHost host = new ServiceHost(typeof(ToUpperService), new Uri("http://localhost:8081/DiscoverMe")); host.AddServiceEndpoint(typeof(IToUpper), new BasicHttpBinding(), "ToUpper"); host.AddServiceEndpoint(typeof(IToUpper), new WS2007HttpBinding(), "ToUpper2"); host.Description.Behaviors.Add( new ServiceMetadataBehavior() { HttpGetEnabled = true } ); ServiceDiscoveryBehavior discoveryBehavior = new ServiceDiscoveryBehavior(); host.Description.Behaviors.Add(discoveryBehavior); host.AddServiceEndpoint(new UdpDiscoveryEndpoint()); discoveryBehavior.AnnouncementEndpoints.Add( new UdpAnnouncementEndpoint() ); host.Open(); Console.WriteLine("Service running"); Console.ReadKey(); } public class ToUpperService : IToUpper { public string ToUpper(string Input) { return Input.ToUpper(); } } }
[ServiceContract] public interface IToUpper { [OperationContract] string ToUpper(string Input); } }
We now need to generate a proxy to enable us to call the service in the Chapter7.WCFDiscovery project. To create the proxy, we need to have Chapter7.WCFDiscovery running, so right-click the Chapter7.WCFDiscovery project and select Debug "Start new instance" (click Allow if you get a security warning).
You can check that the service is running correctly by opening a web browser and going to http://localhost:8081/DiscoverMe, where you should be presented with the service metadata page.
Copy the generated proxy class (which will be at the Visual Studio command prompt location) to the Chapter7.WCFFindServices project.
In Chapter7.WCFFindServices, amend Program.cs to the following:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.ServiceModel.Discovery; using System.ServiceModel; namespace Chapter7.WCFFindServices { class Program { static void Main(string[] args) { DiscoveryClient discoveryClient = new DiscoveryClient(new UdpDiscoveryEndpoint()); Console.WriteLine( "Finding end points please wait this may take some time.." ); FindResponse discoveryResponse = discoveryClient.Find(new FindCriteria(typeof(ToUpperClient)));
for (int Index = 0; Index < discoveryResponse.Endpoints.Count; Index++) { Console.WriteLine("Found end point at: " + discoveryResponse.Endpoints[Index].Address.ToString()); } Console.WriteLine("Using end point: " + discoveryResponse.Endpoints[0].Address.ToString()); EndpointAddress address = discoveryResponse.Endpoints[0].Address; ToUpperClient service = new ToUpperClient(new BasicHttpBinding(), address); Console.WriteLine(service.ToUpper("make me uppercase!")); Console.ReadKey(); } } }
OK, we're ready to go, so start up the Chapter7.WCFDiscovery project first (otherwise, you are not going to find anything) by right-clicking it, and select Debug "Start new instance." Once Chapter7.WCFDiscovery is running, start up the Chapter7.WCFFindServices project in the same manner. After a few minutes, you should find that the service is discovered and invoked as shown in Figure 7-2.
WS-Discovery is also used when services go on- and offline. WCF4 allows you to hook into this capability by subscribing to the AnnouncementService's OnlineAnnouncementReceived and OfflineAnnouncementReceived events.
3.16.48.143