diff --git a/src/Components/Components/src/ITempData.cs b/src/Components/Components/src/ITempData.cs
new file mode 100644
index 000000000000..70f637e7af6e
--- /dev/null
+++ b/src/Components/Components/src/ITempData.cs
@@ -0,0 +1,32 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+namespace Microsoft.AspNetCore.Components;
+
+///
+/// Provides a dictionary for storing data that is needed for subsequent requests.
+/// Data stored in TempData is automatically removed after it is read unless
+/// or is called, or it is accessed via .
+///
+public interface ITempData : IDictionary
+{
+ ///
+ /// Gets the value associated with the specified key and then schedules it for deletion.
+ ///
+ object? Get(string key);
+
+ ///
+ /// Gets the value associated with the specified key without scheduling it for deletion.
+ ///
+ object? Peek(string key);
+
+ ///
+ /// Makes all of the keys currently in TempData persist for another request.
+ ///
+ void Keep();
+
+ ///
+ /// Makes the element with the persist for another request.
+ ///
+ void Keep(string key);
+}
diff --git a/src/Components/Components/src/PublicAPI.Unshipped.txt b/src/Components/Components/src/PublicAPI.Unshipped.txt
index 908e19bcf6f2..2e3f440a6e8b 100644
--- a/src/Components/Components/src/PublicAPI.Unshipped.txt
+++ b/src/Components/Components/src/PublicAPI.Unshipped.txt
@@ -1,4 +1,23 @@
#nullable enable
+Microsoft.AspNetCore.Components.ITempData
+Microsoft.AspNetCore.Components.ITempData.Get(string! key) -> object?
+Microsoft.AspNetCore.Components.ITempData.Keep() -> void
+Microsoft.AspNetCore.Components.ITempData.Keep(string! key) -> void
+Microsoft.AspNetCore.Components.ITempData.Peek(string! key) -> object?
+Microsoft.AspNetCore.Components.TempData
+Microsoft.AspNetCore.Components.TempData.ContainsValue(object? value) -> bool
+Microsoft.AspNetCore.Components.TempData.TempData() -> void
+Microsoft.AspNetCore.Components.TempData.Get(string! key) -> object?
+Microsoft.AspNetCore.Components.TempData.this[string! key].get -> object?
+Microsoft.AspNetCore.Components.TempData.this[string! key].set -> void
+Microsoft.AspNetCore.Components.TempData.Keep() -> void
+Microsoft.AspNetCore.Components.TempData.Keep(string! key) -> void
+Microsoft.AspNetCore.Components.TempData.Peek(string! key) -> object?
+Microsoft.AspNetCore.Components.TempData.Clear() -> void
+Microsoft.AspNetCore.Components.TempData.Remove(string! key) -> bool
+Microsoft.AspNetCore.Components.TempData.ContainsKey(string! key) -> bool
+Microsoft.AspNetCore.Components.TempData.Load(System.Collections.Generic.IDictionary! data) -> void
+Microsoft.AspNetCore.Components.TempData.Save() -> System.Collections.Generic.IDictionary!
Microsoft.AspNetCore.Components.IComponentPropertyActivator
Microsoft.AspNetCore.Components.IComponentPropertyActivator.GetActivator(System.Type! componentType) -> System.Action!
*REMOVED*Microsoft.AspNetCore.Components.ResourceAsset.ResourceAsset(string! url, System.Collections.Generic.IReadOnlyList? properties) -> void
diff --git a/src/Components/Components/src/TempData.cs b/src/Components/Components/src/TempData.cs
new file mode 100644
index 000000000000..3778e385bf32
--- /dev/null
+++ b/src/Components/Components/src/TempData.cs
@@ -0,0 +1,200 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System.Collections;
+
+namespace Microsoft.AspNetCore.Components;
+
+///
+public class TempData : ITempData
+{
+ private readonly Dictionary _data = new(StringComparer.OrdinalIgnoreCase);
+ private readonly HashSet _retainedKeys = new(StringComparer.OrdinalIgnoreCase);
+
+ ///
+ public object? this[string key]
+ {
+ get => Get(key);
+ set
+ {
+ _data[key] = value;
+ _retainedKeys.Add(key);
+ }
+ }
+
+ ///
+ public object? Get(string key)
+ {
+ _retainedKeys.Remove(key);
+ return _data.GetValueOrDefault(key);
+ }
+
+ ///
+ public object? Peek(string key)
+ {
+ return _data.GetValueOrDefault(key);
+ }
+
+ ///
+ public void Keep()
+ {
+ _retainedKeys.Clear();
+ _retainedKeys.UnionWith(_data.Keys);
+ }
+
+ ///
+ public void Keep(string key)
+ {
+ if (_data.ContainsKey(key))
+ {
+ _retainedKeys.Add(key);
+ }
+ }
+
+ ///
+ public bool ContainsKey(string key)
+ {
+ return _data.ContainsKey(key);
+ }
+
+ ///
+ public bool Remove(string key)
+ {
+ _retainedKeys.Remove(key);
+ return _data.Remove(key);
+ }
+
+ ///
+ /// Returns true if the TempData dictionary contains the specified .
+ ///
+ public bool ContainsValue(object? value)
+ {
+ return _data.ContainsValue(value);
+ }
+
+ ///
+ /// Gets the data that should be saved for the next request.
+ ///
+ public IDictionary Save()
+ {
+ var dataToSave = new Dictionary();
+ foreach (var key in _retainedKeys)
+ {
+ dataToSave[key] = _data[key];
+ }
+ return dataToSave;
+ }
+
+ ///
+ /// Loads data from a into the TempData dictionary.
+ ///
+ public void Load(IDictionary data)
+ {
+ _data.Clear();
+ _retainedKeys.Clear();
+ foreach (var kvp in data)
+ {
+ _data[kvp.Key] = kvp.Value;
+ _retainedKeys.Add(kvp.Key);
+ }
+ }
+
+ ///
+ public void Clear()
+ {
+ _data.Clear();
+ _retainedKeys.Clear();
+ }
+
+ ICollection IDictionary.Keys => _data.Keys;
+
+ ICollection