浏览器cookie中的ASP.NET MVC TempData

5 cookies tempdata asp.net-mvc-2

我正在尝试使用自定义ITempDataProvider提供程序将TempData存储在浏览器的cookie而不是会话状态中.但是,一切正常,但我无法在读取后从Response流中删除cookie.

有任何想法吗?
谢谢!

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

        public CookieTempDataProvider(HttpContextBase httpContext)
        {
            if (httpContext == null)
            {
                throw new ArgumentNullException("httpContext");
            }
            _httpContext = httpContext;
        }

        public HttpContextBase HttpContext
        {
            get
            {
                return _httpContext;
            }
        }

        protected virtual IDictionary<string, object> LoadTempData(ControllerContext controllerContext)
        {
            HttpCookie cookie = _httpContext.Request.Cookies[TempDataCookieKey];
            if (cookie != null && !string.IsNullOrEmpty(cookie.Value))
            {
                IDictionary<string, object> deserializedTempData = DeserializeTempData(cookie.Value);

                // Remove cookie                
                cookie.Expires = DateTime.MinValue;
                cookie.Value = string.Empty;
                _httpContext.Request.Cookies.Remove(TempDataCookieKey);

                if (_httpContext.Response != null && _httpContext.Response.Cookies != null)
                {
                    HttpCookie responseCookie = _httpContext.Response.Cookies[TempDataCookieKey];
                    if (responseCookie != null)
                    {
                        // Remove cookie
                        cookie.Expires = DateTime.MinValue;
                        cookie.Value = string.Empty;
                        _httpContext.Response.Cookies.Remove(TempDataCookieKey);

                    }
                }

                return deserializedTempData;
            }

            return new Dictionary<string, object>();
        }

        protected virtual void SaveTempData(ControllerContext controllerContext, IDictionary<string, object> values)
        {

            string cookieValue = SerializeToBase64EncodedString(values);  
            var cookie = new HttpCookie(TempDataCookieKey);
            cookie.HttpOnly = true;
            cookie.Value = cookieValue;

            _httpContext.Response.Cookies.Add(cookie);
        }

        public static IDictionary<string, object> DeserializeTempData(string base64EncodedSerializedTempData)
        {
            byte[] bytes = Convert.FromBase64String(base64EncodedSerializedTempData);
            var memStream = new MemoryStream(bytes);
            var binFormatter = new BinaryFormatter();
            return binFormatter.Deserialize(memStream, null) as IDictionary<string, object> /*TempDataDictionary : This returns NULL*/;
        }

        public static string SerializeToBase64EncodedString(IDictionary<string, object> values)
        {
            MemoryStream memStream = new MemoryStream();
            memStream.Seek(0, SeekOrigin.Begin);
            var binFormatter = new BinaryFormatter();
            binFormatter.Serialize(memStream, values);
            memStream.Seek(0, SeekOrigin.Begin);
            byte[] bytes = memStream.ToArray();
            return Convert.ToBase64String(bytes);
        }

        IDictionary<string, object> ITempDataProvider.LoadTempData(ControllerContext controllerContext)
        {
            return LoadTempData(controllerContext);
        }

        void ITempDataProvider.SaveTempData(ControllerContext controllerContext, IDictionary<string, object> values)
        {
            SaveTempData(controllerContext, values);
        }
    }
Run Code Online (Sandbox Code Playgroud)

Ami*_*ila 3

您好,我也遇到了同样的问题,这是 CookieTempDataProvider 的实现问题。

所以我对代码做了一些修改,现在它可以完美运行了。

当它从 cookie 中读取数据时,会将其从请求和响应中删除。但在请求处理完成时调用的 SaveData 函数中添加另一个具有空值的 cookie。

注意事项:如果你想删除cookie,你必须设置超时值并将其发送回客户端,然后浏览器将删除它。我们不能通过代码来做到这一点,cookie 由浏览器处理

我发现将过期时间设置为 DateTime.MinValue 不会使 chrome 中的 cookie 过期(不知道其他浏览器),所以我将其设置为 2001-01-01 :)

这是工作代码

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

    public CookieTempDataProvider(HttpContextBase httpContext)
    {
        if (httpContext == null)
        {
            throw new ArgumentNullException("httpContext");
        }
        _httpContext = httpContext;
    }

    public HttpContextBase HttpContext
    {
        get
        {
            return _httpContext;
        }
    }

    protected virtual IDictionary<string, object> LoadTempData(ControllerContext controllerContext)
    {
        if (_httpContext.Request.Cookies.AllKeys.Contains(TempDataCookieKey)) //we need this because
        //Cookies[TempDataCookieKey] will create the cookie if it does not exist
        {
            HttpCookie cookie = _httpContext.Request.Cookies[TempDataCookieKey];
            if (cookie != null && !string.IsNullOrEmpty(cookie.Value))
            {
                IDictionary<string, object> deserializedTempData = DeserializeTempData(cookie.Value);

                // Remove cookie                
                cookie.Expires = new DateTime(2000, 1, 1);
                cookie.Value = string.Empty;
                _httpContext.Request.Cookies.Remove(TempDataCookieKey);

                if (_httpContext.Response != null && _httpContext.Response.Cookies != null)
                {
                    HttpCookie responseCookie = _httpContext.Response.Cookies[TempDataCookieKey];
                    if (responseCookie != null)
                    {
                        // Remove cookie
                        cookie.Expires = new DateTime(2000, 1, 1);
                        cookie.Value = string.Empty;
                        _httpContext.Response.Cookies.Remove(TempDataCookieKey);

                    }
                }

                return deserializedTempData;
            }
        }
        return new Dictionary<string, object>();
    }

    protected virtual void SaveTempData(ControllerContext controllerContext, IDictionary<string, object> values)
    {
        if (values != null && values.Count > 0)
        {
            //there are values to set, so add the cookie. But no need to expire it as we need the browser to send the 
            //cookie back with the next request
            string cookieValue = SerializeToBase64EncodedString(values);
            var cookie = new HttpCookie(TempDataCookieKey);
            cookie.HttpOnly = true;
            cookie.Value = cookieValue;

            _httpContext.Response.Cookies.Add(cookie);
        }
        else
        {
            //Still we need to add the cookie with the expiration set, to make the client browser remove the cookie from the request.
            //Otherwise the browser will continue to send the cookie with the response

            //Also we need to do this only if the requet had a tempdata cookie

            if (_httpContext.Request.Cookies.AllKeys.Contains(TempDataCookieKey))
            {
                {
                    HttpCookie cookie = _httpContext.Request.Cookies[TempDataCookieKey];

                    // Remove the request cookie                
                    cookie.Expires = new DateTime(2000, 1, 1);
                    cookie.Value = string.Empty;
                    _httpContext.Request.Cookies.Remove(TempDataCookieKey);

                    var rescookie = new HttpCookie(TempDataCookieKey);
                    rescookie.HttpOnly = true;
                    rescookie.Value = "";
                    rescookie.Expires = new DateTime(2000, 1, 1); //so that the browser will remove the cookie when it receives the request
                    _httpContext.Response.Cookies.Add(rescookie);
                }
            }
        }
    }

    public static IDictionary<string, object> DeserializeTempData(string base64EncodedSerializedTempData)
    {
        byte[] bytes = Convert.FromBase64String(base64EncodedSerializedTempData);
        var memStream = new MemoryStream(bytes);
        var binFormatter = new BinaryFormatter();
        return binFormatter.Deserialize(memStream, null) as IDictionary<string, object> /*TempDataDictionary : This returns NULL*/;
    }

    public static string SerializeToBase64EncodedString(IDictionary<string, object> values)
    {
        MemoryStream memStream = new MemoryStream();
        memStream.Seek(0, SeekOrigin.Begin);
        var binFormatter = new BinaryFormatter();
        binFormatter.Serialize(memStream, values);
        memStream.Seek(0, SeekOrigin.Begin);
        byte[] bytes = memStream.ToArray();
        return Convert.ToBase64String(bytes);
    }

    IDictionary<string, object> ITempDataProvider.LoadTempData(ControllerContext controllerContext)
    {
        return LoadTempData(controllerContext);
    }

    void ITempDataProvider.SaveTempData(ControllerContext controllerContext, IDictionary<string, object> values)
    {
        SaveTempData(controllerContext, values);
    }
}
Run Code Online (Sandbox Code Playgroud)