Skip to content
This repository was archived by the owner on Dec 14, 2018. It is now read-only.

Commit db1b708

Browse files
committed
Serialize only simple types to session in TempData
1 parent 6058ad0 commit db1b708

File tree

5 files changed

+94
-4
lines changed

5 files changed

+94
-4
lines changed

src/Microsoft.AspNet.Mvc.Core/Formatters/JsonContractResolver.cs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
22
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
33

4-
using System;
54
using System.ComponentModel.DataAnnotations;
65
using System.Reflection;
76
using Newtonsoft.Json;

src/Microsoft.AspNet.Mvc.Core/Properties/Resources.Designer.cs

Lines changed: 16 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/Microsoft.AspNet.Mvc.Core/Resources.resx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -451,4 +451,7 @@
451451
<data name="ModelType_WrongType" xml:space="preserve">
452452
<value>The model's runtime type '{0}' is not assignable to the type '{1}'.</value>
453453
</data>
454+
<data name="TempData_CannotSerializeToSession" xml:space="preserve">
455+
<value>The type {0} cannot be serialized to Session.</value>
456+
</data>
454457
</root>

src/Microsoft.AspNet.Mvc.Core/SessionStateTempDataProvider.cs

Lines changed: 37 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
using System.Collections.Generic;
66
using System.IO;
77
using Microsoft.AspNet.Http;
8+
using Microsoft.AspNet.Mvc.Core;
89
using Microsoft.Framework.Internal;
910
using Newtonsoft.Json;
1011
using Newtonsoft.Json.Bson;
@@ -16,8 +17,8 @@ namespace Microsoft.AspNet.Mvc
1617
/// </summary>
1718
public class SessionStateTempDataProvider : ITempDataProvider
1819
{
19-
private static JsonSerializer jsonSerializer = new JsonSerializer();
20-
private static string TempDataSessionStateKey = "__ControllerTempData";
20+
private string TempDataSessionStateKey = "__ControllerTempData";
21+
private JsonSerializer jsonSerializer = new JsonSerializer();
2122

2223
/// <inheritdoc />
2324
public virtual IDictionary<string, object> LoadTempData([NotNull] HttpContext context)
@@ -59,6 +60,9 @@ public virtual void SaveTempData([NotNull] HttpContext context, IDictionary<stri
5960
var hasValues = (values != null && values.Count > 0);
6061
if (hasValues)
6162
{
63+
// We want to allow only primitive types to be serialized in session.
64+
EnsureObjectCanBeSerialized(values);
65+
6266
// Accessing Session property will throw if the session middleware is not enabled.
6367
var session = context.Session;
6468

@@ -76,9 +80,39 @@ public virtual void SaveTempData([NotNull] HttpContext context, IDictionary<stri
7680
}
7781
}
7882

79-
private static bool IsSessionEnabled(HttpContext context)
83+
private bool IsSessionEnabled(HttpContext context)
8084
{
8185
return context.GetFeature<ISessionFeature>() != null;
8286
}
87+
88+
private void EnsureObjectCanBeSerialized(IDictionary<string, object> values)
89+
{
90+
foreach (var item in values.Values)
91+
{
92+
var itemType = item.GetType();
93+
Type[] actualTypes = null;
94+
95+
if (itemType.IsArray)
96+
{
97+
itemType = itemType.GetElementType();
98+
}
99+
else if (TypeHelper.IsCollectionType(itemType))
100+
{
101+
actualTypes = itemType.GetGenericArguments();
102+
}
103+
104+
actualTypes = actualTypes ?? new Type[] { itemType };
105+
106+
foreach (var actualType in actualTypes)
107+
{
108+
var underlyingType = Nullable.GetUnderlyingType(actualType) ?? actualType;
109+
if (!TypeHelper.IsSimpleType(actualType))
110+
{
111+
var message = Resources.FormatTempData_CannotSerializeToSession(underlyingType);
112+
throw new InvalidOperationException(message);
113+
}
114+
}
115+
}
116+
}
83117
}
84118
}

test/Microsoft.AspNet.Mvc.Core.Test/SessionStateTempDataProviderTest.cs

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,44 @@ public void Save_NullSession_NonEmptyDictionary_Throws()
7676
});
7777
}
7878

79+
[Theory]
80+
[MemberData(nameof(InvalidTypes))]
81+
public void Save_InvalidType_Throws(string key, object value, Type type)
82+
{
83+
// Arrange
84+
var testProvider = new SessionStateTempDataProvider();
85+
86+
// Act & Assert
87+
var exception = Assert.Throws<InvalidOperationException>(() =>
88+
{
89+
testProvider.SaveTempData(
90+
GetHttpContext(session: null, sessionEnabled: false),
91+
new Dictionary<string, object> { { key, value } }
92+
);
93+
});
94+
Assert.Equal(string.Format("The type {0} cannot be serialized to Session.", type), exception.Message);
95+
}
96+
97+
public static TheoryData<string, object, Type> InvalidTypes
98+
{
99+
get
100+
{
101+
return new TheoryData<string, object, Type>
102+
{
103+
{ "Object", new object(), typeof(object) },
104+
{ "ObjectArray", new object[3], typeof(object) },
105+
{ "TestItem", new TestItem(), typeof(TestItem) },
106+
{ "ListTestItem", new List<TestItem>(), typeof(TestItem) },
107+
{ "DictTestItem", new Dictionary<string, TestItem>(), typeof(TestItem) }
108+
};
109+
}
110+
}
111+
112+
private class TestItem
113+
{
114+
public int DummyInt { get; set; }
115+
}
116+
79117
private HttpContext GetHttpContext(ISessionCollection session, bool sessionEnabled=true)
80118
{
81119
var httpContext = new Mock<HttpContext>();

0 commit comments

Comments
 (0)