當前位置:成語大全網 - 書法字典 - ASP.NET MVC中臨時數據的實現機制

ASP.NET MVC中臨時數據的實現機制

本文主要討論如何在ASP NET MVC中實現TempData。通過研究MVC的源代碼,妳會清楚地了解MVC是如何實現TempData函數的。

TempData特征

TempDataDictionary和ITempDataProvider

臨時數據字典的設計

SessionStateTempDataProvider和ITempDataProvider

臨時數據功能頂部

TempData的特點是它可以在兩個操作之間傳輸數據。它會將數據的副本保存到下壹個操作中,並隨著下壹個操作的到來而變得無效,因此它用於在兩個操作之間保存數據。例如,在這樣的場景中,您的壹個操作接受壹些post數據,然後將其交給另壹個操作進行處理並顯示在頁面上。此時,可以使用TempData來傳輸此數據。

那麽TempData到底是如何完成這個功能的呢?讓我們從MVC的源代碼開始分析TempData的機制。

TempDataDictionary和ITempDataProviderTop

首先,我們來看看ITempDataProvider接口。從字面上看,讓我們將其轉換為臨時數據的提供者所遵循的規則。它規定了兩種方法。

公共接口ITempDataProvider

{

IDictionary LoadTempData(controller context controller context);

void SaveTempData(controller context controller context IDictionary值);

}

這兩個方法是LoadTempData和SaveTempData。我們猜測這兩個方法用於獲取TempData容器和保存TempData數據,因為LoadTempData返回具體類型而save TempData不返回類型,並且參數ControllerContext是不同的。用戶上下文設計的指示是操作該上下文的TempData,事實確實如此,我們的猜測稍後將得到驗證。

我們來看看TempDataDictionary。我們對這門課的第壹印象是什麽?ControllerBase類中的TempData屬性。在普通控制器中,我們鍵入tempdata vs來幫助我們完成的屬性實際上是ControllerBase類中的tempdata,因此我們理解對TempData的所有操作在控制器和視圖中都是正確的。TempDataDictionary類型操作,ITempDataProvider如何聯系TempDataDictionary?看壹下TempDataDictionary的設計就壹目了然了。

TempDataDictionary設計頂部

公共類tempdata dictionary:IDictionary & lt;字符串對象& gt可伊斯蘭化

這是TempDataDictionary的簽名,我們看到它繼承了idictionary

internal const string _ tempDataSerializationKey = _ _ tempData;?內部詞典& lt字符串對象& gt_ data

在帶有參數的構造函數中發現使用了_tempDataSerializationKey。

受保護的tempdata dictionary(serialization info info streaming context上下文)

{

_ initialKeys = new HashSet & lt字符串& gt(string comparer ordinal ignore case);

_ modifiedKeys = new HashSet & lt字符串& gt(string comparer ordinal ignore case);

_ data = info GetValue(_ tempDataSerializationKey type of(Dictionary & lt;字符串對象& gt))

作為詞典& lt字符串對象& gt;

}

我們可以看到這是壹個用於從流中反序列化字典類型的過程。

另壹點是我們可以像這樣在控制器中使用TempData。

TempData【msg】= new Object();?object obj = TempData【msg】as object;在了解它的索引器之前,我們先來看看它的字段和方法。TempDataDictionary類中有三個重要的字段。

內部詞典& lt字符串對象& gt_ data?私有哈希表& lt字符串& gt_ initialKeys?私有哈希表& lt字符串& gt_ modifiedKeys_data用於存儲真實數據_initialKeys用於存儲原始數據key _modifiedKeys用於存儲修改或新添加的數據。這是為什麽呢?回想壹下TempData的特征。當TempData只在第三個操作中存儲壹次數據時,第壹個操作中存儲的數據將無效,因此_initialKeys旨在存儲那些原始的數據_modifiedKeys旨在存儲那些修改或新添加的數據,從而區分舊數據和新數據。下壹步是刪除舊數據並記錄新數據。

讓我們再次進入索引器,因為我們對TempData的操作是從索引器開始的。下面是索引器的代碼。

此公共對象【字符串鍵】

{

得到

{

對象值;

if(try getvalue(鍵控輸出值))

{

返回值;

}

返回null

}

設置{

_ data【key】= value;

_ modified keys Add(key);

}

}

當我們TempData【msg】= new Object();當不僅數據被添加到_data中,而且_modifiedKeys保存了新數據的鍵時,新數據何時被保存,舊數據何時被刪除才能真正執行?這個過程發生在加載和保存方法中。讓我們看看他們的具體實現。

公共void加載(controller context controller context ITempDataProvider tempdata provider)

{

字典& lt字符串對象& gtprovider dictionary = tempdata provider LoadTempData(?controller context);?_ data =(provider dictionary!= null)?新詞典& lt字符串對象& gt提供者字典

StringComparer OrdinalIgnoreCase):新詞典& lt字符串對象& gt

(string comparer ordinal ignore case);

_ initialKeys = new HashSet & lt字符串& gt(_數據鍵);

_ modified keys Clear();

}

公共void保存(controller context controller context ITempDataProvider tempdata provider)

{

if(_ modified keys Count & gt;)

{

//應用更改跟蹤

foreach(字符串x in _initialKeys)

{

如果(!_modifiedKeys包含(x)

{

_數據刪除(x);

}

}

//存儲字典

tempdata provider save tempdata(controller context _ data);

}

}

我們看到TempDataDictionary的Load方法首先調用ITempDataProvider的LoadTempData方法來獲取TempData容器,然後使_initialKeys等於_data Keys,這相當於保存舊數據的鍵,然後清除_modifiedKeys,這相當於目前沒有。新數據和保存方法是檢查_modifiedKeys計數是否大於或等於檢查是否有新數據。如果有,調用ITempDataProveder的SaveTempData方法保存新數據,這也驗證了我們之前的猜測是正確的。

說到這裏,我們似乎還沒有找到調用TempDataDictionary的Load和Save方法的地方,也就是說新舊數據壹直都在in _data中。似乎舊數據並沒有被真正刪除,新數據也從未有過穩定的歸宿。

我們說TempData中數據的刷新操作(即刷新操作是刪除舊數據並保存新數據)應該在執行操作時發生。我們在哪裏執行的行動?它在IController的execute方法中

受保護的覆蓋void ExecuteCore()

{

TempData Load(controller context TempData provider);

嘗試{

string action name = routed data GetRequiredString(action);

如果(!action invoker invoke action(controller context actionName))

{?HandleUnknownAction(action name);

}

}

最後

{

TempData保存(controller context TempData provider);

}

}

我們在這裏看到,在執行動作之前,先執行TempData Load動作,然後執行TempData Save,實現了對TempData的刷新操作。

SessionStateTempDataProvider和ITempDataProviderTop

此時,我們發現我們似乎並不確切知道數據是如何保存的。我們只知道ITempDataProvider提供了這樣壹個保存數據和獲取容器的約定。然後具體實現必須繼承ITempDataProvider接口的類來執行SessionStateTempDataProvider,它就是這樣壹個類。

我們知道刷新操作是在控制器類的ExecuteCore方法中執行的。我們還知道TempDataDictionary的Load和Save方法需要ITempDataProvider的壹個方法,因此我們可以推斷出我們必須按照預期在Controller類中尋找ITempDataProvider的實現。

public ITempDataProvider tempdata provider {

獲取{

if(_ tempdata provider = = null)

{

_ tempdata provider = new session statestempdata provider();

}

return _ tempDataProvider

}

設置{

_ tempDataProvider = value

}

}

這裏使用屬性註入來註入sessionstatempdataprovider對象,因此如何實現存儲取決於sessionstatempdataprovider類。

SessionStateTempDataProvider有壹個常量字符串字段。

內部常量字符串TempDataSessionStateKey = _ _ ControllerTempData;以下是LoadTempData方法

公共虛擬字典LoadTempData(controller context controller context)

{

HttpContextBase

if(= = null)

{

拋出新的InvalidOperationException(

MVCResources sessionstatempdataprovider _ sessionstatedisaled);

}

詞典& lt字符串對象& gttempdata dictionary =【TempDataSessionStateKey】?作為詞典& lt字符串對象& gt;

if(tempdata dictionary!=空)

{

//如果我們從會話中獲取它,請將其刪除,以便其他請求無法獲取它

(TempDataSessionStateKey);

返回tempDataDictionary

}

其他

{

返回新詞典& lt字符串對象& gt(string comparer ordinal ignore case);

}

}

上面的代碼非常簡單。最初,它在會話【__ControllerTempData】中保存字典類型的數據,當它被讀取時,它只是壹個簡單的類型轉換,然後返回。

下面是SaveTempData方法

公共虛擬void SaveTempData(controller context controller context IDictionary值)

{

HttpContextBase

if(= = null)

{

拋出新的InvalidOperationException(

MVCResources sessionstatempdataprovider _ sessionstatedisaled);

}

【TempDataSessionStateKey】= values;

savetempdata方法也很簡單。

匯總頂部

Lishi Xinzhi/Article/program/net/201311/13479