Data Binding in Live Framework Resource Scripts

Live Framework Resource Scripts are described in a document named About Live Framework Resource Scripts. This has a section with a short example and description of the data binding that can be used in resource scripts. Delving into the example I found it densely coded making understanding more awkward than it could have been.

UPDATE (3/12/2009)

This post has been updated in conformance with the April release of the Live Framework CTP. The most significant change is the deletion of the PropertyBinding class whose functionality has been subsumed into the StatementBinding class. There a pretty significant cleanup and simplification of the Microsoft.LiveFX.ResourceModel.Scripting namespace.

Example

The following contains some example code that does what the document example did – namely create a mesh object, a data feed and a data entry, and then retrieve the data feed and the data entry:

String cloudEndPoint = "https://user-ctp.windows.net/V0.1/";
String scriptsEndPoint = cloudEndPoint + "Script"
;
Uri meshObjectsUri = new Uri(cloudEndPoint + "Mesh/MeshObjects");

MeshObjectResource meshObjectResource = new MeshObjectResource();
meshObjectResource.Type =
"Band"
;
meshObjectResource.Title =
"Calexico";

DataFeedResource dataFeedResource = new DataFeedResource();
dataFeedResource.Type =
"SongsFeed"
;
dataFeedResource.Title =
"Songs"
;

DataEntryResource dataEntryResource = new DataEntryResource();
dataEntryResource.Type =
"Hits"
;
dataEntryResource.Title =
"Minas De Cobre (For Better Metal)"
;

StatementBinding dataFeedStatementBinding = Statement.Bind("CollectionUrl", "meshObjectResource",
   
"Response.DataFeedsLink"
);
StatementBinding dataEntryStatementBinding = Statement.Bind("CollectionUrl", "dataFeedResource",
   
"Response.DataEntriesLink"
);
StatementBinding resourceCollectionStatementBinding = Statement.Bind("CollectionUrl", "dataFeedResource",
   
"Response.DataEntriesLink"
);
StatementBinding readDataEntryStatementBinding = Statement.Bind("EntryUrl", "readDataEntryResourceCollection",
   
"Response.Entries[0].SelfLink"
);

SequenceStatement sequence = Statement.Sequence(
   
Statement.CreateResource<MeshObjectResource>("meshObjectResource", meshObjectsUri, meshObjectResource, null
),
   
Statement.CreateResource<DataFeedResource>("dataFeedResource", null
, dataFeedResource, dataFeedStatementBinding),
   
Statement.CreateResource<DataEntryResource>("dataEntryResource", null
, dataEntryResource,
        dataEntryStatementBinding),
   
Statement.ReadResourceCollection<DataEntryResource>("readDataEntryResourceCollection"
,
        resourceCollectionStatementBinding),
   
Statement.ReadResource<DataEntryResource>("readDataEntryResource"
, readDataEntryStatementBinding) );

ResourceScript<SequenceStatement> resourceScript = sequence.Compile();

NetworkCredential networkCredential = new NetworkCredential(USER_NAME, PASSWORD, scriptsEndPoint);

resourceScript.RunAtServer(networkCredential);

This code: creates a mesh object named Calexico; creates a data feed named Songs; and creates a data entry named Minas De Cobre (For Better Metal). It then gets more interesting because it creates four StatementBinding objects which are used in the subsequent SequenceStatement. Then the resource script is compiled, a network credential is created and, finally, the resource script is run at the server.

Data Binding

This post is going to focus specifically on the StatementBinding objects and their use in the SequenceStatement.

The SequenceStatement comprises:

  • three CreateResource statements each acting on different types
  • one ReadResourceCollection<DataEntryResource> statement
  • one ReadResourceStatement<DataEntryResource>

Each of these statements creates and returns an object of the appropriate class: CreateResourceStatement<TResource>, ReadResourceCollectionStatement<TResource> and ReadResourceStatement<TResource> where TResource is constrained to derive from Resource. These classes expose several properties of their own as well as the properties of the WebOperationStatement and Statement classes from which they are derived.

The CreateResourceStatement<TResource> class is defined as follows:

public sealed class CreateResourceStatement<TResource> : WebOperationStatement  where TResource : Resource {
    // Properties
    public Uri CollectionUrl { get; }
    public TResource Request { get; }
    public TResource Response { get; }
}

The idea with data binding is to to define at compile time a binding between some programmable quantity not known until runtime and a property exposed by a Statement object . For example, binding the MeshObjects collection retrieved earlier in the execution of the resource script to the CollectionUrl property specifying the target of a CreateResourceStatement.

The Statement class exposes several Bind() static methods. The method used in this example is:

public static StatementBinding Bind(String targetProperty, String sourceStatement, String sourceProperty);

This binds the property named sourceProperty of the statement named sourceStatement with the property named targetProperty on the statement to which the binding is applied.

An example of its use is:

StatementBinding dataFeedStatementBinding = Statement.Bind("CollectionUrl", "meshObjectResource", "Response.DataFeedsLink");

This binds the property Response.DataFeedsLink of the statement named meshObjectResource with the CollectionsUrl property of the statement to which the binding is applied.

The Statement class exposes several static factory methods creating Statement objects including those used in this example:

  • CreateResourceStatement<TResource>(…)
  • ReadResourceCollectionStatement<TResource>(…)
  • ReadResourceStatement<TResource>(…)

Each of these has several overloaded members accepting binding. One used in this example is:

public static CreateResourceStatement<TResource> CreateResource<TResource>(String name, Uri collectionUrl,
     TResource request, params StatementBinding[] bindings) where TResource : Resource;

This creates and returns a CreateResourceStatement<TResource> object named name which can be used to create a resource of type TResource that is a copy of the TResource object passed in the request parameter. The bindings parameter is used to pass the runtime bindings into the CreateResourceStatement<TResource> object at runtime. This is used as follows in the example:

Statement.CreateResource<DataFeedResource>("dataFeedResource", null, dataFeedResource, dataFeedStatementBinding),

This statement is named dataFeedResource and, when invoked, it creates a data feed from the dataFeedResource object passed as a parameter. The collectionUrl parameter is null because the CollectionUrl property of the created CreateResourceStatement will be set at runtime using the information passed in the dataFeedStatementBinding created earlier.

A comparison of the Statement.CreateResource<MeshObjectResource> and Statement.CreateResource<DataFeedResource> parameters shows the use of binding:

Statement.CreateResource<MeshObjectResource>("meshObjectResource", meshObjectsUri, meshObjectResource, null),
Statement.CreateResource<DataFeedResource>("dataFeedResource", null, dataFeedResource, dataFeedStatementBinding),

When creating the MeshObjectResource the collectionUrl for the statement is known at compile time and set to meshObjectsUri. Since there is no need to bind anything at runtime the bindings parameter is null. When creating the DataFeedResource the collectionUrl is not known until runtime because it contains the identity for the mesh object created by the CreateResource<MeshObjectResource>. Consequently, binding must be used so collectionUrl is set to null and the bindings parameter is set to dataFeedStatementBinding.

The ReadResourceCollection<DataEntryResource> and ReadResource<DataEntryResource> parameters show the simplification arising from not needing to provide a resource:

Statement.ReadResourceCollection<DataEntryResource>("readDataEntryResourceCollection",
    resourceCollectionStatementBinding),
Statement.ReadResource<DataEntryResource>("readDataEntryResource", readDataEntryStatementBinding) );

There is in also an optimization as the target of the binding is not specified in the parameter list and so does not have to be set to null.All the Statement objects in this example are bound to the same property, CollectionsUrl, except for the ReadResource statement which is bound instead to the EntryUrl as in:

StatementBinding readDataEntryStatementBinding = Statement.Bind("EntryUrl", "readDataEntryResourceCollection",
    "Response.Entries[0].SelfLink");

Statement.ReadResource<DataEntryResource>("readDataEntryResource", readDataEntryStatementBinding)

The statement binds the SelfLink url from the first resource returned from the statement named readDataEntryResource to the EntryUrl of the ReadDataEntryStatement. When invoked, this statement will retrieve the first data entry in the data feed returned from the invocation of the statement named readDataEntryResource specified as Response.Entries[0].SelfLink.

Technorati Tags:

About Neil Mackenzie

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

4 Responses to Data Binding in Live Framework Resource Scripts

  1. Oran says:

    Hi Neil, great post. I agree, resource script code does seem unnecessarily awkward. I think this is because resource scripts were designed with a visual editor in mind that we don’t have yet. In the meantime, I’ve written a helper library that makes scripts easier to work with from code.http://orand.blogspot.com/2008/12/fluent-livefx-resource-scripts.htmlhttp://orand.blogspot.com/2009/01/meshscript-queries-liveitems-and-magic.htmlA bug-fix version of the library can found here:http://orand.blogspot.com/2009/01/exploring-live-framework-triggers.html

  2. Neil says:

    Oran -Thanks for your comment and the link to your mesh script library.I read some of your mesh script postings earlier today before I wrote the above. I didn’t link to them in this post only because I was trying to focus on understanding the raw resource script API even though I remember reading in one of your posts that there is possibly additional developer help coming down the road in the guise of a visual editor – which would render my knowledge somewhat moot.

  3. Vikas says:

    thanks Neil – great post and good information.Your blog post has been tagged: http://delicious.com/LiveFrameworkKeep wirting great posts.

  4. Oran says:

    I don’t think the visual editor will render your raw API knowledge moot. I believe that based on feedback we will see more features that make it easier to work with resource scripts from code. So keep up the good work!🙂

Leave a Reply

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

WordPress.com Logo

You are commenting using your WordPress.com 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