瀏覽模式: 普通 | 列表

AJAX

AJAX結合JavaScript與XML兩種主要的業界標準,讓瀏覽器呈現頁面與伺服器處理回應時,可以不同步運作,減少瀏覽網頁等待的時間,為使用者帶來全新的網路衝浪體驗。

AJAX的出現讓企業重新省視網頁應用(Web Application)設計的兩個重要觀點:開發的方式與互動的模式。在資訊技術快速推陳出新的時代,許多網站設計人員莫不熱情擁抱,深怕落後在潮流以外,AJAX的出現對他們而言卻如同當頭棒喝,它讓網站開發者瞭解到設計網頁並不一定非得採用最新的資訊技術不可,原來使用舊技術也可以開發高互動性的網站。此外,網頁的互動過程,應決定在使用者而不是設計師。

當人們質疑堆砌舊技術所能達成的效果時,Google Maps卻適時地伴演著指標性的範例,結合AJAX互動引擎與簡潔的網頁介面,將虛擬與現實整合等加值應用,讓使用者愛不釋手。只是,對企業而言,Google在AJAX應用的典範上,會不會是一個特例?這一點,仍有待觀望,但它的確為企業在設計網站時,指引新的方向。雖然很少有企業網站會像Google Maps一樣,僅專注在單一商業用途上,但如果AJAX能夠結合JavaEE的應用,重新架構企業網站運作方式,讓企業與使用者間的互動,因網站的改善而更緊密,更重要的是,它是免費的。

儘管如此,當企業採用AJAX這種同屬於RIA技術,開發其商業網站時,雖然它提供一個免費的管道,但必須注意的是,AJAX的應用要適得其所。

AJAX仍存在舊技術的瓶頸
AJAX是新的名詞,但不是全新的技術。這個名稱,原來是「Asynchronous JavaScript and XML」的縮寫,首次出現在Adaptive Path顧問公司的Jesse James Garrett在2005年2月18日,於網路上發表「A New Approach to Web Application」中。這位顧問提出一個新的觀點,認為採用JavaScript與XML等已存在的技術,即可解決網頁設計時,靜態與動態呈現方式難以抉擇的問題,而不是一味地追逐新的資訊技術,並且使得Web Application的操作能像桌上型電腦中的應用程式般,達到RIA(Rich Internet Application)的同樣目的。

傳統網站的設計一直在靜態與動態間游移不定,前者在於執行的效率,後者在於互動的體驗,但很少有兼顧兩者優點的設計管道。雖然Macromedia提出Flash技術,以呈現RIA的強大,但企業也在尋找另一個管道,同時達成靜態與動態的目的。

AJAX雖然採用JavaScript與XML等業界的公開標準,這些技術也已很成熟,但用於開發網站,仍有以下待解決的技術瓶頸:

瀏覽器必需啟用JavaScript:有些使用者會關閉JavaScript功能,因為許多網頁的彈出式廣告,便是以JavaScript所撰寫的,間接影響到AJAX的運作。

瀏覽器必須支援XMLHttpRequest物件:由於AJAX引擎與伺服器間的交談都是經由XML格式,所以瀏覽器必須支援此物件。目前主流瀏覽器都已支援此標準,但Opera尚未完全支援,等更新版本才納入此標準。

使用侷限性:因為AJAX引擎代理瀏覽器與伺服器的交談,雖然使用者不需要按下傳送按鈕,但也因此,無法回到上一頁的畫面,所以在AJAX所撰寫的網頁中,常看不到「前一步(Last)」與「下一步(Next)」等按鈕,這個問題主要是因為JavaScript所造成的,也就是常令人詬病的缺點。接下來,使用者常在這類網站中因為缺少進一步的指引。雖然傳統網頁回傳結果時,會刷新網頁或換頁,但使用者也因此可以判斷處理的過程。可是在AJAX中,卻無法知道目前的狀況是處理前,還是已處理完成,AJAX引擎打斷了一般瀏覽網頁的習慣,也就是稱為「breaking the back botton」的問題。同樣的影響下,我們很難將同一個網頁內容透過URL與朋友分享,即使將JavaScript處理完成後的網頁URL傳給其它人,他們只是看到未處理前的畫面,例如表格欄位仍是空白的狀態。此外,因為AJAX無法記錄狀態,所以使用者也無法經由瀏覽記錄中回到之前的頁面了。

安全性:AJAX引擎因為嵌在用戶端的執行程式中,所以任何使用者可以輕易看到所有程式碼(如IE中「檢視」→「原始碼」或Firefox中「檢視」→「此頁原始內容」)。此外,在AJAX所採用的技術中,並沒有任何一項可以保證資料交換過程的安全性。

雖然AJAX能讓網頁設計者少了傳送按鈕的設計與動作,不過,有些網頁中的傳送按鈕是必要的,主要用來提醒使用者在傳送敏感性資料時,再一次提醒使用者確認此動作,但AJAX中,使用者既無法確認,資料送出後,無論對或錯,都無法反悔。

效能:這個問題根源於JavaScript本身,但因為AJAX包含此技術,所以同樣的問題仍存在。JavaScript本身並非完全的物件導向,而且缺少效能驗證與除錯工具。此外,當網頁中必需包括大量的JavaScript程式碼,因為這些程式都在用戶端執行,所以使用者的電腦處理效能必須足以應付,即使處理器速度夠快,大量的JavaScript程式碼仍足以拖慢瀏覽器的執行速率,這也是JavaScript發展這麼久以來,一直未形成主流應用的原因。

程式開發:因為AJAX所包含的技術都在嵌入同一個程式中,所以開發者很難重複使用程式,但在主流的物件導向中,重複運用程式碼有助於縮短開發時程及加速執行效能,AJAX在這方面顯然力不從心。另外,因為AJAX讓Web Application開發者不僅要懂HTML與JavaScript,也必需懂DOM、CSS、XML等,後續維護上也很困難,因為管理者必需要知道問題發生在那個技術環節上。JavaScript另一個令開發者頭疼的原因是,它既非一般正規的程式語言(如C++或Java),也不是正統的標註語言(如HTML),但嵌入在網頁中後,破壞了整個程式架構與程式的簡潔,讓後續維護變得困難重重。

整合應用程式:AJAX將所有技術混雜,以致於難以整合其它應用,例如串流影音檔案的撥放等。

跨平臺的處理:雖然AJAX所採用的均是開放的標準,但網頁開發者還是必須撰寫程式,主動偵測用戶端的瀏覽器是否支援AJAX所包括的所有技術,如果使用者的瀏覽器不支援,程式中應加上指示,告知使用者如何處理這類網頁,就像網頁處理Flash一樣,提醒使用者下載外掛程式,或選擇跳過Flash撥放的影片。

離線瀏覽行動式周邊:雖然AJAX可以讓Web Application如同操作應用程式一樣便利,但它必須與伺服器互動,以致於離線瀏覽便無法處理頁面資料。如果企業中的Web Application也包括行動式設備的執行環境,例如PDA或Smart Phone,由於這些設備並不完全支援AJAX所包含的各種技術,例如JavaScript或DOM,以致於無法運作。

AJAX企業應用模型:結合JavaEE
AJAX既然能提供使用者減少等待的時間,對許多企業網站而言,只要適當地應用,便能改善原本網站的處理方式,例如:結合JavaEE(Sun將Java Enterprise Edition重新命名為JavaEE,不再使用J2EE)。我們以企業網站常處理的資料庫數據模型為例,說明AJAX如何結合JavaEE。這樣的結合,可以讓許多企業網站的商業邏輯資料在處理的過程中,不致於讓使用者長久地等候,讓使用者在網頁中瀏覽資料庫數據時,如同在企業內部網路中使用般的快速與便利。

依商業邏輯決定AJAX應用
目前,到底哪一種Web Application適合使用AJAX,並沒有定論,但從Google Maps受重視的程度來分析,可以得知單一用途,而且需要大量數據交換的網站形式最適合。不過,主要還是得依企業本身需求而定,也並非整個網頁都必須以AJAX撰寫不可。

AJAX主要能讓開發者更彈性地處理資料交換的過程,而不是侷限在靜態與動態中。如果企業期望能讓Web Application像RIA一般,也不一定非在AJAX與Flash兩者間擇一不可,我們可以在網路中找到同時使用兩種技術的案例,從中發現到其互補的特點。但就像Flash一樣,雖然RIA可以帶給使用者不同的體驗,但也同時改變他們瀏覽網頁的習慣,企業必須在漸進的過程中讓使用者學會並接受。文⊙張瑞隆


AJAX on MSDN

AJAX魔法祭壇

.Net 範例程式及文件




Installing PostgreSQL on Fedora Core4

Postgresql安裝
# useradd postgres
# tar zxvf postgresql-xxxx.tar.gz
# chown -R postgres.postgres postgresql-xxxx
# cd postgresql-xxxx
#./configure --prefix=/usr/local/pgsql --enable-multibyte=MULE_INTERNAL
# make
# make install

檔案:/etc/profile
PATH=$PATH:/usr/local/pgsql/bin
MANPATH=$MANPATH:/usr/local/pgsql/man
export PATH MANPATH
LD_LIBRARY_PATH=/usr/local/pgsql/lib
export LD_LIBRARY_PATH

檔案:/home/postgres/.bash_profile
PGLIB="/usr/local/pgsql/lib"
PGDATA="/usr/local/pgsql/data"
PGBIN="/usr/local/pgsql/bin"
PGLOG="/usr/local/pgsql/log"
PGCLIENTENCODING='BIG5'
export PGLIB PGDATA PGBIN PGLOG PGCLIENTENCODING

# chown -R postgres.postgres /usr/local/pgsql
# su - postgres
# initdb -E MULE_INTERNAL
# postmaster -i -S
# createuser sa(當pgsql系統問你sa是否可以建立db及user都選yes)
# createdb -E EUC_TW test
# psql test
test=# set client_encoding to 'big5';
test=# alter user sa with password '你想要的密碼';
test=# q

在Linux OS環境下用 root 來useradd sa
並且passwd sa(密碼我是設定跟在pgsql內的sa的密碼一樣)
檔案:/home/sa/.bash_profile
PGLIB="/usr/local/pgsql/lib"
PGDATA="/usr/local/pgsql/data"
PGBIN="/usr/local/pgsql/bin"
PGLOG="/usr/local/pgsql/log"
PGCLIENTENCODING='BIG5'
export PGLIB PGDATA PGBIN PGLOG PGCLIENTENCODING

檔案:/etc/rc.d/rc.local
#start pgsql when OS reboot (這行是註解,底下才是內容)
POSTGRESDIR=/usr/local/pgsql
if [ -x $POSTGRESDIR/bin/postmaster -a -d $POSTGRESDIR/data ];then
rm -f /tmp/s.PGSQL.5432
su - postgres -c "postmaster -i -S"
echo -n 'postmaster'
fi

From:JavaNull 無國界 http://blog.yam.com/javanull




Installing Oracle DB on Fedora Core4

Oracle真的是不好裝,沒有教學或說明檔的話,真的不知道從何下手,除了硬體環境的要求之外,軟體套件的檢查也是缺一不可,重新安裝了Fedora Core4,花了一個多小時,終於裝完了,順便記錄一下我的安裝過程。

下載Oracle Database,我下載的版本是Version 10.1.0.3.0,檔名為ship.db.lnx32.cpio.gz
http://otn.oracle.com/software/products/database/oracle10g/index.html

以root身份上傳至 Fedora 後,解壓縮ship.db.lnx32.cpio.gz檔案
gunzip ship.db.lnx32.cpio.gz

解壓縮後使用cpio指令將ship.db.lnx32.cpio檔案還原
cpio -idmv < ship.db.lnx32.cpio

還原後會得到一/Disk1目錄,按照說明文件上是將整個/Disk1燒錄至光碟中進行安裝,但如果磁碟空間允許的話,也是可以放在硬碟中安裝的。至此已經將Oracle Database安裝所需的檔案備妥,然而並非現在即可進行安裝的動作,還必須經過硬體、作業系統及套件(RPM)檢查的動作,才可以確保安裝過程能夠順利進行。

記憶體及系統交換檔空間檢查
根據Oracle 文件上的建議,Oracle Universal Installer (OUI) 必須在 /tmp 有 400 MB 的空間,但實際上 OUI 在安裝檢查時,只會檢查 /tmp 是否足夠 80 MB。

檢查/tmp
df /tmp

若空間不足 400 MB 時,使用下列指令將 /tmp 檔案系統移至空間較大的磁碟分割。
su - root
mkdir /usr/local/tmp
chown root.root /usr/local/tmp
chmod 1777 /usr/local/tmp
export TEMP=/usr/local
export TMPDIR=/usr/local
當完成安裝後(是整個安裝完成後哦~~~不是現在),利用下列指令移除自行設定之暫存空間 /tmp
su - root
rmdir /usr/local/tmp
unset TEMP
unset TMPDIR

安裝Oracle在Fedora Core4作業系統安裝時所需之RPM,這些RPM在一般大學的FTP裡即可找到,或將檔名copy貼在Google也可以找到很多。
rpm -Uvh gcc-4.0.0-8.i386.rpm
           cpp-4.0.0-8.i386.rpm
           glibc-devel-2.3.5-10.i386.rpm
           glibc-headers-2.3.5-10.i386.rpm
           glibc-kernheaders-2.4-9.1.94.i386.rpm

  rpm -Uvh compat-libstdc++-33-3.2.3-47.fc4.i386.rpm

  rpm -Uvh openmotif-2.2.3-10.i386.rpm
           xorg-x11-deprecated-libs-6.8.2-31.i386.rpm

  rpm -Uvh openmotif21-2.1.30-14.i386.rpm

  rpm -Uvh libaio-0.3.104-2.i386.rpm

  rpm -Uvh selinux-policy-targeted-1.25.2-4.noarch.rpm

最有趣的一件事,基本上,Oracle Database預設是無法於Fedora上安裝的,但是可以透過欺騙OUI,來達到安裝的目的。
su - root
cp /etc/redhat-release /etc/redhat-release.orig
cat > /etc/redhat-release << EOF
Red Hat Enterprise Linux AS release 3 (Taroon)
EOF

安裝完後的版本還原
su - root
cp /etc/redhat-release.orig /etc/redhat-release

檢查系統核心參數
su - root
sysctl -a

檔案:/etc/sysctl.conf
kernel.shmmax=2147483648
kernel.sem=250 32000 100 128
fs.file-max=65536
net.ipv4.ip_local_port_range=1024 65000

為了讓上述修改生效,執行下列指令
su - root
sysctl -p

另外還有一些磁碟空間檢查的動作,但磁碟空間在一開始切Partition時就已經決定,且目前的硬碟應該都有超過2.5G的容量,故我直接略過該檢查程序。

跟其它資料庫一樣, Oracle Database 不可以使用 root 身份進行安裝或啟動,因此我們必須建立一個 User 供 Oracle 使用,命令如下:
su - root
groupadd dba
groupadd oinstall
useradd -c "Oracle software owner" -g oinstall -G dba oracle
passwd oracle

在Unix系統,大部份的Shell都有對每個User能使用的File及Process做限制,而在Oracle安裝過程中會使用大量的File及Process,因此我們必須對oracle帳號所使用的shell做修改:
檔案:/etc/security/limits.conf
oracle           soft    nofile          4096
oracle           hard    nofile          63536
oracle           soft    nproc           2047
oracle           hard    nproc           16384

使用下列指令讓上述修改生效
su - oracle
cat >> ~oracle/.bash_profile << EOF
ulimit -u 16384
EOF

建立 Oracle Database 的安裝目錄
su - root
mkdir -p /u01/app/oracle
chown oracle.oinstall /u01/app/oracle

如果要使用 Oracle's Optimal Felexible Architecture (OFA),即使用下列設定
su - root
mkdir -p /u02/oradata/orcl
chown oracle.oinstall /u02/oradata/orcl

設定 Oracle 環境變數
su - oracle
檔案:~oracle/.bash_profile
cat >> ~oracle/.bash_profile << EOF
export ORACLE_BASE=/u01/app/oracle
export ORACLE_SID=orcl
EOF

環境設定檢查就緒,可以開始安裝囉!但由於 Oracle 是使用 GUI 介面安裝的,我是經由 SSH 協定遠端連線進入 Fedora 來設定剛剛的步驟,安裝手冊上說明可以利用Xwindow進行遠端的安裝,指令如下:
ssh -X oracle@oracle_remote_server_name

但因為試了幾次都不成功,我看還是直接跑到機器前面安裝比較快一點。
mv /root/Disk1/ /home/oracle/
chown -R oracle:oinstall /home/oracle/
su - oracle
/Disk1/runInstall


按照上述的步驟,在安裝時即可順利進行,安裝完畢業,記得設定下列參數。
檔案:~oracle/.bash_profile
export ORACLE_HOME=$ORACLE_BASE/product/10.1.0/Db_1
export PATH=$PATH:$ORACLE_HOME/bin
export LD_LIBRARY_PATH=$ORACLE_HOME/lib

安裝完成後檢視Oracle Enterprise Manager的畫面

attachments/959608.jpg



連接各J2EE Web Based Applications 管理工具網址
Ultra Search URL:
http://localhost.localdomain:5620/ultrasearch
Ultra Search Administration Tool URL:
http://localhost.localdomain:5620/ultrasearch/admin
iSQL*Plus URL:
http://localhost.localdomain:5560/isqlplus
iSQL*Plus DBA URL:
http://localhost.localdomain:5560/isqlplus/dba
Enteprise Manager 10g Database Control URL:
http://localhost.localdomain:5500/em


安裝Oracle的相關資源:
http://www.puschitz.com/InstallingOracle10g.shtml
http://www.oracle.com/technology/global/cn/pub/articles/smiley_10gdb_install.html

Reference:www.puschitz.com AUTHOR:Werner Puschitz. Installing Oracle Database 10g Release 1 and 2 (32-bit/64-bit) on Red Hat Enterprise Linux AS 4, 3, 2.1, Red Hat Fedora Core 4, 3, 1, RH 9 on x86 and x86-64 (AMD64/EM64T) Architecture




.Net資源 - 建立可加總的Datagrid

Summary Rows in DataGrid Controls

Summary.cs
// Summary.cs - code-behind file

namespace BWSLib
{
    using System;
    using System.Web.UI;
    using System.Web.UI.WebControls;
    using System.Data;
    using System.Data.SqlClient;
    using System.Drawing;
    using System.Text;

    public class MyPage : Page
    {
        // Declare as PUBLIC or PROTECTED members all
        // the controls in the layout
        protected DataGrid grid;
        protected Label lblMsg;
        protected DropDownList ddYears;

        // Page OnLoad
        protected override void OnLoad(EventArgs e)
        {
            if (!IsPostBack)
            {
                // Load data and refresh the view
                DataFromSourceToMemory("MyDataSet");
                UpdateDataView();
            }
        }


        // DataFromSourceToMemory
        private void DataFromSourceToMemory(String strDataSessionName)
        {
            // Gets rows from the data source
            DataSet oDS = PhysicalDataRead();
    
            // Stores it in the session cache
            Session[strDataSessionName] = oDS;
        }

        // PhysicalDataRead
        private DataSet PhysicalDataRead()
        {
            String strCnn = "server=localhost;initial catalog=northwind;uid=sa;";
            SqlConnection conn = new SqlConnection(strCnn);

            // Command text using WITH ROLLUP
            StringBuilder sb = new StringBuilder("");
            sb.Append("SELECT ");
            sb.Append("  CASE GROUPING(o.customerid) WHEN 0 THEN o.customerid ELSE '(Total)' END AS MyCustomerID, ");
            sb.Append("  CASE GROUPING(od.orderid) WHEN 0 THEN od.orderid ELSE -1 END AS MyOrderID, ");
            sb.Append("  SUM(od.quantity*od.unitprice) AS price ");
            sb.Append("FROM Orders o, [Order Details] od ");
            sb.Append("WHERE Year(orderdate) = @TheYear AND od.orderid=o.orderid ");
            sb.Append("GROUP BY o.customerid, od.orderid WITH ROLLUP ");
            sb.Append("ORDER BY o.customerid, price");
            String strCmd = sb.ToString();
            sb = null;

            SqlCommand cmd = new SqlCommand();
            cmd.CommandText = strCmd;
            cmd.Connection = conn;    

            SqlDataAdapter da = new SqlDataAdapter();
            da.SelectCommand = cmd;

            // Set the "year" parameter
            SqlParameter p1 = new SqlParameter("@TheYear", SqlDbType.Int);
            p1.Direction = ParameterDirection.Input;
            p1.Value = Convert.ToInt32(ddYears.SelectedItem.Text);
            cmd.Parameters.Add(p1);
    
            // The DataSet contains two tables: Orders and Orders1.
            // The latter is renamed to "OrdersSummary" and the two will be put into
            // relation on the CustomerID field.
            DataSet ds = new DataSet();
            da.Fill(ds, "Orders");

            return ds;
        }

        // Refresh the UI
        private void UpdateDataView()
        {
            // Retrieves the data
            DataSet ds = (DataSet) Session["MyDataSet"];
            DataView dv = ds.Tables["Orders"].DefaultView;

            // Re-bind data
            grid.DataSource = dv;
            grid.DataBind();
        }

        // EVENT HANDLER: ItemCreated            
        public void ItemCreated(Object sender, DataGridItemEventArgs e)
        {
            // Get the newly created item
            ListItemType itemType = e.Item.ItemType;

            ///////////////////////////////////////////////////////////////////
            // ITEM and ALTERNATINGITEM
            if (itemType == ListItemType.Item || itemType == ListItemType.AlternatingItem)
            {
                DataRowView drv = (DataRowView) e.Item.DataItem;
                if (drv != null)
                {
                    // Check here the app-specific way to detect whether the
                    // current row is a summary row

                    if ((int) drv["MyOrderID"] == -1)
                    {
                        // Modify the row layout as needed. In this case,
                        //  + change the background color to white
                        //  + Group the first two cells and display company name and #orders
                        //  + Display the total of orders
                        // Graphical manipulations can be done here. Manipulations that require
                        // data access should be done hooking ItemDataBound. They can be done
                        // in ItemCreated only for templated columns.
                        e.Item.BackColor = Color.White;  
                        e.Item.Font.Bold = true;
                        e.Item.Cells.RemoveAt(1);            // remove the order # cell
                        e.Item.Cells[0].ColumnSpan = 2;        // span the custID cell
                        e.Item.Cells[1].HorizontalAlign = HorizontalAlign.Right;
                    }

                }
            }                    
        }

        // EVENT HANDLER: PageIndexChanged
        public void PageIndexChanged(Object sender, DataGridPageChangedEventArgs e)
        {
            grid.CurrentPageIndex = e.NewPageIndex;
            UpdateDataView();
        }

        // EVENT HANDLER: ItemDataBound
        public void ItemDataBound(Object sender, DataGridItemEventArgs e)
        {
            // Retrieve the data linked through the relation
            // Given the structure of the data ONLY ONE row is retrieved
            DataRowView drv = (DataRowView) e.Item.DataItem;
            if (drv == null)
                return;

            // Check here the app-specific way to detect whether the
            // current row is a summary row
            if ((int) drv["MyOrderID"] == -1)
            {
                if (drv["MyCustomerID"].ToString() == "(Total)")
                {
                    e.Item.BackColor = Color.Yellow;
                    e.Item.Cells[0].Text = "Orders total";
                }
                else
                    e.Item.Cells[0].Text = "Customer subtotal";
            }
        }

        public void OnLoadYear(Object sender, EventArgs e)
        {
            DataFromSourceToMemory("MyDataSet");
            UpdateDataView();
        }
    }
}


Summary.cs
‹%@ Page Language="C#" Inherits="BWSLib.MyPage" Src="Summary.cs" Trace="false" %›

‹html›
‹title›Summary Rows‹/title›
‹style›
  a                {behavior:url(....mouseover.htc);}
  hr            {height:2px;color:black;}
  .StdTextBox    {font-family:verdana;font-size:x-small;border:solid 1px black;filter:progid:DXImageTransform.Microsoft.dropshadow(OffX=2, OffY=2, Color='gray', Positive='true');}
  .StdText        {font-family:verdana;font-size:x-small;}
‹/style›


‹BODY bgcolor="ivory" style="font-family:verdana;font-size:small"›
‹h2›Orders and Customers‹/h2›

‹!-- ASP.NET Form --›
‹form runat="server"›

‹!-- Grid and the remainder of the page --›
‹table›‹tr›
‹td valign="top"›

‹asp:DataGrid id="grid" runat="server"
    AutoGenerateColumns="false"
    AllowPaging="true" PageSize="15"
    Font-Size = "xx-small"
    CellSpacing="0" CellPadding="4"
    DataKeyField="MyCustomerId"
    BorderStyle="solid" BorderColor="skyblue" BorderWidth="1" GridLines="both"
    OnItemCreated="ItemCreated"
    OnItemDataBound="ItemDataBound"
    OnPageIndexChanged="PageIndexChanged"›
    
    ‹headerstyle backcolor="skyblue" font-size="9pt" font-bold="true" /›
    ‹itemstyle backcolor="#eeeeee" /›
    ‹pagerstyle backcolor="skyblue" font-name="webdings" font-size="10pt" PrevPageText="3" NextPageText="4" /›
    
    ‹Columns›
          ‹asp:BoundColumn DataField="MyCustomerId" HeaderText="Customer" /›
          ‹asp:BoundColumn DataField="MyOrderId" HeaderText="Order #" /›
       ‹asp:BoundColumn DataField="price" HeaderText="Amount" DataFormatString="{0:c}"›
        ‹itemstyle horizontalalign="right" /›
       ‹/asp:BoundColumn›
    ‹/Columns›
‹/asp:DataGrid›

‹/td›
‹td valign="top" width="20px"›‹/td›
‹td valign="top"›
    ‹b›Year‹/b›
    ‹asp:dropdownlist runat="server" id="ddYears"›
        ‹asp:listitem runat="server" ›1998‹/asp:listitem›
        ‹asp:listitem runat="server" ›1997‹/asp:listitem›
        ‹asp:listitem runat="server" ›1996‹/asp:listitem›
    ‹/asp:dropdownlist>
    
    ‹asp:linkbutton runat="server" text="Load..." onclick="OnLoadYear" />
    ‹br>‹br>
    ‹asp:label runat="server" cssclass="StdText" id="lblMsg" />
‹/td>
‹/tr>‹/table>
‹hr>
‹/form>
‹/body>
‹/html›




ASP.Net按鈕控制項防止重覆送出的方式

防止使用者將表單重覆送出,目的在保持資料的完整性與一致性,同時也可保護伺服器不被Web Bot類程式的侵擾,解決方案依架構來區分可分為Server端及Client等,Server端的解決方案最簡單的是用Session來記錄每條連線的Submit狀態,讓重覆送出的PostBack不會對程式碼產生重覆執行的效果,方法較為可靠,但也較耗伺服器資源,本文針對使用Client端的客製化屬性將表單按鈕做特別的處理,確保表單可以不受干擾的執行。

public class WebForm1 : System.Web.UI.Page
{
    protected System.Web.UI.WebControls.Button Button1;
    
    private void Page_Load(object sender, System.EventArgs e)
    {
    
    
    }
    #region Web Form Designer generated code
    override protected void OnInit(EventArgs e)
    {
        Button1.Attributes.Add("onclick","javascript:" +
                  Button1.ClientID + ".disabled=true;" +
                  this.GetPostBackEventReference(Button1));
        InitializeComponent();
        base.OnInit(e);
    }
    
    /// <summary>
    /// Required method for Designer support - do not modify
    /// the contents of this method with the code editor.
    /// </summary>
    private void InitializeComponent()
    {
        this.Button1.Click +=
                new System.EventHandler(this.Button1_Click);
        this.Load += new System.EventHandler(this.Page_Load);
    }
    #endregion
    private void Button1_Click(object sender, System.EventArgs e)
    {
        System.Threading.Thread.Sleep(5000);
        //Response.Redirect("http://www.msn.com");
    }
}