Share your Mesh data with Contacts

Now to one of the most powerful items in the Mesh: ability to share the data between anyone with a live passport.

So if you have been following the past few entries I have been working through the MeshageBoard Walkthrough, and the final part is to allow your friends to post on your message boards too.

First off from where we left off we had the ability to post messages to a meshage board and view all messages which were posted.

We first want to have a way to list our contacts, so in the class library add a new class called Contacts.

Add the usual using statements:

 using Microsoft.LiveFX.Client;
using Microsoft.LiveFX.ResourceModel;

using System.Collections.ObjectModel;

Add the public and static modifiers to the class:

 public static class Contacts

And add a method to return an ObservableCollection of ContactResource called ReadAll:

 public static ObservableCollection<ContactResource> ReadAll(LiveOperatingEnvironment env)
{
   if (!env.Contacts.IsLoaded)
   {
      env.Contacts.Load();
   }
   ObservableCollection<ContactResource> contacts = new ObservableCollection<ContactResource>();
   foreach (Contact contact in env.Contacts.Entries)
   {
      contacts.Add(contact.Resource);
   }
   return contacts;
}

This will simply iterate through the entries and return the collection.

Next we want a class to manage our contacts, invite, add to the mesh etc.

Create a new Class in the class library called MeshageBoardMembers.  Add the usual using statements:

 using Microsoft.LiveFX.Client;
using Microsoft.LiveFX.ResourceModel;

using System.Collections.ObjectModel;

Add the public and static modifiers to the class:

 public static class MeshageBoardMembers

Then add the methods to add Members and send an invitation Email:

Firstly we’ll want to get the users Email address from the Contact list in the Live Operating Environment (note that Contact and Profiles are unavailable in the Local Mesh, so you’ll need to be connected to the cloud for this).

 private static string GetMemberEmail(LiveOperatingEnvironment env, string MemberName)
{
   if (!env.Contacts.IsLoaded)
   {
      env.Contacts.Load();
   }
   Contact contact = (from i in env.Contacts.Entries
                  where string.Equals(i.Resource.FormattedName, MemberName)
                  select i).FirstOrDefault<Contact>();
   if (String.IsNullOrEmpty(contact.Resource.Emails[0].Value))
   {
      throw new Exception(MemberName + " does not seem to have a valid email address.");
   }
   return contact.Resource.Emails[0].Value;
}

Again this uses a nice LINQ query to find the data.

Now we can access our friend’s email address, we want to send an invitation… The Resource Model is nice in that it gives an Invitation class which will do all the legwork for you:

 private static void AddMemberAndSendInvitation(LiveOperatingEnvironment env, MeshObject messageBoard, string BoardTitle, string InvitationText, string MemberName)
{
   MemberResource pendingMemberResouce = new MemberResource();
   pendingMemberResouce.Title = MemberName;
   string newMemberEmail = GetMemberEmail(env, MemberName);
   pendingMemberResouce.Email = newMemberEmail;
   pendingMemberResouce.Role = RoleType.Full;
   Invitation invitation = new Invitation();
   invitation.Email = newMemberEmail;
   DateTimeOffset expires = DateTimeOffset.UtcNow.Add(new TimeSpan(4 * 24, 0, 0));
   invitation.Expires = expires;
   Member member = new Member(pendingMemberResouce);
   member.Resource.PendingInvitation = invitation;
   if (!messageBoard.Members.IsLoaded)
   {
      messageBoard.Members.Load();
   }
   messageBoard.Members.Add(ref member);
   messageBoard.Update();
}

Finally we want a way to call this from our program, so use this method to make it visible:

 public static void AddMembers(LiveOperatingEnvironment env, string BoardTitle, 
   string InvitationText, List<String> Members)
{
   MeshObject messageBoard = MeshageBoard.GetMeshageBoardMeshObject(env, BoardTitle);
   if (messageBoard == null)
   {
      throw new Exception("Mesh Object can not be null");
   }
   foreach (string member in Members)
   {
      AddMemberAndSendInvitation(env, messageBoard, BoardTitle, InvitationText, member);
   }
}

Back in our program we need to implement the InviteMembers method in HandleUserInput.  We want the user to select which board to invite the contact to (already implemented as UserSelectionBoard), select the contact using the following method:

 private static string UserSelectionMember()
{
   ObservableCollection<ContactResource> contactList = Contacts.ReadAll(env);
Selection:
   // List members (similar to how we list boards)
   int i = 0;
   Console.WriteLine("#\tDisplay Name\tLiveId");
   foreach (ContactResource res in contactList)
   {
      Console.WriteLine(i + ":\t" + res.DisplayName + "\t" + res.WindowsLiveId);
      i++;
   }
   string selectedMember = null;
   try
   {
      int intMemberNum = Int32.Parse(Console.ReadLine());
      selectedMember = contactList[intMemberNum].FormattedName;
   }
   catch (FormatException)
   {
      Console.Write("Please make your selection using the numbers proceeding the title\r\n\r\nTry Again (y/n)?\r\n>");
      string yesOrNo = Console.ReadLine();
      if (yesOrNo.ToLower() == "y")
      {
         goto Selection;
      }
      else
      {
         return null;
      }
   }
   catch (ArgumentOutOfRangeException)
   {
      Console.Write("Please select a number from the range given\r\n\r\nTry Again (y/n)?\r\n>");
      string yesOrNo = Console.ReadLine();
      if (yesOrNo.ToLower() == "y")
      {
         goto Selection;
      }
      else
      {
         return null;
      }
   }
   return selectedMember;
}

Then call the class library to add the member:

 public static void InviteMembers()
{
   string selectedTitle = UserSelectionBoard();
   Console.WriteLine(selectedTitle + " was selected. Now select a member to add.");
   
   string selectedMember = UserSelectionMember();
   if (selectedMember != null)
   {
      List<string> nameList = new List<string>();
      nameList.Add(selectedMember);
      string invitationText = env.Mesh.ProvisionedUser.Name + " has invited you to participated in a MeshageBoard!";
      try
      {
         MeshageBoardMembers.AddMembers(env, selectedTitle, invitationText, nameList);
      }
      catch (Exception ex)
      {
         Console.WriteLine(ex.Message);
         return;
      }
      Console.WriteLine(selectedMember + " has been added to " + selectedTitle);
   }
}

And that’s it.  An email will be sent to the contact to accept, and you can start sharing your MeshageBoards.  Obviously this is a bit harder with a rich client application as they will need an equivalent, but if you make a silvelight shell for this and deploy it as a mesh-enabled application onto Windows Azure, you will instantly be able to communicate via meshage boards.

The code for these posts is available here

MeshageBoard.zip