2015-02-05 3 views
1

Я пытаюсь использовать TempData для отправки данных с одного запроса другому.Реализация ITempDataProvider vs Использование файлов cookie

Однако, поскольку TempData использует сеанс сервера, и это приложение должно быть веб-фермой, я должен будет либо использовать 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); 
    } 
... 

Ref. http://brockallen.com/2012/06/11/cookie-based-tempdata-provider/

Однако ни один из этих методов, похоже, не удаляет файл cookie после завершения запроса.

Не все время использования TempData для истечения срока действия данных после завершения запроса (если вы не используете TempData.Keep("myKey");)?

Почему бы не использовать файлы cookie вместо внедрения ITempDataProvider? В чем разница/польза?

Дальнейшее чтение:

Вот простой печенье на основе реализации:

Вот реализация от Microsoft поставщика SessionState:

Edit для уточнения: В следующем коде Microsoft удаляет сессию после того, как он будет загружен таким образом, что она не может быть загружен снова:

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

В чем проблема с удалением файла cookie в вашей реализации? –

+0

Ну, мне было немного любопытно, почему ни одна из других реализаций, которые я нашел, не удалил cookie. Я ожидал, что файл cookie будет удален так же, как Microsoft удаляет сеанс; однако это не то, что я нашел в приведенном выше кодексе Брок Аллена. – user1477388

ответ

1

Ни одно из решений я не нашел на в Интернете истек файл cookie; так, в основном они фактически не были временные данные. Все они просто позволяют печенью выжить после LoadTempData(), поэтому в этот момент вы даже не можете использовать TempData.

В следующей реализации куки-файлы будут сохраняться только на протяжении 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 
      } 
     } 
    } 
}