top
Loading...
ASP.NET入門隨想之明明白白我的心
有一群說著同樣語言的人,計劃修一座高聳入云的高塔直達天庭,以證明族群團結的力量,塔很快就初具規模。這下可驚動天庭的神,他想這人和神都成鄰居了,還怎么去統治人類?于是便施魔法擾亂人們的語言,使他們無法溝通,于是高塔再也無法繼續修建。

■ 明明白白我的心 - 人機交互(Human-Computer Interaction)

博客園里有一篇《給媽媽寫程序》感人肺腑,說的是作者常常為了指導50出頭的媽媽完成COPY之類的操作耗盡心思,最后為其定做一個只需點擊兩下的程序,由此推出UI設計的重要性。誠然,就用戶而言軟件等于N個用戶界面。他們中的大多數壓根不關心里頭有多少令開發者陶醉的所謂高級技術,簡單、快捷、美觀是他們要求的全部。人機交互的研究領域就在搗騰這些看似瑣碎的東西。


在系統設計中,需要劃分自動化系統邊界,即把系統劃分成手工操作和系統自動兩個部份,兩者通過用戶界面(User Interface)完成對接,如圖8-1。用戶界面完成系統的輸入輸出工作:收集用戶觸發事件及相關數據,傳遞給系統內部進行處理并接收處理結果,可視化處理結果。在企業級的c/s應用中,aspx及其后臺編碼文件功能單純得只剩下一個--完成人機交互。一個漂亮的網頁不是用戶界面設計的全部內涵,它更應該象一位面容姣好、語音甜美的接待者,輕聲細語地詢問用戶需求,聆聽用戶雜亂無章的訴說,耐心指導用戶完成操作流程,寬容用戶錯誤,準確為用戶送上最終結果--"您的賬戶里只剩0.4元,無法完成支付操作。"總之一句話,要充分認識和領會白居易同志寫詩的偉大精神,讓50出頭的媽媽愉快地完成人機交互。

■ 人動則影動 - ASP.NET的靜態模型

在ASP.NET架構中,服務器端的ASP.NET頁面對應客戶端的HTML頁面,包含一個交互Web Form,繼承于FrameWork的Page類。ASPX文件是人,HTML編碼臨時文件是影,人動則影動,兩者合成完整意義上的用戶界面。用戶對影進行各種操作,系統通過人進行相應處理,"request-response"回饋機制完成兩者的映像過程,如圖8-2。


HTTP是一個無狀態協議,所以WEB服務器是位打個磕睡就忘事的先生,當響應發送后將丟棄所有請求信息。這事必會影響應用程序的可用性,如因為數據驗證錯誤而要求用戶重新輸入幾十個輸入框的所有信息,連媽媽的指頭都會發出抗議的聲音。為了彌補這個缺陷,ASP.NET使用視圖狀態(ViewState)來完成狀態保持。原理很簡單,服務器將每次HTTP請求中的頁面數據寫入生成的HTML文件中,下次頁面提交時一并帶上,如下例。在ASP時代我們曾用<input type="hidden">手工實現,而在.Net中您會發現HTML源代碼會自動產生一個 _VIEWSTATE標簽,其值即為系統保存的頁面數據。

<%@ Page Language="C#" %>
<script runat="server">
protected override void OnLoad(EventArgs e){
int val = int.Parse(_sum.InnerText);
_sum.InnerText = (val+1).ToString();
base.OnLoad(e);
}
</script>
<html><body><form runat="server">
<span id="_sum" runat="server">0</span>
<input type="submit" />
</form></body></html>

ViewState減少了不少麻煩,但也存在問題。在默認情況下它將被啟用,即使沒有任何用處也去收集所有頁面信息并穿梭往返于C/S兩端,其用base 64編碼的龐大身軀常吞噬大量帶寬,并存在被脅持的可能而引起系統安全性問題。

用戶會對界面做出各種操作,并希望得到系統的回應,這些用戶界面的操作被.Net統稱為事件(event,系統內部也會產生事件),而對應的系統回應稱為事件處理。在《隨想四》中的Login頁面,當用戶點擊btnLogin按鈕后, btnLogin對象(這時它被稱為事件源)大叫:"我被點啦,十年了,我終于第一次被點擊啦,555'''"但Button類本身并未定義相應的事件處理程序,那么又是誰來完成系統的實際響應操作呢?

在編寫Login類時我們已經定義成員btnLogin_Click方法,并希望由此完成btnLogin.click事件的處理,但MS工程師在定義Button類時并不知道其作用,所以需要一個媒介將兩者連接起來,這時我們不禁回想起《隨想七》中的委托。.net用EventHandler委托作為連接事件源與事件處理程序的媒介,將兩者綁定:

// 該段程序為《隨想四》中Login.aspx.cs的代碼片段并有所修改
// EventHandler為System命名空間中定義的公共委托
// sender為事件源對象,EventArgs類負責收集事件數據
public delegate void EventHandler(object sender,EventArgs e);
// Login為受托類,完成事件處理定義和連結
public class Login : System.Web.UI.Page{
// Login.OnInit 為Page類受保護方法,執行創建和設置實例所需的初始化步驟
// 調用OnInit方法時引發 Init事件
override protected void OnInit(EventArgs e){
// new System.EventHandler生成一委托實例
// += 完成事件處理委托的連接過程,同一事件可以觸發多個處理程序,稱為多路廣播
// base.OnInit(e)用于調用父類的同名方法
this.btnLogin.Click += new System.EventHandler(this.btnLogin_Click);
base.OnInit(e);
}
private void btnLogin_Click(object sender, System.EventArgs e){……}
}

■ 苦旅 - ASP.NET的動態模型

每一個HTTP請求出發前可謂悲壯,壯士一去兮不復返!Login.aspx頁面請求將URL和相關數據打包背上,胸前掛著自己的IP地址身份牌,從客戶端瀏覽器出發,翻越電信網通人為制造的各種障礙,爬雪山過草地,步履蹣跚地走到Web服務器的IIS門前,正想狂喜一陣,當看到大門口排著長長的數以萬計的請求隊列,還常有些餓死骨無人理彩時,它終于倒下了。

矇眬中Login.aspx頁面請求被傳送到HttpRuntime實例,HttpRuntime實例將:

·獲取一個HTTP Application 對象;

·讓HTTP Application 對象讀取配置文件;

·由HTTP Module 實例們分別提供會話維護、驗證或配置文件維護等各項服務;

·HTTP Handler接口實例化具體Page類實現處理。


Login是HTML頁面生產車間的工人,每天他負責按照嚴格的標準和固定的流程為客戶制作HTML編碼的Login.aspx頁面。一天早上,login正在硬盤里愜意地喝著咖啡,身寬體胖的主管HttpHandler大叔通知他立即開工。

今天是第一次進入內存,所以他先準備好頁面構架和所有控件零件并設置其默認狀態;然后嚴格按OnInit方法完成Init事件;之后會在頁面請求中尋找_VIEWSTAT。如果找到就對數據進行讀取和解碼;并讓控件更新其狀態以準確反映客戶端相應元素狀態; 隨后他拿出OnLoad方法操作手冊來處理Load事件;然后應付一系列被觸發的頁面事件,如果頁面正在被回送,還會包括用戶觸發的事件;用onPreRender方法處理的PreRender事件可以改變提交頁面的方式;然后把當前的頁面狀態保存到新的視圖狀態中。

完成所有操作后即可生成HTML編碼文件,期間可通過覆寫(override)Render方法以附加一些HTML代碼,為頁面做最后的修飾。

最后Login釋放所有占用的文件、圖形對象、數據庫連接等關鍵資源,匆忙跑出內存,"真是太悶了!"出門時他小聲地嘀咕了一聲。
作者:http://www.zhujiangroad.com
來源:http://www.zhujiangroad.com
北斗有巢氏 有巢氏北斗