|
|
For best results, install APL385 Unicode and use Firefox ![]() |
Building Web applications usually includes many evolutionary stages where different programming languages and tools have to be combined. With the new .NET-framework it is relatively easy to add dynamic DyalogAPL components as .NET classes into various parts of IIS/ASP.NET applications and even into the HTTP-pipeline. As a case study we will show how to add several functional extensions (dynamic image generation, dynamic components etc.) into a third party statistical web application called PX-Web. PX-Web belongs to a widely used family of PX-products, which are authored by a consortium of statistical offices in Europe (the main developer being Statistics Sweden).
This extended Web application is used to publish statistical data and automatically created vector graphics using techniques and languages like ASP, ASP.NET, C#, SVG, JavaScript and of course DyalogAPL and RainPro. We will also discuss the difficulties in learning and using .Net and also the pros and cons of involving DyalogAPL in such a complex environment.
PX-Web is a system for storing statistical data and publishing it on the web. It belongs to the group of PX-products which are based on open architecture. The main platforms for running PX-Web are Windows 200X Server Families and IIS web servers.
What is PX-Web?
Figure 1. Px-Web Architecture
PX-Web features include
Px-DataBase features include
Px-Web is an ASP application, which is the older version of Microsoft Active Server Pages technology. Eventually there will be an ASP.NET release and we had to design our software extensions to be able to function correctly even with the future releases. This was a very strong argument in favour of independent and pluggable technical solutions.
Px-Web extensions can be grouped into four categories:
In this paper we will not be covering the functionality of these extensions because other articles will be available for that purpose. Therefore the next sections will mainly concentrate on showing the techniques and basic ideas for adding modularity to your applications and how DyalogAPL is used in this context.
The next figure shows the PX-Web functionality after adding Dinosoft extensions:

Figure 2. Extended Px-Web Architecture.
Programming and run-time environment management for ASP.NET applications has more moving parts than one might guess.
The following list shows the different environments and versions into which we currently have to adjust our software.
So there is a lot of variety regarding possible problems with software updates, testing, troubleshooting etc. Sooner or later development and testing becomes a nightmare unless there is a way to utilize components and modularity. Especially bugs found in a single software module should not force any large recompilation and testing in other application modules.
Here is a sample screenshot, where the user has selected some statistical table from her personal menu and gets a graphical output image of that data.
Figure 3. Basic Screen Layout for Menu and Graphics
In the figure above
One way to add modularity to your applications is to use the tools provided by the .Net framework and ASP.NET. They can easily be utilized in software development and help you to build pluggable and maintainable solutions, which customers can further extend according to their needs.
Before going into the details of implementing .Net related components, lets first have a brief overview of the Request Pipeline and its functionality.

Figure 4. HttpRequest Pipeline (Copyright Microsoft).
When the client browser sends a request to IIS, it maps the extension of the received request according to stored configuration parameters and passes .aspx, .asmx, plus other extensions to aspnet_isapi.dll, which is an ISAPI filter. This in turn starts a new ASP.NET runtime (a chain of managed objects dubbed the HTTP Pipeline). An object of the HttpApplication class, which is the class behind your global.asax file, is created and started and it acts as the host for the ASP.NET Web application. This functionality differs between different versions of IIS and ASP.NET, but usually the following steps are the same
In ASP.NET you can extend, replace or reconfigure any of the module or handler classes or provide your own custom modules and handlers. Both of these can be configured on the application level or globally on machine level with *.config files.
HttpModules are in fact event-handlers: they respond to a certain event fired in the HttpPipeline. A module subscribes to an event by providing a method, which gets executed.
The request pipeline has a predefined set of events which will all be fired in a certain order (BeginRequest, AuthenticateRequest,...EndRequest) during the lifetime of the request. There are also other events which can be processed with HttpModules (for instance ApplicationError).
It is good to remember that these modules will be executed for all requests and therefore performance issues should be considered carefully before adding your own modules into the pipeline.
For defining a module you need to implement the module interface IHttpModule in your class definition and add the following section to your web.config file
<httpModules>
<add name = "ModuleName" type = "ModuleType"/>
</httpModules>
where name stands for an arbitrary chosen module name and type is defined as ModuleNameSpace.ModuleClass, ModuleAssembly.
You hook a module to your application by copying its dll to /bin - directory and adding the code above to your web.config file.
HttpModules can be used for URL-rewriting, authentication, authorization and for anything where the needed data is included in the request or response. Logging user activity is one example.
HttpHandlers are programs responsible for serving requests. Each time you define an aspx-page, you actually make a new HttpHandler. This is because a handler is defined by implementing an interface called IHttpHandler and that is what the System.Web.UI.Page class does. A handler for a certain resource serves the request by delivering a corresponding response. Defining a handler is very similar to defining a module: you implement the IHttpHandler interface and add some configuration information to your web.config file:
<httpHandlers>
<add verb="*"path="*.extension" type="HandlerType" />
</httpHandler>
Here verb stands for the verb used in the request (GET,SET,POST) and path defines path and extension for this handler (the URL in the request). Type is once again defined as HandlerNameSpace.HandlerClass, HandlerAssembly.
Adding a handler to your application works the same way as with modules: copy assembly to /bin and edit web.config.
One more thing has to be done, if you define a totally new extension: IIS must be configured to pass this request to the ASP.NET runtime. Otherwise IIS will try process it itself and the request will never reach your handler.
With handlers you can easily serve requests for special resources and as a side effect implement web pages which do not actually exist.
With HttpModules and HttpHandlers it is possible to get
The background for integrating DyalogAPL components into PX-Web was that we were asked to explore the possibility of making a vector graphics extension in addition to the existing Px-Web graphics component, which is still raster based.
As we were familiar with RainPros capabilities (and that time SharpPlot did not exist) we decided to try to make a component in DyalogAPL. The other alternative of using various control libraries seemed to be too difficult to handle after trying some of them.
Because statistical data is often multi-dimensional, one thing soon led to another and we were forced to make more components in DyalogAPL.
We tried APL in various forms (AplScripts, aspx-pages, class libraries) but somehow we are gradually moving towards solutions where apl is only used as a pure .Net class without any UI components. There are several reasons for doing so, the most important one being the reusability of such classes.
Currently Px-Web Extensions include DyalogAPL in
The technical ways of using DyalogAPL are
Because the traditional use of APL is something we are all familiar with, the next chapters will cover topics perhaps not so widely known. Thw first example shows how to design a HttpModule both in C# as well as in APL. The second case study shows a combination of both languages in implementing a HttpHandler.
In Px-Web we have used custom HttpModules for
While building these modules we needed to get access to a third party software which used a customized cookie-based authentication. The test phase was carried out to generate similar cookies in a HttpModule, which could be plugged in to any application.
Implementing a HttpModule is just as simple as using the corresponding interface class as the base class and writing your versions of every needed method and property.
The interface for HttpModules contain only two methods: Init and Dispose. Init is used for assigning your eventhandler method to an event and Dispose is just a dummy method belonging to this interface.
So we have (in C#):
namespace Graph.Modules {
using System;
using System.Web;
public class CookieWriter: IHttpModule {
public void Init (HttpApplication application) {
application.BeginRequest += (new
EventHandler(this.WriteCookie));
}
public void Dispose() {
}
The CookieWriter class implements IHttpModule with two public methods. Init method just assigns our Writecookie method to the BeginRequest event so that this method will be called on every request.
This is very dangerous, but this class is only used for test purposes.
Then we need the code for the WriteCookie method:
private void WriteCookie(Object source, EventArgs e) {
HttpApplication app = (HttpApplication) source;
HttpContext context = app.Context;
string cdata = String.Empty;
... Get cookiedata from somewhere ....
cdata = ...
HttpCookie ck = new HttpCookie(cookiename,cdata);
context.Request.Cookies.Set(ck);
}
It gets cookie data from somewhere and then makes a new HttpCookie instance. This instance is added to the Collection of the current request. (It would have been better to use a copy, but this is an example.)
After compiling our class to a dll (Cookie.dll) and moving it to /bin directory, we only have to change our web.config by adding the following module information into <httpModules> section.
<httpModules>
...
<add
name ="cookie1" type = "Graph.Modules.CookieWriter, Cookie" />
The DyalogAPL version is quite similar, but there are minor changes. I have tested this solution and it works, but there might be more elegant solutions for passing the eventhandler information to application events.
)ns CookieTest #.CookieTest
)cs CookieTest #.CookieTest
⎕using←'System' 'System.Web,System.Web.dll' 'Util, Util.dll'
'CookieGenerator' ⎕wc 'NetType' ('Interfaces' 'IHttpModule')
)cs CookieGenerator #.CookieTest.CookieGenerator
)ed Init
)ed Dispose
)ed AddCookie
[0] Init appl;eh
[1] ⍝ Init is the basic method for IHttpInterface where you
[2] ⍝ first create a new eventhandler and then assign it to
[3] ⍝ some event in the HttpPipeline
[4] ⍝ appl: HttpApplication
[5]
[6] ⍝ Let's create a new eventhandler to be called
[7] eh∆EventHandler.New(⎕OR'AddCookie')
[8]
[9] ⍝ Next we assign it to application BeginRequest event
[10] ⍝ Here we use a little utility class to do the
[11] ⍝ actual assigning
[12] Util.EvUtil.BeReqAdd appl eh
[0] Dispose
[1] ⍝ Dispose is part of the IHttpModule interface
[2] ⍝ Do nothing in this context
[0] AddCookie x;appl;args;req;cookie
[1] ⍝ This is a callback function for some web application event
[2] ⍝ It takes standard arguments: source, args.
[3]
[4] appl args∆x
[5]
[6] ⍝ Source refers to HttpApplication Object, which has a HttpContext property
[7] ⍝ which in turn has a HttpRequest property.
[8]
[9] req∆appl.Context.Request
[10]
[11] ⍝ Then we generate a new HttpCookie and assing our data to it.
[12] cookie∆HttpCookie.New 'mycookie' 'this is data: a very important cookie test string'
[13]
[14] ⍝ And finally we add this new cookie to request's CookieCollection
[15] req.Cookies.Set cookie
The little C#-method in the Util-namespace only assigns our event-handler to an application event (here BeginRequest):
namespace Util {
using System;
using System.Web;
public class EvUtil {
public static void BeReqAdd (HttpApplication application,
EventHandler eh)
{
application.BeginRequest += eh;
}
....
}
I moved this simple assignment statement outside APL due to syntax difficulties, which might occur with some events. The utility can also be used from any .Net language and at the same time one does not have to worry about operational difficulties with multicast delegates. So far this has only been used in test environments.
Next we have to assign the .Net related properties to our new functions:
After this we are ready to Export our workspace to a dll library and copy it to applications /bin directory.
The last thing we still need to do is edit our web.config by adding information to <HttpModules> section before our cookiegenerator is ready to be used.
When the next user-request arrives for this application, each request will be added as a custom cookie by our new HttpModule.
I used different class names so that both versions actually run at the same time. The reason for this is the way that events are assigned: each event has several eventhandler delegates and they all will be called when the event (BeginRequest) fires. After that we have two extra cookies in our request.
Of course you can always use the traditional way of handling application events by adding your code directly to the global.asax file, but then you have to recompile this (perhaps a code behind) file. In this case you will lose the dynamics of true plugins where code can be added and removed without touching any parts of the actual application.
In global.asax this would be :
...
protected void Application_BeginRequest(Object sender, EventArgs e)
{
new CookieTest.CookieGenerator().AddCookie(sender, e);
}
...
The second case study uses C# code for building the HttpHandler and DyalogAPL classes to do the actual dirty work. Of course this time you can do it directly in APL without C#, but when you look at the code, you’ll see a comment explaining why we use C#.
Steps we need to take:
In fact we are implementing the rightmost parts of the following true scenario:
Figure 5. Basic steps in invoking dynamic graphics.
Here we have a HttpHandler which serves requests assigned to ‘.svg’ extensions and return svg image definitions (xml to be precise) for the client.
Svg-handler generates images using url-parameters, global data from the workspace, and data from global initial parameters (called when the application starts) and it stores global data in the APL workspace.
The skeleton for the Httphandler is very simple:
// DemoHandlers.cs
// By Dinosoft
namespace Graph.Handlers
{
using System;
using System.IO;
....
/// <summary>
/// Summary description for SvgHandler.
/// Author: Dinosoft Oy - PK
/// </summary>
public class SvgHandler: IHttpHandler,IRequiresSessionState
{
public override void ProcessRequest(HttpContext context)
{
string output = string.Empty;
// first we just check that this request is for a dynamic image
if (context.Request.Path.IndexOf(GraphApplication.Graphserver)>-1)
{
// Get some parameters from the request and/or from user session
NameValueCollection rs=context.Request.QueryString;
string par1 = (rs["parname1"])...;
string par2 = (rs["parname2"])...;
string par3 ...
...
// Get corresponding px-data from the picture base
//(which uses DyalogAPL classes)
GraphFile gf=new GraphFile(par1,par2,...);
// Create a instance of our graphics generator
//(which is a DyalogAPL class)
GserverPage gp=new GserverPage(par3,par4,...);
// Pass database information for the generator
// to make the desired image
output=gp.MakeSvg(gf);
}
else
{
// This request was for a static recource,
// so get it from somewere else
// We don't want to drag this stuff into apl
// do we ?
}
// and finally write the response
context.Response.ContentType="image/svg+xml";
context.Response.Write(output);
}
public virtual bool IsReusable
{
get { return false; }
}
}
What the code above does is:
We wont be showing any DyalogAPL code in this example, because space is limited.The following figure will give you an idea what is happening inside the apl workspace.

Figure
6. DyalogAPL classes for making graphical images.
In web.config we still have to add some configuration information:
<httpHandlers>
<add verb="*" path="*.svg" type="Graph.Handlers.SvgHandler,Graph.Handlers" />
....
This time we also have to configure IIS to pass .svg extensions to ASP.NET. That can be done easily using the IIS Manager.
Every request following this application path that has the extension .svg will be forwarded to our new HttpHandler. It is supposed to manage all internal exceptions and return a response corresponding the client side expectations of the responses contents type.
In fact things are not as simple as the two examples above may suggest. If we want to pass startup parameters to our new modules or handlers, we should do it in a similar way: independently of the current application. This can also be done with web.config by adding a section where we place our configuration information.
Luckily asp.net provides us most of the framework needed to read this information, but complex data has to be dealt with otherwise.
Another thing is to find a way to use customer/third party extensions which are designed to extend our own application extensions i.e. when someone has derived a class from our base class and we should be able to use it in our application.
One of our HttpModules (coded in C#) uses this kind of approach where the customer can implement her/his own derived class to be used instead of our base class. The .Net Framework also provides the facilities for building such plugin solutions.
Here are some general principles for passing information and designing general plugins for both asp.net and windows applications.
So far we havent tried this in DyalogAPL, but there is actually no reason why it should not work after minor adjustments.
Below we have an example of a section in a configuration file, which defines a new group called <graph.logs>. This section just groups a set of subsections for us. The subsection <userLog> contains the relevant information: which implementation of userLog should be used. The type field has the class name and assembly information to be passed to our application. This class is a derived class from our base class, and was implemented afterwards.
<configuration>
<!-- Allows for a new section group to the Web.config -->
<configSections>
<sectionGroup name="graph.logs">
<section
name="userLog"
type="System.Configuration.SingleTagSectionHandler,
System, Version=1.0.5000.0, Culture=neutral,
PublicKeyToken=b77a5c561934e089" />
</sectionGroup>
</configSections>
<graph.logs>
<userLog
type="Graph.Logs.XmlUserLog, Graph.Modules.Logs"/>
<!--
<userLog
type="Graph.Logs.CompFileUserLog,
Graph.Modules.Logs" />
-->
</graph.logs>
...
Here is a short list of pros and cons of using DyalogAPL to be used as a reference in further discussions.
We have touched the surface of the wonderful world of HttpModules and HttpHandlers and shown some examples of how DyalogAPL has been used in this context. Hopefully there will be more elegant examples and shared solutions to be seen in the near future.
Several articles in the MSDN library written by Scott Mitchell, Atif Aziz, Roy Osherove, Dino Esposito, Rick Strahl and others.
Pertti Kalliojärvi is one of the senior partners and founders of Dinosoft Oy (Finland) and has been working with APL for the past 20 years.
October 2005