Tuesday, December 4, 2012

Metadata Extensions

From last article Ad hoc Discovery . When YallaTech discovered other chat instances all we knew about them was the Uri of the service endpoint. So her chat window shows a chat with the host machine name. besho, on the other hand, knew that the chat message came from YallaTech because the chat message included her name. In this article we will learn how we can extend the metadata used in WS-Discovery to supply additional information (such as the username used for the chat session).




  1. Open the starting solution Begin.sln from last article Ad hoc Discovery
       Watch Out
    Visual Studio 2010 must be run in elevated mode. To do this, right-click the Visual Studio 2010 icon and select Run as Administrator.
  2. Open the SimpleChat.cs (C#) or SimpleChat.vb (Visual Basic) file from the DiscoveryChat project. We can open the code view by selecting the file and pressing F7.
  3. We can add XML to the endpoint metadata when responding to a discovery probe. To do this, we will need to add namespaces directives, in particular the System.ServiceModel.Description namespace.
    C#
    using System.Linq;
    using System.Xml.Linq;
    using System.ServiceModel.Description;
    Visual Basic
    Imports System.ServiceModel.Description
  4.  Locate the OpenServices method and modify it as shown in the following code.
    C#
    private void OpenServices()
    {
        // Create a singleton instance for the host
        ChatService chatService = new ChatService(this);
        chatServiceHost = new ServiceHost(chatService, _localAddress);

        // Create a discovery behavior
        var endpointDiscoveryBehavior = new EndpointDiscoveryBehavior();

        // Add an extension element with the username
        endpointDiscoveryBehavior.Extensions.Add(
            new XElement(
                "root",
                new XElement("Name", this.userName)));

        // Find the endpoint
        ServiceEndpoint simpleEndpoint =
            this.chatServiceHost.Description.Endpoints.Find(typeof(ISimpleChatService));

        // Add our behavior to the endpoint before opening it
        simpleEndpoint.Behaviors.Add(endpointDiscoveryBehavior);

        ShowStatus("Opening chat service...");
        chatServiceHost.BeginOpen(
            (result) =>
            {
                chatServiceHost.EndOpen(result);
                ShowStatus("Chat service ready");
            },
            null);
    }
    Visual Basic
    Private Sub OpenServices()
        ' Create a singleton instance for the host
        Dim chatService As New ChatService(Me)
        Me.chatServiceHost = New ServiceHost(chatService, Me._localAddress)

        ' Create a discovery behavior
        Dim endpointDiscoveryBehavior As New EndpointDiscoveryBehavior()

        ' Add an extension element with the username
        endpointDiscoveryBehavior.Extensions.Add(<root><Name><%= Me.UserName %></Name></root>)

        ' Find the endpoint
        Dim simpleEndpoint = Me.chatServiceHost.Description.Endpoints.Find(GetType(ISimpleChatService))

        ' Add our behavior to the endpoint before opening it
        simpleEndpoint.Behaviors.Add(endpointDiscoveryBehavior)

        Me.ShowStatus("Opening chat service...")
        Me.chatServiceHost.BeginOpen(Sub(result)
                                         chatServiceHost.EndOpen(result)
                                         Me.ShowStatus("Chat service ready")
                                     End Sub, Nothing)
    End Sub
    Note: (For Visual Basic users) The above code snippet uses implicit typing. You will need to set Option Infer On in the VB file or set Option Infer at the project level.
  5. Next we need to add code to look for this metadata when doing discovery of other services.  Add the GetPeerName method which returns the first node named “Name” from the extension metadata right after the OpenServices method.
    C#
    private static string GetPeerName(EndpointDiscoveryMetadata metadata)
    {
        XElement peerNameElement =
            metadata.Extensions.Elements("Name").FirstOrDefault();

        if (peerNameElement != null)
            return peerNameElement.Value;

        return null;
    }
    Visual Basic
    Private Shared Function GetPeerName(ByVal metadata As EndpointDiscoveryMetadata) As String
        Dim peerNameElement = metadata.Extensions.

        If peerNameElement IsNot Nothing Then Return peerNameElement.Value

        Return Nothing
    End Function
  6. Now that the name is discoverable as well as the service endpoint, we need to modify the PopulateUserList method to invoke the GetPeerName method. If the name node exists, the PeerUser class will use it as the display name in the list box. To do this, replace the current call to the AddUser method with the following one.
    C#
    private void PopulateUserList(
        EndpointDiscoveryMetadata endpointDiscoveryMetadata)
    {
        if (!EndpointIsSelf(endpointDiscoveryMetadata.Address.Uri))
        {
            this.AddUser(new PeerUser(GetPeerName(endpointDiscoveryMetadata), endpointDiscoveryMetadata.Address));
            this.EnableUsersBox();
        }
    }

    Visual Basic
    Private Sub PopulateUserList(
                    ByVal endpointDiscoveryMetadata As EndpointDiscoveryMetadata)
        If Not Me.EndpointIsSelf(endpointDiscoveryMetadata.Address.Uri) Then
            Me.AddUser(New PeerUser(GetPeerName(endpointDiscoveryMetadata), endpointDiscoveryMetadata.Address))
            Me.EnableUsersBox()
        End If
    End Sub
  7. Press Ctrl+Shift+B to build the solution.
  8. Press Ctrl+F5 to start an instance of the DiscoveryChat application without debugging.
  9. Switch back to Visual Studio and press Ctrl+F5 again to launch another instance of the application.
  10. Switch to one of the instances of DiscoveryChat.exe and setup the chat as follows:
    a. 
    User Name: YallaTech
    b. 
    Click Sign In
  11. Switch to the other DiscoveryChat.exe instance and setup the chat as follows:
    a. 
    Username: Besho
    b. Click Sign In 
  12. Besho's chat window will discover YallaTech’s after signing in.  Switch to YallaTech’s chat window and click on the Discover Users button to find Besho
  13. We should see the other instance’s username appear in the Available Users pane. You can double-click on it to start a chat.
    Extensions allow us to send the username in discovery metadata
    Extensions allow us to send the username in discovery metadata
    1. Close both instances of the DiscoveryChat application


    No comments:

    Post a Comment

    YallaTech Facebook page