「無重新整理頁面」本質是客戶端 JavaScript 呼叫伺服器端方法並處理回傳資料。ASP.NET 2.0 內建 ICallbackEventHandler 介面與 ClientScriptManager.GetCallbackEventReference,底層採用 XMLHTTP,提供零依賴、極輕量的伺服器回呼機制,是 UpdatePanel 之外的精簡選擇。
System.Web.UI.ICallbackEventHandler。RaiseCallbackEvent(string eventArgument):接收參數,執行邏輯,設定結果。GetCallbackResult():回傳結果字串給客戶端。ClientScript.GetCallbackEventReference 產生客戶端呼叫腳本。<input id="txtMessage" type="text" />
<input type="button" value="呼叫伺服器" onclick="callToServer()" />
結果:<input id="txtResult" type="text" />
<script type="text/javascript">
function callToServer() {
var param = document.getElementById("txtMessage").value;
// <%= ClientScript %> 會在渲染時被替換為 GetCallbackEventReference 產生的腳本
// 此處假設頁面已註冊 CallServer 函式
CallServer(param, "");
}
function handleResultFromServer(result, context) {
document.getElementById("txtResult").value = result;
}
</script>
public partial class CallbackDemo : System.Web.UI.Page, System.Web.UI.ICallbackEventHandler
{
private string _result;
public void RaiseCallbackEvent(string eventArgument)
{
_result = $"伺服器時間 [{DateTime.Now:HH:mm:ss}] 收到參數 [{eventArgument}]";
}
public string GetCallbackResult()
{
return _result;
}
protected void Page_Load(object sender, EventArgs e)
{
// 產生並註冊客戶端呼叫函式
string callbackRef = ClientScript.GetCallbackEventReference(
this, "param", "handleResultFromServer", "context", "OnError", true);
string script = $"function CallServer(param, context) {{ {callbackRef}; }}";
ClientScript.RegisterClientScriptBlock(this.GetType(), "CallServer", script, true);
}
}
this:實作 ICallbackEventHandler 的目標(頁面或控制項)。"param":客戶端參數變數名,對應 RaiseCallbackEvent(string eventArgument)。"handleResultFromServer":成功回呼 JS 函式名,簽章 function(result, context)。"context":可選內容變數,原樣傳回回呼函式。"OnError":可選錯誤處理函式名,簽章 function(error, context)。true:非同步 XMLHTTP(不阻塞瀏覽器)。<%@ Page Async="true" %>
啟用非同步頁面管線,配合 useAsync=true 達成真正非阻塞。
private string ClientScript
{
get
{
return ClientScript.GetCallbackEventReference(this, "param", "handleResultFromServer", "context");
}
}
在頁面標記中直接使用 <%= ClientScript %> 嵌入呼叫腳本(舊版寫法,現建議 RegisterClientScriptBlock)。
public class AjaxLabel : Label, ICallbackEventHandler
{
public void RaiseCallbackEvent(string eventArgument) { /* ... */ }
public string GetCallbackResult() { return _result; }
protected override void OnPreRender(EventArgs e)
{
base.OnPreRender(e);
string callbackRef = Page.ClientScript.GetCallbackEventReference(this, "arg", "OnResult", "ctx", "OnErr", true);
string script = $"function CallServer(arg, ctx) {{ {callbackRef}; }}";
Page.ClientScript.RegisterClientScriptBlock(this.GetType(), "AjaxLabelCallback", script, true);
}
}
| 方案 | 優點 | 缺點 | 適用場景 |
|---|---|---|---|
| ICallbackEventHandler | 極輕量、零依賴、精確控制傳輸、無 ViewState | 僅字串參數/結果、無完整生命週期、需手寫 JS | 自動完成、即時驗證、簡單查詢、計算 |
| UpdatePanel | 開發簡單、保留生命週期/驗證/ViewState、部分更新 | 傳輸量大、整個面板回傳、效能較低 | 複雜表單、GridView 分頁排序、一般 AJAX 化 |
| Web Service + AJAX.NET | 獨立服務、跨頁面複用、強型別 Proxy | 需額外設定、ScriptManager 依賴 | 多頁面共用邏輯、獨立部署服務 |
回傳 JSON 字串:
using System.Web.Script.Serialization;
public void RaiseCallbackEvent(string eventArgument)
{
var data = new { Time = DateTime.Now, Echo = eventArgument, Items = new[] { 1, 2, 3 } };
_result = new JavaScriptSerializer().Serialize(data);
}
客戶端 JSON.parse(result) 解析物件。
ICallbackEventHandler 是 ASP.NET 2.0 邁向 AJAX 體驗的原生輕量基石,掌握其機制可在適當場景打造極致效能的無重新整理互動。