[Fixes #5243] Handle null values in TempData properly

This commit is contained in:
Ajay Bhargav Baaskaran 2016-09-13 15:51:43 -07:00
parent d9ff1d81d6
commit 42027b6cc2
2 changed files with 52 additions and 8 deletions

View File

@ -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())

View File

@ -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; }