From 0fedda5855dbe6fbde0fda02241e20cdc0796494 Mon Sep 17 00:00:00 2001 From: Pranav K Date: Tue, 20 Oct 2015 14:50:48 -0700 Subject: [PATCH] Allow enums to be serialized by SessionStateTempDataProvider Fixes #3141 --- .../SessionStateTempDataProvider.cs | 38 +++++++++----- .../SessionStateTempDataProviderTest.cs | 51 ++++++++++++++++++- 2 files changed, 75 insertions(+), 14 deletions(-) diff --git a/src/Microsoft.AspNet.Mvc.ViewFeatures/ViewFeatures/SessionStateTempDataProvider.cs b/src/Microsoft.AspNet.Mvc.ViewFeatures/ViewFeatures/SessionStateTempDataProvider.cs index 996491695a..01a2f4e524 100644 --- a/src/Microsoft.AspNet.Mvc.ViewFeatures/ViewFeatures/SessionStateTempDataProvider.cs +++ b/src/Microsoft.AspNet.Mvc.ViewFeatures/ViewFeatures/SessionStateTempDataProvider.cs @@ -9,7 +9,6 @@ using System.IO; using System.Linq; using System.Reflection; using Microsoft.AspNet.Http; -using Microsoft.AspNet.Http.Features; using Microsoft.Extensions.Internal; using Newtonsoft.Json; using Newtonsoft.Json.Bson; @@ -73,10 +72,13 @@ namespace Microsoft.AspNet.Mvc.ViewFeatures tempDataDictionary = _jsonSerializer.Deserialize>(writer); } - var convertedDictionary = new Dictionary(tempDataDictionary, StringComparer.OrdinalIgnoreCase); + var convertedDictionary = new Dictionary( + tempDataDictionary, + StringComparer.OrdinalIgnoreCase); foreach (var item in tempDataDictionary) { var jArrayValue = item.Value as JArray; + var jObjectValue = item.Value as JObject; if (jArrayValue != null && jArrayValue.Count > 0) { var arrayType = jArrayValue[0].Type; @@ -85,7 +87,9 @@ namespace Microsoft.AspNet.Mvc.ViewFeatures { var arrayConverter = _arrayConverters.GetOrAdd(returnType, type => { - return (Func)_convertArrayMethodInfo.MakeGenericMethod(type).CreateDelegate(typeof(Func)); + return (Func)_convertArrayMethodInfo + .MakeGenericMethod(type) + .CreateDelegate(typeof(Func)); }); var result = arrayConverter(jArrayValue); @@ -97,14 +101,9 @@ namespace Microsoft.AspNet.Mvc.ViewFeatures throw new InvalidOperationException(message); } } - else + else if (jObjectValue != null) { - var jObjectValue = item.Value as JObject; - if (jObjectValue == null) - { - continue; - } - else if (!jObjectValue.HasValues) + if (!jObjectValue.HasValues) { convertedDictionary[item.Key] = null; continue; @@ -116,7 +115,9 @@ namespace Microsoft.AspNet.Mvc.ViewFeatures { var dictionaryConverter = _dictionaryConverters.GetOrAdd(valueType, type => { - return (Func)_convertDictMethodInfo.MakeGenericMethod(type).CreateDelegate(typeof(Func)); + return (Func)_convertDictMethodInfo + .MakeGenericMethod(type) + .CreateDelegate(typeof(Func)); }); var result = dictionaryConverter(jObjectValue); @@ -128,6 +129,16 @@ namespace Microsoft.AspNet.Mvc.ViewFeatures throw new InvalidOperationException(message); } } + else if (item.Value is long) + { + var longValue = (long)item.Value; + if (longValue < int.MaxValue) + { + // BsonReader casts all ints to longs. We'll attempt to work around this by force converting + // longs to ints when there's no loss of precision. + convertedDictionary[item.Key] = (int)longValue; + } + } } tempDataDictionary = convertedDictionary; @@ -245,7 +256,10 @@ namespace Microsoft.AspNet.Mvc.ViewFeatures private static bool IsSimpleType(Type type) { - return type.GetTypeInfo().IsPrimitive || + var typeInfo = type.GetTypeInfo(); + + return typeInfo.IsPrimitive || + typeInfo.IsEnum || type.Equals(typeof(decimal)) || type.Equals(typeof(string)) || type.Equals(typeof(DateTime)) || diff --git a/test/Microsoft.AspNet.Mvc.ViewFeatures.Test/ViewFeatures/SessionStateTempDataProviderTest.cs b/test/Microsoft.AspNet.Mvc.ViewFeatures.Test/ViewFeatures/SessionStateTempDataProviderTest.cs index e59c2c3244..b384c90881 100644 --- a/test/Microsoft.AspNet.Mvc.ViewFeatures.Test/ViewFeatures/SessionStateTempDataProviderTest.cs +++ b/test/Microsoft.AspNet.Mvc.ViewFeatures.Test/ViewFeatures/SessionStateTempDataProviderTest.cs @@ -133,7 +133,8 @@ namespace Microsoft.AspNet.Mvc.ViewFeatures { new DateTimeOffset() }, { 100.1m }, { new Dictionary() }, - { new Uri[] { new Uri("http://Foo"), new Uri("http://Bar") } } + { new Uri[] { new Uri("http://Foo"), new Uri("http://Bar") } }, + { DayOfWeek.Sunday }, }; } } @@ -185,7 +186,7 @@ namespace Microsoft.AspNet.Mvc.ViewFeatures var TempData = testProvider.LoadTempData(context); // Assert - var intVal = Convert.ToInt32(TempData["int"]); + var intVal = Assert.IsType(TempData["int"]); Assert.Equal(10, intVal); } @@ -253,6 +254,52 @@ namespace Microsoft.AspNet.Mvc.ViewFeatures Assert.Equal(inputGuid, guidVal); } + [Fact] + public void SaveAndLoad_EnumCanBeSavedAndLoaded() + { + // Arrange + var key = "EnumValue"; + var testProvider = new SessionStateTempDataProvider(); + var expected = DayOfWeek.Friday; + var input = new Dictionary + { + { key, expected } + }; + var context = GetHttpContext(); + + // Act + testProvider.SaveTempData(context, input); + var TempData = testProvider.LoadTempData(context); + var result = TempData[key]; + + // Assert + var actual = (DayOfWeek)result; + Assert.Equal(expected, actual); + } + + [Fact] + public void SaveAndLoad_LongCanBeSavedAndLoaded() + { + // Arrange + var key = "LongValue"; + var testProvider = new SessionStateTempDataProvider(); + var expected = 3100000000L; + var input = new Dictionary + { + { key, expected } + }; + var context = GetHttpContext(); + + // Act + testProvider.SaveTempData(context, input); + var TempData = testProvider.LoadTempData(context); + var result = TempData[key]; + + // Assert + var actual = Assert.IsType(result); + Assert.Equal(expected, actual); + } + [Fact] public void SaveAndLoad_ListCanBeStoredAndLoaded() {