LA.NET [EN]

Nov 09

Here we are again, for more on the MS AJAX library. In the previous post, we’ve seen that we can interact with ADO.NET Data Services by using the AdoNetDataContext instances. Today, we’ll be looking at more advanced features of the ADO.NET Data Services which are also available in the MS AJAX library.

Before going on, I must confess that I’m not really an ADO.NET Data Service user (I guess this has made me curious enough for taking a peek in the future). However, since the MS AJAX library offers such great support for it, I couldn’t resist doing some digging and seeing which options are available for interacting with an existing data service.

According to the docs, ADO.NET Data Services can “be surfaced as a REST-style resource collection that is addressable with URIs and that agents can interact with using standard HTTP verbs such as GET, POST, PUT or DELETE”. In practice, and if we go back to our previous example, we can get all the images by using the uri http://:…/Services/ImageDataService.svc/Images. Besides this simple option,which returns all the images contained in the object,there are still other interesting options. For instance:

  • we can navigate through related properties;
  • we can expand associated properties;
  • we can filter the returned results;
  • we can paginate the returned data.

All these operations are specified through uris. We can easily do them by building the uris by hand. For instance, we can modify the previous example so that it also displays the associated :

<body xmlns:sys="javascript:Sys"
      xmlns:dv="javascript:Sys.UI.DataView">
    <div
      id="myView"
      class="sys-template"
      sys:attach="dv"
      dv:autofetch="true"
      dv:dataprovider="{{ _ctx }}"
      dv:fetchoperation="Images"
      dv:fetchparameters="{{ {$expand: ''Tags''} }}">
        <h2>{{Name}}</h2>
        <img sys:src="{{Uri}}" sys:alt="{{Name}}" />
        <div class="sys-template"
            sys:attach="dv"
            dv:data="{{ Tags }}">
            <span>{{Name}}</span>,
        </div>
    </div>
</body>

By using the $expand parameter, we’ll end up getting each image’s associated tags and we can display them by using a nested DataView control. The next image shows what happens when we load the previous page:

expand

We could specify all the “special” parameters this way. However, there is another way: we can rely on the Sys.Data.AdoNetQueryBuilder class for doing building the uri for us.

The AdoNetQueryBuilder’s constructor expects the base uri and exposes several properties which we can use to build the uri which performs a specific operation against the existing ADO.NET Data Service. You’ll probably end up using the ones which are present in the following list:

  • skip and top: we can combine them for paginating data;
  • orderby: used for indicating the sorting order;
  • filter: responsible for filtering the returned data;
  • expand: used for specifying the properties which will be “expanded” and included in the response.

I must confess that I really didn’t find the use of this object intuitive at first. However, after running some experiences, everything started making sense. In order to show you how you might end up using this object, suppose we want to get all the images and associated tags and that we want to order them by name. Here’s a possible solution:

<head runat="server">
    <style type="text/css">
      .sys-template{
        display: none;
      }
      img{
        width:320px;
        height:212px;
      }
    </style>
    <script type="text/javascript"
      src="../Scripts/MicrosoftAjax/start.debug.js">
    </script>
    <script type="text/javascript">
      var _ctx = null;
      Sys.require([Sys.components.adoNetDataContext,
                   Sys.components.dataView],
      function () {
        var uriBuilder = 
new Sys.Data.AdoNetQueryBuilder("Images"); uriBuilder.set_expand("Tags");//$expand uriBuilder.set_orderby("Name");//$orderby _ctx = Sys.create.adoNetDataContext({ serviceUri: "../Services/ImagesDataService.svc" }); Sys.create.dataView( Sys.get("#myView"), { dataProvider: _ctx, autoFetch: true, fetchOperation: uriBuilder.toString() }); }); </script> </head> <body xmlns:sys="javascript:Sys" xmlns:dv="javascript:Sys.UI.DataView"> <div id="myView" class="sys-template"> <h2>{{Name}}</h2> <img sys:src="{{Uri}}" sys:alt="{{Name}}" /> <div class="sys-template" sys:attach="dv" dv:data="{{ Tags }}"> <span>{{Name}}</span>, </div> </div> </body>

This time, I’ve opted for using an imperative approach. Things are really similar to what we had before; however, notice that now we’re using an AdoNetQueryBuilder object to set the fetchOperation property of the DataView object.

We start by instantiating the AdoNetQueryBuilder object. If you recall it, I said that this wasn’t really intuitive…it was only looking at the source code that I’ve understood that I was supposed to pass the name of the resource I wanted to access (instead of passing the base uri for the service – not sure on why the constructor’s only parameter is called uri, when resource would have make things so much easier!). Since I was interested in retrieving images, I only had to pass the string “Images” to the constructor.

After having an instance and setting the required properties (recall from above that we wanted to get images+tags and to order everything by name), we can simply call the toString method to get the string which represents the operation we need to perform. And that’s it. We’ll still be speaking about MS AJAX in future posts, so stay tuned for more!

1 comment so far

  1. Kellycgm
    6:18 pm - 2-8-2010

    nice read. I would love to follow you on twitter. By the way, did you guys learn that some chinese hacker had busted twitter yesterday again.