Tasklist Tutorial

Date: 2008-01-27
Author: Mike Amundsen

Abstract

In this tutorial you'll learn how to use the exyus engine to build a simple task list web application. This also covers the process of defining HTTP resources using the XmlFileResource base class that supports basic REST constraints. In addition, you'll learn how to define XSL and XSD documents to handle mime-types and PUT/POST validations for the resource. Finally, you'll see examples of simple client scripting and CSS to add client-side functionality and styling to the web app.

You can test the online version of the TaskList application.

Feedback and comments are welcome via the Exyus Discussion Group.

Introduction

01-composite The process of implementing a this Task List web application is fairly simple. First, you need to determine the data you wish to capture as a "task" object along with the functionality you want to support (adding, editing, and deleting tasks from a list). In this example, HTML will be one of the supported content types. That means you need to create a minimal XHTML markup to support displaying and updating the list of tasks.Eventually, you need to add client scripting to support the determined actions and CSS styles to lend a better 'look and feel' to the app.

Along with the client-side work of authoring an HTML UI w/ scripting and styles, you need to implement a server-side HTTP resource to respond to the HTTP methods and support the accepted content types. In this example, the HTTP resouce will be built using the XmlFileResource base class. That means the data will be stored on the server in a structured (XML) file. The XmlFileResource class uses XSL transforms for each supported content-type to render responses to the client. In this case, you need to create transforms to render XHTML and XML to the client. The XmlFileResource class also uses XSD schema to validate content sent to the server via HTTP PUT and POST. For the purposes of this tutorial, we'll only support POST for HTML FORMS. We'll support both POST and PUT for the XML content-type. This is an arbitrary decision that makes the article a bit shorter, but still illustrates how the exyus engine can be used to support multiple content-types for the same HTTP resource.

Once the server and client resources are implemented, you need to also configure the exyus engine to set the authentication and authorization rules for the new HTTP resource.

top

Basic Functionality

02-xml-task-objects.JPG Before deailing with the details of coding, the first step is to explicitly outline the data elements to work with, the content-types you wish to support, and the actions you plan to allow for the resource. You also need to determine the URL patterns to which the HTTP resource will respond. Once these decisions are made, implementing the HTTP resource and authoring the transforms and validators will be fairly straight-forward.

The Task Object

For this example, a single "task" object is needed to track a set of tasks in a list. To make this as simple as possible, this web app will need only three elements of data:

  1. task id
  2. task name
  3. completed flag

Since this example will use the XmlFileResource class, we need to define an XML document that will represent the data elements above. Here is a simple XML document definition for the task object:

<task>
  <name />
  <is-completed />
</task>

Note that the XML document does not include an id element. The XmlFileResource creates unique id elements for all data sent via the HTTP POST command. We'll use this unique value as the id for the task.

Content Types Supported

One of the key features of the exyus engine is that it makes it relatively easy to support multiple content-types for the same HTTP Resource URL. For this example, we'll support both HTML and XML as content-types. HTML will be used as the default type to make it easy for Web browsers to interact with the resource. The XML content-type will make is possible to use javscript and the XmlHttpRequest object to provide an Ajax interface to the task data.

It should be noted that XML (text/xml) is not a very useful "content type" for building HTTP applications. Other content types that would be more useful would be Atom (application/atom+xml) or RDF (application/rdf+xml). However, for this example, we'll use XML to keep things as simple as possible. If you wish, you can use this example as a starting point to add support for your favorite content type.

Action Matrix

The "action matrix" is a simple table that shows the actions supported for the HTTP resource along with the content-types, document bodies exchanged and the typical response code. This matrix will be used to implement the actual resouce class and it's associated transforms and validators. The action matrix also details the URL patterns supported by the HTTP resource. The exyus engine allows you to map URL patterns directly to the resource class. This is how the web server handles dispatching HTTP requests at runtime.

Since our example will support the actions of add, edit, and delete for tasks objects, we will need to provide support for the GET, POST (add), PUT (update), and DELETE HTTP methods. GET will return either a list of tasks or a single task (if the task id is part of the URL). POST and PUT will expect the task data as input. And DELETE will use the task id in the URL.

Below is the action matrix for our example task object.

Method URL Content Type Request Body Response Body Status
GET /tasklist/ text/html task list and form 200, 404
text/xml task list
/tasklist/{taskid} text/html task object
text/xml task object
POST /tasklist/ application/x-www-form-urlencoded name/value pairs 302, 400
text/xml task xml document
PUT /tasklist/{taskid} text/xml task xml document 200, 400, 404
DELETE /tasklist/{taskid} text/xml 200, 404
top

XHTML MarkUp

03-html-markup.JPG Since this example will support HTML Web browsers, we need to build an HTML page that will show the list of current tasks, and their status. It should also show controls to add a new task, change the status of a task, and delete a task. Below is a minimal HTML markup that contains all the elements that are needed:

<?xml version="1.0" encoding="utf-8"?>
<html xmlns="http://www.w3.org/1999/xhtml">
  <head>
    <!-- simple markup example for task list -->
    <title>my task list</title>
  </head>
  <body>
    <h1>my task list</h1>
    <ul>
      <li>
        <a href="#">o</a>
        <a href="#">x</a>
        <span>task 1</span>
      </li>
      <li>
        <a href="#">o</a>
        <a href="#">x</a>
        <span>completed task</span>
        <span>[d]</span>
      </li>
    </ul>
    <form method="post" action=".">
      <fieldset>
        <legend>Add a Task</legend>
        <input type="text" name="name" value="" />
        <input type="hidden" name="is-completed" value="0" />
        <input type="submit" value="add task" />
      </fieldset>
    </form>
  </body>
</html>

A more complete document that includes all the ncessary 'hooks' for attaching javascript events and CSS styles can be viewed here.

top

The Server Resource

04-taskedit.JPG Once the action matrix and the client markup are completed, you can implement the server-side HTTP Resource with which clients can interact. All resource classes within the exyus engine have a pre-determined set of methods. These are:

As you can see from the list above, these methods correspond to the standard HTTP commands. The exyus engine automatically routes HTTP requests to the resource to the appropriate method. This is handled by 'decorating' the resource class with the UriPatterns attribute (see the sample code below). Adding these patterns is all you need to do. There is no need for a "resource map" or any other code to handle request routing.

The base classes are also designed to make it relatively easy to add support for multiple content types. This is handled by adding a list of content-types (via the MediaTypes attribute) to the definition of the class. Like the UriPatterns attribute, this is a direct association and there is no other code needed in order to inidicate support for one or more content types.

The exyus engine also supports standard caching directives to optimize client-server interactions. This is handled via functions in the Cache.cs class that are called within the handling of the GET and HEAD requests. The IsCachedResouceValid() and CacheResource() methods are available for handling this step.

This version of exyus is built for ASP.NET over IIS running on Windows XP and higher. The runtime was written in C# 2.0 using Visual Studio. However, to build and run this sample, you only need the command-line C# compiler and a running version of IIS with ASP.NET 2.0 installed. You also need to download and configure the exyus runtime for you web server.

Building the TaskList.cs Class

For the task list example, we'll use the XmlFileResource class since it is very easy to set up. Using the action matrix from above, we can also set the URI pattern, content-type, and support for HTTP methods all in the class declaration. You can view the C# source code for the TaskList.cs resource class online. This is all the compiled code that is needed in order to publish an HTTP resource that supports GET, POST, PUT, and DELETE methods.

Note that the DocumentsFolder and the StorageFolder values have been initialized to the location of the XSL/XSD documents and the file storage locations, respectively. When you install this HTTP resource on the server, you need to make sure these physical folders exist on the web server.

Once the HTTP resource has been compiled as a .NET assembly, you need to copy that assembly DLL to the BIN folder at the root of the ASP.NET web application. For standard installations, this is the /exyus/bin/ folder.

Configuring the TaskList Resource

Before you can access the /tasklist/ resource on the web server, you need to configure the proper security. There are two steps in this process. First you need to configure the URL for authentication and second, you need to configure the URL for authorization (access rights).

Setting the authentication for a URL is done by making an entry in the config/auth-urls.xml file. The line below shows how to configure the /tasklist/ URL to allow anonymous users to access the resource:

<url path="/xcs/tasklist/" auth="false" />

Setting the authorization for a URL is done by making an entry in the config/auth-users.xml file. Add the line below to the anonymous user's list of permissions. Ths will grant authorization to all users for all the standard HTTP methods (GET, POST, PUT, and DELETE):

<permission path="/xcs/tasklist/" methods="*" />
NOTE: Usually resources that allow users to edit server objects will be set to require authentication. But for the purposes of this example, we'll allow all users to edit the task list.

Once you have compiled and configured the HTTP resource, you're ready to create the XSL transforms and XSD validators for the resource to use at runtime.

top

The XSL Transforms

05-xsl-edit.JPG Many of the HTTP Resource classes in the exyus engine use XSL transform documents to handle incoming requests and format outgoing responses. Transforms are used in three important cases:

  1. Interpreting the URL of an incoming request
  2. Transforming the body of an incoming request
  3. Transforming the content of the outgoing response

Handling Arguments

When exyus recieves an HTTP request, the URL is broken down into a set of parameters that can be used throughout the processing of the request itself. Other information about the request is also available including any HTTP cookies, the username of the logged in user, the arugments passed in the query string of the URL, etc.

It is common to create an XSL transform to inspect the URL of incoming requests to return the document id on the URL. This value is required for the HTTP PUT command and is also useful for the HTTP GET and HTTP DELETE commands. The document id is forbidden for most HTTP POST commands. For this example application, we'll need this transform to make sure the document id is present in the URL for only the appropriate HTTP methods.

To support this transform, you need to create a file in the resource's Documents folder (see the DocumentsFolder setting on the C# class above) called args.xsl. You can view the contents of the args.xsl file online. Notice that the XSL transform expects an incoming xsl:param named taskid. This is the same parameter outlined in the UriPattern associated with the TaskList.cs resource class created in the previous section.

XML GET Responses

Since the resource is marked to support both text/html and text/xml content types, we need to create XSL transform documents that will supply the proper responses for the HTTP Get methods. Like most resources, the GET method is used to return either a list of items (GET /tasklist/) or a single item (GET /tasklist/{taskid}). For the text/xml transform, we need to write code that supports both these "modes" of the GET request.

The runtime looks for transform documents named based on three indicators:

  1. HTTP Method (GET)
  2. Command state (request or response)
  3. content-type (XML, HTML, etc.)

For this example, the document used to transform the output of a GET request for a content-type XML query from a client will be named: get_response_xml.xsl. Note that the three key indicators are used to build up the name of the document: [method]_[state]_[type].xsl. All XSL transform documents for exyus use this naming pattern. You can view the contents of the get_response_xml.xsl file online. This file must be placed in the Documents folder as defined for the resource.

You can view typical XML output from this transform for a list request (GET /tasklist/) and for a single item request (GET /tasklist/123)

Note that the XSL transform uses the $_mode parameter to determine whether the request for a list of tasks or a single task object. Also note that the XSL transform uses the XSLT document() function to access the contents of the stored objects in the file system.

HTML GET Responses

The get_response_html.xsl document controls the output of GET requests sent by clients that accept the text/html content type. This transform (placed in the Documents folder) is a bit more involved than the transform for the XML content type. In this case, the transform needs to return valid XHTML that contains not only the list of tasks, but also an HTML FORM that can be used to POST new task objects to the server.

Notice that the checked-in version of the transform includes added markup for CSS and Javascript files as well as additional content for the live demo. These items are not essential for the transform and are included as part of this example to complete the online demo.

FORM POST Requests

The last XSL transform needed for this example is the post_request_form.xsl document. This transform converts the incoming values POSTed from the HTML form into a valid task object for storage on the disk. This document assumes that all values posted form an HTML form will be supplied as an XML document in the following format:

<form>
  <name1>value1</name1>
  <name2>value2</name2>
  ...
</form>
This process of converting the urlencoded body of the HTML form POST into an XML document is automatically handled by the exyus engine.
top

The XSD Validators

06-xsd-edit.JPG Along with XSL transforms, the XmlFileResource class uses XSD Schema documents to validate incoming documents. In the previous section you learned that the exyus engine automatically converts POSTed HTML form values into a valid XML document (with the root of form). Other typical content types (XML, Atom, RDF) can also post valid XML documents. In this section, you'll learn how to create and save XSD Schema documents that can be used at runtime.

Like the naming pattern for XSL transforms, exyus expects XSD documents to follow a standard pattern that includes:

  1. HTTP Method
  2. Content Type

For example, the XSD document that will be used to validate data sent to the server using the HTTP PUT method with a content-type header of text/xml will be named: put_xml.xsd. Similarly, the document for data sent using an HTML FORM POST will be named: post_form.xsd. So, the pattern for naming XSD validators is [method]_[type].xsd. As with XSL transform documents, all validators need to be placed in the Documents folder for the resource class.

The actual content-type for HTML FORM POST is application/x-www-form-urlencoded. However, the XSD filename pattern uses "form." The exyus engine uses a configuration file (config/media-types.xml) to associate content-types with a file keyword. Adding support for a new content-type is easy. You just need to make a new entry in the config/media-types.xml and start using that keyword for your XSL and XSD documents.

XML POST and XML PUT

This example application supports both POST and PUT for the text/xml content type. That means two documents are needed: post_xml.xsd and put_xml.xsd. The validators will automatically be called when clients send data to the server via then PUT and POST methods. If the contents of the HTTP body is invalid, an error will be returned. You can view an example of an invalid POST online.

top

The Client Script and CSS Styles

07-js-edit.JPG The final step in completing this example web application is adding some client scripting and CSS styles to the HTML representation of the task list. These are only referenced for the HTML version since the XML content-types do not need them.

Adding Client Script

In this example, client script is needed for the HTML version to handle the "update" and "delete" actions for the user interface. The "add" action is handled by the FORM POST and requires no script. However, this script also performs a client-side validation of the inputs before completing the POST. The update and delete actions are handled using the XmlHttpRequest object (Ajax scripting) library.

There are only a few 'interesting' methods in the tasklist.js file. They are:

  1. validateForm()
  2. updateItem()
  3. deleteItem()

You can view the complete tasklist.js file online. Note the use of the ajax.httpHead() method to retrieve the ETag header of an item before attempting to update it. This prevents other user's edits from overwriting the current update.

Styling the UI w/ CSS

The final step is to add CSS styles to the HTML document to improve the 'look and feel' of the application. Unlike the javascript file, which is required to complete the functionality of this web app, none of the styles are needed to operate the application - they just enhance the user experience. You can view the contents of the tasklist.css file online.

If you are using a browser that allows you to turn CSS styles off (Opera, Firefox, etc.), you can test the online version of the TaskList application. both with and without the CSS styles.
top

Summary

01-composite In this article, you learned how to use the exyus engine to build HTTP applications that comply with REST constraints. You learned how to create an "action matrix" to detail the client-server interactions and how to use the base classes in the exyus engine to create C# classes that include all the important details from the action matrix including the UriPatterns, MediaTypes, and which HTTP methods are supported. The use of XSL transforms and XSD schema documents to support processing both incoming requests and outgoing responses was also covered. Finally, you go to see how you can add code-on-demand using javascript and CSS styles to the HTML responses of the HTTP resource.

The aim of this article was to illustrate the power and flexibility of HTTP programming with REST constraints as well as how you can use the exyus engine to implement HTTP/REST with relative ease. Hopefully, this small example will encourage you to use HTTP/REST and exyus when building your future web applications.

top

About the Author

Mike Amundsen Mike Amundsen lives and works as a contract programmer in Kentucky, USA. He currently spends most of his time creating and supporting large-scale web sites running under Windows and ASP.NET. In the past, he spent quite a bit of time as a trainer/speaker and was involved in the writing of several books on programming with Microsoft technologies.