c# - 实现 ITempDataProvider 与使用 Cookie

标签 c# asp.net-mvc cookies tempdata

我正在尝试使用 TempData 将数据从一个请求发送到另一个请求。

但是,由于 TempData 使用服务器 session ,并且该应用程序是网络农场的,因此我必须使用 cookie 或数据库持久性,因为 session 不会从一台服务器传输到另一台服务器。

有许多实现可以使用 cookie 来代替默认 session :

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");)吗?

为什么不直接使用 cookies 而不是实现 ITempDataProvider?有什么区别/好处?

进一步阅读:

这是一个更简单的基于 cookie 的实现:

这是 Microsoft 的 SessionState 提供程序的实现:

编辑以澄清:在以下代码中,Microsoft 在加载 session 后将其删除,以便无法再次加载:

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

最佳答案

我在网上找到的解决方案都没有使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
            }
        }
    }
}

关于c# - 实现 ITempDataProvider 与使用 Cookie,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28351198/

相关文章:

c# - ASP.NET:我试图设置一个标签来显示图像按钮,但它没有显示页面,我该怎么做?

c# - 如何正确使用仓库模式?

PHP CURL 似乎忽略了 cookie jar/文件

c# - 如何删除 HttpOnly cookie?

javascript - 在MVC中获取从View到Controller的数组属性?

javascript - 如何设置第三方 cookie

C# 杀死一个 labview 应用程序

c# - 使用 RestSharp 反序列化 XML 文档时出错

c# - Avalon 中的 BraceFolding 编辑

asp.net-mvc - 在 MVC2 中使用 FormsAuthenticationTicket cookie 自定义 IIdentity 和 IPrincipal