Enable your applications for Windows Azure CTP - Live
Mesh
Using the Live Framework
Article written by Peter Himschoot,
Lieven Iliano and Wim Uyttersprot.
Abstract
Live Mesh, which is part of the Windows Azure CTP,
allows you to share data with your devices and others. In this article you
will learn about Mesh and how to enable your application for Mesh. As an
example we will add Mesh support to the U2U Email Snippets for Outlook 2007
plug-in, which can be found here:
http://www.u2u.be/res/Tools/EMailSnippets.aspx
What is Live Mesh?
In today’s digital lifestyle we all have
several devices connected to the internet. Live Mesh is Microsoft’s solution to
synchronize files and other data between all your devices and contacts. For
example: if you take a picture with your mobile phone, you can use Mesh to sync
all pictures automatically to your portable, or to one of your friend’s desktop
PC. So with Mesh you can synchronize folders and files between devices and
users. In the future we can imagine most of your digital devices will connect
to the internet, such as your digital camera, GPS, etc… If you’d like to know
what has happened to your data, you can subscribe to notifications. And if you
need some data from one of your other devices, you can use Live Mesh to connect
to the desktop of this device and access it as if you were sitting in front of
it. And even when you don’t have access to one of your devices, you can access
your data on the internet because Live Mesh also keeps data synchronized with www.mesh.com. All you need is a Microsoft Live
ID. Live Mesh tackles complex problems like synchronization, authentication and
authorization…
Mesh Enabling your application
In the Windows Azure CTP Mesh can be extended by either
building a web site that uses Mesh (and can be used as part of the Mesh
desktop), or you can add Mesh capabilities to an existing application. In this
case the Mesh desktop will normally not display your data, but you can always
build a Silverlight application to show your data on the Mesh desktop. In this
article we will extend an existing application: the U2U Email Snippets for
Outlook 2007 plug-in. To do this we need to use the Live Framework.
What is the Live Framework?
The Microsoft Live Framework is the way to
program against Mesh, from any platform, programming language, application and
device. Currently in CTP, it provides us with a simple and uniform programming
model to talk to Mesh using REST (and AtomPub). To use it, you will first need
to have access to a developer token, which you can apply for at http://dev.live.com/liveframework/sdk/.
Once you have your token you can download the API and the Mesh client. The
API’s come with a number of flavors, like .NET, JavaScript, etc… If your flavor
isn’t available you still can use ‘bare’ REST to talk to Mesh, so you’re not
limited to any technology, as long as it can use HTTP and XML.
For simplicity we’ll be using the .NET
libraries to talk to Mesh.
The Live Framework also includes a Mesh
client, which is required if you want Mesh to synchronize to your local
machine. For the current CTP it is only available for Windows, but in the
future you’ll be able to use it for Mobile devices, Apple computers, and so on.
In this case you can work offline and go to http://localhost:2048.
The Mesh Client will also install a Windows
Service called MOE. This service takes care of synchronization with the cloud
and other devices. So once you’re online again MOE will synchronize
automatically. You can choose which folders and files to share with your
devices and other Mesh users.
Adding Mesh Capabilities to the U2U Email Snippets for
Outlook 2007
In this article we want to show you how to
Mesh enable your application. By enabling Mesh your application gets the
advantages that you can easily share data on several of your devices, or with
other people, without having to build and deploy your own services on the Web.
You don't need to worry about authentication, security, etc... As an example we
have added Mesh capabilities to our U2U Email Snippets for Outlook 2007. With this add-in you can save your email
message, or a part of the message, as a snippet. When composing a new email
message you can reuse this ready-made snippet by inserting it in your new email
message.

Here you see the Outlook editor with the
Email Snippets pane enabled. To the right you see a bunch of snippets, which
you can drag and drop to your email, inserting standard clauses quite easily.
This utility can store these snippets in a
SharePoint list, or in Outlook folders, or in a SQL Server database. By
clicking on the Settings link you can choose which provider you’d like:

In this article we’re going to look at how
you can store these snippets in Mesh, and its advantages.
Live Framework Resource Browser
While developing with Mesh and the Live
Framework SDK you will want to see the result of what you’ve done on Mesh. For
this, Microsoft built a tool that allows you to browse Mesh in the cloud and
locally. It’s the Live Framework Resource Browser and you will find it in the
Tools directory of where you installed the SDK.

With this tool you can look at all the
objects stored in the Live Operating Environment. For example if you click on
Devices you can see the list of all your devices stored in Mesh. This tool is
very handy for debugging and we will use it to illustrate some of the
things we need to do.
Creating the Mesh Provider
The U2U Email snippets for Outlook has a
plug-in model where you basically need to create a couple of classes. The main
classes are a connection, a snippet service and some UI. Let’s start with the
snippet service. This class need to inherit from SnippetService, a class with a
number of abstract methods like GetSnippetsFromStoreList, CreateSnippet,
UpdateSnippet, etc… You get the idea.
Live Mesh’s single point of contact is
represented through the LiveOperatingEnvironment (LOE) class. You use
this class to access your Mesh objects, contacts, etc… The LOE gives us a
common way for storing data, will synchronize this data for us on devices and
in the cloud, and uses a very simple common programming model using HTTP. Each
object stored in the LOE is accessible through its id, which is an Uri.
Through it we first authenticate and then
use Mesh. For example:
LiveOperatingEnvironment env = new LiveOperatingEnvironment();
LiveItemAccessOptions accessOptions = new LiveItemAccessOptions(true);
try
{
String
token = new NetworkCredential(Username,
Password, Environment)
.GetWindowsLiveAuthenticationToken();
Uri
environmentUri = new Uri(Environment);
env.Connect(token, AuthenticationTokenType.UserToken,
environmentUri, accessOptions);
}
catch
{
env.ConnectLocal(accessOptions);
}
In this code example, we first create an
instance of the LiveOperatingEnvironment class. When we connect we need
to pass it a LiveItemAccessOptions instance, which we also create. This
is used to automatically load relations, and whether or not we want to receive
notifications.
Next we need an authentication token, which
we can create using a NetworkCredential instance and GetWindowsLiveAuthenticationToken
extension method. We also need the Uri to the Mesh environment, which is
currently https://user-ctp.windows.net/.
We’ve wrapped this code in a try catch
block in case there is no network access. In that case we connect to the local
environment using the ConnectLocal method. This method doesn’t require
credentials because the user should authenticate through the Mesh client.

Figure 1: The
Mesh object model
Because later on
Microsoft could add more features to the LiveOperatingEnvironment Mesh
is just one part of the LOE.
For example, you can use the LOE to access
all your contacts which we will discuss next.
Inviting contacts
Mesh also makes it very easy to synchronize MeshObjects with other users of Mesh. For this we have an “Invite members to
this list…” which opens the Invite Members dialog:

You can type any contact’s e-mail address
here, but to simplify things we also add a contacts dialog, showing all your
contacts from Windows Live:

Contacts in the list have been blurred for
privacy reasons…
Getting the list of contacts from the
Live Operating Environment is very easy:
public class MeshContact
{
public string DisplayName { get; set; }
public string Email { get; set; }
public static List<MeshContact> GetListOfContactsFromMesh(
LiveOperatingEnvironment env )
{
if (env == null)
throw new ArgumentNullException(
"LiveOperatingEnvironment
is required");
// Ensure contacts
have been loaded
if (!env.Contacts.IsLoaded)
env.Contacts.Load();
// Get all
contacts
var contactsQuery = from contact in
env.CreateQuery<Contact>()
select contact;
// Convert these
contacts to MeshContacts
List<MeshContact> contactsList = new List<MeshContact>();
foreach (var contact in
contactsQuery.ToList())
{
if (contact.Resource.Emails.Count > 0)
{
string name =
contact.Resource.FormattedName;
string email =
contact.Resource.Emails[0].Value;
if (string.IsNullOrEmpty(name))
name = email;
contactsList.Add(new MeshContact()
{
DisplayName = name,
Email = email
});
}
}
return contactsList;
}
}
The GetListOfContactsFromMesh method
first does a couple of checks, for example if the Contacts have been loaded. If
not, it explicitly does the Load. Then we create a query with LINQ to search for all
contacts:
var
contactsQuery = from contact in env.CreateQuery<Contact>()
select
contact;
Then we execute the query and convert each
Contact into a MeshContact (our own type). The query itself is interesting,
because it uses LINQ syntax, which is converted by the Live Framework into an
appropriate REST call (similar to how a LINQ to SQL query is converted into
SQL). This call then executes the query on the server side, which is very
efficient.
Using Collections vs. Queries
In the part where we retrieve the list of
contacts, we used a query with the CreateQuery<T> method. In this case we
didn’t really need a query because we retrieve all contacts anyway. We could
have retrieved contacts using the Contacts.Entries collection. So what is the
difference? In Live Mesh queries are executed server side, so if there are a
lot on entries, a server side query will limit the number of objects sent over
the wire. Using the collection we will do a client-side query, requiring Mesh
to send over all objects. So, when possible, we would advise using queries.
Storing Data: Mesh Objects, Data Feeds and Data Entries
Live Mesh stores its folders and files as
MeshObject instances, and so can you. Actually, each MeshObject is identified
through a hyperlink (as an Uri), has data stored as a resource and describes
relationships to other resources. Because relations are represented through
hyperlinks, we can directly access these relationships without going through
the base object, but most of the time we will do this as it is simpler. All
other objects in Mesh follow this same pattern, except the data is stored in
another resource type. MeshObjects are used as the root for synchronization between
devices and the cloud and for sharing with other users.
Each Mesh object has a number of data
feeds, and each data feed contains a number of data entries.

Where the MeshObject level is used to
define sharing and mapping to devices, the DataFeed is used for synchronization
and security. Each DataFeed has security set on it, and will be used to notify
your application when synchronization collisions occur. DataEntries are used to
keep track of data.
For example, on Mesh each Folder is
represented as a MeshObject, and that is why we can share and map each folder
individually. Each Folder MeshObject contains a single DataFeed, and each file
in this folder is represented as a DataEntry. When Mesh synchronizes a folder
on two devices, any collisions will be at the data entry level, and should
normally be resolved automatically through Mesh. This synchronization mechanism
will not be explained in this article.
Each of these objects wraps a resource,
which is a collection of properties. For example a DataFeed instance has a
DataFeedResource instance containing properties like the DataEntriesLink
(a collection of Uri’s to link to the data entries). A data entry can store any
data you want, and it has special methods to make it really easy to do. For
example, any class that is a Windows Communication Foundation DataContract
can be stored like this:
DataFeed list = …
DataEntry de = new DataEntry(snippet.Title);
snippet.Id = LastId;
de.Resource.Title = snippet.Id.ToString();
de.Resource.Type = MeshTypes.Snippet;
de.Resource.SetUserData<EmailSnippet>(snippet);
list.DataEntries.Add(ref de);
For example, the DataContract used here looks
like:
[DataContract(Name
= "snippet", Namespace = "urn://www.u2u.be")]
public class EmailSnippet
{
[DataMember(Name
= "text", Order = 0)]
public string Text
{
get;
set;
}
…
}
To store some data which is a data
contract, we first create a DataEntry instance. To keep track of what is
in the data entry we can set the Title and Type properties of the DataEntryResource.
The Title and Type can then be used to find all snippets using a query. And then to serialize the data itself,
we use the SetUserData generic method.
To retrieve the data we first look for all
the wanted data entries using a query (using the CreateQuery method),
and then use the GetUserData method to deserialize the object:
DataFeed list = …
var
query = from de in
list.CreateQuery<DataEntry>()
where
de.Resource.Type == MeshTypes.Snippet
select
de;
foreach (var de in
query)
{
EmailSnippet
snippet = de.Resource.GetUserData<EmailSnippet>();
result.Add(snippet);
}
Creating Snippet Lists
But how can we store our snippets in Mesh?
Snippets are grouped into SnippetLists, and we decided to store these in a
single MeshObject. MeshObjects can be synchronized to any device and shared
between users, ideal since this is what we want to do with SnippetLists. Each
SnippetList has a number of snippets, and we’ve decided to store this in a
single DataFeed, and make each snippet a DataEntry.

When you create a MeshObject you can
specify a title and a type, and this is ideal to separate our MeshObject from
anyone else’s. So the code to create a SnippetList:
public override void
CreateSnippetList<T>(string listName, out T createdList)
{
MeshObject
newList = new MeshObject(listName);
newList.Resource.Type = MeshTypes.Root;
newList.Resource.Title = listName;
Mesh.MeshObjects.Add(ref
newList);
Connection.SnippetListName = listName;
Connection.SnippetListId =
new Guid(newList.Resource.Id.ToGuid().ToString());
// Each MeshObject
requires at least one DataFeed
DataFeed
list = new DataFeed(Snippets.DefaultList);
list.Resource.Type = MeshTypes.List;
list.Resource.Title =
Connection.SnippetListName;
newList.DataFeeds.Add(ref
list);
createdList = (T)(object)new MeshSnippetList()
{
Title = listName,
Id =
newList.Resource.Id.ToGuid()
};
}
In our method we first create a new
MeshObject and set its Type and Title. Then we add it to Mesh, simply by adding
to a collection. The .NET API’s will create our MeshObject using REST but this
is an implementation detail.
The Snippet plugin also uses the concept of
a Connection, and when we create a new list we make it the default list by
storing its name in the connection. We also store its ID which is easily
converted from the GUID uses as the id in Mesh.
Each MeshObject can have a number of
DataFeed instances, and we need one. So we create a DataFeed instance and add
it to our MeshObject DataFeeds collection. Again this is very simple with the
API’s.
Finally we return an empty MeshSnippetList
object because this is required by the snippet plugin.
Devices
Live Mesh can synchronize any data to any
device, but you need to install the local client. Mesh keeps track of all of
your registered devices in the Device Ring, which you can see here:
In this case you see my mobile and my
portable. The mobile phone has the Mesh local client installed while my
portable doesn’t. If you want to install the local client, simply click on Add
Device:

This will make your device available in the
Devices collection. For each device you can discover its name, if it is the
local device, if it is connected, etc…
However, creating a MeshObject and MeshDevice
is not enough to automatically synchronize it to your device. You need to
create a mapping to do this, which is a special kind of relation. So to
understand mappings we first need to understand relations:
Setting up relations
Every object in Mesh has an Uri as its
unique identifier. Relations use these Uri’s to represent a relation from one
object to another. For example, using the Live Framework Resource Browser you can
look at one of the Mesh objects:
<entry>
<id>urn:uuid:7c2365c6-657c-4108-9b1f-74139f95d371</id>
<title
type="text">EmailSnippets</title>
<published>2009-01-05T22:11:49Z</published>
<updated>2009-01-05T22:11:49Z</updated>
<author>
<name>U2U Trainer</name>
</author>
<link rel="LiveFX/DataFeeds"
title="LiveFX/DataFeeds"
href="Mesh/MeshObjects/YZSSG7D4MUEEDGY7OQJZ7FOTOE/DataFeeds"
/>
<link rel="LiveFX/Members"
title="LiveFX/Members"
href="Mesh/MeshObjects/YZSSG7D4MUEEDGY7OQJZ7FOTOE/Members"
/>
<link rel="LiveFX/Mappings"
title="LiveFX/Mappings"
href="Mesh/MeshObjects/YZSSG7D4MUEEDGY7OQJZ7FOTOE/Mappings"
/>
<link rel="LiveFX/Activities"
title="LiveFX/Activities"
href="Mesh/MeshObjects/YZSSG7D4MUEEDGY7OQJZ7FOTOE/Activities"
/>
<link rel="LiveFX/NewsItems"
title="LiveFX/NewsItems"
href="Mesh/MeshObjects/YZSSG7D4MUEEDGY7OQJZ7FOTOE/News"
/>
<link rel="LiveFX/Subscription"
title="LiveFX/Subscription"
href="Mesh/MeshObjects/YZSSG7D4MUEEDGY7OQJZ7FOTOE/Subscriptions"
/>
<link rel="self"
title="self" href="Mesh/MeshObjects/YZSSG7D4MUEEDGY7OQJZ7FOTOE"
/>
<link rel="edit"
title="edit" href="Mesh/MeshObjects/YZSSG7D4MUEEDGY7OQJZ7FOTOE"
/>
<link
rel="LiveFX/AuthorProfile" title="LiveFX/AuthorProfile"
href="email-info@u2u.be/Profiles"
/>
<category
term="Snippets_Root_Type" label="Snippets_Root_Type"
scheme="http://user.windows.net/MeshObject" />
<category term="MeshObject"
label="MeshObject"
scheme="http://user.windows.net/Resource" />
</entry>
Here we can see that there are relations
(<link>) to for example DataFeeds, Members, etc… The handy thing about
these Uri's is that they can be used to access these objects directly through
REST. So to create a relation
we need to get the link to the destination and add it to the relation. Let’s do
this with a mapping.
Mapping devices
The snippets utility will store all
snippets in the cloud, but if you want, you can have it synchronize to any
device in your device ring. Doing this will make the snippets available
offline, and on other devices. This makes it easy to share your snippets on
your different machines (we don’t have support for our snippets yet on other
devices like a mobile phone). To do this we added a “Map to Devices…” button to
the configuration dialog:

Clicking this button will open a dialog
listing all devices in your device ring and which are currently mapped to your
snippet list:

With it you can now map any device so the
snippet list is synchronized locally.
Each MeshObject has a collection of
mappings, which will setup synchronization between the MeshObject and the
device. Once you create a MeshObject, you need to use code like this so Mesh
will sync the MeshObject to a device:
MeshObject root = …
string deviceName = (MeshDeviceResource)(device.Resource).Title;
Mapping entry = new
Mapping(deviceName);
entry.Resource.DeviceLink =
device.Resource.SelfLink;
root.Mappings.Add(ref
entry);
root.Update();
In this code example, we first retrieve the
MeshObject somehow. Then we create a Mapping instance passing the name of the
device. Next we setup a relation between the mapping and the device. And then
we add this to the collections of mappings. Next time Mesh synchronizes, it
will put this MeshObject on that device for local access.
This will then add a relation as a link in
the mappings object:
<entry>
<id>urn:uuid:b04330f0-14d9-4bfe-b86c-6b9d21289e44</id>
<title
type="text">U2U-PC</title>
<published>2009-01-13T13:51:01Z</published>
<updated>2009-01-13T13:51:01Z</updated>
<author>
<name>U2U Trainer</name>
</author>
<link
rel="LiveFX/MeshObject" title="LiveFX/MeshObject"
href="Mesh/MeshObjects/YZSSG7D4MUEEDGY7OQJZ7FOTOE"
/>
<link rel="LiveFX/Device"
title="LiveFX/Device"
href="Mesh/Devices/4A3SOOKHK64UJHICRS2MV7R2QQ-QVSQREPBQKIE7JFE3JGZ6I65OM"
/>
…
</entry>
Members
If you want to, you can share a MeshObject
between different users. For this to work we need to add a Member in the
MeshObject Members collection, and send an invite. Mesh will always send an
invite, but we can customize this invite to a certain extent. For example we
can change to expiry date for the invite.
To do this, first we need a MeshObject
(root) and a role (roleType).
RoleType roleType = …
MeshObject root = …
Next we check if the root’s Members have
been loaded, and load them if needed:
if
(!root.Members.IsLoaded)
root.Members.Load();
Then we create a MemberResource to
represent the user to share with:
MemberResource pendingMemberResource = new MemberResource();
pendingMemberResource.Title = name;
pendingMemberResource.Email = email;
pendingMemberResource.Role = roleType;
And we create an invitation with an expiry date
of 7 days:
Invitation invitation = new Invitation();
invitation.Email = email;
DateTimeOffset expires = DateTimeOffset.UtcNow.Add(new TimeSpan(7, 0,
0, 0));
invitation.Expires = expires;
Then we create the Member, and add it to the
Members collection of our Mesh object:
Member shareWith = new Member(pendingMemberResource);
shareWith.Resource.PendingInvitation =
invitation;
root.Members.Add(ref
shareWith);
root.Update();
Getting all SnippetLists from Mesh
Creating a SnippetList is one thing, but
later we will need to get the list of all the SnippetLists stored in Mesh.
Again this is simple; with the API we can build a query which will be executed
at the server side – so very efficient – to retrieve all MeshObjects with the
correct type:
var
query = from mo in
Mesh.CreateQuery<MeshObject>()
where
mo.Resource.Type == MeshTypes.Root
select
mo;
Because the snippet tool doesn’t understand
MeshObjects we need to convert each one to one of our own types. You cannot do
this immediately, because the IQueryable implementation doesn’t support this.
To we execute our prior query using ToList() and then convert the MeshObjects
into MeshSnippetList instances.
var
toList = from mo in
query.ToList()
select
new MeshSnippetList()
{
Title = mo.Resource.Title,
Id = new
Guid(mo.Resource.Id.Substring(9))
};
Getting the Snippets from the SnippetList
Once the uses selects one of the lists, we
need to retrieve all snippets stored there. This is very similar: we create a
query to search for the right DataEntry instances and convert them to our own
representation:
private EmailSnippetCollection
CollectMeshSnippets()
{
EmailSnippetCollection
result = new EmailSnippetCollection();
DataFeed
list = GetCurrentSnippetListNameDataFeed();
var query = from de in
list.CreateQuery<DataEntry>()
where
de.Resource.Type == MeshTypes.Snippet
select
de;
foreach (var de in query)
{
EmailSnippet
snippet = de.Resource.GetUserData<EmailSnippet>();
CheckLastId(snippet.Id);
result.Add(snippet);
}
return result;
}