Practical ASP.NET

Retrieving and Displaying a Single Object with dataView and WCF

Continuing his investigation of what works and doesn't work with the AJAX library and .NET 4, Peter Vogel continues to explore how to retrieve data from the client... and discovers that it can be very easily done.

We're getting to the half-way point in the project where I'm building an ASP.NET page with full CRUD functionality but no code in the code file. Everything is done in the client using the JavaScript code, except for some server-side services (specifically a WCF Data Service -- it makes a difference in this column).

The page I'm building has a DropDownList (filled on the server) displaying all the customers from the Northwind database. When the user selects a customer, I want to run a JavaScript routine to retrieve a Customer object. So the first step is to attach a function in Source View to the onChange even of my DropDownList. This example adds a function called GetCustomerData:

<asp:DropDownList ID="DropDownList1" runat="server" 
   onChange="return GetCustomerData(this);"
   DataSourceID="NorthwindCustomerDataSource" 
   DataTextField="CompanyName" 
   DataValueField="CustomerID">
</asp:DropDownList>

When the GetCustomerData method is called, the function will be passed a reference to the DropDownList through the this keyword.

Before looking at the GetCustomerData function, I'll set up the HTML that will display the data. The HTML elements that I'll use are held inside a span element. That element must have its class attribute set to "sys-template" so that the dataView can find it. Inside the span tag I'll use an ASP.NET Label control to display the CustomerID and an input tag to display the CompanyName. I bind the Customer object's CustomerID property to the Text property of the Label using Microsoft's double braces syntax:

<div id="custData" class="sys-template">
 <asp:label ID="Label1" runat="server" Text="{{ CustomerID }}"/>

As discussed in my previous column (Using the dataView and dataContext: What Doesn't Work), since I'm binding to the input's value attribute, I have to add the sys: prefix to the attribute so that the dataView can find it:

  <input id="companyName" type="text" sys:value="{{CompanyName}}"/> 
</div>

Retrieving Data
Now I can write my GetCustomerData function. The function accepts the reference to the DropDownList and calls the Sys object's require method. The require method ensures that all the necessary components are downloaded before it calls an anonymous function:

function GetCustomerData(ddl) 
{
  Sys.require([Sys.components.dataView, Sys.components.adoNetDataContext], 
  function () 
  {

My first step in retrieving data from my Service is to create an adoNetDataContext object that points to the Service:

dNwind = Sys.create.adoNetDataContext(
  {
   serviceUri: "NorthwindDataServices.svc"
  });

A dataView handles moving the data from the dataContext to the HTML objects that will display the data. When creating the dataView I pass the value of the HTML object's id attribute and specify both the dataContext I'm using and the method on the Web Service that I'll call:

vCust = Sys.create.dataView("#custData",
  {
   dataProvider: dNwind,
   fetchOperation: "Customers"
  });

I'm just about ready to fetch data through the dataView, which will in turn call the dataContext and retrieve the objects. I have to pass a parameter to the dataView that specifies the Customer object that I want. This is the point at which it makes a difference that the Web service that I'm using is a WCF Data Service.

I can call my WCF Data Service (see Creating a WCF Data Service), which draws on an Entity Framework model based on the Northwind database, so I can retrieve the entity for customer ALFKI. I'd just use this URL, which includes the predefined keyword $filter:

http://MyServer/MySite/NorthwindDataServices.svc/Customers?$filter='ALFKI'

However, all I need to pass to the dataContext is the querystring that goes at the end of the URL. I build the querystring in my function and then pass it to the dataView's set_fetchParameters method:

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

Once I've done that, I can call the fetchData method on the dataView to populate the HTML elements in the span tag:

vCust.fetchData();

I have to be honest: If you look in the download, you'll see that I actually create my dataContext and dataView as soon as the page is loaded. In the GetCustomerData method, I just set the parameters and call the dataView's fetchData method. But, no matter how I divide the code up, with only 16 lines of code in the client I've got a faster, more responsive application that makes fewer demands on the server than I would with standard ASP.NET processing.

Except of course, nothing is being updated... yet. That's my next column!

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

Subscribe on YouTube