LA.NET [EN]

Nov 07

Today we’ll keep looking at the DataContext component and we’ll see how it supports deferred properties. Deferred properties are properties which are lazy loaded as “needed”. Using deferred properties means that the component will try to make a remote call for getting the value of that property. As you’re probably expecting, this means that you’ll have to write code on the client and server side. On the client, we’ll need some JavaScript functions which are responsible for:

  • checking if a specific property is deferred;
  • returning an instance of the Sys.NetWebServiceOperation which has all the data needed for performing the remote call which returns the value of that property.

After creating the functions and configuring the DataContext component’s isDeferredPropertyMethod and getDeferredPropertyFetchOperationMethod , we can get the deferred value of the property by using the DataContext’s fetchDeferredProperty method. Let’s take a look at the client side code (which augments the code we introduced in previous posts):

var entityManager = {
    metaCounter: {},
    getEntityId: function (dataContext, entity) {
       //removed: check previous posts
    },
    getNewIdentity: function (dataContext, entity, entitySet) {
        //removed: check previous posts
    },
    isDeferredProperty: function (dataContext, entity, propertyName) {
        var id = dataContext.getIdentity(entity);
        return propertyName === "contacts" &&
               id !== null &&
               /$new/.test(id);
    },getDeferredProperty: function (
dataContext,entity, propName, parameters, userContext) {
//returns web service operation var id = dataContext.getIdentity(entity); return new Sys.Net.WebServiceOperation( "GetContactsFor", {id: parseInt(/(d+)/.exec(id)[0]) }, "get" ) ; } };


It goes without saying (I think!) that this is just demo code (you’ll need better code for real world scenarios). As you can see, the contacts property will only be lazily loaded when we’re trying to get it from an object which has been previously persisted in the server side (once again, you’ll need to go back to the previous posts to understand what’s going on here). In the real world, I’d probably check that property against undefined too so that you’d only ask for the data when the property hasn’t been initialized.



The getDeferredProperty tries to find the id of the current person’s instance (don’t forget that person instances which have been previously persisted are on the form people$xxx where xxx is an integer which identifies the current instance) and uses it to build a JS literal object which is used to pass parameters to the server side code. Notice that the Sys.Net.WebService’s “constructor” expects three parameters: the first identifies the name of the operation; the second is a literal object which represent the parameters that will be passed to the server side method. Finally, the third parameter is a string which identifies the HTTP method that should be used in the server side call.



Now, we’re ready to create a new DataContext instance:



var ctx = Sys.create.dataContext(
  {
    serviceUri: "PeopleService.svc",
    getIdentityMethod: entityManager.getEntityId,
    getNewIdentityMethod: entityManager.getNewIdentity,
    isDeferredPropertyMethod: entityManager.isDeferredProperty,
    getDeferredPropertyFetchOperationMethod: 
entityManager.getDeferredProperty } );


One additional note before looking at the server side code: we *really* need to set the serviceUri property when we intend to use deferred property fetching. If you don’t set it, you’ll end up receiving an exception when you try to get the value of the property from the server side:



ctx.fetchDeferredProperty(
    people[0],
    "contacts",
    null,
    null,
    function(){
        var contacts = people[0].contacts;
       //contacts already filled here!
    });


The fetchDeferredProperty method receives several parameters:



  • a reference to the entity whose property is going to be obtained through the remote call;
  • name of the property which is being lazily fetched;
  • parameter: literal object with parameter info that will be passed to the server side. Note that this object will be merged with the parameter object encapsulated by the WebServiceOperation returned from the DataContext’s getDeferredPropertyFetchOperationMethod function;
  • mergeOptions: the Sys.Data.MergeOption which identifies the merge which will be used when the data is returned from the web service;
  • succeededCalback: callback function which will be invoked when the data is returned from the server and has already been passed to the property;
  • failedCallback: function invoked when the remote call ends up generating an error;
  • timeout: timeout defined in ms;
  • userContext: object which will be passed to the callback method when the DataContext receives a response from the server side.


In order for the previous client code work, we need to update our server side service’s code by adding the GetContactsFor method. Once again, and since is just demo code, I’ll implement in the easiest way possible: I’ll make it return a collection with a single predefined contact:



[OperationContract]
public IEnumerable<Contact> GetContactsFor(Int32 id) {
    return new List<Contact>{
        new Contact{
                Type = ContactType.Phone,
                Ct  = "123123123"
        }
    };
}


And there you go: you don’t need anything else for making the DataContext component get the value of the contacts property lazily. And that’s it for now. Stay tuned for more on MS AJAX.

Leave a Reply

Your email address will not be published. Required fields are marked *


*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>