Practical ASP.NET

Handling Multiple Records in the Client

Peter moves on from working with one record to working with multiple records and explores Microsoft's current templating solution.

Two columns back (Retrieving and Displaying a Single Object with dataView and WCF) I downloaded the data for a single Customer object from my Web service using only client-side code. In my last column (Updating Data with the dataContext and WCF Data Services) I enabled updates for that single record, again using only client-side code. In this column, I'll retrieve and handle updates for multiple records: All the orders for a Customer (though I'll only work with two properties: OrderID and ShipCity)

The first step is to create a table with a body that can repeat table rows for each Order that's retrieved. There's nothing here that I haven't discussed in those previous columns:

<table>
  <thead><tr><td>Order Id</td><td>Ship To</td></tr></thead>
  <tbody id="ordData" class="sys-template">
    <tr>
      <td>{{OrderID}}</td>
      <td>
       <input id="orderDate" type="text" sys:value="{binding ShipCity}"/>
      </td>
    </tr>
  </tbody>
</table>

Now I need to create a dataView and bind it to the table body, the dataContext, and the method that will supply me with Order objects (which, since I'm using a WCF Data Service, is just called "Orders"). Again, there's nothing here not discussed in the previous columns:

vOrds = Sys.create.dataView("#ordData",
 {
  dataProvider: dNwind,
  fetchOperation: "Orders"
 });

Finally, I need to specify which Order objects to retrieve by adding some code to the method I'm calling when the user selects a Customer from the drop down list. Again, this new code is very similar to the code I used to retrieve a single object:

var custId = ddl.options[ddl.selectedIndex].value;
var parms = { $filter: "CustomerID eq '" + custId + "'" };
vOrds.set_fetchParameters(parms);
vOrds.fetchData();

And that's it: I have a table displaying the orders for the customer selected in the drop down list. Now it's time to allow updates.

Adding Updates
Saving changes that the user makes to existing orders in the table is easy: As before, I just call the SaveChanges method on my dataContext object. The dataContext and dataView will transfer the new values out of the table and back to my WCF Web Service which will update my database. For inserts, I could try and add a blank row into my table for users to enter new order information. But it's a lot easier to add a second table of text boxes to the page right below my order table and let the user add new values there. So that's what I did.

Deletes are more complicated, however. For deletes, I need to know which Order the user wants to delete. To do that, I first set the onCommand property on my dataView to the name of a function. Whenever one of the predefined commands in the dataView is fired, this method will be called. Here, I've used a function I've called onHandleOrder:

vOrds = Sys.create.dataView("#ordData",
          {
           dataProvider: dNwind,
           fetchOperation: "Orders",
           onCommand: onHandleOrder
          });

To get one of those commands raised, I need to add the sys:command attribute to an element in my Orders table. I added another column to my table and put a button in it. Adding the sys:command attribute, set to "Delete", to the button causes the button to raise the dataView's Delete command. I also add the sys:commandargument attribute to the button, which allows me to specify an argument to be passed to my function. For the commandargument, I'm using the predefined $index value, which returns the position of the data item bound to this row:

<tbody id="ordData" class="sys-template">
 <tr>
  <td>
    <input type="button" sys:command="Delete" 
           sys:commandargument="{{$index}}" value="Delete"/> 
  </td>
  <td>{{OrderID}}</td>
  …rest of table…

My onHandleOrder function has to accept a single parameter (which I've called args). This args parameter is used to pass the command name and argument. If the command name is "Delete", I retrieve the position of the data item from the command argument. As I did when deleting a customer in my last column, I can use that to retrieve the data item from the dataView, use that item with the dataContext's removeEntity method to mark the item for deletion, and save my changes which will update the database:

function onHandleOrder(args) 
{
 switch (args.get_commandName()) 
 {
  case "Delete":
    var idx = args.get_commandArgument();
    var enty = vOrds.get_data()[idx];
    dNwind.removeEntity(enty);
    dNwind.saveChanges();
  }

And I'm done

I've ignored a whole bunch of stuff in this project. Templating has special support for creating master/detail forms, for instance, which I may look at in a later column. As the syntax for my delete function suggests, I could have put all of my update code in that function. And I've ignored the other dataView commands ("Select" is very cool).

But it's time to return to what works right now in the versions of ASP.NET that most people are using. In my next column, I'm going to pause to reflect on the future of server-side code but then it's back to "practical" ASP.NET.

About the Author

Peter Vogel is a system architect and principal in PH&V Information Services. PH&V provides full-stack consulting from UX design through object modeling to database design. Peter tweets about his VSM columns with the hashtag #vogelarticles. His blog posts on user experience design can be found at http://blog.learningtree.com/tag/ui/.

comments powered by Disqus

Featured

  • Compare New GitHub Copilot Free Plan for Visual Studio/VS Code to Paid Plans

    The free plan restricts the number of completions, chat requests and access to AI models, being suitable for occasional users and small projects.

  • Diving Deep into .NET MAUI

    Ever since someone figured out that fiddling bits results in source code, developers have sought one codebase for all types of apps on all platforms, with Microsoft's latest attempt to further that effort being .NET MAUI.

  • Copilot AI Boosts Abound in New VS Code v1.96

    Microsoft improved on its new "Copilot Edit" functionality in the latest release of Visual Studio Code, v1.96, its open-source based code editor that has become the most popular in the world according to many surveys.

  • AdaBoost Regression Using C#

    Dr. James McCaffrey from Microsoft Research presents a complete end-to-end demonstration of the AdaBoost.R2 algorithm for regression problems (where the goal is to predict a single numeric value). The implementation follows the original source research paper closely, so you can use it as a guide for customization for specific scenarios.

  • Versioning and Documenting ASP.NET Core Services

    Building an API with ASP.NET Core is only half the job. If your API is going to live more than one release cycle, you're going to need to version it. If you have other people building clients for it, you're going to need to document it.

Subscribe on YouTube