Implementing ITempDataProvider vs Using Cookies

会有一股神秘感。 提交于 2019-12-24 13:14:44

问题


I am trying to use TempData to send data from one request to another.

However, since TempData uses a server session, and this application is to be web-farmed, I will have to either use cookies or database persistance, instead, since the session won't transfer from one server to the other.

There are a number of implementations available to use cookies instead of the default 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);
    }
...

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

However, none of these methods seem to remove the cookie after the request has ended.

Isn't the whole point of using TempData to expire the data after the request has finished (unless you use TempData.Keep("myKey");)?

Why not just use cookies instead of implementing ITempDataProvider? What's the difference/benefit?

Further reading:

Here is a simpler cookie-based implementation:

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

Here is Microsoft's implementation of SessionState provider:

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

Edit for clarification: In the following code, Microsoft is removing the session after it is loaded such that it cannot be loaded again:

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

回答1:


None of the solutions I found on the web expired the cookie; so, basically they weren't actually temporary data. They all just let the cookie survive past the LoadTempData() so at that point, you may as well not even be using TempData at all.

In the following implementation, the cookie will only survive for the duration of the HTTP request (as TempData is only supposed to) and if you want to keep it longer, you can use TempData.Keep("yourKey") as you normally would which will call the SaveTempData() method again (as per the MVC source).

One last thing, this code is NOT optimized for speed or security.

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


来源:https://stackoverflow.com/questions/28351198/implementing-itempdataprovider-vs-using-cookies

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!