实施ITempDataProvider VS使用Cookie(Implementing ITempD

2019-10-21 19:18发布

我试图用TempData的从一个请求到另一个发送数据。

然而,由于TempData的使用服务器会话,这种应用是Web的养殖,我将不得不要么使用cookies或持久性的数据库,而不是,因为会议将不会从一台服务器转移到另一个。

有许多可使用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的到期请求完成后数据的整点(除非你使用TempData.Keep("myKey"); )?

为什么不使用cookie,而不是实施ITempDataProvider的? 有什么区别/效益?

延伸阅读:

下面是一个简单的基于cookie的实现:

  • http://vijayt.com/Post/Custom-TempDataProvider-for-Azure

下面是微软的落实SessionState的供应商:

  • https://github.com/ASP-NET-MVC/aspnetwebstack/blob/master/src/System.Web.Mvc/SessionStateTempDataProvider.cs

编辑澄清:在下面的代码,微软移除会话被加载后,使得它不能被再次装入:

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

Answer 1:

我在网上找到的解决方案中没有过期的饼干; 所以,基本上他们不是真正的临时数据。 他们都只是让饼干生存过去LoadTempData(),所以在这一点上,你可能也没有,甚至在所有使用的TempData。

在下面的实现,cookie将只能存活的HTTP请求的时间(如TempData的情况应该只是一个),如果你想保持更长的时间,你可以使用TempData.Keep("yourKey")你通常会这将再次调用SaveTempData()方法(根据所述MVC源 )。

最后一两件事,这段代码是不求速度和安全性进行了优化。

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
            }
        }
    }
}


文章来源: Implementing ITempDataProvider vs Using Cookies