I thought TempData was supposed to become null after one refresh or page redirect. It takes two refreshes of my page to clear the data though which isn't what I want, how do I make it go null after 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
}
I recently went through its source code to find out how TempData works.
So the lifespan of tempdata is rather unusual as it is one request only. In order to achieve this it maintains 2 HashSets to manage keys as well as the data dictionary:
private Dictionary<string, object> _data;
private HashSet<string> _initialKeys = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
private HashSet<string> _retainedKeys = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
When you read some data using an indexer or TryGetValue method it removes that key from _initalKeys collection.
public bool TryGetValue(string key, out object value)
{
_initialKeys.Remove(key);
return _data.TryGetValue(key, out value);
}
The actual dictionary that holds the data is intact at this point. That's why we can read same data consecutively without any issues. It only removes the key from _initialKeys collection, basically marking it to be deleted when the data is persisted.
If you want your values in TempData last longer you can use Peek and Keep methods. What Peek does is return the value without removing it from the _initialKeys:
public object Peek(string key)
{
object value;
_data.TryGetValue(key, out value);
return value;
}
Alternatively, you can call Keep method. Similarly it doesn't manipulate the data directly but just marks the key to be persisted by adding it to the _retainedKeys collection.
public void Keep(string key)
{
_retainedKeys.Add(key);
}
And it finally saves the data (to Session by default) by calling provider's Save method:
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);
}
So only the data that remained in the _initialKeys collection (unread) and the ones that are specifically instructed to retain (the keys in the _retainedKeys collection) will be saved. Hence the lifespan!
Reference: TempDataDictionary source code