LA.NET [EN]

Oct 29

DataView and remote web service invocation: adapting the data returned from the server

Posted in Javascript MS AJAX      Comments Off on DataView and remote web service invocation: adapting the data returned from the server

Yesterday I’ve ended up receiving an interesting question regarding the code I’ve used in the posts which explain how to get data from a remote web service. The question was: how do we adapt the data returned from the web service before it is used by the DataView for rendering its HTML?

This is an interesting question. Fortunately, the answer is not really complicated. To illustrate this problem and its solution, we’ll start by going back to  the Person class we’ve introduced in the server side:

[DataContract]
public class Person {
    [DataMember(Name="name")]
    public String Name { get; set; }
    [DataMember(Name="address")]
    public String Address { get; set; }
}

As you can see, we’re using the DataMemberAttribute for influencing the name of the properties used in the JavaScript objects that will be returned from the service. Now, let’s assume that we don’t own the service and that the Person class looks like this:

[DataContract]
public class Person {
    [DataMember()]
    public String Name { get; set; }
    [DataMember()]
    public String Address { get; set; }
}

Now the problem: we want to adapt the data received from the server so that we don’t have to change the template used by the view. Btw, here’s how the template is currently defined:

 <tr>
    <td>{{name}}</td>
    <td>{{address}}</td>
  </tr>

If we leave the code as is, we’ll end up getting errors because *now* each JavaScript Person instance has two properties named Name and Address (instead of name and address). Ok, I guess you could say that it’s a lot easier to just update the names of the properties used in the templates than to change the data; however, changing the data gives me the chance to introduce another technique which might be useful for you in other less contrived scenarios…

When I thought about intercepting and changing the data, I thought that the fetchSucceeded event would be a good place to do that. Unfortunately, this event is only fired after the DataView control has refreshed itself: by then, you’d already received an exception saying that name is undefined!

Ok,time to go back to the prototype definition of the control…and to read a previous post on the topic of DataView events. And yes,the answer to our problem is right there, on the first event described on this post:

rendering: this event is generated when the DataView control is about to start instantiating its template to get the rendered HTML. Any function which handles this event receives two parameters: the first, references the DataView control which generated the event; the second is an instance of the Sys.Data.DataEventArgs type;

Hooking up the rendering event is all we need to adapt the data. here’s some code that adapts the JavaScript objects returned by the server (as you can see, we’re replacing each instance with a new one that has the correct names):

function updateData(sender, e) {
  var data = e.get_data();
  for (var i = 0; i < data.length; i++) {
    data[i] = { name: data[i].Name, 
address: data[i].Address } } }

Since we’re using a declarative approach, hooking up the event can be done by using the on rendering attribute:

dv:onrendering="{{ updateData }}"

And that’s it for now. Keep tuned for more on MS AJAX.