Practical ASP.NET
Working With a Client-Side AJAX Control
If you're going to work with AJAX you should be, at least, considering using "pure" client-side code to create your UI. Peter looks at a popular (and free) JavaScript grid.
An
earlier column on ASP.NET MVC led to a discussion about working with JavaScript client-side controls. I'm returning to that topic to walk through using a client-side control in ASP.NET or ASP.NET MVC. As you'll see, the major difference (at least from my point of view) in working with the client-side controls is the absence of wizards and designers. You're going to have to type everything in yourself.
I use ExtJs, a popular (and very functional) set of client-side widgets. In this column, I'm going to look at the code you'd need in an ASP.NET page to get the grid shown in Figure 1 to display data retrieved from a Web service using JSON objects. To start using ExtJs, download the package here, unzip it, and copy the ext-all.js file, ext-base.js, and ext-all.css files into folders in your ASP.NET project (adding JavaScript libraries is the equivalent of adding items to your toolbox).
[Click on image for larger view.] |
Figure 1. This grid, built using a JavaScript client-side control, is displaying data retrieved from an ASMX Web Service. |
To support getting data to the client-side control, I created a Web Service to return Customer objects from the Northwind database, using Entity Framework and LINQ (mostly because it was easy that way). My Webmethod returns a data transfer object called CustomerDTO. I put this code in an ASMX file because it's harder to get ASMX files to return JSON objects so that I can demonstrate the solution later in this column:
<WebServiceBinding(ConformsTo:=WsiProfiles.BasicProfile1_1)> _
<ScriptService()> _
<Global.Microsoft.VisualBasic.CompilerServices.DesignerGenerated()> _
Public Class NorthwindCustomers
Inherits System.Web.Services.WebService
<WebMethod()> _
Public Function GetCustomers() As List(Of CustomerDTO)
Dim nw As New northwndModel.northwndEntities
Dim res = From cust As northwndModel.Customers _
In nw.Customers _
Select New CustomerDTO With { _
.ContactName = cust.CustomerID, _
.CustomerId = cust.CustomerID}
Return res.ToList
End Function
End Class
<Serializable()> _
Public Class CustomerDTO
Private _ContactName As String
Private _CustomerID As String
Sub New()
End Sub
Public Sub New(ByVal ContactName As String, _
ByVal CustomerID As String)
_ContactName = ContactName
_CustomerID = CustomerID
End Sub
Public Property ContactName() As String
Get
Return _ContactName
End Get
Set(ByVal value As String)
_ContactName = value
End Set
End Property
Public Property CustomerId() As String
Get
Return _CustomerID
End Get
Set(ByVal value As String)
_CustomerID = value
End Set
End Property
End Class
In the browser, I added some tags to pick up the ExtJs script libraries and cascading stylesheets -- the equivalent of dragging the controls onto the page:
<script type="text/javascript"
src="Scripts/ext/ext-base.js"></script>
<script type="text/javascript"
src="Scripts/ext/ext-all.js"></script>
<link rel="stylesheet" type="text/css"
href="CSS/ext-all.css"/>
At a high level, there's a lot of similarity between the server side controls you're used to and client side control. To retrieve data from a Web Service, instead of a DataSource, you need an HttpProxy to call your Web Service, a JsonReader to process the objects returned, and a data Store to pull the two together. I created a function, tied it to the onclick event of a button on my page, and wrote that code:
var dsCustomer;
var colCustomer;
var proxyCustomer;
var readerCustomer;
var gridCustomer;
var windowCustomer;
function getCustomers() {
proxyCustomer = new Ext.data.HttpProxy({
url: "NorthwindCustomers.asmx/GetCustomers",
method: "POST",
headers: {"Content-type": "application/json"}
});
readerCustomer = new Ext.data.JsonReader({
root: "d",
idProperty: "CustomerId",
fields: ["CustomerId", "ContactName"]
});
dsCustomer = new Ext.data.Store({
id: "dsCustomer",
proxy: proxyCustomer,
reader: readerCustomer});
The HttpProxy requires the most explanation. Its url property must be set to the name of the ASMX file and the WebMethod that you want to call; the method property must be set to POST (the HttpProxy defaults to GET), and the headers property must be set as shown to get the ASMX file to return JSON objects. On the JsonReader, if you're returning a collection, you must set the root property to the letter "d" to support the convention for returning collections.
The next step is to create a ColumnModel that defines columns for the grid. That requires specifying, for each column, its header and the property from the JSON object to display. Once the column is defined, you can define a grid (in my case, I'm using an EditorGridPanel) by bringing together your data Store and your ColumModel:
colCustomer = new Ext.grid.ColumnModel([
{ header: "Customer ID", dataIndex: "CustomerId"},
{ header: "Contact Name", dataIndex: "ContactName"}
]);
gridCustomer = new Ext.grid.EditorGridPanel({
id: "CustomerGrid",
store: dsCustomer,
cm: colCustomer,
height: 225
});
I could just have had the grid generate its HTML into an element on the page but I decided to use an ExtJs Window to display the grid (very much like putting a GridView into a Panel). I gave the Window a name, a width (slightly larger than the total width of my grid's columns), a height and, finally, pointed it at my grid:
windowCustomer = new Ext.Window({
id: 'CustomerWindow',
title: 'Northwind Customers',
width: 235,
height: 250,
items: gridCustomer});
Again, this bears at least a passing familiarity to creating a GridView and binding it to a DataSource.
The last two steps are to load the data Store and display the Window (sort of like calling the DataBinding method on a DataView):
dsCustomer.load();
windowCustomer.show();
The result is shown in Figure 1. Of course, this is the only first step in building a client side control to go into your ASP.NET or ASP.NET MVC page. The next steps are to allow the user to do updates, deletes, and inserts. I'll be back.
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/.