Sunday, March 21, 2010

Client Side AJAX Applications in SharePoint 2010 - Part 3

Note: This is one of a multi-part series exploring building client side AJAX applications with ASP.Net AJAX 4 Templating and the WCF Data Services (aka ADO.Net Data Services, aka oData, aka Astoria) in SharePoint 2010.

In the previous two posts in this series I’ve shown how you can access SharePoint data using WCF Data Services and consume that data using ASP.Net AJAX 4 templates. In this post I’ll update the previous example in order to show how to write data back to SharePoint.

Templates and Linking

Before we go into writing data back let’s modify our example to link each item back to the SharePoint DispForm.aspx page. A naïve approach would look like this:

It turns out this approach doesn’t work because the DataView won’t look for the data binding syntax inside of attributes. The next approach that might make sense would now be to set href to a data binding syntax and inside there do some string concatenation like so:

It turns out this doesn’t work either, but for a different reason. Apparently the DataView can’t natively convert some HTML attributes like href and src for reasons Bertrand La Roy describes. The solution is to prefix the attribute with the ASP.Net AJAX system namespace. Typically you would define the system namespace on the HTML body element. But with SharePoint you don’t have access to this element. Fortunately you can declare this namespace on any element so the following code works:

The {{ }} template syntax we’ve seen so far is what’s known as one time binding. When you use this syntax the expression is evaluated only once when the template is rendered. What we want is one way live binding and/or two way live binding.

In order to understand the live bindings you need to understand that behind the scenes the DataView keeps an in memory copy of all of the JSON objects it downloads. It's possible for the data in these objects to change. And that's where one way live bindings come in. When you use the syntax { binding [FieldName] }, the DataView will automatically update the binding when the underlying JSON object changes.

Two way live binding happens automatically when you use the one way live binding syntax on HTML INPUT elements. For these scenarios the DataView automatically updates the in memory JSON objects. Then the DataView updates any one way live binding's.

So let’s throw two DataViews onto the page, one with one way live bound hyperlinks, one with two way bound HTML INPUT textbox elements and see what happens:

Notice the input element with the sys:value bound to title and the new binding syntax in the text of the a href. The result looks like this:

It may not be all that pretty yet, but if you change the text in any of the text boxes the result is immediately updated in the hyperlinks on mouse out. But if you hop back to SharePoint or refresh the page you’ll see that our data hasn’t been updated.

Updating SharePoint, For Real This Time

Just because the DataView updated the in memory JSON objects it’s bound to doesn’t mean it sent a POST request back to ListData.svc. To accomplish that we need to call dataContext.saveChanges(). If you toss in a button below the table like this:

Then when you click the button the AdoNetDataContext figures out which JSON objects changed and sends just those objects back to ListData.svc. How do you know it only sends the rows that changed? If you look at Fiddler there will be a POST to ListData.svc/$batch with something like the following:

And that, as you may have noticed, is the JSON for just a single of the rows that we were displaying.

But how did the AdoNetDataContext know which objects were changed? Jonathan Carter explains this better than I could but basically when the data context downloads JSON objects it injects them with the ability to notify itself when they change. As Jonathan points out it’s a neat trick that would not be possible in a statically typed language.

Summary

We’ve finally gotten to some of the core benefits of using ASP.Net AJAX 4 Templating. With very little JavaScript we were able to cleanly separate our UI from our data access code and write data back to the server. And the amount of HTTP traffic and server operations was kept to a bare minimum, keeping things as fast and responsive as possible. So all we’re missing at this point is how to use it to make something real out of these technologies. And that will be the topic for the next post.