ÿþ<?xml version="1.0" encoding="utf-8"?> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <title>Tasklist Tutorial</title> <base href="http://exyus.com/articles/tasklist/" /> <style type="text/css"> table.matrix { border: 1px solid black; } table.matrix th, table.matrix td { color:black; background-color:silver; padding: .2em; } table.matrix td { background-color:#e6e6e6; vertical-align:top; } div.section { margin: 1em 0; } div.abstract, pre { border:1px solid black; background-color:#e6e6e6; padding: .3em; margin-bottom: 1em; } div.abstract { margin-top: 1em; } blockquote { border:1px solid black; background-color:silver; color:black; padding: .3em; font-style:italic; } code { font-style:normal; } h1,h2,h3 { margin: 0; } p { margin-top:0; } address { font-size:smaller; } img { border:no; float:right; border: 1px solid black; } </style> </head> <body> <h1>Tasklist Tutorial</h1> <address class="doc-info"> Date: 2008-01-27<br/> Author: <a href="http://amundsen.com/blog" title="mca blog" target="_blank">Mike Amundsen</a> </address> <div class="abstract"> <h2>Abstract</h2> <p> In this tutorial you'll learn how to use the <a href="http://exyus.com" title="exyus">exyus</a> engine to build a simple task list web application. This also covers the process of defining HTTP resources using the <a href="http://exyus.googlecode.com/svn/trunk/exyus/Resources/XmlFileResource.cs" title="XmlFileResource" target="_blank">XmlFileResource</a> base class that supports basic <a href="http://en.wikipedia.org/wiki/Representational_State_Transfer" title="Representationl State Transfer" target="_blank">REST</a> 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. </p> <p> You can test the online version of the <a href="http://exyus.com/xcs/tasklist/" title="TaskList" target="_blank">TaskList</a> application.</a> </p> <p> Feedback and comments are welcome via the <a href="http://groups.google.com/group/exyus" title="Exyus Discussion Group">Exyus Discussion Group</a>. </p> </div> <div class="menu"> <h2>Sections</h2> <ul> <li><a href="#Introduction" title="Introduction">Introduction</a></li> <li><a href="#Functionality" title="Functionality">Basic Functionality</a></li> <li><a href="#MarkUp" title="MarkUp">XHTML MarkUp</a></li> <li><a href="#Resource" title="Resource">The Server Resource</a></li> <li><a href="#Transforms" title="Transforms">The XSL Transforms</a></li> <li><a href="#Validators" title="Validators">the XSD Validators</a></li> <li><a href="#Client" title="Client">The Client Script and CSS Styles</a></li> <li><a href="#Summary" title="Summary">Summary</a></li> <li><a href="#Author" title="Author">About the Author</a></li> </ul> </div> <div class="section"> <h2><a name="Introduction" title="Introduction">Introduction</a></h2> <p> <a href="http://lh6.google.com/amundsen.mike/R50-MZev0kI/AAAAAAAABAU/O7QuqJHO8VE/01-composite.JPG?imgmax=720" title="01-composite" target="_blank"> <img src="http://lh6.google.com/amundsen.mike/R50-MZev0kI/AAAAAAAABAU/O7QuqJHO8VE/s144/01-composite.JPG" title="01-composite" alt="01-composite" /> </a> 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. </p> <p> 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 <a href="http://exyus.googlecode.com/svn/trunk/exyus/Resources/XmlFileResource.cs" title="XmlFileResource" target="_blank">XmlFileResource</a> base class. That means the data will be stored on the server in a structured (XML) file. The <a href="http://exyus.googlecode.com/svn/trunk/exyus/Resources/XmlFileResource.cs" title="XmlFileResource" target="_blank">XmlFileResource</a> 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 <a href="http://exyus.googlecode.com/svn/trunk/exyus/Resources/XmlFileResource.cs" title="XmlFileResource" target="_blank">XmlFileResource</a> 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 <a href="http://exyus.com" title="exyus" target="_blank">exyus</a> engine can be used to support multiple content-types for the same HTTP resource. </p> <p> Once the server and client resources are implemented, you need to also configure the <a href="http://exyus.com" title="exyus" target="_blank">exyus</a> engine to set the authentication and authorization rules for the new HTTP resource. </p> <a href="#top" title="top">top</a> </div> <div class="section"> <h2><a name="Functionality" title="Functionality">Basic Functionality</a></h2> <p> <a href="http://lh6.google.com/amundsen.mike/R50-LZev0jI/AAAAAAAABAM/L1BqXeK3toA/02-xml-task-objects.JPG?imgmax=576" title="02-xml-task-objects.JPG" target="_blank"> <img src="http://lh6.google.com/amundsen.mike/R50-LZev0jI/AAAAAAAABAM/L1BqXeK3toA/s144/02-xml-task-objects.JPG" title="02-xml-task-objects.JPG" alt="02-xml-task-objects.JPG" /> </a> 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. </p> <h3>The Task Object</h3> <p> 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: <ol> <li>task id</li> <li>task name</li> <li>completed flag</li> </ol> </p> <p> Since this example will use the <a href="http://exyus.googlecode.com/svn/trunk/exyus/Resources/XmlFileResource.cs" title="XmlFileResource" target="_blank">XmlFileResource</a> 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: <pre>&lt;task&gt; &lt;name /&gt; &lt;is-completed /&gt; &lt;/task&gt;</pre> </p> <p>Note that the XML document does not include an <code>id</code> element. The <a href="http://exyus.googlecode.com/svn/trunk/exyus/Resources/XmlFileResource.cs" title="XmlFileResource" target="_blank">XmlFileResource</a> creates unique id elements for all data sent via the HTTP POST command. We'll use this unique value as the <code>id</code> for the task. </p> <h3>Content Types Supported</h3> <p> One of the key features of the <a href="http://exyus.com" title="exyus" target="_blank">exyus</a> 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. </p> <blockquote> It should be noted that XML (<code>text/xml</code>) is not a very useful "content type" for building HTTP applications. Other content types that would be more useful would be Atom (<code>application/atom+xml</code>) or RDF (<code>application/rdf+xml</code>). 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. </blockquote> <h3>Action Matrix</h3> <p> 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 <a href="http://exyus.com" title="exyus" target="_blank">exyus</a> engine allows you to map URL patterns directly to the resource class. This is how the web server handles dispatching HTTP requests at runtime. </p> <p>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. </p> <p> Below is the action matrix for our example task object. </p> <table class="matrix"> <thead> <tr> <th>Method</th> <th>URL</th> <th>Content Type</th> <th>Request Body</th> <th>Response Body</th> <th>Status</th> </tr> </thead> <tbody> <tr> <td rowspan="4">GET</td> <td rowspan="2">/tasklist/</td> <td>text/html</td> <td></td> <td>task list and form</td> <td rowspan="4">200, 404</td> </tr> <tr> <td>text/xml</td> <td></td> <td>task list</td> </tr> <tr> <td rowspan="2">/tasklist/{taskid}</td> <td>text/html</td> <td></td> <td>task object</td> </tr> <tr> <td>text/xml</td> <td></td> <td>task object</td> </tr> <tr> <td rowspan="2">POST</td> <td rowspan="2">/tasklist/</td> <td>application/x-www-form-urlencoded</td> <td>name/value pairs</td> <td></td> <td rowspan="2">302, 400</td> </tr> <tr> <td>text/xml</td> <td>task xml document</td> <td></td> </tr> <tr> <td>PUT</td> <td>/tasklist/{taskid}</td> <td>text/xml</td> <td>task xml document</td> <td></td> <td>200, 400, 404</td> </tr> <tr> <td>DELETE</td> <td>/tasklist/{taskid}</td> <td>text/xml</td> <td></td> <td></td> <td>200, 404</td> </tr> </tbody> </table> <a href="#top" title="top">top</a> </div> <div class="section"> <h2><a name="MarkUp" title="MarkUp">XHTML MarkUp</a></h2> <p> <a href="http://lh4.google.com/amundsen.mike/R50-K5ev0iI/AAAAAAAABAE/dTphEqAjWms/03-html-markup.JPG?imgmax=576" title="03-html-markup.JPG" target="_blank"> <img src="http://lh4.google.com/amundsen.mike/R50-K5ev0iI/AAAAAAAABAE/dTphEqAjWms/s144/03-html-markup.JPG" title="03-html-markup.JPG" alt="03-html-markup.JPG" /> </a> 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: </p> <pre>&lt;?xml version="1.0" encoding="utf-8"?&gt; &lt;html xmlns="http://www.w3.org/1999/xhtml"&gt; &lt;head&gt; &lt;!-- simple markup example for task list --&gt; &lt;title&gt;my task list&lt;/title&gt; &lt;/head&gt; &lt;body&gt; &lt;h1&gt;my task list&lt;/h1&gt; &lt;ul&gt; &lt;li&gt; &lt;a href="#"&gt;o&lt;/a&gt; &lt;a href="#"&gt;x&lt;/a&gt; &lt;span&gt;task 1&lt;/span&gt; &lt;/li&gt; &lt;li&gt; &lt;a href="#"&gt;o&lt;/a&gt; &lt;a href="#"&gt;x&lt;/a&gt; &lt;span&gt;completed task&lt;/span&gt; &lt;span&gt;[d]&lt;/span&gt; &lt;/li&gt; &lt;/ul&gt; &lt;form method="post" action="."&gt; &lt;fieldset&gt; &lt;legend&gt;Add a Task&lt;/legend&gt; &lt;input type="text" name="name" value="" /&gt; &lt;input type="hidden" name="is-completed" value="0" /&gt; &lt;input type="submit" value="add task" /&gt; &lt;/fieldset&gt; &lt;/form&gt; &lt;/body&gt; &lt;/html&gt;</pre> <p> A more complete document that includes all the ncessary 'hooks' for attaching javascript events and CSS styles can be viewed <a href="/xcs/tasklist/source/?f=tasklist-markup.html" title="task list markup" target="_blank">here</a>. </p> <a href="#top" title="top">top</a> </div> <div class="section"> <h2><a name="Resource" title="Resource">The Server Resource</a></h2> <p> <a href="http://lh6.google.com/amundsen.mike/R50-KZev0hI/AAAAAAAAA_8/tivwVgaH3U8/04-taskedit.JPG?imgmax=576" title="04-taskedit.JPG" target="_blank"> <img src="http://lh6.google.com/amundsen.mike/R50-KZev0hI/AAAAAAAAA_8/tivwVgaH3U8/s144/04-taskedit.JPG" title="04-taskedit.JPG" alt="04-taskedit.JPG" /> </a> 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 <a href="http://exyus.com" title="exyus" target="_blank">exyus</a> engine have a pre-determined set of methods. These are:</p> <ul> <li>Get()</li> <li>Head()</li> <li>Post()</li> <li>Put()</li> <li>Delete()</li> <li>Options()</li> </ul> <p> As you can see from the list above, these methods correspond to the standard HTTP commands. The <a href="http://exyus.com" title="exyus">exyus</a> engine automatically routes HTTP requests to the resource to the appropriate method. This is handled by 'decorating' the resource class with the <a href="http://exyus.googlecode.com/svn/trunk/exyus/Uri/UriPatternAttribute.cs" title="UriPatternsAttribute">UriPatterns</a> 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. </p> <p> 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 <a href="http://exyus.googlecode.com/svn/trunk/exyus/Mime/MediaTypesAttribute.cs" title="MediaTypesAttribute.cs">MediaTypes</a> attribute) to the definition of the class. Like the <a href="http://exyus.googlecode.com/svn/trunk/exyus/Uri/UriPatternAttribute.cs" title="UriPatternsAttribute">UriPatterns</a> attribute, this is a direct association and there is no other code needed in order to inidicate support for one or more content types. </p> The <a href="http://exyus.com" title="exyus">exyus</a> engine also supports standard caching directives to optimize client-server interactions. This is handled via functions in the <a href="http://exyus.googlecode.com/svn/trunk/exyus/Caching/Cache.cs" title="Cache.cs">Cache.cs</a> class that are called within the handling of the GET and HEAD requests. The <code>IsCachedResouceValid()</code> and <code>CacheResource()</code> methods are available for handling this step. </p> <blockquote> This version of <a href="http://exyus.com/" title="exyus" target="_blank">exyus</a> is built for <a href="http://asp.net/" title="asp.net" target="_blank">ASP.NET</a> over <a href="http://iis.net/" title="Internet Information Services" target="_blank">IIS<a> running on Windows XP and higher. The runtime was written in <a href="http://msdn2.microsoft.com/en-us/vcsharp/aa336809.aspx" title="C# 2.0" target="_blank">C# 2.0</a> using <a href="http://msdn2.microsoft.com/en-us/ie/bb188238.aspx" title="Microsoft Visual Studio 2005" target="_blank">Visual Studio</a>. 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 <a href="http://code.google.com/p/exyus/downloads/list" title="downloads">download</a> and configure the <a href="http://exyus.com/" title="exyus" target="_blank">exyus</a> runtime for you web server. </blockquote> <h3>Building the TaskList.cs Class</h3> <p> For the task list example, we'll use the <a href="http://exyus.googlecode.com/svn/trunk/exyus/Resources/XmlFileResource.cs" title="XmlFileResource" target="_blank">XmlFileResource</a> 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 <a href="/xcs/tasklist/source/?f=tasklist.cs" title="TaskList.cs" target="_blank">TaskList.cs</a> 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. </p> <blockquote> Note that the <code>DocumentsFolder</code> and the <code>StorageFolder</code> 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. </blockquote> <p> 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 <code>/exyus/bin/</code> folder. </p> <h3>Configuring the TaskList Resource</h3> <p> Before you can access the <code>/tasklist/</code> 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). </p> <p> Setting the authentication for a URL is done by making an entry in the <code>config/auth-urls.xml</code> file. The line below shows how to configure the <code>/tasklist/</code> URL to allow anonymous users to access the resource: </p> <pre>&lt;url path="/xcs/tasklist/" auth="false" /&gt;</pre> <p>Setting the authorization for a URL is done by making an entry in the <code>config/auth-users.xml</code> 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): </p> <pre>&lt;permission path="/xcs/tasklist/" methods="*" /&gt;</pre> <blockquote> 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. </blockquote> <p> 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. </p> <a href="#top" title="top">top</a> </div> <div class="section"> <h2><a name="Transforms" title="Transforms">The XSL Transforms</a></h2> <p> <a href="http://lh3.google.com/amundsen.mike/R50-Jpev0gI/AAAAAAAAA_0/-qJZEGViJ54/05-xsl-edit.JPG?imgmax=640" title="05-xsl-edit.JPG" target="_blank"> <img src="http://lh3.google.com/amundsen.mike/R50-Jpev0gI/AAAAAAAAA_0/-qJZEGViJ54/s144/05-xsl-edit.JPG" title="05-xsl-edit.JPG" alt="05-xsl-edit.JPG" /> </a> Many of the HTTP Resource classes in the <a href="http://exyus.com" title="exyus" target="_blank">exyus</a> engine use XSL transform documents to handle incoming requests and format outgoing responses. Transforms are used in three important cases: </p> <ol> <li>Interpreting the URL of an incoming request</li> <li>Transforming the body of an incoming request</li> <li>Transforming the content of the outgoing response</li> </ol> <h3>Handling Arguments</h3> <p> When <a href="http://exyus.com/" title="exyus">exyus</a> 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. </p> <p> 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. </p> <p> To support this transform, you need to create a file in the resource's Documents folder (see the <code>DocumentsFolder</code> setting on the C# class above) called <code>args.xsl</code>. You can view the contents of the <a href="/xcs/tasklist/source/?f=args.xsl" title="args.xsl" target="_blank">args.xsl</a> file online. Notice that the XSL transform expects an incoming <code>xsl:param</code> named <code>taskid</code>. This is the same parameter outlined in the <code>UriPattern</code> associated with the <a href="/xcs/tasklist/source/?f=tasklist.cs" title="TaskList.cs" target="_blank">TaskList.cs</a> resource class created in the previous section. </p> <h3>XML GET Responses</h3> <p> Since the resource is marked to support both <code>text/html</code> and <code>text/xml</code> 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 <code>text/xml</code> transform, we need to write code that supports both these "modes" of the GET request. </p> <p> The runtime looks for transform documents named based on three indicators: </p> <ol> <li>HTTP Method (GET)</li> <li>Command state (request or response)</li> <li>content-type (XML, HTML, etc.)</li> </ol> <p> 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: <code>get_response_xml.xsl</code>. Note that the three key indicators are used to build up the name of the document: <code>[method]_[state]_[type].xsl</code>. All XSL transform documents for <a href="http://exyus.com/" title="exyus" target="_blank">exyus</a> use this naming pattern. You can view the contents of the <a href="/xcs/tasklist/source/?f=get_response_xml.xsl" title="get_response_xml.xsl" target="_blank">get_response_xml.xsl</a> file online. This file must be placed in the Documents folder as defined for the resource. </p> <p> You can view typical XML output from this transform for a list request (<a href="/xcs/tasklist/source/?f=get-xml-list.txt" title="GET /tasklist/" target="_blank">GET /tasklist/</a>) and for a single item request (<a href="/xcs/tasklist/source/?f=get-xml-item.txt" title="GET /tasklist/123" target="_blank">GET /tasklist/123</a>) </p> <blockquote> Note that the XSL transform uses the <code>$_mode</code> 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 <code>document()</code> function to access the contents of the stored objects in the file system. </blockquote> <h3>HTML GET Responses</h3> <p> The <a href="/xcs/tasklist/source/?f=get_response_html.xsl" title="get_response_html.xsl" target="_blank">get_response_html.xsl</a> document controls the output of GET requests sent by clients that accept the <code>text/html</code> 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. </p> <blockquote> 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. </blockquote> <h3>FORM POST Requests</h3> <p> The last XSL transform needed for this example is the <a href="/xcs/tasklist/source/?f=post_request_form.xsl" title="post_request_form.xsl" target="_blank">post_request_form.xsl</a> 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: </p> <pre>&lt;form&gt; &lt;name1&gt;value1&lt;/name1&gt; &lt;name2&gt;value2&lt;/name2&gt; ... &lt;/form&gt;</pre> <blockquote> This process of converting the urlencoded body of the HTML form POST into an XML document is automatically handled by the <a href="http://exyus.com" title="exyus" target="_blank">exyus</a> engine. </blockquote> <a href="#top" title="top">top</a> </div> <div class="section"> <h2><a name="Validators" title="Validators">The XSD Validators</a></h2> <p> <a href="http://lh5.google.com/amundsen.mike/R50-JJev0fI/AAAAAAAAA_s/PDRLHjILQoU/06-xsd-edit.JPG?imgmax=640" title="06-xsd-edit.JPG" target="_blank"> <img src="http://lh5.google.com/amundsen.mike/R50-JJev0fI/AAAAAAAAA_s/PDRLHjILQoU/s144/06-xsd-edit.JPG" title="06-xsd-edit.JPG" alt="06-xsd-edit.JPG" /> </a> Along with XSL transforms, the <a href="http://exyus.googlecode.com/svn/trunk/exyus/Resources/XmlFileResource.cs" title="XmlFileResource" target="_blank">XmlFileResource</a> class uses XSD Schema documents to validate incoming documents. In the previous section you learned that the <a href="http://exyus.com" title="exyus" target="_blank">exyus</a> engine automatically converts POSTed HTML form values into a valid XML document (with the root of <code>form</code>). 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. </p> <p> Like the naming pattern for XSL transforms, <a href="http://exyus.com" title="exyus" target="_blank">exyus</a> expects XSD documents to follow a standard pattern that includes: </p> <ol> <li>HTTP Method</li> <li>Content Type</li> </ol> </p> <p> 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 <code>text/xml</code> will be named: <code>put_xml.xsd</code>. Similarly, the document for data sent using an HTML FORM POST will be named: <code>post_form.xsd</code>. So, the pattern for naming XSD validators is <code>[method]_[type].xsd</code>. As with XSL transform documents, all validators need to be placed in the Documents folder for the resource class. </p> <blockquote> The actual content-type for HTML FORM POST is <code>application/x-www-form-urlencoded</code>. However, the XSD filename pattern uses "form." The <a href="http://exyus.com" title="exyus" target="_blank">exyus</a> engine uses a configuration file (<code>config/media-types.xml</code>) 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 <code>config/media-types.xml</code> and start using that keyword for your XSL and XSD documents. </blockquote> <h3>XML POST and XML PUT</h3> <p> This example application supports both POST and PUT for the <code>text/xml</code> content type. That means two documents are needed: <a href="/xcs/tasklist/source/?f=post_xml.xsd" title="post_xml.xsd" target="_blank">post_xml.xsd</a> and <a href="/xcs/tasklist/source/?f=put_xml.xsd" title="put_xml.xsd" target="_blank">put_xml.xsd</a>. 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 <a href="/xcs/tasklist/source/?f=post-xml-error.txt" title="post-xml-error.txt" target="_blank">an invalid POST</a> online. </p> <a href="#top" title="top">top</a> </div> <div class="section"> <h2><a name="Client" title="Client">The Client Script and CSS Styles</a></h2> <p> <a href="http://lh4.google.com/amundsen.mike/R50-I5ev0eI/AAAAAAAAA_k/R4wTVdJ3m8Q/07-js-edit.JPG?imgmax=144" title="07-js-edit.JPG" target="_blank"> <img src="http://lh4.google.com/amundsen.mike/R50-I5ev0eI/AAAAAAAAA_k/R4wTVdJ3m8Q/s144/07-js-edit.JPG" title="07-js-edit.JPG" alt="07-js-edit.JPG" /> </a> 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. </p> <h3>Adding Client Script</h3> <p> 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. </p> <p> There are only a few 'interesting' methods in the <a href="/xcs/tasklist/source/?f=tasklist.js" title="tasklist.js" target="_blank">tasklist.js</a> file. They are: </p> <ol> <li>validateForm()</li> <li>updateItem()</li> <li>deleteItem()</li> </ol> <p> You can view the complete <a href="/xcs/tasklist/source/?f=tasklist.js" title="tasklist.js" target="_blank">tasklist.js</a> file online. Note the use of the <code>ajax.httpHead()</code> method to retrieve the <code>ETag</code> header of an item before attempting to update it. This prevents other user's edits from overwriting the current update. </p> <h3>Styling the UI w/ CSS</h3> <p> 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 <a href="/xcs/tasklist/source/?f=tasklist.css" title="tasklist.css" target="_blank">tasklist.css</a> file online. </p> <blockquote> 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 <a href="http://exyus.com/xcs/tasklist/" title="TaskList" target="_blank">TaskList</a> application</a>. both with and without the CSS styles. </blockquote> <a href="#top" title="top">top</a> </div> <div class="section"> <h2><a name="Summary" title="Summary">Summary</a></h2> <p> <a href="http://lh6.google.com/amundsen.mike/R50-MZev0kI/AAAAAAAABAU/O7QuqJHO8VE/01-composite.JPG?imgmax=720" title="01-composite" target="_blank"> <img src="http://lh6.google.com/amundsen.mike/R50-MZev0kI/AAAAAAAABAU/O7QuqJHO8VE/s144/01-composite.JPG" title="01-composite" alt="01-composite" /> </a> In this article, you learned how to use the <a href="http://exyus.com" title="exyus" target="_blank">exyus</a> engine to build HTTP applications that comply with <a href="http://en.wikipedia.org/wiki/Representational_State_Transfer" title="Representationl State Transfer" target="_blank">REST</a> constraints. You learned how to create an "action matrix" to detail the client-server interactions and how to use the base classes in the <a href="http://exyus.com" title="exyus">exyus</a> 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. </p> <p> 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 <a href="http://exyus.com" title="exyus">exyus</a> engine to implement HTTP/REST with relative ease. Hopefully, this small example will encourage you to use HTTP/REST and <a href="http://exyus.com" title="exyus">exyus</a> when building your future web applications. </p> <a href="#top" title="top">top</a> </div> <div class="section"> <h2><a name="Author" title="Author">About the Author</h2> <p> <a href="http://amundsen.com/blog/" title="mca blog" target="_blank"> <img src="http://tkfiles.storage.live.com/y1pMfQTxeoXgoyXiMtX6BY3Rv_gtQyA6X774cPln4o1tj-UKfCMHh9zMKPPhpKfnT7cnLgAYsyReFc" title="Mike Amundsen" alt="Mike Amundsen" /> </a> 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. </p> </div> <script type="text/javascript"> var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www."); document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E")); </script> <script type="text/javascript"> var pageTracker = _gat._getTracker("UA-2399548-2"); pageTracker._initData(); pageTracker._trackPageview(); </script> </body> </html>