刷新后TempData不为空

本文关键字:TempData 刷新 | 更新日期: 2023-09-27 18:12:07

我认为TempData应该在一次刷新或页面重定向后变为空。它需要两次刷新我的页面来清除数据,虽然这不是我想要的,我如何使它在1刷新/重定向后变为空?

@using (Html.BeginForm())
{
    <div class="form-group">
        <button class="btn btn-default" type="submit">test</button>
    </div>
}
public void test()
{
    List<int> integers = new List<int>();
    integers.Add(10);
    integers.Add(20);
    //First Refresh and myList still has values when I want it to be null
    List<int> myList = (List<int>)TempData["test"]; // Take the value from the current data variable
    if (myList == null) // Not yet stored in session, create a new list and store it as a session variable
    {
        myList = new List<int>();
        TempData.Add("test", myList);
    }
    myList.AddRange(integers); // Add a new entry          
}

刷新后TempData不为空

我最近查看了它的源代码,以了解TempData是如何工作的。

所以tempdata的生命周期是相当不寻常的,因为它只有一个请求。为了实现这一点,它维护了2个hashset来管理键和数据字典:

private Dictionary<string, object> _data;
private HashSet<string> _initialKeys = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
private HashSet<string> _retainedKeys = new HashSet<string>(StringComparer.OrdinalIgnoreCase);

当您使用索引器或TryGetValue方法读取一些数据时,它会从_initalKeys集合中删除该键。

public bool TryGetValue(string key, out object value)
{
    _initialKeys.Remove(key);
    return _data.TryGetValue(key, out value);
}

保存数据的实际字典此时是完整的。这就是为什么我们可以连续读取相同的数据而没有任何问题。它只从_initialKeys集合中删除键,基本上将其标记为在数据持久化时删除。

如果你想让你的值在TempData持续更长时间,你可以使用Peek和Keep方法。Peek所做的是返回值而不从_initialKeys中删除它:

public object Peek(string key)
{
    object value;
    _data.TryGetValue(key, out value);
    return value;
}

也可以调用Keep方法。类似地,它不直接操作数据,而只是通过将键添加到_retainedKeys集合来标记要持久化的键。

public void Keep(string key)
{
    _retainedKeys.Add(key);
}

最后通过调用提供者的Save方法保存数据(默认情况下保存到Session):

public void Save(ControllerContext controllerContext, ITempDataProvider tempDataProvider)
{
    _data.RemoveFromDictionary((KeyValuePair<string, object> entry, TempDataDictionary tempData) =>
        {
            string key = entry.Key;
            return !tempData._initialKeys.Contains(key) 
                && !tempData._retainedKeys.Contains(key);
        }, this);
    tempDataProvider.SaveTempData(controllerContext, _data);
}

因此,只有保留在_initialKeys集合中的数据(未读)和特别指示保留的数据(_retainedKeys集合中的键)将被保存。因此就有了寿命!

参考:TempDataDictionary源代码

我们有不同的状态管理技术,如Viewbag,ViewData和TempData。TempData的特殊之处在于,它甚至可以在多个连续请求中保存该值,这取决于该值在视图中被读取的方式。

  1. 如果它是一个正常的读取,那么在下一个请求时该值将变为空。2.如果是Peek读取,例如使用了TempData的Peek()方法,则值将保留到下一个请求。3.如果它是一个Keep读,这意味着你已经使用了TempData的Keep()方法,那么这个值也将在下一个请求中可用。4.如果您没有读取视图中的值,则该值将保留,直到未读取为止。

    MVC中的TempData与示例

如果您想在请求完成后保留TempData对象中的值,您需要在当前操作中调用keep方法。

教程