Unveil the Data Binding Architecture inside Microsoft ASP.NET Ajax 1.0 - Part 2
page 4 of 7
by Xianzhong Zhu
Feedback
Average Rating: This article has not yet been rated.
Views (Total / Last 10 Days): 32627/ 67

Sample 1 - binding a HTML ListView control to a Web Service

Please first note that there are many similarities in the example introduced here with the first one in Part 1; however, we will lay emphasis on the other aspects not yet mentioned previously. Now, you can start Visual Studio 2005 and still select the "ASP.NET AJAX CTP-Enabled Web Site" template to create a new website and name it ListEmployees. The following Figure shows its design-time snapshot.

Figure 2: The design-time sample web page

In this sample we will still use a ListView control to display an employee list, which is automatically executed when the page has been loaded completely. Now, let us follow the steps explained above to work.

1. Design the web page

Listing 2

//……omitted
    <link rel="stylesheet" type="text/css" href="site.css" />
    //……omitted
            <span style="font-size: 24pt; color: #6600cc">
                <strong>Employee Info Searching Results:</strong>
            </span>
            <div id="header">
                <span >
                <strong>EmpID</strong> &nbsp;
                </span>
               <span >
                <strong>Name</strong> &nbsp;
                </span>
                <span>
                <strong>Address</strong>
                </span>
            </div>
            <hr style="width: 457px" align="left" />
 
            <div id="searchResults">
            </div>
            <div style="visibility:hidden;display: none;">
                  <div id="searchResults_layoutTemplate">
                        <div id="searchResults_itemTemplate" >
                         &nbsp; &nbsp;<span id="searchResults_ID"></span> &nbsp;&nbsp;&nbsp;&nbsp;
                        <span id="searchResults_Name"></span>&nbsp;&nbsp;
                        <span id="searchResults_Address"></span>
                      </div>
                    <div id="searchResults_separatorTemplate" class="TaskSeparator">
                    </div>
                  </div>
                <div id="NoDataTemplate">Waiting...</div>
            </div>    

Here, we first create a constant header line within a div block to elegantly list the employee records below. Then starting from the line in bold, we construct the HTML elements in relation to each possible template of the advanced MS AJAX client-side controlListView. Here we have also used the separatorTemplate template to separate the neighboring records. As mentioned in Part 1, control ListView shows records in the AJAX way. So here we have also used the emptyTemplate templateNoDataTemplate so that when data from the WebService is being loaded the user can get a friendly hint.

2. Create the corresponding MS AJAX client-side controls

Here, mainly one MS AJAX client-side control, ListView, is created to match the HTML elements (mainly a set of divs), with its each template in correspondence with different div elements. Additionally, we have also defined three label elements matching the three span elements above.

Create the Web Service

Right click the project and choose "Add new item" and create a new Web Service named EmployeeDataService.asmx. Here, we have also made the Web Service derived from DataService, and then we have created four CRUD WebMethods. Listing 3 shows the crucial code snippet.

Listing 3

//……
using System.ComponentModel;
using System.Web.Script.Services;
using Microsoft.Web.Preview.Services;
//……
[ScriptService]
public class EmployeeDataService: DataService
{
  static List < Employees > _data;
  static int _nextId;
  static object _dataLock = new object();
  private static List < Employees > Data
  {
    get
    {
      if (_data == null)
      {
        lock(_dataLock)
        {
          if (_data == null)
          {
            _data = new List < Employees > ();
            _data.Add(new Employees(0, "John Smitch""1970 Napa Ct."));
            _data.Add(new Employees(1, "Mary Smitch""9833 Mt. Dias Blv."));
            _data.Add(new Employees(2, "Mike Jodan""7484 Roundtree Drive"));
            _data.Add(new Employees(3, "Ronald Adina""9539 Glenside Dr"));
            _data.Add(new Employees(4, "Blue Yonder Airlines""1226 Shoe St."))
              ;
            _data.Add(new Employees(5, "Milton Albury""1399 Firestone Drive"))
              ;
            _data.Add(new Employees(6, "Phyllis Allen""5672 Hale Dr."));
            _data.Add(new Employees(7, "Stanley Alan""6387 Scenic Avenue"));
            _data.Add(new Employees(8, "Alexander Berger""8713 Yosemite Ct."))
              ;
            _nextId = 9;
          }
        }
      }
      return _data;
    }
  }
  [WebMethod][DataObjectMethod(DataObjectMethodType.Delete)]
  public void DeleteRecords(int id)
  {
    foreach (Employees row in _data)
    {
      if (row.Id == id)
      {
        lock(_dataLock)
        {
          _data.Remove(row);
        }
        break;
      }
    }
  }
  [WebMethod][DataObjectMethod(DataObjectMethodType.Select)]
  public Employees[]SelectRecords()
  {
    return EmployeeDataService.Data.ToArray();
  }
  [WebMethod][DataObjectMethod(DataObjectMethodType.Insert)]
  public Employees InsertRecords(string name, string Address)
  {
    Employees newRow;
    lock(_dataLock)
    {
      newRow = new Employees(_nextId++, name, Address);
      _data.Add(newRow);
    }
    return newRow;
  }
  [WebMethod][DataObjectMethod(DataObjectMethodType.Update)]
  public void UpdateRecords(Employees updateRow)
  {
    foreach (Employees row in _data)
    {
      if (row.Id == updateRow.Id)
      {
        row.Name = updateRow.Name;
        row.Address = updateRow.Address;
        break;
      }
    }
  }
}
 
public class Employees
{
  private int _id;
  private string _name;
  private string _address;
  [DataObjectField(truetrue)]
  public int Id
  {
    get
    {
      return _id;
    }
    set
    {
      _id = value;
    }
  }
  [DataObjectField(false)][DefaultValue("")]
  public string Name
  {
    get
    {
      return _name;
    }
    set
    {
      _name = value;
    }
  }
  [DataObjectField(false)][DefaultValue("")]
  public string Address
  {
    get
    {
      return _address;
    }
    set
    {
      _address = value;
    }
  }
  public Employees()
  {
    _id =  - 1;
  }
  public Employees(int id, string name, string address)
  {
    _id = id;
    _name = name;
    _address = address;
  }
}

Here, for simplicity, we have used an in-memory data source, a static Array with basic element being Employees object to simulate the web service with states; while in enterprise development this is not a good habit.

Next, let us dwell upon the mysterious DataService.

About DataService

To be honest, I have scoured the entire Internet with the word "DataService," but obtained nearly nothing besides several discontinuous articles (such as this one on http://forums.asp.net) referring to it and the newest MS AJAX samples shipped with the framework. In addition, I use the object browser and the reflector tool inside Visual Studio 2005 to grab a little more info about it. So now I have pieced them together and drawn some conclusions on the mysterious "DataService."

Recently, from the web and MS AJAX tutorials, you can easily find many related tips on consuming general web services (derived from WebService) from inside the client-side JavaScript of ASP.NET AJAX framework, while there are few samples on DataService derived web services accessed from the client side. According to my preliminary research, DataService should be used under the following typical circumstance: when we use the advanced client-side rendering controls, such as ItemView, ListView, etc. and their data sources are database-related data operations (e.g. CRUD) provided by web services, while under the other kinds of circumstances we can choose the more common WebService. Is it true that Microsoft has specially designed DataService for ListView/ItemView? By examining the assemblyMicrosoft.Web.Preview.dll using the .NET object browser and Lutz Roeder's advanced .NET Reflector tool (note: this is an excellent thing; with it you can easily obtain the complete source code for class DataService). We have found DataService is derived from WebService and only exposed the following two Web Methods.

Listing 4

public DataTable <span class=Bold>GetData</span>(object parameters, string loadMethod);
public DataTable <span class=Bold>SaveData</span>(ChangeList changeList, object parameters, string loadMethod);

By examining the source code of Sys.Preview.Data.DataSource.save and Sys.Preview.Data.DataSource.load in file PreviewScript.js, you can easily find the following.

1. Method save requires that property serviceType of DataSource must be of type of Sys.Preview.Data.ServiceType.DataService and then the save method is directed to call method SaveData of class DataService.

2, There are two things with method load: when property serviceType of DataSource is of type of DataService, then the load method is directed to call method GetData of class DataService; when property serviceType of DataSource is not of type of DataService, i.e. Handler according to discuss with DataSource in Part 1, the system will create a general delegate and then method load is directed to Sys.Net.WebRequest(). When we further study the methods SaveData and GetData of class DataService using .NET Reflector, we can find more interesting thingsyou will know what the meaning of property loadMethod of DataSource is and how the database CRUD operations correspond to the Delete (DeleteRecords), Insert (InsertRecords), Select (SelectRecords), and Update (UpdateRecords) methods of your DataService and even more secrets…

For brevity, here we do not give their detailed analyses, but I leave this to the readers.

Author's Note: I highly recommend you study the source code of class DataService carefully, so that you can get the most of you originally want.

With the newly-introduced attributes, DataObjectMethod and DataObjectField (you can also refer to two classes DataObjectFieldAttribute and DataObjectMethodAttribute in MSDN for further research), we can easily achieve our aims in providing properties and methods to be used by control DataSource, such as Fill, Select, Update, Insert, and Delete operations. All these are to be provided by the easy xml-script declarative programming in the following section.

Implement the binding

Now, let us see how to use the xml-script declarative mode to achieve the ListView control data binding. Here is the xml-script part in correspondence with HTML elements definitions in Listing 2 above.

Listing 5

<script type="text/xml-script">
      <page xmlns="http://schemas.microsoft.com/xml-script/2005">
        <components>
       <dataSource id="EmployeeDataSource" serviceURL="EmployeeDataService.asmx" >
        </dataSource>
          
          <listView id="searchResults" itemTemplateParentElementId="searchResults_layoutTemplate" >
            <bindings>
              <binding dataContext="EmployeeDataSource" dataPath="data" property="data" />
            </bindings>
            <layoutTemplate>
              <template layoutElement="searchResults_layoutTemplate" />
            </layoutTemplate>
            <itemTemplate>
              <template layoutElement="searchResults_itemTemplate">
                <label id="searchResults_ID">
                  <bindings>
                    <binding dataPath="Id" transform="Add" property="text" />
                  </bindings>
                </label>
                <label id="searchResults_Name">
                  <bindings>
                    <binding dataPath="Name" property="text" />
                  </bindings>
                </label>
                <label id="searchResults_Address">
                  <bindings>
                    <binding dataPath="Address" property="text" />
                  </bindings>
                </label>
              </template>
            </itemTemplate>
            <separatorTemplate>
                 <template layoutElement="searchResults_separatorTemplate" />
            </separatorTemplate>
            <emptyTemplate>
                <template layoutElement="NoDataTemplate" />
            </emptyTemplate>
          </listView>
          
          <application>
            <load>
                <invokeMethodAction target="EmployeeDataSource" method="load" />
            </load>
        </application>  
        </components>
      </page>
</script>                    

In the first lines of code in bold, we have define a dataSource to be used in the following components. Note here that although not explicitly declared, the ServiceType property of this dataSource has been set to DataService. From the second part of code in bold, we start the concrete data binding, with property dataContext to specify the data source of ListView, dataPath to specify the binding property of the source, property to specify the bound property of the target. And further, we start to bind property Id of to property text of label searchResults_ID, property Name of to property text of label searchResults_Name, and property Address of to property text of label searchResults_Address. In the first binding, we introduce a transformer of type Add (there are several types, refer to the source code of class Sys.Preview.BindingBase in file PreviewScript.js). Since the value of property DataIndex exposed by DataTable (the data format bound to ListView when data from DataService arrives at the client side) starts from 0, using of Add transformer can automatically lead to its value plus 1, which will rather adapt to the flavors of common users. The final <application> block tells the system to automatically invoke the load method of data source EmployeeDataSource. Why load and what behind load? Please find the answer in the DataService discuss above.

Harvesting

It is no use wasting more words, so just see the final run-time screenshot in Figure 3.

Figure 3

When the sample application starts up, the data bindings automatically happen and then the ListView control gets rendered on the screen.


View Entire Article

User Comments

Title: binding the listview   
Name: silo
Date: 2010-08-02 8:14:52 AM
Comment:
the sample code has a crc error when i try to extract it.






Community Advice: ASP | SQL | XML | Regular Expressions | Windows


©Copyright 1998-2024 ASPAlliance.com  |  Page Processed at 2024-04-25 3:28:58 AM  AspAlliance Recent Articles RSS Feed
About ASPAlliance | Newsgroups | Advertise | Authors | Email Lists | Feedback | Link To Us | Privacy | Search