2015-02-05 91 views
1

我正在嘗試使用TempData將數據從一個請求發送到另一個請求。實現ITempDataProvider vs使用Cookies

但是,由於TempData使用的是服務器會話,並且此應用程序將用於web養殖,所以我將不得不使用cookie或數據庫持久性,因爲會話不會從一臺服務器轉移到另一臺服務器。

有可用的使用,而不是默認的會話cookie多種實施方式:

public class CookieTempDataProvider : ITempDataProvider 
{ 
    const string CookieName = "TempData"; 

    public void SaveTempData(
     ControllerContext controllerContext, 
     IDictionary<string, object> values) 
    { 
     // convert the temp data dictionary into json 
     string value = Serialize(values); 
     // compress the json (it really helps) 
     var bytes = Compress(value); 
     // sign and encrypt the data via the asp.net machine key 
     value = Protect(bytes); 
     // issue the cookie 
     IssueCookie(controllerContext, value); 
    } 

    public IDictionary<string, object> LoadTempData(
     ControllerContext controllerContext) 
    { 
     // get the cookie 
     var value = GetCookieValue(controllerContext); 
     // verify and decrypt the value via the asp.net machine key 
     var bytes = Unprotect(value); 
     // decompress to json 
     value = Decompress(bytes); 
     // convert the json back to a dictionary 
     return Deserialize(value); 
    } 
... 

參考。 http://brockallen.com/2012/06/11/cookie-based-tempdata-provider/

但是,在請求結束後,這些方法似乎都沒有刪除cookie。

在請求完成後(除非使用TempData.Keep("myKey");),是不是使用TempData過期數據的要點?

爲什麼不使用cookie而不是實現ITempDataProvider?有什麼區別/好處?

延伸閱讀:

下面是一個簡單的基於cookie的實現:

下面是微軟的落實SessionState的供應商:

編輯澄清:在下面的代碼,微軟移除會話被加載後,使得它不能被再次裝入:

// If we got it from Session, remove it so that no other request gets it 
session.Remove(TempDataSessionStateKey); 
+1

在您的實施中刪除cookie有什麼問題? – 2015-02-05 18:20:55

+0

嗯,我有點好奇,爲什麼沒有發現其他的實現我刪除了cookie。我預計Cookie將被刪除,就像微軟將刪除會話一樣;然而,這並非我在上面引用的Brock Allen的代碼中找到的。 – user1477388 2015-02-05 18:26:54

回答

1

的解決方案中沒有我發現網絡過期了cookie;所以,基本上他們實際上並不是臨時數據。他們都只是讓cookie在LoadTempData()之後生存下來,所以在這一點上,你甚至可以根本不使用TempData。

在下面的實現中,cookie只會在HTTP請求期間存活(因爲TempData只能這樣做),並且如果要保留更長的時間,您可以像平常那樣使用TempData.Keep("yourKey"),這會調用SaveTempData()方法再次(根據the MVC source)。

最後一件事,此代碼未針對速度或安全性進行優化。

public class CookieTempDataProvider : ITempDataProvider 
{ 
    public const string TempDataCookieKey = "__ControllerTempData"; 

    public IDictionary<string, object> LoadTempData(ControllerContext controller) 
    { 
     HttpCookie cookie = controller.HttpContext.Request.Cookies[TempDataCookieKey]; 

     Dictionary<string, object> tempDataDictionary = new Dictionary<string, object>(); 

     if (cookie != null) 
     { 
      for (int keyIndex = 0; keyIndex < cookie.Values.Count; keyIndex++) 
      { 
       string key = cookie.Values.GetKey(keyIndex); 
       if (!string.IsNullOrEmpty(key)) 
       { 
        string base64Value = cookie.Values.Get(keyIndex); 
        byte[] buffer = Convert.FromBase64String(base64Value); 
        using (MemoryStream ms = new MemoryStream(buffer)) 
        { 
         BinaryFormatter formatter = new BinaryFormatter(); 
         object value = formatter.Deserialize(ms); 
         tempDataDictionary.Add(key, value); 
        } 
       } 
      } 

      cookie.Expires = DateTime.Now.AddDays(-1d); // expire cookie so no other request gets it 
      controller.HttpContext.Response.SetCookie(cookie); 
     } 

     return tempDataDictionary; 
    } 

    public void SaveTempData(ControllerContext controller, IDictionary<string, object> values) 
    { 
     HttpCookie cookie = controller.HttpContext.Request.Cookies[TempDataCookieKey]; 
     bool hasValues = (values != null && values.Count > 0); 

     if (cookie == null) 
     { 
      cookie = new HttpCookie(TempDataCookieKey); 
      controller.HttpContext.Response.Cookies.Add(cookie); 
     } 

     if (hasValues) 
     { 
      foreach (KeyValuePair<string, object> kvp in values) 
      { 
       BinaryFormatter formatter = new BinaryFormatter(); 
       using (MemoryStream ms = new MemoryStream()) 
       { 
        formatter.Serialize(ms, kvp.Value); 
        byte[] bytes = ms.GetBuffer(); 
        string base64Value = Convert.ToBase64String(bytes); 

        string keyExists = cookie.Values.Get(kvp.Key); 
        if (keyExists != null) 
        { 
         cookie.Values.Set(kvp.Key, base64Value); 
        } 
        else 
        { 
         cookie.Values.Add(kvp.Key, base64Value); 
        } 
       } 
      } 

      cookie.Expires = DateTime.Now.AddDays(1d); 
      controller.HttpContext.Response.SetCookie(cookie); 
     } 
     else 
     { 
      // delete session if null values are passed 
      if (controller.HttpContext.Request.Cookies[TempDataCookieKey] != null) 
      { 
       cookie.Expires = DateTime.Now.AddDays(-1d); // expire cookie so no other request gets it 
      } 
     } 
    } 
}