Exercise 7: Discovery Proxy

All the previous exercises have relied on a well-known UDP multicast endpoint for discovery. The port and multicast address are specified by the WS-Discovery protocol documentation. The utilization of this multicast discovery is referred to as ad hoc discovery. Ad hoc discovery is limited to recognizing only services on the same subnet. Managed discovery allows you to locate services no matter where they are, as long as they are registered with a discovery proxy. In this section of the lab, you will create a discovery proxy.

The following diagram shows how a Discovery Proxy responds on behalf of the target services:

Figure 18

Discovery Proxy used in service discovery

Note:
Discovery Proxy

For more information about Discovery Proxy and WS-Discovery message exchanges, see section 3 of the WS-Discovery Specification.

Task 0 – Opening the Solution

To begin this exercise, you can use the solution you finished from Exercise 6. Alternatively, you can follow the following steps to begin with Exercise 7.

  1. Open the starting solution for Exercise 7 located under the Source\Ex7-DiscoveryProxy\Begin (choosing the folder that matches the language of your preference.) Use it as the starting point for this exercise.
  2. Press CTRL+SHIFT+B to build the solution.

Task 1 – Creating a DiscoveryProxy

The System.ServiceModel.Discovery namespace includes a base class to help you in building your Discovery Proxy. To implement your proxy you will have to override a number of methods provided by the System.ServiceModel.Discovery.DiscoveryProxy class. These methods are all asynchronous to guarantee maximum scalability for the server. For this Hands-on Lab, you will focus on supporting only Announcements in the proxy. When a chat client goes online or offline the cache of metadata will be updated. Then you will respond to find requests when a client wants to query the proxy for list of chat clients.

  1. Add a new Console Application project to the solution. To do this, in Solution Explorer right-click the Begin solution, point to Add and click New Project. Use the following settings.

    Setting

    Value

    Language

    Visual C# or Visual Basic

    Target Framework

    .NET Framework 4

    Installed Templates

    Windows

    Template

    Console Application

    Name

    ChatProxy

    Location

    Source\Ex7-DiscoveryProxy\Begin

    Figure 19

    Adding a new Console Application Project named “ChatProxy” (C#)

    Figure 20

    Adding a new Console Application Project named “ChatProxy” (Visual Basic)

  2. Console applications use the .NET Framework Client Profile by default. To build a discovery proxy you need to change the target framework of the ChatProxy project to .NET Framework 4.

    1. C#: In Solution Explorer, right-click the ChatProxy project, and select Properties. In the Application tab, change the target framework to .NET Framework 4. Visual Studio will warn you that it has to unload and reload the project before continuing.
    2. Visual Basic: In Solution Explorer, right-click the ChatProxy project and select Properties. In the Compile tab, click Advance Compile Options at the bottom and change the target framework to .NET Framework 4. Visual Studio will warn you that it has to unload and reload the project before continuing.

    Figure 21

    Change to the full .NET Framework 4 Profile (C#)

    Figure 22

    Change to the full .NET Framework 4 Profile (Visual Basic)

  3. Right-click ChatProxy project, and click Add Reference. Using the Projects tab, add a project reference to the DiscoveryChat project. Repeat these steps, using the .NET tab to add a reference to the System.ServiceModel and System.ServiceModel.Discovery libraries.
  4. Press CTRL+SHIFT+B to build the solution.
  5. Your discovery proxy will need a class to implement the proxy service. Next step is to create the ChatDiscoveryProxy class. In Solution Explorer, right-click ChatProxy project, point to Add, and then click Class. Type ChatDiscoveryProxy in the Name box.

    Figure 23

    Adding a new Class called “ChatDiscoveryProxy” (C#)

    Figure 24

    Adding a new Class called “ChatDiscoveryProxy” (Visual Basic)

  6. Add the following using directives for the new class.

    (Code Snippet - What is new in WCF4 Lab – ChatDiscoveryProxy Using Statements CSharp)

    C#

    using System.ServiceModel; using System.ServiceModel.Discovery; using System.Collections.ObjectModel; using Microsoft.Samples.Discovery.Contracts;

    (Code Snippet - What is new in WCF4 Lab – ChatDiscoveryProxy Using Statements VB)

    Visual Basic

    Imports System.ServiceModel Imports System.ServiceModel.Discovery Imports System.Collections.ObjectModel Imports Microsoft.Samples.Discovery.Contracts

  7. Make your class inherit from System.ServiceModel.Discovery.DiscoveryProxy base class.

    C#

    public class ChatDiscoveryProxy : DiscoveryProxy

    Visual Basic

    Public Class ChatDiscoveryProxy Inherits DiscoveryProxy

  8. In this lab, your class will maintain a thread-safe in-memory cache. For this reason, you need to make your WCF service instance to be a singleton. In addition, because it is thread safe and you want to guarantee maximum scalability, you will also allow multiple concurrent calls. Modify the ChatDiscoveryProxy class signature, to add the following attributes.

    (Code Snippet - What is new in WCF4 Lab – Proxy ServiceBehavior CSharp)

    C#

    [ServiceBehavior( InstanceContextMode = InstanceContextMode.Single, ConcurrencyMode = ConcurrencyMode.Multiple)]
    public class ChatDiscoveryProxy : System.ServiceModel.Discovery.DiscoveryProxy

    (Code Snippet - What is new in WCF4 Lab – Proxy ServiceBehavior VB)

    Visual Basic

    <ServiceBehavior(InstanceContextMode:=InstanceContextMode.Single, ConcurrencyMode:=ConcurrencyMode.Multiple)>
    Public Class ChatDiscoveryProxy

    Note:
    Using an in-memory cache means that if your discovery proxy host shutdowns, all information regarding services is lost. More robust implementations would use durable storage, such as a database; this will insure that service metadata is not lost even when the service is down.

  9. You will need to create a thread safe collection class to hold instances of services you have discovered. Right-click ChatProxy project, point to Add, and then click Class. Type ChatServiceCollection in the Name box.

    Note:

  10. Add the following using directives for the new class.

    C#

    using System.ServiceModel.Discovery;

    Visual Basic

    Imports System.ServiceModel.Discovery

  11. Mark your class as internal (C#) friend (Visual Basic), and make it inherit from the SynchronizedKeyedCollection base class.

    C#

    internal class ChatServiceCollection : SynchronizedKeyedCollection<Uri, EndpointDiscoveryMetadata>

    Visual Basic

    Friend Class ChatServiceCollection Inherits SynchronizedKeyedCollection(Of Uri, EndpointDiscoveryMetadata)

  12. Implement the GetKeyForItem method of the SynchronizedKeyedCollection class as shown in following code.

    (Code Snippet - What is new in WCF4 Lab – GetKeyForItem Method CSharp)

    C#

    internal class ChatServiceCollection : 
    FakePre-02c5fe395c3c403097ed5765ba1b5a49-1ff5d95530b341b5938cbaa494ca2dc3FakePre-c0170ff1450b4508bce1e4a6048c5b5b-c7c62d7b70ba4182808a896fe56ab113FakePre-7efa58c72b704812b1bf72c67f7027ff-36b2157b1af146efb8d729a0e5170c71protected override Uri GetKeyForItem(EndpointDiscoveryMetadata item) { if (item == null) { throw new ArgumentNullException("item"); } return item.Address.Uri; }FakePre-64a9fec1b55a4b94a6249a6d21b6d3e7-e7d59d4993e1414c8584fd0d1cea7d71FakePre-eea74fd06c9c4529a2fd77182948004c-93296c7ad88740cdbf9ae49a5e84922cFakePre-195168836da1491e8ecc8cb9846cde31-132e02afa9f94eabb18cfdcebaec799f

    (Code Snippet - What is new in WCF4 Lab – GetKeyForItem Method VB)

    Visual Basic

    Friend Class ChatServiceCollection
    FakePre-614e5bb3e7af48d6bab716300ab90894-2645235f671744de9be032c6fa330898FakePre-0e5c6b02fc6f4115b08a582d63d0611b-cd5ebf86cd114363b292594f323ce12a Protected Overrides Function GetKeyForItem(ByVal item As System.ServiceModel.Discovery.EndpointDiscoveryMetadata) As System.Uri If item Is Nothing Then Throw New ArgumentNullException("item") End If Return item.Address.Uri End FunctionFakePre-d6c65f2f6d6f4461b05ccfbf43838831-8f9a1731583f4c2fbc7227ccb7aa9d77FakePre-701477fa4d284bd0833bb3f6f6611ede-72f52428b7b04bc7b3e3306e72bde382

  13. Switch back to the ChatDiscoveryProxy class implementation, and add a static ChatServiceCollection property and its backing field as shown in following code.

    (Code Snippet - What is new in WCF4 Lab – ChatServiceCollection Member CSharp)

    C#

    public class ChatDiscoveryProxy : DiscoveryProxy
    FakePre-db7149daabd0425db5c2bf3de6e55745-325b24c50450493e93caba30c6a17cbb private static ChatServiceCollection cache = new ChatServiceCollection(); internal static ChatServiceCollection Cache { get { return cache; } }FakePre-761a4f01a8c742e5931e1d6683c0bae9-ed69834f83c64c2db5de89111cf608b2FakePre-1837444bc2bb4200a9a07818dbe86717-c420d11caa244186bac67f94d168f08e

    (Code Snippet - What is new in WCF4 Lab – ChatServiceCollection Member VB)

    Visual Basic

    Public Class ChatDiscoveryProxy
    FakePre-9d1ab3113cb94a6eb64d604426e7e786-0d327a3d09464beaa834a13ed606e848FakePre-6cb03125b95043b6982994b0ac6b4ebe-7fad147e71b04f1f8eb178c58201df9f Private Shared cache_Renamed As New ChatServiceCollection() Friend Shared ReadOnly Property Cache() As ChatServiceCollection Get Return cache_Renamed End Get End PropertyFakePre-0e86b8197c2d43489e63690e82aa1374-c57b1a9eba454fe4b15d3c5f839f4a46FakePre-232f50756b5f419eb6c30fee0804a99d-bcd7234048784d71b3dd44be2c526eee

  14. To complete the service, you will add several helper classes, which are already developed for simplicity. To do this, right-click the ChatProxy project, point to Add, and click Existing Item. Then, browse to the Source\Assets\ChatProxy(choosing the folder that matches the language of your preference) folder, and add the following files:
    1. AsyncResult.cs / AsyncResult.vb
    2. CompletedAsyncResult.cs / CompletedAsyncResult.vb
    3. FindAsyncResult.cs / FindAsyncResult.vb
    4. EndpointDiscoveryMetadataExtensions.cs / EndpointDiscoveryMetadataExtensions.vb
  15. When an online announcement is received, you need to determine if the service is one that you want to cache. If so, add it to your cache. Override the OnBeginOnlineAnnouncement method inside the ChatDiscoveryProxy class by adding the following code.

    (Code Snippet - What is new in WCF4 Lab – OnBeginOnlineAnnouncement Method CSharp)

    C#

    protected override IAsyncResult OnBeginOnlineAnnouncement(DiscoveryMessageSequence messageSequence, EndpointDiscoveryMetadata endpointDiscoveryMetadata, AsyncCallback callback, object state) { if (endpointDiscoveryMetadata == null) { throw new ArgumentNullException("endpointDiscoveryMetadata"); } // You care only about ISimpleChatService services FindCriteria criteria = new FindCriteria(typeof(ISimpleChatService)); if (criteria.IsMatch(endpointDiscoveryMetadata)) { endpointDiscoveryMetadata.WriteLine("Adding"); Cache.Add(endpointDiscoveryMetadata); } return new CompletedAsyncResult(callback, state); }
    FakePre-278a7c44644740718027e29ef49379dc-926b05198bc04afdab26d2e8fefb285dFakePre-1ced7b25eeed48199787edda62eaf9ee-4ec16eb203584ca8bc4231ab65bd7b6e
    

    (Code Snippet - What is new in WCF4 Lab – OnBeginOnlineAnnouncement Method VB)

    Visual Basic

    Protected Overrides Function OnBeginOnlineAnnouncement(ByVal messageSequence As DiscoveryMessageSequence, ByVal endpointDiscoveryMetadata As EndpointDiscoveryMetadata, ByVal callback As AsyncCallback, ByVal state As Object) As IAsyncResult If endpointDiscoveryMetadata Is Nothing Then Throw New ArgumentNullException("endpointDiscoveryMetadata") End If ' You care only about ISimpleChatService services Dim criteria As New FindCriteria(GetType(ISimpleChatService)) If criteria.IsMatch(endpointDiscoveryMetadata) Then endpointDiscoveryMetadata.WriteLine("Adding") Cache.Add(endpointDiscoveryMetadata) End If Return New CompletedAsyncResult(callback, state) End Function
    FakePre-b1ba108bb08043bf8af2455878fa6b9a-5199ade9826b4fe88ec8748cf521a229FakePre-c6c3233cfd4242a3a1a81c857b77d14c-44945ff0bde04697868a81507d3a4542
    

  16. When an offline announcement message is received, you want to remove the metadata from the cache if it is there. Override the OnBeginOfflineAnnouncement method by adding the following code.

    (Code Snippet - What is new in WCF4 Lab – OnBeginOfflineAnnouncement Method CSharp)

    C#

    protected override IAsyncResult OnBeginOfflineAnnouncement(DiscoveryMessageSequence messageSequence, EndpointDiscoveryMetadata endpointDiscoveryMetadata, AsyncCallback callback, object state) { try { if (endpointDiscoveryMetadata == null) { throw new ArgumentNullException("endpointDiscoveryMetadata"); } // You care only about ISimpleChatService services FindCriteria criteria = new FindCriteria(typeof(ISimpleChatService)); if (criteria.IsMatch(endpointDiscoveryMetadata)) { endpointDiscoveryMetadata.WriteLine("Removing"); Cache.Remove(endpointDiscoveryMetadata.Address.Uri); } } catch (KeyNotFoundException) { // No problem if it does not exist in the cache } return new CompletedAsyncResult(callback, state); }
    FakePre-dc5e22e0ecb94476a90eb0c471908123-0f879c7244784172b4484f7cddc5b745FakePre-bab7ebc841584c10a7a48365aadb599b-65df8624a9e3416d84af8a6335d08d76
    

    (Code Snippet - What is new in WCF4 Lab – OnBeginOfflineAnnouncement Method VB)

    Visual Basic

    Protected Overrides Function OnBeginOfflineAnnouncement(ByVal messageSequence As DiscoveryMessageSequence, ByVal endpointDiscoveryMetadata As EndpointDiscoveryMetadata, ByVal callback As AsyncCallback, ByVal state As Object) As IAsyncResult Try If endpointDiscoveryMetadata Is Nothing Then Throw New ArgumentNullException("endpointDiscoveryMetadata") End If ' You care only about ISimpleChatService services Dim criteria As New FindCriteria(GetType(ISimpleChatService)) If criteria.IsMatch(endpointDiscoveryMetadata) Then endpointDiscoveryMetadata.WriteLine("Removing") Cache.Remove(endpointDiscoveryMetadata.Address.Uri) End If Catch e1 As KeyNotFoundException ' No problem if it does not exist in the cache End Try Return New CompletedAsyncResult(callback, state) End Function
    FakePre-d345e716bd04456b935fb2cdc005595f-f773bcab5561432f94bd3770f2e4c57aFakePre-76cc695699b042e0a1ed507ecc576f04-5b09422e8ebc448694c6dbe7732f3bbb
    

  17. Now you can override the OnBeginFind method, which is called when a client issues a Discovery Find request to the proxy. Here is where you can search the cache of known service endpoints and reply to the client Find request with any matching endpoints.

    (Code Snippet - What is new in WCF4 Lab – OnBeginFind Method CSharp)

    C#

    protected override IAsyncResult OnBeginFind(FindRequestContext findRequestContext, AsyncCallback callback, object state) { if (findRequestContext == null) { throw new ArgumentNullException("findRequestContext"); } Console.WriteLine( "Find request for contract {0}", findRequestContext.Criteria.ContractTypeNames.FirstOrDefault()); // Query to find the matching endpoints var query = from service in Cache where findRequestContext.Criteria.IsMatch(service) select service; // Collection to contain the results of the query var matchingEndpoints = new Collection<EndpointDiscoveryMetadata>(); // Execute the query and add the matching endpoints foreach (EndpointDiscoveryMetadata metadata in query) { metadata.WriteLine("\tFound"); matchingEndpoints.Add(metadata); findRequestContext.AddMatchingEndpoint(metadata); } return new FindAsyncResult(matchingEndpoints, callback, state); }
    FakePre-9299a630b6ff41d09e5dc4a3b9d1f64f-a5a9ac63dfa540f19f33c1ec049be8a4FakePre-e02648a141a1433e867aa0ed578d299e-bb5840a929874f22948869f9a1cb7094FakePre-bdbf1a8676be47cb975cd27881532667-fee41cac4ae747ecbcf82ffd7c27a8dbFakePre-987199ad7689494fadba61023575e717-4848ec0f0f1249dcbea76dfbf8e97b9e
    

    (Code Snippet - What is new in WCF4 Lab – OnBeginFind Method VB)

    Visual Basic

    Protected Overrides Function OnBeginFind(ByVal findRequestContext As FindRequestContext, ByVal callback As AsyncCallback, ByVal state As Object) As IAsyncResult If findRequestContext Is Nothing Then Throw New ArgumentNullException("findRequestContext") End If Console.WriteLine("Find request for contract {0}", findRequestContext.Criteria.ContractTypeNames.FirstOrDefault()) ' Query to find the matching endpoints Dim query = From service In Cache Where findRequestContext.Criteria.IsMatch(service) Select service ' Collection to contain the results of the query Dim matchingEndpoints = New Collection(Of EndpointDiscoveryMetadata)() ' Execute the query and add the matching endpoints For Each metadata As EndpointDiscoveryMetadata In query metadata.WriteLine(Constants.vbTab & "Found") matchingEndpoints.Add(metadata) findRequestContext.AddMatchingEndpoint(metadata) Next metadata Return New FindAsyncResult(matchingEndpoints, callback, state) End Function
    FakePre-ea10a55b2eca4fa49916d272ce7df3b6-fd8e7a7ee0c5464a9f4108f77ae2b61aFakePre-d13a6ddc75fa453c9ed50bf002e9c4cf-1bc7f9b1979841b3a66ce3b6be3adce2FakePre-b44b841ab4e84e03a451e51962235f5f-a4328d66433c40d18f36cd4481ee8077FakePre-68d0c63ed08f4d6087a8a69826fa81cb-fada7c0e503848ceaf4d41204e39a7c5
    

  18. Override the OnEndFind method to complete the find operation.

    (Code Snippet - What is new in WCF4 Lab – OnEndFind Method CSharp)

    C#

    protected override void OnEndFind(IAsyncResult result) { FindAsyncResult.End(result); }

    (Code Snippet - What is new in WCF4 Lab – OnEndFind Method VB)

    Visual Basic

    Protected Overrides Sub OnEndFind(ByVal result As System.IAsyncResult) FindAsyncResult.End(result) End Sub

    Note:
    In this lab solution, the Discovery Proxy is implemented as a Console Application. Production environments would use a more robust hosting solution such as a Windows Service.

  19. Override the rest of the required methods declared abstract in System.ServiceModel.Discovery.DiscoveryProxyclass.

    (Code Snippet - What is new in WCF4 Lab – DiscoveryProxy Abstract Methods CSharp)

    C#

    protected override IAsyncResult OnBeginResolve(ResolveCriteria resolveCriteria, AsyncCallback callback, object state) { return new CompletedAsyncResult(callback, state); } protected override EndpointDiscoveryMetadata OnEndResolve(IAsyncResult result) { return CompletedAsyncResult<EndpointDiscoveryMetadata>.End(result); } protected override void OnEndOfflineAnnouncement(IAsyncResult result) { CompletedAsyncResult.End(result); } protected override void OnEndOnlineAnnouncement(IAsyncResult result) { CompletedAsyncResult.End(result); }
    FakePre-e13599bfe59247fe8df57f885497e2f4-1e409604d83847d79f71327bbdcf7da3FakePre-df37bbf6894c482689796c49db4a8559-df3dbaa508a843189a1a32b1fe804122
    

    (Code Snippet - What is new in WCF4 Lab – DiscoveryProxy Abstract Methods VB)

    Visual Basic

    Protected Overrides Function OnBeginResolve(ByVal resolveCriteria As ResolveCriteria, ByVal callback As AsyncCallback, ByVal state As Object) As IAsyncResult Return New CompletedAsyncResult(callback, state) End Function Protected Overrides Function OnEndResolve(ByVal result As IAsyncResult) As EndpointDiscoveryMetadata Return CompletedAsyncResult(Of EndpointDiscoveryMetadata).End(result) End Function Protected Overrides Sub OnEndOfflineAnnouncement(ByVal result As IAsyncResult) CompletedAsyncResult.End(result) End Sub Protected Overrides Sub OnEndOnlineAnnouncement(ByVal result As IAsyncResult) CompletedAsyncResult.End(result) End Sub
    FakePre-11f9ea0ac82842de84b04012495ad8f1-a6692efcf1fa430aaab958cacb4a7c58FakePre-e193e1a0d53a4dc489ac9439b70ed7a9-7d29d107142e4758883ccba0d2b1cc21
    

  20. Now you need to modify the Main method to create a ServiceHost for your ChatDiscoveryProxy service. To do this, open Program.cs (C#) or Module1.vb (Visual Basic) in the ChatProxy project.
  21. Add the following using directives to Program.cs (C#) or Module1.vb (Visual Basic).

    C#

    using System.Net; using System.ServiceModel; using System.ServiceModel.Discovery;

    Visual Basic

    Imports System.Net Imports System.ServiceModel Imports System.ServiceModel.Discovery

  22. For hosting the ChatDiscoveryProxy service, you will create the DiscoveryEndpoint endpoint for the service host. Add the following method inside the Program class (C#) or the Module1 module (Visual Basic).

    Note:
    Note: In this lab solution, you will be using TCP port 8001 for your proxy service.

    (Code Snippet - What is new in WCF4 Lab – HostDiscoveryEndpoint Method CSharp)

    C#

    private static ServiceHost HostDiscoveryEndpoint(string hostName) { // Create a new ServiceHost with a singleton ChatDiscovery Proxy ServiceHost myProxyHost = new ServiceHost(new ChatDiscoveryProxy()); string proxyAddress = "net.tcp://" + hostName + ":8001/discoveryproxy"; // Create the discovery endpoint DiscoveryEndpoint discoveryEndpoint = new DiscoveryEndpoint( new NetTcpBinding(), new EndpointAddress(proxyAddress)); discoveryEndpoint.IsSystemEndpoint = false; // Add UDP Annoucement endpoint myProxyHost.AddServiceEndpoint(new UdpAnnouncementEndpoint()); // Add the discovery endpoint myProxyHost.AddServiceEndpoint(discoveryEndpoint); myProxyHost.Open(); Console.WriteLine("Discovery Proxy {0}", proxyAddress); return myProxyHost; }
    FakePre-74cf1fb31dd043a89391643e4030b383-6743f62b860d44a78c925b50f5d7a1a9FakePre-7eec7656cb714d4aaad5d3797c29fc78-d17f0a27361e4bbd863aad3d3d9a5a02FakePre-3afad84733cb44f0b87d936d3138d194-8e2c38833f734002a007250f2f5214a5FakePre-d11c86ff6b7c4ac8b71bfc6208854ea3-969ed59a91a14ecfbf94f00abbf029aeFakePre-b91951f363824c47ae9159ae8d2e4fee-32509d83b2964ab3aea21013826c0ad3FakePre-947be1c1842d4832806ff718faeee839-0a76ef0212924ab9bcfa85e404d10a8e
    

    (Code Snippet - What is new in WCF4 Lab – HostDiscoveryEndpoint Method VB)

    Visual Basic

    Private Function HostDiscoveryEndpoint(ByVal hostName As String) As ServiceHost ' Create a new ServiceHost with a singleton ChatDiscovery Proxy Dim myProxyHost As New ServiceHost(New ChatDiscoveryProxy()) Dim proxyAddress As String = "net.tcp://" & hostName & ":8001/discoveryproxy" ' Create the discovery endpoint Dim discoveryEndpoint As New DiscoveryEndpoint(New NetTcpBinding(), New EndpointAddress(proxyAddress)) discoveryEndpoint.IsSystemEndpoint = False ' Add UDP Annoucement endpoint myProxyHost.AddServiceEndpoint(New UdpAnnouncementEndpoint()) ' Add the discovery endpoint myProxyHost.AddServiceEndpoint(discoveryEndpoint) myProxyHost.Open() Console.WriteLine("Discovery Proxy {0}", proxyAddress) Return myProxyHost End Function
    FakePre-0486229422cc4f64bb3394b10c74d465-dc4b5c1038944935b48f6b576523ceaaFakePre-d5b8bf008fe64b46ae1ca51ba3b8055b-346649c486a947edbf43bc0f4c02a784FakePre-5fb73f20a78f4bb7ae42f0a3b150356c-3aac02d0bd374ff0b53afb6f513d3ff0FakePre-d61744215f4145e291e73e7d41dd19fe-10d92293c5a14ceb84aff098c08d71dbFakePre-c4c8b8e994de4cd1b8257ca97a4b80c7-cdebd8ff30384771a96f270f13524cf2FakePre-e04d165d1677454eab8f88b67ac5fd95-6c8009c3d865453c9399d5b1fea8171e
    

  23. Modify the Main method as shown in the following code, to host the ChatDiscoveryProxy service.

    (Code Snippet - What is new in WCF4 Lab – DiscoveryProxy Main Method CSharp)

    C#

    static void Main(string[] args)
    FakePre-e991b5ca804a4c36b2f1abd34e51e954-e36bbf337f08476eb8b0ae28f98c9c7d Console.Title = "ChatProxy Service"; Console.WriteLine("ChatProxy Console Host"); string hostName = Dns.GetHostName(); using (ServiceHost proxyHost = HostDiscoveryEndpoint(hostName)) { Console.WriteLine("Press <Enter> to exit"); Console.ReadLine(); proxyHost.Close(); }FakePre-a2c47a795de844e299cf36942f2c55ec-075b2551d51a4c2eafeb30d70ccf36b3FakePre-3e7ccff58fd443e7a7d1b070ad7716cd-c5c7af1314884ea5a7e8ae94f9b5f014

    (Code Snippet - What is new in WCF4 Lab – DiscoveryProxy Main Method CSharp)

    C#

    Sub Main()
    Console.Title = "ChatProxy Service" Console.WriteLine("ChatProxy Console Host") Dim hostName As String = Dns.GetHostName() Using proxyHost As ServiceHost = HostDiscoveryEndpoint(hostName) Console.WriteLine("Press <Enter> to exit") Console.ReadLine() proxyHost.Close() End UsingFakePre-40dfd4ed279e4a62bdb226629707ac51-17abff80c9c0407d990ab7e28499c121FakePre-fec69a253d6244adae3da20a51051c18-86fd889381e94604b24a84c628bb95af

  24. Press CTRL+SHIFT+B to build the solution.

Task 2 – Modifying the DiscoveryChat Application to use Managed Discovery

Now that you have implemented a discovery proxy, you need to modify the chat application to make use of it.

  1. Open the SimpleChat form in code view from the DiscoveryChat project. You can open the code view by selecting the file and pressing F7.
  2. Locate the ManagedDiscovery method. The UI is already calling this method if the Managed Discovery radio button is checked. As you have already implemented the handlers for ad hoc discovery, the only thing pending is to add code to implement this managed discovery as shown in the following code.

    (Code Snippet - What is new in WCF4 Lab – ManagedDiscovery Method CSharp)

    C#

    private void ManagedDiscovery()
    FakePre-12bc1eb665f64a2eac85b000f94bd13a-ebf37bc5da7144c6bb58904e8d02cc47 try { // Create an endpoint for the proxy DiscoveryEndpoint proxyEndpoint = new DiscoveryEndpoint( new NetTcpBinding(), new EndpointAddress(proxyAddressText.Text)); // Create the DiscoveryClient with a proxy endpoint // for managed discovery this.discoveryClient = new DiscoveryClient(proxyEndpoint); // Same handlers as ad hoc discovery this.discoveryClient.FindCompleted += new EventHandler<FindCompletedEventArgs>(this.OnFindCompleted); this.discoveryClient.FindProgressChanged += new EventHandler<FindProgressChangedEventArgs>(this.OnFindProgressChanged); // Setup the form for discovery this.ShowDiscoveryInProgress(true); this.discoveryClient.FindAsync(new FindCriteria(typeof(ISimpleChatService))); } catch (UriFormatException) { MessageBox.Show( Resources.InvalidUriMessage, this.Text, MessageBoxButtons.OK, MessageBoxIcon.Information, MessageBoxDefaultButton.Button1, (MessageBoxOptions)0); }FakePre-3a11b2c9d961460987ab75f2f666f137-d279b4fba74b45b2a659e1cb767849afFakePre-3b38a10027dd4c27a203b144706d3ad3-cd7b8e8460e54466ac3184d863ce8b50FakePre-1a1e17154faf4b778d39263935c38f33-87978d6b586f4755a22aad591016f49dFakePre-79f78e4ef3a14e33b2e819f6d4b53d50-cbb3332138404c89be0a74dc430f7de4FakePre-3c6028893c8345618accda41d702e410-686fef43cd3b49a2b42348f4c2152e63

    (Code Snippet - What is new in WCF4 Lab – ManagedDiscovery Method VB)

    Visual Basic

    Private Sub ManagedDiscovery()
    Try ' Create an endpoint for the proxy Dim proxyEndpoint As New DiscoveryEndpoint(New NetTcpBinding(), New EndpointAddress(proxyAddressText.Text)) ' Create the DiscoveryClient with a proxy endpoint ' for managed discovery Me._discoveryClient = New DiscoveryClient(proxyEndpoint) ' Same handlers as ad hoc discovery AddHandler _discoveryClient.FindCompleted, AddressOf OnFindCompleted AddHandler _discoveryClient.FindProgressChanged, AddressOf OnFindProgressChanged ' Setup the form for discovery Me.ShowDiscoveryInProgress(True) Me._discoveryClient.FindAsync(New FindCriteria(GetType(ISimpleChatService))) Catch e1 As UriFormatException MessageBox.Show(My.Resources.InvalidUriMessage, Me.Text, MessageBoxButtons.OK, MessageBoxIcon.Information, MessageBoxDefaultButton.Button1, CType(0, MessageBoxOptions)) End TryFakePre-226e84cd369f4aa184cf824bc0038dc5-08ede53f76564d86b47563bbc8b7b49cFakePre-ebb7690c669a41ad87ab2bd0de4422b8-ef2476208d6d4382a7fdd46ad1211289FakePre-01dbcab6220149f48468ed9bb2a33d53-a066db5a2d804223a9b4b7f84f5fd58cFakePre-341f3716dc7d496ca90f747a3f25ef79-d003098069bd4ae58aae79f52db93e9dFakePre-0840d1722fa2447db8f6afe0b7af7ed2-7278ae3cd085457cab9253f3a33f08f4

  3. Locate the InitializeManagedDiscovery method, and set the managed radio button Checked property to True.

    C#

    private void InitializeManagedDiscovery()
    FakePre-775994c1dee548e995f0622bee53265b-cda0aedda55741eeb34a63fa786da155 this.managedRadioButton.Checked = true;FakePre-139919427fc14ff7a823bc455670dfdf-81f76fa096214a4ca067b6bfac8e3720

    Visual Basic

    Private Sub InitializeManagedDiscovery()
    Me.managedRadioButton.Checked = TrueFakePre-a8ba3ea70694486fb164b9a54eb7f972-bccbac8d3e744908be763483d86d2689

  4. Press CTRL+SHIFT+B to build the solution.

Next Step

Exercise 7: Verification