本帖並無高來高去的高深技術,但提供一個做 ASP.NET 項目時,很實用的 Ajax 樣本下載。透過 AJAX.NET 的功能,改善舊式 Callback 寫法的缺點,讓使用者在一或多個 TextBox 輸入完尋找條件、滑鼠離開並觸發 onBlur 事件時,透過 JavaScript 調用 C# 自訂類的函數,實現高速訪問資料庫、尋找對應多個欄位的值。
之前我曾寫了一篇「用 ASP.NET Callback 和 JavaScript 高速訪問資料庫」,並提供樣本下載,內容是用 Callback 非同步呼叫技術 (ASP.NET AJAX 還沒出現前,微軟提供的過渡技術),讓 Client-side (JavaScript) 能和 Server-side (.NET CLR) 直接溝通,讓使用者在 TextBox 失去焦點、觸發 onBlur 事件時,能透過 C# 自訂類的函數,以相當高的效率訪問資料庫並傳回值。但該樣本有兩個缺點:
- 只能透過固定單一個內附的 RaiseCallbackEvent 函數,去訪問資料庫。當頁面上有多個 TextBox 同時要實現相同功能時,程式撰寫上會很困難。
- 無法透過 try-catch-finally block 捕捉錯誤資訊。當發生錯誤時,也無法提供相關資訊給使用者或程式員。
因為在 ASP.NET 項目中常會用到此一功能,因此日前我用 AJAX.NET 這套 free library 重寫了一個樣本 (相關的 dll 已內附), 及功能如下:
-------------------------------------------------
本帖的範例程式碼下載點:
http://files.cnblogs.com/WizardWu/090828.zip
(執行本樣本,需要 SQL Server 的 Northwind 資料庫,以及 VS 2008 或 IIS)
-------------------------------------------------
此樣本功能:
- 如 1,在第一個 TextBox1 輸入 EmployeeID,滑鼠離開 TextBox1 失去焦點、觸發 onBlur 事件時,會自動高速訪問資料庫,取得該筆記錄的另外兩個欄位,顯示在下方的兩個 TextBox 中。
- 如 2,當使用者輸入不合理的 EmployeeID 時,會提示錯誤資訊,並清空另外兩個 TextBox 裡既有的文字。
- 當使用者輸入不存在於資料表 Employees 的 EmployeeID 時,會提示錯誤資訊,並清空另外兩個 TextBox 裡既有的文字。
- 當使用者手動清空 TextBox1,滑鼠離開 TextBox1 失去焦點、觸發 onBlur 事件時,會清空另外兩個 TextBox 裡既有的文字。
圖 1 網站項目中常用到的功能。以本樣本的做法,不論網頁上有多少個 TextBox 需要此功能,都不會相互幹擾
圖 2 輸入不合理或錯誤類型的 EmployeeID,JavaScript 接收到 C# 返回的錯誤資訊
關鍵代碼如下:
Default.aspx.cs
public partial class _Default : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
//設定 TextBox 的 OnBlur 事件被觸發時,所要調用的 JavaScript 函數
this.TextBox1.Attributes["onblur"] = "getEmployeeInfo('TextBox1', 'TextBox2', 'TextBox3');";
this.TextBox4.Attributes["onblur"] = "getProductInfo('TextBox4', 'TextBox5', 'TextBox6');";
//設定在 JavaScript 檔案中,所能調用的 C# 自訂類的名稱
Ajax.Utility.RegisterTypeForAjax(typeof(MyClass01));
}
}
我們看到上方,透過 RegisterTypeForAjax 函數,可向 AJAX.NET 註冊我們寫的 C# 自訂類 MyClass01。接著 AJAX.NET 會瀏覽這個自訂類,裡面標示有 AjaxMethodAttribute 的函數,如下方代碼中的 getEmployeeInfo 和 getProductInfo 函數,我們並在這兩個函數裡,實際去訪問資料庫並取回需要的一或多個欄位的值。
App_Code/MyClass01.cs
public class MyClass01
{
public static string strConnString = WebConfigurationManager.ConnectionStrings["ConnString_SqlClient"].ConnectionString;
//由 EmployeeID (如: 1, 2 ,3 , ...),去資料庫取出他的 LastName、Title
[Ajax.AjaxMethod()] //告知 Ajax 封裝類,為此方法建立一個 JavaScript 代理,這樣才能被用戶端調用
public string getEmployeeInfo(string strEmployeeID)
{
string strResult = string.Empty;
string strSql = "SELECT LastName, Title FROM EMPLOYEES WHERE EmployeeID = @EmployeeID";
using (SqlConnection conn = new SqlConnection(strConnString))
{
conn.Open();
if (conn.State == ConnectionState.Open)
{
using (SqlCommand cmd = new SqlCommand(strSql, conn))
{
cmd.Parameters.Add("@EmployeeID", SqlDbType.Int).Value = strEmployeeID.Trim();
//若確定要捉的記錄只有一筆,可加上此 ADO.NET 的「SingleRow」參數,以最佳化效能、節省系統資源
using (SqlDataReader dr = cmd.ExecuteReader(CommandBehavior.SingleRow))
{
if (dr.Read())
{
strResult = dr[0].ToString() + "§" + dr[1].ToString();
}
}
}
}
}
return strResult; //strResult = "result1§result2"; //傳回值為用 "§" 字元所分割的一或多個字串
}
//由 ProductID (如: 1, 2 ,3 , ...),去資料庫取出他的 ProductName、QuantityPerUnit
[Ajax.AjaxMethod()] //告知 Ajax 封裝類,為此方法建立一個 JavaScript 代理,這樣才能被用戶端調用
public string getProductInfo(string strProductID)
{
//...中間略...
}
} //end of class
如下,onBlur 事件被觸發時,會在 JavaScript 裡調用 C# 的同名函數,並從資料庫裡取得傳回值。
js/MyJs01.js
//由 EmployeeID (如: 1, 2 ,3 , ...),去資料庫取出他的 LastName、Title
function getEmployeeInfo(TextBox1, TextBox2, TextBox3) {
//調用 App_Code 檔案夾裡,C# 自訂類的 getEmployeeInfo 函數
var response = MyClass01.getEmployeeInfo(document.getElementById(TextBox1).value);
//response 為從 C# 自訂類裡的函數所傳回來的,由一或多個 "§" 字元所組成的一個字串
if ((response.value == null) || (response.value.length == 0)) { //若使用者輸入「不合理的字元」或「無對應資料的ID號碼」
alert('資料庫裡查無資料 !');
document.getElementById(TextBox2).value = "";
document.getElementById(TextBox3).value = "";
}
else if (response.value.length > 0) { //若資料庫裡有尋找到對應的資料
var strArrResult = response.value.split("§");
if (strArrResult[0].length > 0)
document.getElementById(TextBox2).value = strArrResult[0];
if (strArrResult[1].length > 0)
document.getElementById(TextBox3).value = strArrResult[1];
}
}
如下,在 web.config 裡添加配置,讓所有 ajax/*.ashx 的請求,改由 Ajax.PageHandlerFactory 產生的 HTTP Handler 處理,而不再由預設的 System.Web.UI.PageHandlerFactory 處理常式工廠 [9] 來處理。
web.config
<system.web>
<httpHandlers>
<add verb="POST,GET" path="ajax/*.ashx"
type="Ajax.PageHandlerFactory, Ajax" />
</httpHandlers>
</system.web>
因為此一需求我在 ASP.NET 項目常遇到,因此特地整理成一篇文章。若有網友知道 ASP.NET AJAX 3.5 有更好的做法,亦請留言告知。
--------------------------------------------------
相關文章:
[1] AJAX.NET 使用者開發指南, 程守華 譯, 原出處:部落格園
http://dev.yesky.com/msdn/398/2307398.shtml
[2] AJAX .Net Wrapper usage guide (Ajax.dll 下載內附 Word 檔案)
http://ajax.schwarz-interactive.de/download/ajax.zip
[3] Ajax.Utility.RegisterTypeForAjax(typeof(Chat))
http://forums.asp.net/p/1178313/1990148.aspx
[4] AJAX.NET 安裝配置全指南
http://developer.51cto.com/art/200908/142497.htm
http://developer.51cto.com/art/200601/16545.htm
[5] 在 vs 2005 中使用 ajax.dll
http://maybe723.javaeye.com/blog/87341
[6] 在asp.net 1.1中運用AjaxPro簡要步驟
http://www.cnblogs.com/wlb854/archive/2006/10/08/523143.html
[7] ASP.NET ajax.dll ajaxmethod 提示總結
http://and114.blog.hexun.com/34187290_d.html
[8] Ajax 實現無重新整理三聯動下拉框 - 小山 - 部落格園
http://singlepine.cnblogs.com/articles/257954.html
[9] PageHandlerFactory 類 (msdn)
http://msdn.microsoft.com/zh-cn/library/system.web.ui.pagehandlerfactory(VS.80).aspx
--------------------------------------------------