[Fixes #5243] Handle null values in TempData properly
This commit is contained in:
parent
d9ff1d81d6
commit
42027b6cc2
|
|
@ -21,7 +21,9 @@ namespace Microsoft.AspNetCore.Mvc.ViewFeatures
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class SessionStateTempDataProvider : ITempDataProvider
|
public class SessionStateTempDataProvider : ITempDataProvider
|
||||||
{
|
{
|
||||||
private const string TempDataSessionStateKey = "__ControllerTempData";
|
// Internal for testing
|
||||||
|
internal const string TempDataSessionStateKey = "__ControllerTempData";
|
||||||
|
|
||||||
private readonly JsonSerializer _jsonSerializer = JsonSerializer.Create(
|
private readonly JsonSerializer _jsonSerializer = JsonSerializer.Create(
|
||||||
new JsonSerializerSettings()
|
new JsonSerializerSettings()
|
||||||
{
|
{
|
||||||
|
|
@ -61,15 +63,22 @@ namespace Microsoft.AspNetCore.Mvc.ViewFeatures
|
||||||
// Accessing Session property will throw if the session middleware is not enabled.
|
// Accessing Session property will throw if the session middleware is not enabled.
|
||||||
var session = context.Session;
|
var session = context.Session;
|
||||||
|
|
||||||
var tempDataDictionary = new Dictionary<string, object>(StringComparer.OrdinalIgnoreCase);
|
Dictionary<string, object> tempDataDictionary = null;
|
||||||
byte[] value;
|
byte[] value;
|
||||||
|
|
||||||
if (session.TryGetValue(TempDataSessionStateKey, out value))
|
if (session.TryGetValue(TempDataSessionStateKey, out value))
|
||||||
{
|
{
|
||||||
|
// If we got it from Session, remove it so that no other request gets it
|
||||||
|
session.Remove(TempDataSessionStateKey);
|
||||||
|
|
||||||
using (var memoryStream = new MemoryStream(value))
|
using (var memoryStream = new MemoryStream(value))
|
||||||
using (var writer = new BsonReader(memoryStream))
|
using (var writer = new BsonReader(memoryStream))
|
||||||
{
|
{
|
||||||
tempDataDictionary = _jsonSerializer.Deserialize<Dictionary<string, object>>(writer);
|
tempDataDictionary = _jsonSerializer.Deserialize<Dictionary<string, object>>(writer);
|
||||||
|
if (tempDataDictionary == null)
|
||||||
|
{
|
||||||
|
return new Dictionary<string, object>(StringComparer.OrdinalIgnoreCase);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var convertedDictionary = new Dictionary<string, object>(
|
var convertedDictionary = new Dictionary<string, object>(
|
||||||
|
|
@ -142,9 +151,6 @@ namespace Microsoft.AspNetCore.Mvc.ViewFeatures
|
||||||
}
|
}
|
||||||
|
|
||||||
tempDataDictionary = convertedDictionary;
|
tempDataDictionary = convertedDictionary;
|
||||||
|
|
||||||
// If we got it from Session, remove it so that no other request gets it
|
|
||||||
session.Remove(TempDataSessionStateKey);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
@ -153,7 +159,7 @@ namespace Microsoft.AspNetCore.Mvc.ViewFeatures
|
||||||
session.Set(TempDataSessionStateKey, new byte[] { });
|
session.Set(TempDataSessionStateKey, new byte[] { });
|
||||||
}
|
}
|
||||||
|
|
||||||
return tempDataDictionary;
|
return tempDataDictionary ?? new Dictionary<string, object>(StringComparer.OrdinalIgnoreCase);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
|
|
@ -172,8 +178,11 @@ namespace Microsoft.AspNetCore.Mvc.ViewFeatures
|
||||||
{
|
{
|
||||||
foreach (var item in values.Values)
|
foreach (var item in values.Values)
|
||||||
{
|
{
|
||||||
// We want to allow only simple types to be serialized in session.
|
if (item != null)
|
||||||
EnsureObjectCanBeSerialized(item);
|
{
|
||||||
|
// We want to allow only simple types to be serialized in session.
|
||||||
|
EnsureObjectCanBeSerialized(item);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
using (var memoryStream = new MemoryStream())
|
using (var memoryStream = new MemoryStream())
|
||||||
|
|
|
||||||
|
|
@ -54,6 +54,21 @@ namespace Microsoft.AspNetCore.Mvc.ViewFeatures
|
||||||
Assert.Empty(tempDataDictionary);
|
Assert.Empty(tempDataDictionary);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Load_ReturnsEmptyDictionary_WhenSessionDataIsEmpty()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var testProvider = new SessionStateTempDataProvider();
|
||||||
|
var httpContext = GetHttpContext();
|
||||||
|
httpContext.Session.Set(SessionStateTempDataProvider.TempDataSessionStateKey, new byte[] { });
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var tempDataDictionary = testProvider.LoadTempData(httpContext);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.Empty(tempDataDictionary);
|
||||||
|
}
|
||||||
|
|
||||||
public static TheoryData<object, Type> InvalidTypes
|
public static TheoryData<object, Type> InvalidTypes
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
|
|
@ -369,6 +384,26 @@ namespace Microsoft.AspNetCore.Mvc.ViewFeatures
|
||||||
Assert.Null(emptyDictionary);
|
Assert.Null(emptyDictionary);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void SaveAndLoad_NullValue_RoundTripsSuccessfully()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var testProvider = new SessionStateTempDataProvider();
|
||||||
|
var input = new Dictionary<string, object>
|
||||||
|
{
|
||||||
|
{ "NullKey", null }
|
||||||
|
};
|
||||||
|
var context = GetHttpContext();
|
||||||
|
|
||||||
|
// Act
|
||||||
|
testProvider.SaveTempData(context, input);
|
||||||
|
var TempData = testProvider.LoadTempData(context);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.True(TempData.ContainsKey("NullKey"));
|
||||||
|
Assert.Null(TempData["NullKey"]);
|
||||||
|
}
|
||||||
|
|
||||||
private class TestItem
|
private class TestItem
|
||||||
{
|
{
|
||||||
public int DummyInt { get; set; }
|
public int DummyInt { get; set; }
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue