對於Asp.Net 2.0中WebResource的研究(1)
Author: Truly
對於Asp.Net 2.0中,提供了很多指令碼資源檔,以嵌入資源套件含在程式集中:
WebForms.js
WebUIValidation.js
SmartNav.htm
SmartNav.js
Menu.js
MicrosoftAjaxWebForms.js
MicrosoftAjax.js
等
當我們改變Page的屬性或增加某些伺服器控制項之後,頁面會自動將這些資源的引用地址註冊到頁面上。
例如我們啟用了MaintainScrollPositionOnPostback之後,那麼頁面將自動註冊類似下面的語句:
<script src="/WebResource.axd?d=ZnL1CDIew0DLWTT0rctn7A2&t=633118963218359345" type="text/javascript"></script>
這一工作是由System.Web.Handlers.AssemblyResourceLoader的GetWebResourceUrl方法完成的。
需要注意的是這一方法像其它許多方法一樣,出於某些目的,MS將其定義為internal方法,我們知道,標記為 internal 的方法只能被相同程式集中的其他類調用。因此,我們無法手動註冊這一指令碼資源引用。
幸運的是,大多數情況我們並不需要這麼做。
但是由於這些資源中定義了很多webform中常用的一些指令碼函數,有時候也許你希望能夠利用這些函數,那麼如何能得到這一指令碼引用或者將其註冊到頁面上呢?
這裡首先介紹一個調用.net架構類庫中的一些internal方法的技巧,實質是利用反射:
訪問.net類的private或internal成員
Type t = typeof(System.Web.Handlers.AssemblyResourceLoader);
object[] args = new object[] { typeof(Page),"WebForms.js", true };
BindingFlags bindingFlags = BindingFlags.DeclaredOnly | BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.InvokeMethod;
string result = (string)(t.InvokeMember("GetWebResourceUrl", bindingFlags, null, null, args));
Page.ClientScript.RegisterStartupScript(typeof(_Default),"abc", String.Format("<script src=\"{0}\" type=\"text/javascript\"></script>", result));
上面的方式是直接擷取正確的資源檔,並將其註冊到頁面上。
下面介紹另外一種方法,就是直接利用反射調用Page類的RegisterWebFormsScript方法:
Type t = typeof(System.Web.UI.Page);
BindingFlags bindingFlags = BindingFlags.DeclaredOnly | BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.InvokeMethod | BindingFlags.Instance;
t.InvokeMember("RegisterWebFormsScript", bindingFlags, null, this, null);
大家可以仔細比較2者在運行時的區別,從呈現層面來講,前者比較靈活,但是可能重複註冊指令碼引用,後面的方法則不會出現這一情況。事實上,對於前者,Page類中有一個私人變數記錄了頁面是否已經註冊過指令碼引用,該欄位名稱是_fWebFormsScriptRendered,可以根據此變數檢測頁面上是否已經註冊這一指令碼引用
在Asp.Net2.0中還有另外一種方法更加簡便:
this.Page.ClientScript.RegisterClientScriptResource(typeof(System.Web.UI.Page), "WebForms.js");
而另外一條語句也是否有用,通常用作擷取自訂的嵌入檔案引用:
string includeLocation =
Page.ClientScript.GetWebResourceUrl(this.GetType(), "myStyleSheet.css");
這裡我們可以使用:
string includeLocation =
Page.ClientScript.GetWebResourceUrl(typeof(Page), "WebForms.js");
補充說明一下資源引用的URL格式:
WebResource.axd?d=加密後的標識&t=時間戳記
思考一,是否可以使用固定的src來調用資源呢,答案是否定的。
思考二,是否可以在html中使用呢,答案是肯定的,只要網站是放在asp.net2.0環境中的,那麼通常都支援.axd尾碼的檔案請求,對於WebResource.axd這樣的請求將會轉交System.Web.Handlers.AssemblyResourceLoader進行處理。
思考三,效能,未混淆的。
思考四,指令碼的重用。
那麼WebForm.js都包含了什麼方法呢,我整理了一下,方法列表如下:
WebForm_PostBackOptions(eventTarget, eventArgument, validation, validationGroup, actionUrl, trackFocus, clientSubmit)
WebForm_DoPostBackWithOptions(options)
WebForm_DoCallback(eventTarget, eventArgument, eventCallback, context, errorCallback, useAsync)
WebForm_CallbackComplete()
WebForm_ExecuteCallback(callbackObject)
WebForm_FillFirstAvailableSlot(array, element)
WebForm_InitCallback()
WebForm_InitCallbackAddField(name, value)
WebForm_EncodeCallback(parameter)
WebForm_ReEnableControls()
WebForm_ReDisableControls()
WebForm_FireDefaultButton(event, target)
WebForm_GetScrollX()
WebForm_GetScrollY()
WebForm_SaveScrollPositionSubmit()
WebForm_SaveScrollPositionOnSubmit()
WebForm_RestoreScrollPosition()
WebForm_TextBoxKeyHandler(event)
WebForm_AppendToClassName(element, className)
WebForm_RemoveClassName(element, className)
WebForm_GetElementById(elementId)
WebForm_GetElementByTagName(element, tagName)
WebForm_GetElementsByTagName(element, tagName)
WebForm_GetElementDir(element)
WebForm_GetElementPosition(element)
WebForm_GetParentByTagName(element, tagName)
WebForm_SetElementHeight(element, height)
WebForm_SetElementWidth(element, width)
WebForm_SetElementX(element, x)
WebForm_SetElementY(element, y)
欄位:
__disabledControlArray
已停用控制項數組
__enabledControlArray 依賴js外部
函數名 |
說明 |
WebForm_PostBackOptions(eventTarget, eventArgument, validation, validationGroup, actionUrl, trackFocus, clientSubmit) |
將指定的回傳參數作為屬性添加到this對象中。 |
WebForm_DoPostBackWithOptions(options) |
根據WebForm_PostBackOptions方法產生的資料資訊 設定actionUrl和回傳前的最後焦點控制項以及事件參數。 |
WebForm_DoCallback(eventTarget, eventArgument, eventCallback, context, errorCallback, useAsync) |
回呼函數 |
WebForm_CallbackComplete() |
回調完成處理函數 |
WebForm_ExecuteCallback(callbackObject) |
執行回調 |
WebForm_FillFirstAvailableSlot(array, element) |
將指定對象添加到指定數組中第一個空位置。 |
WebForm_InitCallback() |
初始化回調,將所有的input, select textarea等控制項的資料使用WebForm_InitCallbackAddField方法添加到相應的數組和變數中。 |
WebForm_InitCallbackAddField(name, value) |
建立一個自訂對象包含傳入的索引值屬性增加到__theFormPostCollection數組中 並且以“name=value&”的字串形式添加到__theFormPostCollection變數中 |
WebForm_EncodeCallback(parameter) |
對回調參數進行URI編碼,依賴於其他js類庫的encodeURIComponent方法。 |
WebForm_ReEnableControls() |
找到__enabledControlArray數組中所有已停用控制項,啟用它們並將其記錄到__disabledControlArray中。 |
WebForm_ReDisableControls() |
把__disabledControlArray儲存的控制項重新禁用 |
WebForm_FireDefaultButton(event, target) |
當在頁面除textarea外地區中按下斷行符號按鈕時,激髮指定的預設按鈕。target是預設按鈕的用戶端id。 |
WebForm_GetScrollX() |
擷取當前頁面的X捲軸座標(document.body.scrollLeft) |
WebForm_GetScrollY() |
擷取當前頁面的Y捲軸座標(document.body.scrollTop) |
WebForm_SaveScrollPositionSubmit() |
在提交表單時儲存捲軸座標,下面3個函數均利用了表單中的__SCROLLPOSITIONX隱藏欄位。 |
WebForm_SaveScrollPositionOnSubmit() |
與上面方法不同的是,這個方法僅在類ie瀏覽器中有效。 |
WebForm_RestoreScrollPosition() |
恢複提交表單前儲存的捲軸位置 |
WebForm_TextBoxKeyHandler(event) |
可用來設定指定textbox不響應斷行符號事件,例如:<input onkeydown='WebForm_TextBoxKeyHandler(event)' |
WebForm_AppendToClassName(element, className) |
為指定元素增加指定樣式 |
WebForm_RemoveClassName(element, className) |
刪除指定元素的指定樣式 |
WebForm_GetElementById(elementId) |
擷取指定id的元素 |
WebForm_GetElementByTagName(element, tagName) |
擷取指定元素中指定標記的首個元素 |
WebForm_GetElementsByTagName(element, tagName) |
擷取指定元素中指定標記的元素集合 |
WebForm_GetElementDir(element) |
擷取指定元素的dir屬性 |
WebForm_GetElementPosition(element) |
擷取指定元素的位置等資訊 傳回型別:自訂對象( var result = new Object(); result.x = 0; result.y = 0; result.width = 0; result.height = 0;) |
WebForm_GetParentByTagName(element, tagName) |
取得某元素最近的tagName為指定標記的父節點。 |
WebForm_SetElementHeight(element, height) |
設定某元素的高度 |
WebForm_SetElementWidth(element, width) |
設定某元素的寬度 |
WebForm_SetElementX(element, x) |
設定某元素的y座標 |
WebForm_SetElementY(element, y) |
設定某元素的y座標 |