Architecture
Command class
Command class is a super class from which all developer defined command (aka action) classes extend. Command object serves a request and implements well defined unit of work for the application.
By adding more Command objects to the application and configuring those via config.xml developer can easily extend the functionality of the web application.
A developer defined Command object will extend the Command class and override execute(environment, requestCtx) method:
//this is how you would extend Command class using JavaScript prototype mechanism
SecretAction.prototype = new Command();
SecretAction.prototype.constructor = SecretAction;
SecretAction.prototype.init = function (config) {
//this is how we invoke init() method on super class
Command.prototype.init.call(this, config);
return this;
};
//The constructor
function SecretAction(config) {
if (arguments.length) {
this.init(config);
}
}
SecretAction.prototype.execute = function (environment, secretForm) {
var result = new ResponseContext();
//process request
//sets view to forward the results to
result .forward = this.findForward(secretForm, "success");
return result;
}
The execute() method would perform the following steps:
- Create ResponseContext object
- Handle the request set various properties of the ResponseContext
- Return the ResponseContext. If you would like to handle the output within the Command object itself then you should return nothing (undefined value) from execute() method:
SecretAction.prototype.execute = function (environment, secretForm) { environment.response.write("<h1>Hello world</h1>"); }
Activity diagram
- The Command is looked up by URI string submitted by the web browser using the Config class.
- The Config class and all the mappings are caches in ASP application context as JSON string to enable quick access with subsequent requests
- If the RequestContext mapping has been associated with the Command mapping a new RequestContext instance will be created and populated
- Optionally validate() method will be called on the RequestContext object to validate its properties
- If the RequestContext is valid execute() method is called on the Command object. A reference to Environment object (raw ASP request, response, session, server and application adapters) and the RequestContext will be passed to the Command object. This parameters make sure that the Command object has everything its needs to complete the request handling
- The Command object returns ResponseContext object. The ResponseContext object contains references to Forward object, Errors collection if available and Models collection. The Models collection is the place where developer would put response specific objects to be available for transformation layer for rendering
- The ResponseContext is then processed and the response is sent back to the browser

Error handling
Let’s have a look at how the framework handles errors by example.
- Run
troika-asp\build>cscript //nologo tests.wsf //job:helloworld - You will get generated output containing error: ‘Name’ required
- Modify tests.wsf, job Id - helloworld
setRequest("visitorName", "Paul"); - Run the script again, now we have no error message in the output.
This is what we did to raise an error in our Command class, see HelloAction.js:
result.errors.add(new Error("Name cannot be empty!"));
We added a new error to a list of errors of the RequestContext object (result).This is how you would add many errors at once, see LoginAction.js:
var errors = loginForm.validate();
if (errors.size()) {
result.errors.addAll(errors);
}
The errors collection will be expanded by the framework into XML:
<errors>
<elements>
<e0>
<name>Error</name>
<description>'Name' required</description>
<message>'Name' required</message>
</e0>
</elements>
</errors>
The XML can be then transformed into HTML by XSL template, see error.xsl:
<xsl:for-each select="//errors//description">
<li>
<xsl:value-of select="." />
</li>
</xsl:for-each>
If there is unhandled error or exception the framework will transfer the application flow to 500-100.asp custom handler. In debug mode, the ASP page displays the error message and the line number:
if ( Application.Contents("debug") == 1) {
var err = Server.GetLastError();
Response.Write("DEBUG=ON, see Application.Contents(\"debug\") in global.asa\r\n\r\n");
Response.Write("ASP Code=" + err.ASPCode + "\r\n");
Response.Write("Number=" + err.Number + "\r\n");
Response.Write("Source=" + err.Source + "\r\n");
Response.Write("Category=" + err.Category + "\r\n");
Response.Write("File=" + err.File + "\r\n");
Response.Write("Line=" + err.Line + "\r\n");
Response.Write("Column=" + err.Column + "\r\n");
Response.Write("Description=" + err.Description + "\r\n");
Response.Write("ASPDescription=" + err.ASPDescription + "\r\n");
}