本文來自《ASP.NET AJAX程式設計 第II卷:用戶端Microsoft AJAX Library相關》的第五章《應用程式服務和本地化》。
在內建了身份認證應用程式服務之後,ASP.NET 2.0已經提供了對使用者管理的初步支援。然而,使用者資訊卻不僅僅只是使用者名稱和密碼這兩項,對於一般網站來講,我們都需要提供一些與使用者帳號相關聯的自訂屬性。例如在BBS程式中,這類自訂屬性就有使用者的積分、等級、簽名檔、頭像等,這些自訂屬性都與使用者帳號一一對應。為此,ASP.NET 2.0特意內建了使用者個人化應用程式服務,同樣以統一的方式提供給開發人員。ASP.NET 2.0內建的使用者個人化應用程式服務的配置、使用非常簡單,也提供了足夠靈活的擴充能力。
參考:若想瞭解更多有關ASP.NET 2.0的使用者個人化服務,請參考這篇MSDN文章:《ASP.NET Profile Properties 》(http://msdn2.microsoft.com/en-us/library/at64shx3.aspx)。
ASP.NET AJAX架構的使用者個人化服務能夠與ASP.NET 2.0的使用者個人化應用程式服務整合起來,並為其提供用戶端的JavaScript調用代理。ASP.NET AJAX用戶端部分使用者個人化代理的相關功能統一由用戶端ProfileService對象提供。
ProfileService對象的完全限定名為Sys.Services.ProfileService。與AuthenticationService對象類似,ProfileService是一個單例(Singleton)模式的對象,無須手工建立執行個體即可使用。只要頁面中包含有ScriptManager控制項,我們即可在用戶端直接存取到ProfileService對象,進而間接地與伺服器端使用者個人化服務打交道並使用ASP.NET 2.0提供的使用者個人化服務的相關功能,例如載入或儲存使用者的個人化屬性等——ASP.NET AJAX架構將負責整個非同步通訊的實現細節,就像ASP.NET AJAX非同步通訊層為Web Service產生用戶端代理一樣。
ProfileService對象提供了兩個方法:load()和save(),分別用來載入和儲存使用者的個人化屬性,還提供了一個名為properties的欄位,用來以類似伺服器端“強型別訪問方式”的方法在用戶端訪問使用者個人化屬性。此外,ProfileService還暴露出了一系列的常用屬性。下面我們來逐一介紹:
5.3.1 load()方法
load()方法用來載入目前使用者的個人化屬性,在載入完成之後,我們即可在用戶端通過ProfileService對象的properties屬性訪問到已經被載入的各個使用者個人化屬性。調用load()方法的完整文法如下:
Sys.Services.ProfileService.load(
propertyNames,
loadCompletedCallback,
failedCallback,
userContext
);
其中各個參數的含義如表5-4所示。
表5-4 ProfileService對象load()方法的參數
- propertyNames:一個包含string對象的數組,表示需要從伺服器端載入的使用者個人化屬性集合。若是該參數為null的話,則ASP.NET AJAX將自動載入所有允許用戶端讀取的使用者個人化屬性。關於如何將ASP.NET 2.0中的各個使用者個人化屬性有選擇性地暴露給用戶端,將在本章下一節的樣本程式中介紹。
- loadCompletedCallback:載入使用者個人化屬性完成之後的回呼函數。
- failedCallback:載入使用者個人化屬性失敗時的回呼函數。導致失敗的原因可能是網路連接逾時、或是使用者個人化服務內部拋出異常等。
- userContext:隨本次非同步呼叫發送至伺服器端的使用者內容物件。
表5-4中所列出的4個參數均為可選。對於loadCompletedCallback和failedCallback參數,如果為ProfileService對象設定了預設值的話(將在稍後介紹),也可以省略。
載入使用者個人化屬性完成之後的回呼函數,即loadCompletedCallback參數所指定的函數的完整的簽名如下(回呼函數及其參數的名稱可以根據需要自行更改):
function onLoadCompleted(numProperties, userContext, methodName)
其中,ASP.NET AJAX在執行回調時為我們提供了3個參數:
- numProperties:表示此次載入過程中載入了的使用者個人化屬性的個數。
- userContext:在調用load()方法時傳遞的使用者內容物件。
- methodName:調用方法的方法名。
調用認證服務失敗之後的回呼函數,即failedCallback參數所指定的函數的完整的簽名如下(回呼函數及其參數的名稱可以根據需要自行更改):
function onProfileFailed(error, userContext, methodName)
ASP.NET AJAX在執行回調時同樣為我們提供了3個參數:
- error:導致認證服務失敗的異常對象。
- userContext:在調用load()方法時傳遞的使用者內容物件。
- methodName:調用方法的方法名。
5.3.2 save()方法
save()方法用來儲存當前可能經過修改的使用者個人化屬性。調用save()方法的完整文法如下:
Sys.Services.ProfileService.save(
propertyNames,
saveCompletedCallback,
failedCallback,
userContext
);
其中各個參數的含義如表5-5所示。
表5-5 ProfileService對象logout()方法的參數
- propertyNames:一個包含string對象的數組,表示需要儲存至伺服器的使用者個人化屬性集合。若是該參數為null的話,則ASP.NET AJAX將自動儲存所有允許從用戶端寫入的使用者個人化屬性。關於如何將ASP.NET 2.0中的各個使用者個人化屬性有選擇性地暴露給用戶端,將在本章下一節的樣本程式中介紹。
- saveCompletedCallback:儲存使用者個人化屬性完成之後的回呼函數。
- failedCallback :儲存使用者個人化屬性失敗時的回呼函數。導致失敗的原因可能是網路連接逾時、或是使用者個人化服務內部拋出異常等。
- userContext:隨本次非同步呼叫發送至伺服器端的使用者內容物件。
表5-5中所列出的4個參數均是可選的。對於saveCompletedCallback和failedCallback參數,如果為ProfileService對象設定了預設值的話(將在稍後介紹),也可以省略。
儲存使用者個人化屬性完成之後的回呼函數,即saveCompletedCallback參數所指定的函數的完整的簽名如下(回呼函數及其參數的名稱可以根據需要自行更改):
function onSaveCompleted(numProperties, userContext, methodName)
其中,ASP.NET AJAX在執行回調時為我們提供了3個參數:
- numProperties:表示此次儲存過程中儲存了的使用者個人化屬性的個數。
- userContext:在調用save()方法時傳遞的使用者內容物件。
- methodName:調用方法的方法名。
儲存使用者個人化屬性失敗時的回呼函數,即failedCallback參數所指定的函數的完整的簽名如下(回呼函數及其參數的名稱可以根據需要自行更改):
function onProfileFailed(error, userContext, methodName)
ASP.NET AJAX在執行回調時同樣為我們提供了3個參數:
- error:導致認證服務失敗的異常對象。
- userContext:在調用save()方法時傳遞的使用者內容物件。
- methodName:調用方法的方法名。
5.3.3 properties欄位
ASP.NET 2.0所提供了使用者個人化應用程式服務中的一個非常強大的特性就是,它允許開發人員以強型別的方式訪問到各個預定義的使用者個人化屬性。例如,若我們在web.config檔案的<configuration />\<system.web />節中定義了如下的使用者個人化屬性:
<profile enabled="true">
<properties>
<add name="Address" type="System.String" />
<add name="Age" type="System.Int32" />
<add name="InfoPanelPosition" type="System.Drawing.Point" />
</properties>
</profile>
那麼在ASP.NET頁面中,即可直接以強型別的方式訪問到這些屬性。請參考如下一段伺服器端C#代碼:
string address = Profile.Address;
int age = Profile.Age;
System.Drawing.Point infoPanelPosition = Profile.InfoPanelPosition;
雖然在用戶端使用的JavaScript是一門動態語言,其中的變數並沒有那麼“嚴格”的類型約束,不過ProfileService對象所提供的properties欄位依然能夠讓開發人員能夠以類似的文法規則在用戶端訪問使用者個人化屬性。
在調用ProfileService對象的load()方法,並成功載入了使用者個人化屬性之後,我們即可使用其properties欄位以類似上述C#代碼的方式在JavaScript中訪問到各個使用者個人化屬性;
var address =
Sys.Services.ProfileService.properties.Address;
var age =
Sys.Services.ProfileService.properties.Age;
var infoPanelPosition =
Sys.Services.ProfileService.properties.InfoPanelPosition;
ProfileService對象的properties欄位也能夠支援web.config檔案中定義的使用者個人化組(Profile Group)。例如如下使用者個人化組的定義:
<profile enabled="true">
<properties>
<group name="Address">
<add name="Street" type="System.String" />
<add name="City" type="System.String"/>
<add name="PostalCode" type="System.String" />
</group>
</properties>
</profile>
在用戶端JavaScript中,我們也可以使用如下的文法(即[GroupName].[PropertyName])對這個使用者個人化組中的屬性進行訪問:
var street =
Sys.Services.ProfileService.properties.Address.Street;
var city =
Sys.Services.ProfileService.properties.Address.City;
var postCode =
Sys.Services.ProfileService.properties.Address.PostCode;
5.3.4 常用屬性
除了前面介紹的load()、save()方法以及properties屬性之外,ProfileService對象還提供了幾個經常用到的屬性,如表5-6所示。
表5-6 ProfileService對象的常用屬性
- timeout:擷取或設定載入/儲存使用者個人化屬性的逾時時間,單位為毫秒。
- defaultLoadCompletedCallback :擷取或設定預設的載入使用者個人化屬性完成之後的回呼函數。
- defaultSaveCompletedCallback:擷取或設定預設的儲存使用者個人化屬性完成之後的回呼函數。
- defaultFailedCallback:擷取或設定預設的載入/儲存使用者個人化屬性失敗時的回呼函數。
如下代碼示範了設定ProfileService對象的timeout屬性:
Sys.Services.ProfileService.set_timeout(3000);
若是預先設定了defaultLoadCompletedCallback、defaultSaveCompletedCallback和defaultFailedCallback屬性,那麼在調用ProfileService對象的load()和save()方法時,即可不必重複指定各個回呼函數。例如,如下代碼就設定了ProfileService對象的這3個屬性,並定義了相應的預設回呼函數:
Sys.Services.ProfileService.set_defaultLoadCompletedCallback(onLoadCompleted);
Sys.Services.ProfileService.set_defaultSaveCompletedCallback(onSaveCompleted);
Sys.Services.ProfileService.set_defaultFailedCallback(onProfileFailed);
function onLoadCompleted(numProperties, userContext, methodName) {
// ...
}
function onSaveCompleted(numProperties, userContext, methodName) {
// ...
}
function onProfileFailed(error, userContext, methodName) {
// ...
}
隨後,我們即可直接使用如下代碼載入/儲存使用者的個人化屬性了,是不是顯得非常簡單呢?
Sys.Services.ProfileService.load();
Sys.Services.ProfileService.save();