| 特性 | Postback | Callback |
|---|---|---|
| 頁面生命週期 | 完整執行 | 僅執行必要階段 |
| 傳送資料 | 整個表單 (ViewState + 所有控制項) | ViewState + 自訂參數 |
| 回應內容 | 完整 HTML 頁面 | 僅自訂字串結果 |
| 頁面重繪 | 是 | 否 (需客戶端 JS 更新) |
| 適用場景 | 表單送出、頁面導航 | 驗證、查詢、局部更新 |
伺服器端控制項實作此介面即可處理客戶端回呼:
public interface ICallbackEventHandler {
string GetCallbackResult(); // 回傳結果給客戶端
void RaiseCallbackEvent(string eventArgument); // 處理客戶端傳來的參數
}
public partial class CheckUser : Page, ICallbackEventHandler {
private string _callbackResult;
protected void Page_Load(object sender, EventArgs e) {
// 註冊客戶端回呼參考
string callbackRef = ClientScript.GetCallbackEventReference(
this, "arg", "OnCallbackReturn", "context", "OnCallbackError", true);
string script = $"function CheckUser(arg, context) {{{callbackRef};}}";
ClientScript.RegisterClientScriptBlock(GetType(), "CheckUser", script, true);
}
public void RaiseCallbackEvent(string eventArgument) {
// 模擬資料庫查詢
bool exists = UserRepository.Exists(eventArgument);
_callbackResult = exists ? "exists" : "available";
}
public string GetCallbackResult() {
return _callbackResult;
}
}
<input type="text" id="txtUser" onblur="CheckUser(this.value, null)" />
<span id="msg"></span>
<script>
function OnCallbackReturn(result, context) {
var msg = document.getElementById('msg');
if (result === 'exists') {
msg.innerHTML = '<span style="color:red">帳號已存在</span>';
} else {
msg.innerHTML = '<span style="color:green">帳號可用</span>';
}
}
function OnCallbackError(error, context) {
console.error('Callback 錯誤:', error);
}
</script>
public string GetCallbackEventReference(
Control control, // 實作 ICallbackEventHandler 的控制項 (通常是 this)
string argument, // 客戶端傳遞的參數 (JS 變數名稱)
string clientCallback, // 成功時的 JS 函數名稱
string context, // 內容參數 (傳給回呼函數)
string clientErrorCallback,// 錯誤時的 JS 函數名稱
bool useAsync // true=非同步, false=同步
)
GridView 的分頁與排序即使用 Callback 技術:
<asp:GridView ID="gvData" runat="server"
AllowPaging="true" AllowSorting="true"
OnPageIndexChanging="gvData_PageIndexChanging"
OnSorting="gvData_Sorting">
</asp:GridView>
設定 EnableSortingAndPagingCallbacks="true" 即可啟用無刷新分頁/排序(需瀏覽器支援)。
public class AutoCompleteTextBox : TextBox, ICallbackEventHandler {
protected override void OnPreRender(EventArgs e) {
base.OnPreRender(e);
string callbackRef = Page.ClientScript.GetCallbackEventReference(
this, "arg", "AutoComplete_Receive", "context", "AutoComplete_Error", true);
string script = $@"
function AutoComplete_Request(arg, context) {{{callbackRef};}}
function AutoComplete_Receive(result, context) {{ /* 更新下拉清單 */ }}
function AutoComplete_Error(err, context) {{ console.error(err); }}";
Page.ClientScript.RegisterClientScriptBlock(GetType(), "AutoComplete", script, true);
// 綁定輸入事件
Attributes["onkeyup"] = "AutoComplete_Request(this.value, null)";
}
public void RaiseCallbackEvent(string eventArgument) {
_suggestions = SearchService.GetSuggestions(eventArgument);
}
public string GetCallbackResult() {
return JsonSerializer.Serialize(_suggestions);
}
}
ViewStateMode="Disabled"clientErrorCallback 避免靜默失敗| 項目 | Client Callback | UpdatePanel | Web API + JS |
|---|---|---|---|
| 複雜度 | 中 | 低 | 中 |
| 回應格式 | 字串 | HTML 片段 | JSON |
| 前端框架整合 | 困難 | 一般 | 優秀 |
| 除錯容易度 | 較難 | 容易 | 容易 |
| 適用版本 | ASP.NET 2.0+ | ASP.NET AJAX 1.0+ | ASP.NET 4.5+ |