2015-02-05 92 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 
      } 
     } 
    } 
}