Samstag, Juli 30, 2005

Extensions to the proxy generator

With Version 2.0 there is now more support for different datatypes.

Simple data types

Up to now only those methods where supported that where converting of the parameters and result values was not necessary. This applies to strings and numbers.

Now the data types defined on the server and the WSDL are passed to the client so that the data types can be converted using JavaScript at runtime.

In the generated proxy code, the listing of the names of the parameters is now extended by an optional specification of the data type. Without this the values are treated as strings.

proxies.CalcService.AddDouble.params = ["number1:float","number2:float"];
proxies.CalcService.AddDouble.rtype = ["AddDoubleResult:float"];

In the HTML object model, the JavaScript data types are not well supported. The values that is displayed inside an input field is always a string, even if it’s containing only digits. For this all the parameters when calling the proxy are also accepted as JavaScript strings and converted if possible to the right types.

XML data

Passing XML documents was implemented to make it possible to pass complex data. In the browser clients the XMLDocument Object from Microsoft or Firefox and on the server the XmlDocument class can be used.

A Method has to be is declared in C# like this:

[WebMethod()]
public XmlDocument Calc(XmlDocument xDoc) {
...
return (xDoc);
} // Calc

The proxy functions also accept the XML document as a string type. In this case, the contents of the passed string is passed directly to the server any must for this reason contain a valid XML document without the declarations any without any “XML processing Instructions" <? ... ?>.

With this data type it is possible to pass complex data from a HTML form directly to the server an there is no need to define a method with many parameters. If the form is extended with new fields it will not be necessary to give a new signature to the WebService.

The disadvantage of this approach is that the content of the XML document cannot be validated by the WebService infrastructure because there is no schema for this part of the conversation available.

Supported Datatypes
XML data type Alias in the proxy JavaScript data taype
string string / null String
int, unsignedInt,
short, unsignedShort,
unsignedLong,s:long
int Number, (parseInt)
double, float float Number, (parseFloat)
dateTime' date Date
boolean bool Boolean
In Mozilla / Firefox:
XMLDocument
Im Internet Explorer:
ActiveXObject("Microsoft.XMLDOM")
ActiveXObject("MSXML2.DOMDocument")
x System.Xml.XmlDocument

Donnerstag, Juli 28, 2005

Sample for AJAX Forms

This sample implements the processing of data of a form using the AJAX engine and the AJAX Forms.

AJAX also brings some advantages to this kind of application on the validation and calculation of formular data. Instead of "sending" the data and retrieving new to be displayed HTML an asynchronous communication only transfers the data part of the form using XML documents.

The supplementing functions necessary for the handling of AJAX Forms it is necessary to include the ajaxforms.js scripts in the HEADER of the page.

<script type="text/javascript" src="ajaxForms.js"></script>

The connection to the corresponding WebService is done by using the proxy generator:

<script type="text/javascript" src="GetJavaScriptProxy.aspx?service=_Kreditcalc.asmx"></script>

In this example the validation of the input values and the calculation of the new values are together implemented in the same method. The communication of the values between the client and the server uses the XML format defined by ajaxForms.js module. The two functions ajaxForms.getData and ajaxForms.setData that implement the transfer of the data from the XML format to the HTML of objects therefore can be used directly in the setup of the actions.

Exceptions

The function ajaxForms.processException can be used to handle and display the exceptions that occur within validating the passed data.

If a wrong or missing value is detected inside the passed form data the server should throw an ArgumentException using the name of the element as the name of the wrong parameter.

This name is then passed to the client using an exception return package.

ProcessException then recognizes that an ArgumentException was thrown and shows the error text beside the input field. To show these texts, a SPAN element is used for each field inside the form:

<span class="AJAXFORMEXCEPTION" name="LOAN"></span>

The Form

The layout of the form and the data together with the format of the XML document is specified by the HTML code of the page. The DIV element with id frm (having a green border) is used as a container for all fields of the form. Inside this object you can find the INPUT elements like:

<input id="loan" name="LOAN" value="100000">
  ...
<input name="MONTHLYREPAY" disabled="disabled">

The Actions

The first functionality on the server implements the calculation a simple credit case. On the left side of the form some values like the loan amount and the rates can be modified by the user. These values are used to calculate the monthly payment, the duration of the credit and the totals of payment that are displayed on the right side of the form.

For that purpose all the data of the form is send over the network to the server as a XML document as well as the result of the calculation.

The first action uses the functions getData und setData from ajaxForms.js and needs no further programming.

// declare an AJAX action
var action1 = {
  delay: 200,
  prepare: ajaxForms.getData,
  call: proxies.KreditCalc.Calc,
  finish: ajaxForms.setData,
  onException: ajaxForms.processException
} // action1

The second implemented method on the server gets the same XML document information as the first method but returns a XML Document containing the monthly balance of the credit.

The code on the client is the responsible for displaying the chart by using the special local implemented method displayAmortization. Here the XML document passed back from the server is transformed into a HTML document fragment by using a XSLT transformation on the client. This transformation uses a lot of small blue and red images that are sized and positioned as needed to make the chart look like it should.

Because the transformation is done on the client only about 23% of the necessary HTML code is transferred over the network. The XSTL is retrieved only once and is cached on the client.

var action2 = {
  name: "Amortization",
  delay: 800,
  prepare: ajaxForms.getData,
  call: proxies.KreditCalc.Amortization,
  finish: displayAmortization,
  onException: proxies.alertException
} // action2

Starting the actions

To start the asynchronous actions again the onkey event is used. In this sample 2 actions are started by one event. Because both actions have a delay time specified they will stay in the queue and will be removed abd started again when another key is pressed before the delay time is over.

The second parameter on starting the actions is used to reference the AJAX form.

onkeyup="ajax.Start(action1, 'frm');ajax.Start(action2, 'frm')"

Mittwoch, Juli 27, 2005

A lookup example for city names

In example of implementing an AJAX action you can see how to load and display data fragments from a huge dataset on the server.

On the server, there is a big list of German towns and cities in the file orte.txt. If you would include this information into the page as a list of OPTION elements for a SELECT element you would have to download about 400.000 bytes of additional HTML code – too much. Instead a simple INPUT field is combined with the possibility to search in this dataset.

The WebService that implements this lookup functionality can be found in OrteLookUp.asmx and, again, has no AJAX specific implementations. The method gets one parameter passed that contains the first characters of a possible name of a city and returns up to 12 found entries of the list back to the client.

The connection to this WebService is done by using the proxy generator:

<script type="text/javascript" src="GetJavaScriptProxy.aspx?service=OrteLookup.asmx"></script>

This lookup method must be called in several situations: The code on the client that display the list and the completion of the current entered text is somewhat complex and most of the JavaScript of this page is about that. The call ajax.Start(LookupAction) that can be found several times starts the action.

The action itself is implemented very compact in one place and you can see that a not a lot of coding is necessary because the AJAX engine handles a lot.

var LookupAction = {
  delay: 100,
  prepare: function() { return (document.getElementById("inputField").value); },
  call: proxies.OrteLookup.OrteStartWith,
  finish: function (val) {
    var fld = document.getElementById("inputField");
    var dd = createDropdown(fld);
    FillDropdown(dd, val);
    if (isIE)
      NextDropdownEntry(fld);
  },
  onException: proxies.alertException
} // LookupAction

Looking at this script you can again see the actual flow of the action and there is no need to implement several JavaScript methods outside of the definition.

Samstag, Juli 23, 2005

AJAX Form Services

The implementation of the AJAX Form Services, that allows an efficient implementation of forms can be found in the JavaScript include file ajaxForms.js.

Again, only one global object named ajaxForms is defined to minimize possible name conflicts. Attached to this object the following methods are available.

data = ajaxForms.getData(obj)

This method searches all INPUT, TEXTAREA and SELECT elements that are contained inside the passed object and uses their values to build up the elements of a XML document.

The obj parameter can be passed using the id of a formular or as a reference to a HTML Object.

This result of this method is a XmlDocument object.

ajaxForms.setData(obj, data)

This method transfers all values from data into the corresponding INPUT, TEXTAREA and SELECT elements of the HTML form. All HTML elements that are part of the form but have no value in data will be cleared or unchecked.

The obj parameter can be passed using the id of a formular or as a reference to a HTML Object.

The data parameter can be passed as a XML text of a XmlDocument object.

This method also calls clearErrors at the end (see below).

ajaxForms.clearData(obj)

All HTML INPUT, TEXTAREA and SELECT elements that are part of the form are cleared or unchecked.

The data parameter can be passed as a XML text of a XmlDocument object.

ajaxForms.resetData(obj)

All HTML INPUT, TEXTAREA and SELECT elements that are part of the form get their initial value that is coded inside the

The obj parameter can be passed using the id of a formular or as a reference to a HTML Object.

ajaxForms.processException(ex)

AjaxForms implements a mechanism to display exceptions that are thrown by the server nearby the fields that causes them. If exceptions are handled by ajaxForms.processException() all ArgumentException are detected.

To enable the developer how the exception text is shown SPAN elements tagged with the css-class AJAXFORMEXCEPTION can be defined inside the form. The text of the exception is then inserted into this Element and can be formatted by using a CSS rule.

<span class="AJAXFORMEXCEPTION" name="LOANVALUE"></span>

ajaxForms.clearErrors()

This method clears all exception texts inside the form.

Donnerstag, Juli 21, 2005

AJAX and Forms

The good old HTML form element is used by many web pages for the communication of the data from forms. This mechanism was developed to work without any JavaScript or XML and long before AJAX.

It’s a typical scenario in web applications that they have some more or less static forms with input fields for displaying and editing data values. Therefore a concept to handle form situations is also needed in a AJAX engine.

This part is about the programming we need on the client. It’s implemented in JavaScript and uses intensively XML documents. Some words about the extensions in the Proxy Generator as well as the implementation on the server will follow. Some samples can already be found on the samples WebSite.

Classical approach and drawbacks

The mechanism behind form element works since the beginnings of HTML to send the data that is entered or changed by the user back to the WebServer. The format used by these postings has nothing in common with XML but uses for in many cases a URL like format defined by the mime type application/x-www.form-urlencoded. With the upcoming XHTML 2.0 definition also a XML Format and some more advanced form functionalities will be available. But all these good news are not supported by the wide spread browsers available today.

A direct access to the data inside a HTML Form in a whole does not exist in the browser nor in JavaScript. But of course the individual elements can be accessed one by one. The values that are shown to the user are normally included inside the HTML code that is sent from the server to the client. Collecting the values and sending them back to the server is hard coded to the submit action of the form that normally downloads new HTML Code and displays them in the window,

It’s obvious that this approach doesn’t fit into the processing of AJAX. The graphical elements of the form and the data is not separated properly.

Using Form Data

One way to realize an access to the data in a HTML form for AJAX applications is to use JavaScript. The include file ajaxForms.js was written to enable the developer to handle this effectively and without using long scripts in every form but to help with a collection of methods.

The goal of this approach is to distinguish between the data of the form represented as a XML document and the HTML elements that are used to display and edit the data.

To define a form on a HTML page you need a HTML Element that contains all the form elements. This encapsulating element can be a DIV tag.

All the input fields, checkboxes, textareas and select objects with a name that are inside this HTML element are considered holding data in the appropriate object properties. This data is the assembled into a XML document with a data root element by using the names of the HTML elements as the names of the inner tags.

This HTML code ...

<div id="frm" style="margin: 2px; padding: 2px; border: solid 1px green"
  <p>F1: <input name="F1" value="one by one"></p>
  <p>F2: <input type="checkbox" name="F2"></p>
  <p>T1: <textarea name="T1" style="width: 400px; height: 80px">some
text
lines</textarea>
  <p>S1: <SELECT name="S1">
    <option value="10">ten</option>
    <option value="11">eleven</option>
    <option value="12" selected="selected">twelve</option>
    <option value="13">thirteen</option>
  </SELECT>
</div>

... corresponds to this XML document:

<data>
  <F1>one by one</F1>
  <F2>false</F2>
  <T1>some
text
lines</T1>
  <S1>12</S1>
</data>

The data of a form is now available as a single value and therefore fits well into the existing functionalities of the AJAX engine.

In AJAX applications it is a typical that the same HTML Form is reused several times before getting and displaying new HTML code from the server so we also need methods for the reverse data flow that puts the data of an XML document back into the HTML form.

Montag, Juli 18, 2005

More Options for AJAX Actions

Since the first publication I have implemented some changes and additions in the AJAX engine and the framework for WebServices.

ajax.Start(action1, option)

prepare(option) / finish(data, option), onExeption(ex, option)

When starting an AJAX action the only options that could be specified where those that are part of the JavaScript object describing the action. These options are the same for all executions of this action. With this addition it is now possible to define an option for a specific execution.

The ajax.Start Method now has a second parameter. This value is stored into the queue of the AJAX engine together with the fist parameter specifying the action.

When the prepare and finish methods are executed as well on handling en exception, this value is passed as an additional parameter. By using this value it is possible to store a context of an action. That may be for example a HTML object that started the action. Because all methods have access to it, it is now possible to use the same action definition for multiple fields, forms or other situations. Without this parameter it was necessary to implement the direct access to the HTML objects inside the prepare and finish methods.

proxies.cancel()

Calling this method will close the actual connection to the saver by calling the abort method of the xmlhttp object before the result is returned from the server.

This is only possible on asynchronous calls.

proxies.alertResult()

This method makes it easy to watch the communication of the return value of a server call. But the situation is similar to the Heisenberg uncertainty principle: If you watch the package you cannot see the effect anymore because the data from the server is shown to the user but is not passed to the finish method. Also the timing situation is ruined because an alert box is used.

This option can be activated by assigning the alertResult method to the otherwise internally used corefunc property.

proxies.service.method.corefunc = proxies.alertResult;

Even if it breaks, it was necessary from time to time to see the result of a call so this option remains in the client-side WebService framework.

Tip:

It is not well known that the Microsoft Internet Explorer (IE) allows to copy the content of an alert box into the clipboard by using Ctrl+C.

ajax.Cancel()

This method cancels the execution of the currently running action. If a timeout value is specified in the action options this method is called automatically.

ajax.CancelAll()

This method cancels the execution of the currently running and all the pending actions.

Samstag, Juli 16, 2005

The AJAX prime factors sample

The first sample that shows how to use the AJAX engine is in the files CalcFactorsAJAX.htm (Client) and CalcService.asmx (Server). With this sample the principle steps can be analyzed easily.

The connection to the already known WebService is done by using the proxy generator:

<script type="text/javascript" src="GetJavaScriptProxy.aspx?service=CalcService.asmx"></script>

The HTML code contains 2 input elements that are used for the communication with the user.

The import element with the id inputField is editable and used to enter a number that should be split into the prime factors. The event onkeyup was chosen for triggering the AJAX action.

This event is not only triggered by entering characters but by the special keys like backspace, delete or Ctrl+C for pasting a new value.

With IE, there is also the event onpropertychange available that suits better our needs here but the FireFox browser doesn’t implement this and there is no standard event defined for being triggered immediately on any value changes.

The field with id outputField is deactivated and is used to show the calculated prime factors.

...
  <td><input id="inputField" onkeyup="ajax.Start(action1)"></td>
...
  <td><input id="outputField" size="60" disabled="disabled"></td>
...

The AJAX action is declared inside the JavaScript block and there is no other programming necessary except this.

You can see within the methods prepare and finish how to exchange the values with HTML Elements.

The call method is setup by linking to the local method of the generated proxy and exceptions are displayed by using a simple alert box.

The delay parameter is set to 200 msec. This time was chosen after some empirical timing measurements (using myself) and was found being appropriate. When one of the testing people entered a number this time wasn’t exceeded between entering the digits and the action was indeed executed at the end of entering the whole number.

If the action was stared already by entering a digit and when another digit was entered before the delay time was over then the first action was removed from the queue, the second identical action was entered into the queue and the timer was started again.

// declare an AJAX action
var action1 = {
  delay: 200,
  prepare: function() { return (document.getElementById("inputField").value); },
  call: proxies.CalcService.CalcPrimeFactors,
  finish: function (p) { document.getElementById("outputField").value = p; },
  onException: proxies.alertException
} // action1

Looking at this script you can imagine the actual flow of the action. This is a big advantage for everyone that needs to analyze, extend or fix a broken implementation, because all the functionality is not spread over the source code into several methods, callback functions and timer events but kept together in this JavaScript object.

You can find all the samples on http://www.mathertel.de/AJAXEngine/.

Montag, Juli 11, 2005

Handling Exceptions

Also in AJAX architectures failures in the communication and in the execution may raise errors. Fortunately when using a WebServices based framework these cases are also defines in the SOAP communication protocol.

The answer to a call to a WebService in the SOAP format will under normal conditions return the result of the method:

<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <soap:Body>
    <CalcPrimeFactorsResponse xmlns="http://www.mathertel.de/CalcFactorsService/">
      <CalcPrimeFactorsResult>2 2</CalcPrimeFactorsResult>
    </CalcPrimeFactorsResponse>
  </soap:Body>
</soap:Envelope>

In the case of an error the information about the failure of the server-side execution will be passed back to the client.

In the simplest case this information is shown to the user but also other reactions may be appropriate like reloading the whole page.

<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <soap:Body>
    <soap:Fault>
    <faultcode>soap:Server</faultcode>
    <faultstring>Server was unable to process request.
---> Input string was not in a correct format.</faultstring>
    <detail />
    </soap:Fault>
  </soap:Body>
</soap:Envelope>

The client-side implementation allows the handling of the exceptions that occur at the level of the WebService proxies an on the level of the AJAX Actions.

In both cases there is an onException event available and a specialized method handling these exceptions can be plugged in. This method gets passed the thrown exception as a parameter and can organize the further functionality of the page.

There is usable method defined in ajax.js that can be used for showing exceptions:

proxies.alertException(ex):

This method shows the exception object in a readable format using an alert box. This method can be used in proxies.service.method.onException as well as in action.onException.

Mittwoch, Juli 06, 2005

AJAX Actions

The fundamental parts of an AJAX engine that handle all the asynchrony calling of the server-side functionality using JavaScript and the XMLHTTP object are available using the WebService proxies. To make realization easier some more layering is needed above this: AJAX Actions.

2 examples of AJAX actions are already published on the examples Website at http://mathertel.devhost1.centron.net/CalcFactors/.

The actual code to implement an AJAX action is located in the two files CalcFactorsAJAX.htm and OrteLookup.htm. Each sample consists of only some lines of code. The reminding work is covered by the implementation of the engine in the file ajax.js.

As you can see in these samples the logical steps of the actions are written in the source code step by step as they will be executed even if there are timers and callback methods used to implement it behind the scene.

This makes it easy to follow the idea of each action.

The AJAX engine layers upon the WebService proxies shown before.

Every action on the page is described with the assistance of an object that holds all information together. The properties of this object are:

prepare(): This property defines a function that is used directly before sending the SOAP of package to the server. This function has to return the data that is used as the argument of the call to the server. If this function is not defined then a server-side method without parameters is called.

call(): This property refers to a function that was generated by the proxy generator to a WebService.

finish(): This property defines a function that will retrieve the result of the call. This property may be zero.

onException(): This property defines a function that is called in the case of an exception. This property may be zero.

delay: This property defines the time in milliseconds how long the call should be delayed. This is useful together with events that are triggered very often and in a fast order. The default value of 0 deactivates this functionality and the action starts immediately.

timeout: This property defines the time in seconds how long the call to the server can last before it is canceled on the client. When this time runs off without an answer from the server the http connection is closed. The default value of 0 deactivates this functionality.

A timeout of more than approx. 60 seconds does not work well because http requests can be terminated by the network layer before this time.

With some additional flags you can specify how pending actions are handled.

queueClear: This property can be set to true to specify that the queue with the pending actions is cleared before the new action is entered. An already running action will not be stopped. The default value is false.

queueTop : This property can be set to true to specify that the action is entered into the queue in front of all other pending actions. The default value is false.

queueMultiple: This property can be set to true to specify that an action can be queue more than once. The default value is false.

// declare an AJAX action
var action1 = {
  prepare: function() { return (document.getElementById("inputField").value); },
  call: proxies.CalcService.CalcPrimeFactors,
  finish: function (p) { document.getElementById("outputField").value = p; },
  onException: alertException
} // action1

In the samples you can see that it is not necessary to write functions before assembling them into the action object. The implementation of a function is also possible using inline code.

Important Note: The last property of a definition of a JavaScript object MUST NOT have a trailing comma. The otherwise quite tolerant Microsoft Internet Explorer complains of this error during the Firefox tolerates this. I lost some hours not seeing a comma like this.

Freitag, Juli 01, 2005

Overview of the AJAX engine

As one can see from the last posts, the basic elements for a application using the AJAX technologies JavaScript and XMLHHTP are not difficult to realize. However, the selection from the available technologies as well as a suitable abstraction in using these elements is crucial for the success of the realization of an application.

Building an AJAX engine or an AJAX framework that you can reuse every time you want some asynchronous processing or when you need a smart way to refresh information on the current web page will help a lot.

If you realize a web application with only containing one or a only a few Web services you can stay with the kind of realization that is shown in the preceding examples.

The experiences in my job in contrast are within the range of applications with some hundred sides and Web services with in sum about a thousand methods. With more than few Web methods the developer must have a clear and simple kind of the realization of the Javascript code on the client to avoid errors and to not think about the implementation details. Only by using a simple approach a good quality and maintenance can be achieved.

The main idea of an AJAX engine on the client is the simplification of the implementation of the code, which is needed for a specific function on the Client. Like with the webservice framework of ASP.NET on the server the details of communication over SOAP on the client are completely hidden from the developer and also the recurring code portion is only realized once in a central place. Also all details about the different implementations of the XMLHTTP object in Internet Explorer or the Firefox browsers are hidden from your code.

The blue print of the AJAX engine has the following connected components:

HTML form and elements

The static or dynamically provided HTML of objects e.g. < input > elements become for the interaction with the user used.

Buttons & Events

The buttons and events, which start a AJAX functionality must only call a simple Javascript function. This can be used for example using inline code in a onclick attribute. This starts then the processing of the steps that should be executed.

AJAX actions

For the call of a server-side functionality parameters must be retrieved and the result must be processed on the Client. These elements together form a AJAX action.

AJAX functions

AJAX functions are the basic steps that together form a AJAX functionality which is supported by a slim and efficient JavaScript framework that hides the browser specific details from the implementation.

Web methods and proxies

The proxy framework is used on the client to call the server-side methods.

Ajax engine

The execution of the individual steps of an AJAX functionality using a timer and XMLHTTP objects is coordinated and supervised by the AJAX engine. The methods for the implementation of the AJAX engines are available in ajax.js.

Also the AJAX engine needs only one variable with the name Ajax to be declared in the global namespace to minimize name conflicts.

In many cases it is importantly for the implementation of actions that they occur one after the other by using a queue mechanism. This is also necessary from a network perspective because with HTTP connections only 2 simultaneous requests per server should be made at a time.

Therefore the AJAX engine implements a queue. Using some attributes on the AJAX actions it is possible to control the way how the existing entries are treated when starting of a new action.

There are several examples of AJAX actions are published on my Website at http://www.mathertel.de/AJAXEngine/.