Accessing Resources By URL in the Live Framework API

In the post on Data Storage in the Live Framework I suggested that syndication links stored in the Resource.Links property could be useful for linking data entries and data feeds together in interesting ways. There remains the task of using the syndication link URLs stored in the Links property for something useful.

A syndication link is nothing more than a URL so the issue is how to use the Live Framework API to retrieve the resource at that URI and turn it into something useful. Oran Dennison provides code on a forum thread demonstrating how to do this.

There appears to be different solutions depending on whether a feed or an entry is being retrieved. The AtomPubClient class shipped with the Live Framework API can be used to retrieve an entry in the form of a SyndicationItem which can then be converted into an instance of the appropriate Resource-derived class. The ResourceQuery<TEntry> class shipped with the Live Framework API can be used to retrieve a feed in the form of an IEnumerable<TEntry> where TEntry is derived from Resource.

A sample of code demonstrating both of these techniques is:

// Setup the authentication context
NetworkCredential networkCredential = new NetworkCredential(Constants.UserName, Constants.Password);
SyndicationOperationContext syndicationOperationContext = new SyndicationOperationContext(typeof(SyndicationItem));
syndicationOperationContext.Authorization = networkCredential.GetWindowsLiveAuthenticationToken();

// Retrieve a specific mesh object as an Atom <entry>
Uri syndicationItemUri = new
SyndicationItem syndicationItem = AtomPubClient.ReadEntryResource(syndicationItemUri, syndicationOperationContext);
MeshObjectResource meshObjectResource = new MeshObjectResource(syndicationItem);

// Query MeshObjects and retrieve those with title of "Perec" as an Atom <feed>
Uri meshObjectResourceUri = new Uri("$filter=(Title eq ‘Perec’)");
ResourceQuery<MeshObjectResource> meshObjectQuery =
     new ResourceQuery<MeshObjectResource>(networkCredential, meshObjectResourceUri);
IEnumerable<MeshObjectResource> meshObjectResources = meshObjectQuery.Execute();

This provides access to a MeshObjectResource or an enumerable collection of them. A similar technique can be used to access the other types of resource stored in the live operating environment. Note that the order of the network credential and the resource URL is swapped between AtomPubClient.ReadEntryResource() and ResourceQuery<MeshObjectResource>().  Note that query modifiers like filters, as in this example, can be used with ResourceQuery<TResource>() but NOT with AtomPubClient.ReadEntryResource().

Unfortunately, these resources are not hooked into the Mesh hierarchy of MeshObject, DataFeed and DataEntry all connected to the live operating environment via the Live Framework .Net API. For example, you can create a MeshObject from the MeshObjectResource retrieved as above but you cannot update it because it is not directly associated with the live operating environment and there is no way to associate it with the live operating environment.

This means that while storing syndication links in Resource.Links looks promising as a means of associating mesh objects, data feeds and data entries, the practical reality is that it involves creating a parallel world of Resources unconnected to a Mesh/MeshObject/DataFeed/DataEntry hierarchy provided by the Live Framework .Net API.

Ideally, there would be a method on Mesh similar to:

public TEntry LoadLiveItemFrom<TEntry>(Uri url) where TEntry : new(), LiveItem;

However, I suspect the constraint of a RESTful interface retrieving a single resource would probably make this a bit gruesome internally.

Technorati Tags: ,

About Neil Mackenzie

Cloud Solutions Architect. Microsoft
This entry was posted in Uncategorized. Bookmark the permalink.

5 Responses to Accessing Resources By URL in the Live Framework API

  1. Oran says:

    That’s a nice example of using ResourceQuery, definitely nicer than using AtomPubClient. I’m pretty sure query modifiers will work with AtomPubClient.ReadCollectionResource, but why bother when we can use ResourceQuery instead.LiveItem (the base class for MeshObject, DataFeed, etc.) has internal methods named LoadResult and Reload that together load a SyndicationItem into the "dead" LiveItem shell and hook it up to a LOE, bringing the "DeadItem" to life as a fully functional LiveItem. I’ve written a Reload extension method in my FluentResourceScripts library that wraps the calls to these internal methods for the purpose of turning the Resource results of Resource Scripts into functioning LiveItems. So you can write:SyndicationItem syndicationItem = AtomPubClient.ReadEntryResource(albumUri, context);MeshObject meshObject = new MeshObject();meshObject.Reload(syndicationItem, loe, context.ETag);And now you can call things like DataFeeds.Add() on meshObject and it will work. I’ve also written a Reload for LiveItemCollection. I agree, it would sure be nice if this were exposed through the official API so the world of Resources is easily bridged with the world of LiveItems.Here’s the blog post with Reload code:

  2. Oran says:

    Here’s an extension method using my Reload method that’s pretty close to what you specified:public static TEntry LoadLiveItemFrom<TEntry>(this LiveOperatingEnvironment loe, Uri url, string authToken) where TEntry : LiveItem, new(){ SyndicationOperationContext context = new SyndicationOperationContext { Authorization = authToken }; SyndicationItem syndicationItem = AtomPubClient.ReadEntryResource(url, context); var result = new TEntry(); result.Reload(syndicationItem, loe, context.ETag); return result;}You can use it like this:string authToken = new NetworkCredential(username, password).GetWindowsLiveAuthenticationToken();MeshObject meshObject = loe.LoadLiveItemFrom<MeshObject>(albumUri, authToken);The authToken stuff is a bit klunky. Maybe there’s a way to snag the authToken from the LOE using reflection, but I haven’t bothered looking.

  3. Neil says:

    Oran -Once again thanks for your informative comments and pointers to your techniques for linking the world of resources and the world of LiveItems. I will probably suggest an API implementation on the Connect website because I think it could be pretty useful. I started looking at ReadCollectionResource() before I did the post but got tired of looking at Fiddler output and wrote the post instead. By the way, I’ve loaded up your FluentResource library but given its impressive size it will take a while to go through it.

  4. Neil says:

    Oran writes:"I’m pretty sure query modifiers will work with AtomPubClient.ReadCollectionResource, but why bother when we can use ResourceQuery instead."There is one crucial difference between using AtomPubClient and ResourceQuery that I forgot to put in the post. ResourceQuery authenticates using a NetworkCredential while AtomPubClient authenticates using a SyndicationOperationContext that contains a Windows Live authentication token string obtained by calling GetWindowsLiveAuthentication(). This means that the user is authenticated EVERY time the ResourceQuery constructor is called while the AtomPubClient methods NEVER authenticates the user because the SyndicationOperationContext already contains the authentication token. In other words, ResourceQuery involves additional overhead of an authentication over the wire for every query.The differing methods of authentication provided at various places in the Live Framework API add to the surface of the API and could cause grief to the developer who may not understand the implications of using a raw NetworkCredential as opposed to something like an authentication token returned by GetWindowsLiveAuthentication(). The surface is also increased by the opposite positioning of the URL and authentication information in ResourceQuery and AtomPubClient. I will probably have a closer look at these issues and add it to Connect as a suggestion – although I would argue that it is really a bug in the API.

  5. Neil says:

    A correction to my last comment.In fact, a ResourceQuery can be constructed using an authentication token and a token type thereby removing the performance advantage I suggested AtomPubClient had. However, my point about parameter order still stands and affects both AtomPubClient and FeedSyncClient which both put the target URL before the authentication context – unlike the other classes which put the authentication token first.

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s