asp.net|指令碼
將Delphi視為指令碼語言
支援ASP.net的第一件事是讓ASP.NET將Delphi視為指令碼語言,讓ASP.NET能夠為各種ASP檔案類型調用Delphi的.NET編譯器。
ASP.NET要在IIS虛路徑的根目錄下尋找Web.config檔案。下面是ASP.NET中使用Delphi作指令碼語言的web.config配製檔案內容:
<configuration>
<system.web>
<compilation debug="true">
<assemblies>
<add assembly="DelphiProvider" />
</assemblies>
<compilers>
<compiler language="Delphi" extension=".pas"
type="Borland.Delphi.DelphiCodeProvider,DelphiProvider" />
</compilers>
</compilation>
</system.web>
</configuration>
關於web配製檔案的詳情請參MSDN:
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpguide/html/cpconformatofconfigurationfiles.asp
在我的機器(Win2K Pro)上測試Delphi對ASP.NET的支援。要增加一個虛路徑來安放Delphi指令碼,我把這個路徑名定為"vslive"。
在我的機器配製檔案上作了這個小改動後就可以來看ASP.NET是如何將Delphi視為指令碼語言的。
在ASP.NET中使用Delphi代碼
首先編寫一個簡單應用來確認我們的Delphi支援配製是正確的。下面是editdemo.aspx檔案的代碼,有一個文本輸入框,一個按鈕。按鈕事件觸發顯示輸入框內容。
<html>
<script language="Delphi" runat="server">
procedure ButtonClick(Sender: System.Object; E: EventArgs);
begin
Message.Text := Edit1.Text;
end;
</script>
<body>
<form runat="server">
<asp:textbox id="Edit1" runat="server"/>
<asp:button text="Click Me!" runat="server"/>
</form>
<p><b><asp:label id="Message" runat="server"/></b></p>
</body>
</html>
可以看到,ASP按鈕對象的OnClick事件觸發Delphi的ButtonClick過程,而Delphi程式裡卻使用了ASP對象label Message和text box Edit1。雖然在Delphi過程中沒有定義ASP的二個變數,Delphi代碼卻能找到它們。這是因為指令碼中含有的Delphi服務模組能夠產生相應的Delphi代碼。
現在可以用本地瀏覽器來瀏覽這個網頁了。因為我把指令碼放在"vslive"虛路徑,所以開啟:
http://localhost/vslive/editdemo.aspx.
以下是編譯之後形成的Delphi代碼,代碼產生WebForm:
//------------------------------------------------------------------------------
// <autogenerated>
// 本代碼由一個工具產生
// 運行版本:1.0.3705.209
//
// 修改本檔案將導致異常行為並丟失產生的程式碼。
// </autogenerated>
//------------------------------------------------------------------------------
unit ASP;
interface
uses System.Collections, System.Collections.Specialized, System.Configuration,
System.Text, System.Text.RegularExpressions, System.Web, System.Web.Caching,
System.Web.SessionState, System.Web.Security, System.Web.UI, System.Web.UI.WebControls,
System.Web.UI.HtmlControls, System.Globalization;
var
editdemo_aspx___autoHandlers: Integer;
editdemo_aspx___intialized: Boolean = False;
editdemo_aspx___fileDependencies: System.Collections.ArrayList;
type
editdemo_aspx = class(System.Web.UI.Page, System.Web.SessionState.IRequiresSessionState)
protected
Edit1: System.Web.UI.WebControls.TextBox;
__control3: System.Web.UI.WebControls.Button;
__control2: System.Web.UI.HtmlControls.HtmlForm;
Message: System.Web.UI.WebControls.Label;
procedure ButtonClick(Sender: System.Object; E: EventArgs);
public
constructor Create;
function get_AutoHandlers: Integer; override;
function get_ApplicationInstance: System.Web.HttpApplication; virtual;
function get_TemplateSourceDirectory: System.String; override;
procedure set_AutoHandlers(Value: Integer); override;
protected
property AutoHandlers: Integer read get_AutoHandlers write set_AutoHandlers;
property ApplicationInstance: System.Web.HttpApplication read get_ApplicationInstance;
public
property TemplateSourceDirectory: System.String read get_TemplateSourceDirectory;
private
function __BuildControlEdit1: System.Web.UI.Control;
function __BuildControl__control3: System.Web.UI.Control;
function __BuildControl__control2: System.Web.UI.Control;
function __BuildControlMessage: System.Web.UI.Control;
procedure __BuildControlTree(__ctrl: System.Web.UI.Control);
protected
procedure FrameworkInitialize; override;
public
function GetTypeHashCode: Integer; override;
end;
implementation
procedure editdemo_aspx.ButtonClick(Sender: System.Object; E: EventArgs);
begin
Message.Text := Edit1.Text;
end;
constructor editdemo_aspx.Create;
var
dependencies: System.Collections.ArrayList;
begin
inherited Create;
if (ASP.editdemo_aspx___intialized = False) then
begin
dependencies := System.Collections.ArrayList.Create;
dependencies.Add('d:\vslive\editdemo.aspx');
ASP.editdemo_aspx___fileDependencies := dependencies;
ASP.editdemo_aspx___intialized := True;
end;
Self.Server.ScriptTimeout := 30000000;
end;
function editdemo_aspx.get_AutoHandlers: Integer;
begin
Result := ASP.editdemo_aspx___autoHandlers;
end;
function editdemo_aspx.get_ApplicationInstance: System.Web.HttpApplication;
begin
Result := Self.Context.ApplicationInstance as System.Web.HttpApplication;
end;
function editdemo_aspx.get_TemplateSourceDirectory: System.String;
begin
Result := '/vslive';
end;
procedure editdemo_aspx.set_AutoHandlers(Value: Integer);
begin
ASP.editdemo_aspx___autoHandlers := Value;
end;
function editdemo_aspx.__BuildControlEdit1: System.Web.UI.Control;
var
__ctrl: System.Web.UI.WebControls.TextBox;
begin
__ctrl := System.Web.UI.WebControls.TextBox.Create;
Self.Edit1 := __ctrl;
__ctrl.ID := 'Edit1';
__ctrl.Width := System.Web.UI.WebControls.Unit.Parse('300px', System.Globalization.CultureInfo.InvariantCulture);
Result := __ctrl;
end;
function editdemo_aspx.__BuildControl__control3: System.Web.UI.Control;
var
__ctrl: System.Web.UI.WebControls.Button;
begin
__ctrl := System.Web.UI.WebControls.Button.Create;
Self.__control3 := __ctrl;
__ctrl.Text := 'Click Me!';
__ctrl.add_Click(Self.ButtonClick);
Result := __ctrl;
end;
function editdemo_aspx.__BuildControl__control2: System.Web.UI.Control;
var
__parser: System.Web.UI.IParserAccessor;
__ctrl: System.Web.UI.HtmlControls.HtmlForm;
begin
__ctrl := System.Web.UI.HtmlControls.HtmlForm.Create;
Self.__control2 := __ctrl;
__parser := __ctrl as System.Web.UI.IParserAccessor;
__parser.AddParsedSubObject(System.Web.UI.LiteralControl.Create(''#13#10' '));
Self.__BuildControlEdit1;
__parser.AddParsedSubObject(Self.Edit1);
__parser.AddParsedSubObject(System.Web.UI.LiteralControl.Create(''#13#10' '));
Self.__BuildControl__control3;
__parser.AddParsedSubObject(Self.__control3);
__parser.AddParsedSubObject(System.Web.UI.LiteralControl.Create(''#13#10' '));
Result := __ctrl;
end;
function editdemo_aspx.__BuildControlMessage: System.Web.UI.Control;
var
__ctrl: System.Web.UI.WebControls.Label;
begin
__ctrl := System.Web.UI.WebControls.Label.Create;
Self.Message := __ctrl;
__ctrl.ID := 'Message';
Result := __ctrl;
end;
procedure editdemo_aspx.__BuildControlTree(__ctrl: System.Web.UI.Control);
var
__parser: System.Web.UI.IParserAccessor;
begin
__parser := __ctrl as System.Web.UI.IParserAccessor;
__parser.AddParsedSubObject(System.Web.UI.LiteralControl.Create('<html>'#13#10' '));
__parser.AddParsedSubObject(System.Web.UI.LiteralControl.Create(''#13#10' <body>'#13#10' '));
Self.__BuildControl__control2;
__parser.AddParsedSubObject(Self.__control2);
__parser.AddParsedSubObject(System.Web.UI.LiteralControl.Create(''#13#10' <p><b>'));
Self.__BuildControlMessage;
__parser.AddParsedSubObject(Self.Message);
__parser.AddParsedSubObject(System.Web.UI.LiteralControl.Create('</b></p>'#13#10' </body>'#13#10'</html>'#13#10));
end;
procedure editdemo_aspx.FrameworkInitialize;
begin
Self.__BuildControlTree(Self);
Self.FileDependencies := ASP.editdemo_aspx___fileDependencies;
Self.EnableViewStateMac := True;
end;
function editdemo_aspx.GetTypeHashCode: Integer;
begin
Result := -764444463;
end;
end.
注意:這裡介紹的是Delphi的.NET編譯器功能的預覽。正式發布的Delphi 7產生的程式碼與上面將有顯著不同。本文僅是樣本說明如何在ASP.NET中使用Delphi及其功能。
更高技術的網頁
ASP.net的一些控制項遠比HTML控制項要更加智能化。其中之一就是日曆(Calendar)控制項。
以下代碼是calendar.aspx中的一部分。代碼提供二種方法讓控制項設定日期:
瀏覽日曆然後選擇日期;
按照日期格式輸入日期,確認選擇。這種方法由.NET的Convert類支援。
<script language="Delphi" runat="server">
procedure Calendar1Selected(Sender: System.Object; E: EventArgs);
begin
Label1.Text := 'Delphi for .NET says you picked ' + Calendar1.SelectedDate.ToString('D');
end;
procedure Button1Click(Sender: System.Object; E:EventArgs);
begin
Calendar1.VisibleDate := System.Convert.ToDateTime(Edit1.Text);
Label1.Text := 'Delphi for .NET says you set ' + Calendar1.VisibleDate.ToString('D');
end;
</script>
<body style="font:18pt Verdana">
<form runat="server">
<center>
<h1>Delphi for .NET running in ASP.NET</h1>
<p>Please pick a date</p>
<asp:Calendar id="Calendar1" runat="server" ForeColor="#0000FF" BackColor="#FFFFCC"
OnSelectionChanged="Calendar1Selected">
<TodayDayStyle Font-Bold="True"/>
<NextPrevStyle ForeColor="#FFFFCC"/>
<DayHeaderStyle BackColor="#FFCC66"/>
<SelectedDayStyle ForeColor="Black" BackColor="#CCCCFF"/>
<TitleStyle Font-Size="14pt" Font-Bold="True" ForeColor="#FFFFCC" BackColor="#990000"/>
<OtherMonthDayStyle ForeColor="#CC9966"/>
</asp:Calendar>
<p><asp:TextBox id="Edit1" width=200 runat="server"/>
<asp:Button text="Set date" id="Button1" runat="server" />
</p>
<p><asp:Label id="Label1" runat="server"/></p>
</center>
</form>
</body>
在日曆上選擇日期觸發OnSelectionChanged事件,調用Delphi的Calendar1Selected()過程。
輸入日期,點擊"Set data"按鈕觸發Button1Click事件,調用Delphi的Button1Click()過程。
資料處理
現在通過日曆的日期選擇來選擇顯示資料庫資料。在這個ASP.NET Delphi網頁上,增加一個DataGrid和一個TextBox,前者顯示資料庫資料,後者輸入要顯示的資料庫域。
<%@Import Namespace="System.Data"%>
<%@Import Namespace="System.Data.SqlClient"%>
<script language="Delphi" runat="server">
const
ProdName = 'Delphi for .NET';
DispFields = 'OrderID, CustomerID, ShipName, ShipCity, ShipCountry';
procedure DateSelected(Sender: System.Object; E: EventArgs);
begin
Label1.Text := ProdName + ' says you picked ' + Calendar1.SelectedDate.ToString('D');
DataGrid1.DataSource := GetOrders(Calendar1.SelectedDate);
DataGrid1.DataBind;
end;
procedure Button1Click(Sender: System.Object; E:EventArgs);
begin
Calendar1.VisibleDate := System.Convert.ToDateTime(Edit1.Text);
Label1.Text := ProdName + ' says you set ' + Calendar1.VisibleDate.ToString('D');
end;
procedure Button2Click(Sender: System.Object; E:EventArgs);
begin
DisplayFields.Text := DispFields;
end;
function GetOrders(Date : DateTime) : DataSet;
var
Adapter : SqlDataAdapter;
begin
Adapter := SqlDataAdapter.Create(
'select ' + DisplayFields.Text + ' from Orders '+
'where OrderDate = ''' + date.ToString('d')+'''',
'Server=(local);Database=Northwind;Trusted_Connection=yes');
Result := DataSet.Create;
Adapter.Fill(Result);
end;
</script>
<body style="font:18pt Verdana">
<form runat="server">
<h1><%=ProdName %> with a Calendar, DataGrid, & SqlClient in ASP.NET</h1>
<table>
<tr valign="top"><td>
<p><b>Pick a date</b></p>
<asp:Calendar id="Calendar1" runat="server" ForeColor="#0000FF" BackColor="#FFFFCC"
OnSelectionChanged="DateSelected">
<TodayDayStyle Font-Bold="True"/>
<NextPrevStyle ForeColor="#FFFFCC"/>
<DayHeaderStyle BackColor="#FFCC66"/>
<SelectedDayStyle ForeColor="Black" BackColor="#CCCCFF"/>
<TitleStyle Font-Size="14pt" Font-Bold="True" ForeColor="#FFFFCC" BackColor="#990000"/>
<OtherMonthDayStyle ForeColor="#CC9966"/>
</asp:Calendar>
<p><asp:TextBox id="Edit1" width=150 runat="server"/>
<asp:Button text="Set date" id="Button1" runat="server" />
</p>
</td><td valign="top">
<p><b>Display fields:</b> <asp:TextBox id="DisplayFields"
text="OrderID, CustomerID, ShipName, ShipCity, ShipCountry" width=500 runat="server"/>
<asp:Button text="Reset fields" id="Button2" runat="server" /></p>
<asp:DataGrid id="DataGrid1" runat="server" BorderColor="#FFCC66" ForeColor="#0000FF">
<HeaderStyle ForeColor="#FFFFCC" BackColor="#990000"/>
</asp:DataGrid>
</td></tr></table>
<p><asp:Label id="Label1" runat="server"/></p>
</form>
</body>
每當使用者點擊日曆選擇日期時,就觸發OnSelectionChanged事件,調用DateSelected()函數。
在GetOrders函數中,資料庫的串連由命名空間定義的SqlClient實現,資料庫是MS SQL 2000的示範庫Northwind。SqlDataAdapter將查詢結果安裝到DataGrid中,顯示出資料表格,如附圖。
改變域輸入框的網域名稱,再點擊日曆,就得到不同的結果。
這就是日曆驅動的資料庫查詢系統,由Delphi for .NET與ASP.NET共同完成。
結語
本文試圖簡略說明在ASP.NET中應用Delphi是如何方便。
請記住,本文樣本是Delphi 7的預覽樣本,正式版本的結果也許不完全如此,當然也許就是如此。