Bob Swart (aka Dr.Bob)
Delphi for .NET, ASP.NET en Code Behind

Dit artikel verschijnt vlak voor de Conference to the Max (mei 2003). Een aardig moment om vast iets te schrijven over een onderwerp dat tijdens een van mijn sessies aan de orde komt, namelijk het gebruik van de Delphi for .NET preview command-line compiler in combinatie met ASP.NET. In dit artikel wil ik met name aandacht besteden aan de zogenaamde Code Behind functionaliteit, omdat die (nog) niet zondermeer goed werkt voor Delphi for .NET gebruikers.

Let op: Ik maak voor dit artikeltje gebruik van de Delphi for .NET preview command-line compiler met Update 3 (van februari 2003) - mocht er inmiddels een nieuwe(re) update beschikbaar zijn, dan heb je kans dat het probleem dat we straks tegenkomen inmiddels reeds verholpen is.

ASP.NET
De Delphi for .NET preview command-line compiler is te gebruiken als scripting taal binnen ASP.NET. Dit betekent concreet dat we ook al bestaande Delphi code kunnen gebruiken als scripting code binnen ASP.NET pagina's. Een klein voorbeeld betreft het converteren van temperatuur waarden, van Celsius naar Fahrenheit, wat door de volgende ASP.NET pagina (in Celsius.aspx) gedaan kan worden:

  <html>
  <head>
    <title>Delphi for .NET en ASP.NET</title>
    <script language="Delphi" runat="server">
 
      procedure Celsius2FahrenheitClick(Sender: System.Object; E: EventArgs);
      begin
        edtFahrenheit.Text := Convert.ToString(9 / 5 *
          Convert.ToDouble(edtCelsius.Text) + 32)
      end;

      procedure Fahrenheit2CelsiusClick(Sender: System.Object; E: EventArgs);
      begin
        edtCelsius.Text := Convert.ToString(5 / 9 * 
          (Convert.ToDouble(edtFahrenheit.Text) - 32))
      end;

    </script>
  </head>

  <body bgcolor="ffffcc">
    <font face="verdana" size="2">
    <form runat="server">
       <br><b>Celsius:</b> <asp:textbox id="edtCelsius" runat="server"/>
       <br><b>Fahrenheit:</b> <asp:textbox id="edtFahrenheit" runat="server"/>
       <p>
       <asp:button text="Celsius naar Fahrenheit"
            OnClick="Celsius2FahrenheitClick" runat="server"/>
       <asp:button text="Fahrenheit naar Celsius"
            OnClick="Fahrenheit2CelsiusClick" runat="server"/>
    </form>
  </body>
  </html>
De twee OnClick event handlers van de buttons bevatten hierbij gewoon Delphi code! Wie dit voorbeeld in praktijk wil zien werken, kan naar http://www.eBob42.com/cgi-bin/Celsius.aspx gaan waar het op het web uit te proberen is.

Code Behind
Nadeel van de code zoals we die in de eerste listing zagen is dat de HTML en de Delphi code in hetzelfde bestand staat (in mijn geval Celsius.aspx). En het zou veel "netter" (en makkelijker te onderhouden) zijn als de code en de presentatie gescheiden is. Dat kan met ASP.NET, en wordt ook wel Code Behind genoemd. Als ik bovenstaand voorbeeld neem, zou dit in Code Behind vorm leiden tot twee nieuwe bestanden: Celsius2.aspx en Celsius2.pas. Het Celsius2.aspx bestand zou er als volgt uit komen te zien (zonder één regel Delphi code):

  <%@ Page language="Delphi" src="Celsius2.pas" Inherits="Celsius2.WebForm42" %>

  <html>
  <head>
    <title>Delphi for .NET en ASP.NET</title>
  </head>

  <body bgcolor="ffffcc">
    <font face="verdana" size="2">
    <form runat="server">
       <br><b>Celsius:</b> <asp:textbox id="edtCelsius" runat="server"/>
       <br><b>Fahrenheit:</b> <asp:textbox id="edtFahrenheit" runat="server"/>
       <p>
       <asp:button id="btnCelsius2Fahrenheit" text="Celsius naar Fahrenheit"
        OnClick="Celsius2FahrenheitClick" runat="server"/>
       <asp:button id="btnFahrenheit2Celsius"text="Fahrenheit naar Celsius"
        OnClick="Fahrenheit2CelsiusClick" runat="server"/>
    </form>
  </body>
  </html>
En de bijbehorende code - los van de user interface opmaak codes - zit dan in Celsius2.pas:
  unit Celsius2;
  interface
  uses
    System.Web.UI,
    System.Web.UI.WebControls;

  type
    WebForm42 = class(System.Web.UI.Page)
      edtCelsius: TextBox;
      edtFahrenheit: TextBox;
      btnCelsius2Fahrenheit: Button;
      btnFahrenheit2Celsius: Button;
    protected
      procedure Celsius2FahrenheitClick(Sender: System.Object; E: EventArgs);
      procedure Fahrenheit2CelsiusClick(Sender: System.Object; E: EventArgs);
    end;
  
  implementation
  
    procedure WebForm42.Celsius2FahrenheitClick(Sender: System.Object; E: EventArgs);
    begin
      edtFahrenheit.Text := Convert.ToString(9 / 5 *
        Convert.ToDouble(edtCelsius.Text) + 32)
    end;

    procedure WebForm42.Fahrenheit2CelsiusClick(Sender: System.Object; E: EventArgs);
    begin
      edtCelsius.Text := Convert.ToString(5 / 9 * 
        (Convert.ToDouble(edtFahrenheit.Text) - 32))
    end;
  end.
Helaas gaat dit nog niet goed met de Delphi for .NET preview command-line compiler. We krijgen een foutmelding die betrekking heeft of het koppelen van de OnClick event handlers aan de buttons (de Delphi code die achter de schermen gegenereerd wordt is niet correct). Als we C# als taal hadden gebruikt dan werkt het voorbeeld wel. Vervang hiertoe de eerste regel van Celsius2.aspx door:
  <%@ Page language="C#" src="Celsius2.cs" Inherits="Celsius2.WebForm42" %>
En gebruik de volgende C# code in Celsius2.cs om dit te demonstreren:
  using System;
  using System.Web.UI;
  using System.Web.UI.WebControls;
  
  namespace Celsius2
  {
    public class WebForm42: System.Web.UI.Page
    {
      public TextBox edtCelsius;
      public TextBox edtFahrenheit;
      public Button btnCelsius2Fahrenheit;
      public Button btnFahrenheit2Celsius;
      
      public void Celsius2FahrenheitClick(System.Object Sender, EventArgs E)
      {
        edtFahrenheit.Text = Convert.ToString(9.0 / 5.0 *
          Convert.ToDouble(edtCelsius.Text) + 32);
      }
  
      public void Fahrenheit2CelsiusClick(System.Object Sender, EventArgs E)
      {
        edtCelsius.Text = Convert.ToString(5.0 / 9.0 * 
          (Convert.ToDouble(edtFahrenheit.Text) - 32));
      }
    }
  }
Dit probleem zou een show-stopper kunnen zijn voor ASP.NET en Code Behind met de preview van de Delphi for .NET command-line compiler (tot er weer een volgende update uitkomt), ware het niet dat er nog een manier is om de event handlers niet het Celsius2.aspx bestand aan te geven, maar dynamisch te koppelen.

Code Behind met AutoEventWireup
Het dynamisch koppelen van event handlers (achter de schermen dus) kunnen we doen in de Page_Load event handler, die echter pas wordt aangeroepen als de we AutoEventWireup optie in de eerste regel van het Celsius2.aspx bestand toevoegen. De aangepaste Celsius2.aspx komt er dan als volgt uit te zien:

  <%@ Page language="Delphi" src="Celsius2.pas" AutoEventWireup="true"
    Inherits="Celsius2.WebForm42" %>

  <html>
  <head>
    <title>Delphi for .NET en ASP.NET</title>
  </head>
  
  <body bgcolor="ffffcc">
  <font face="verdana" size="2">
    <form runat="server">
     <br><b>Celsius:</b> <asp:textbox id="edtCelsius" runat="server"/>
     <br><b>Fahrenheit:</b> <asp:textbox id="edtFahrenheit" runat="server"/>
     <p>
     <asp:button id="btnCelsius2Fahrenheit" text="Celsius naar Fahrenheit"
      runat="server"/>
     <asp:button id="btnFahrenheit2Celsius" text="Fahrenheit naar Celsius"
      runat="server"/>
    </form>
  </body>
  </html>
Merk op dat het nu verplicht is om de buttons een ID mee te geven, om zodoende de koppeling tussen een asp:button in het Celsius2.aspx bestand en de Delphi Button in het Celsius2.pas bestand tot stand te kunnen brengen. De AutoEventWireup zorgt ervoor dat de Page_Load event handler wordt aangeroepen, en daarbinnen kunnen we dan gebruik maken van de btnCelsius2Fahrenheit en btnFahrenheit2Celsius en bij allebei deze buttons een event handler aan hun OnClick toe te voegen via de Add_Click methode.
  unit Celsius2;
  interface
  uses
    System.Web.UI,
    System.Web.UI.WebControls;

  type
    WebForm42 = class(System.Web.UI.Page)
      edtCelsius: TextBox;
      edtFahrenheit: TextBox;
      btnCelsius2Fahrenheit: Button;
      btnFahrenheit2Celsius: Button;
    protected
      procedure Celsius2FahrenheitClick(Sender: System.Object; E: EventArgs);
      procedure Fahrenheit2CelsiusClick(Sender: System.Object; E: EventArgs);
    public
      procedure Page_Load(Sender: System.Object; E: EventArgs);
    end;

  implementation

    procedure WebForm42.Page_Load(Sender: System.Object; E: EventArgs);
    begin
      btnCelsius2Fahrenheit.Add_Click(Self.Celsius2FahrenheitClick);
      btnFahrenheit2Celsius.Add_Click(Self.Fahrenheit2CelsiusClick)
    end;

    procedure WebForm42.Celsius2FahrenheitClick(Sender: System.Object; E: EventArgs);
    begin
      edtFahrenheit.Text := Convert.ToString(9 / 5 *
        Convert.ToDouble(edtCelsius.Text) + 32)
    end;

    procedure WebForm42.Fahrenheit2CelsiusClick(Sender: System.Object; E: EventArgs);
    begin
      edtCelsius.Text := Convert.ToString(5 / 9 * 
        (Convert.ToDouble(edtFahrenheit.Text) - 32))
    end;
  end.
Deze combinatie - een .aspx bestand zonder event handlers maar met AutoEventWireup, en een .pas bestand waarin de Page_Load event handler wordt gebruikt om alle andere event handlers neer te zetten - werkt in ieder geval wel, en kan dus gebruikt worden om ook met de preview van de Delphi for .NET command-line compiler aan ASP.NET met Code Behind te doen.
De daadwerkelijke versie is hier uit te proberen

Meer Informatie...
Voor de liefhebber zal ik tijdens mijn ASP.NET sessie op de CttM zal ik hier nog wat dieper op ingaan (en ook op de andere zaken die nog niet helemaal vlekkenloos werken, zoals het gebruik van een globals.axa bestand). Daarnaast loont het de moeite om mijn eigen website (www.eBob42.com) in de gaten te houden alsmede de nieuwe SDGN website waar ik regelmatig met wat kleine artikeltjes voor aanvulingen zal zorgen (vooral als er weer nieuwe updates van de Delphi for .NET preview command-line compiler mochten verschijnen).

Mocht iemand nog vragen, opmerkingen of suggesties hebben, dan hoor ik die het liefst via .


Dit artikel is eerder verschenen in SDGN Magazine #77 - april 2003

This webpage © 2003-2006 by webmaster drs. Robert E. Swart (aka - www.drbob42.com). All Rights Reserved.