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
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.
- 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.
- 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.
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.
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)
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.
- 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.
- 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)
- 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.
- Press CTRL+SHIFT+B to build the solution.
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)
Add the following using directives for the new class.
(Code Snippet - What is new in WCF4 Lab – ChatDiscoveryProxy Using Statements CSharp)
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)
Imports System.ServiceModel Imports System.ServiceModel.Discovery Imports System.Collections.ObjectModel Imports Microsoft.Samples.Discovery.Contracts
Make your class inherit from System.ServiceModel.Discovery.DiscoveryProxy base class.
public class ChatDiscoveryProxy : DiscoveryProxy
Public Class ChatDiscoveryProxy Inherits DiscoveryProxy
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)
[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)
<ServiceBehavior(InstanceContextMode:=InstanceContextMode.Single, ConcurrencyMode:=ConcurrencyMode.Multiple)> Public Class ChatDiscoveryProxy
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.
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.
Add the following using directives for the new class.
using System.ServiceModel.Discovery;
Imports System.ServiceModel.Discovery
Mark your class as internal (C#) friend (Visual Basic), and make it inherit from the SynchronizedKeyedCollection base class.
internal class ChatServiceCollection : SynchronizedKeyedCollection<Uri, EndpointDiscoveryMetadata>
Friend Class ChatServiceCollection Inherits SynchronizedKeyedCollection(Of Uri, EndpointDiscoveryMetadata)
Implement the GetKeyForItem method of the SynchronizedKeyedCollection class as shown in following code.
(Code Snippet - What is new in WCF4 Lab – GetKeyForItem Method CSharp)
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)
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
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)
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)
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
- 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:
- AsyncResult.cs / AsyncResult.vb
- CompletedAsyncResult.cs / CompletedAsyncResult.vb
- FindAsyncResult.cs / FindAsyncResult.vb
- EndpointDiscoveryMetadataExtensions.cs / EndpointDiscoveryMetadataExtensions.vb
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)
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)
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
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)
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)
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
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)
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)
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
Override the OnEndFind method to complete the find operation.
(Code Snippet - What is new in WCF4 Lab – OnEndFind Method CSharp)
protected override void OnEndFind(IAsyncResult result) { FindAsyncResult.End(result); }
(Code Snippet - What is new in WCF4 Lab – OnEndFind Method VB)
Protected Overrides Sub OnEndFind(ByVal result As System.IAsyncResult) FindAsyncResult.End(result) End Sub
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.
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)
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)
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
- 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.
Add the following using directives to Program.cs (C#) or Module1.vb (Visual Basic).
using System.Net; using System.ServiceModel; using System.ServiceModel.Discovery;
Imports System.Net Imports System.ServiceModel Imports System.ServiceModel.Discovery
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: 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)
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)
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
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)
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)
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
- 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.
- Open the SimpleChat form in code view from the DiscoveryChat project. You can open the code view by selecting the file and pressing F7.
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)
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)
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
Locate the InitializeManagedDiscovery method, and set the managed radio button Checked property to True.
private void InitializeManagedDiscovery()
FakePre-775994c1dee548e995f0622bee53265b-cda0aedda55741eeb34a63fa786da155 this.managedRadioButton.Checked = true;FakePre-139919427fc14ff7a823bc455670dfdf-81f76fa096214a4ca067b6bfac8e3720
Private Sub InitializeManagedDiscovery()
Me.managedRadioButton.Checked = TrueFakePre-a8ba3ea70694486fb164b9a54eb7f972-bccbac8d3e744908be763483d86d2689
- Press CTRL+SHIFT+B to build the solution.
Next Step
Exercise 7: Verification
|
|