刷新后 TempData 不为空

TempData not null after refresh

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

@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对象中的值,你需要在当前操作中调用Keep方法。

tutorial

我最近浏览了它的源代码以了解 TempData 的工作原理。

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

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 所做的是 return 值而不从 _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);
}

最后调用provider的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 source code

在 Asp.Net MVC 中,我们有不同的状态管理技术,如 Viewbag、ViewData 和 TempData。 TempData 的特殊之处在于它甚至可以针对多个连续请求保存值,具体取决于值在视图中的读取方式。

  1. 如果是正常读取那么下一次请求时该值会变为null。 2.If 这是一个 Peek 读取,就像如果您使用了 TempData 的 Peek() 方法,那么下一个请求将保留该值。 3.If 这是一个 Keep read,这意味着您已经使用了 TempData 的 Keep() 方法,那么该值也将可用于下一个请求。 4.If您还没有读取视图中的值,那么该值将一直保留到未被读取为止。

    TempData in MVC with example