diff --git a/src/Microsoft.AspNet.Routing/RouteValueDictionary.cs b/src/Microsoft.AspNet.Routing/RouteValueDictionary.cs index f924c3fa39..664497b1fc 100644 --- a/src/Microsoft.AspNet.Routing/RouteValueDictionary.cs +++ b/src/Microsoft.AspNet.Routing/RouteValueDictionary.cs @@ -23,7 +23,7 @@ namespace Microsoft.AspNet.Routing private readonly Dictionary _dictionary; /// - /// Creates an empty RouteValueDictionary. + /// Creates an empty . /// public RouteValueDictionary() { @@ -31,28 +31,32 @@ namespace Microsoft.AspNet.Routing } /// - /// Creates a RouteValueDictionary initialized with the provided input values. + /// Creates a initialized with the provided input value. /// - /// Input values to copy into the dictionary. - public RouteValueDictionary([NotNull] IDictionary values) - { - _dictionary = new Dictionary(values, StringComparer.OrdinalIgnoreCase); - } - - /// - /// Creates a RouteValueDictionary initialized with the provided input values. - /// - /// Input values to copy into the dictionary. + /// An object to initialize the dictionary. The value can be of type + /// or or + /// any other object. + /// /// - /// The input parameter is interpreted as a set of key-value-pairs where the property names - /// are keys, and property values are the values, and copied into the dictionary. Only public - /// instance non-index properties are considered. + /// If the value is a dictionary, then its entries are copied. Otherwise the object is interpreted as a set + /// of key-value-pairs where the property names are keys, and property values are the values, and copied + /// into the dictionary. Only public instance non-index properties are considered. /// public RouteValueDictionary(object obj) : this() { if (obj != null) { + var keyValuePairCollection = obj as IEnumerable>; + if (keyValuePairCollection != null) + { + foreach (var kvp in keyValuePairCollection) + { + Add(kvp.Key, kvp.Value); + } + return; + } + var type = obj.GetType(); var allProperties = type.GetRuntimeProperties(); diff --git a/src/Microsoft.AspNet.Routing/Template/TemplateBinder.cs b/src/Microsoft.AspNet.Routing/Template/TemplateBinder.cs index 1a0adb9409..9ab5e547b1 100644 --- a/src/Microsoft.AspNet.Routing/Template/TemplateBinder.cs +++ b/src/Microsoft.AspNet.Routing/Template/TemplateBinder.cs @@ -370,11 +370,7 @@ namespace Microsoft.AspNet.Routing.Template if (_defaults != null) { - _filters = new RouteValueDictionary(defaults); - foreach (var kvp in _defaults) - { - _filters.Add(kvp.Key, kvp.Value); - } + _filters = new RouteValueDictionary(_defaults); } } diff --git a/test/Microsoft.AspNet.Routing.Tests/RouteValueDictionaryTests.cs b/test/Microsoft.AspNet.Routing.Tests/RouteValueDictionaryTests.cs index 2183d3f938..9d9f0810bf 100644 --- a/test/Microsoft.AspNet.Routing.Tests/RouteValueDictionaryTests.cs +++ b/test/Microsoft.AspNet.Routing.Tests/RouteValueDictionaryTests.cs @@ -168,6 +168,48 @@ namespace Microsoft.AspNet.Routing.Tests expected); } + [Fact] + public void CreateFromReadOnlyDictionary_CopiesValues() + { + // Arrange + var dictionary = new Dictionary(); + dictionary.Add("Name", "James"); + dictionary.Add("Age", 30); + var readonlyDictionary = (IReadOnlyDictionary)dictionary; + + // Act + var dict = new RouteValueDictionary(readonlyDictionary); + + // Assert + Assert.Equal(2, dict.Count); + Assert.Equal("James", dict["Name"]); + Assert.Equal(30, dict["Age"]); + } + + [Fact] + public void CreateFromReadOnlyDictionary_ModifyRouteValueDictionary() + { + // Arrange + var dictionary = new Dictionary(); + dictionary.Add("Name", "James"); + dictionary.Add("Age", 30); + dictionary.Add("Address", new Address() { City = "Redmond", State = "WA" }); + var readonlyDictionary = (IReadOnlyDictionary)dictionary; + + // Act + var routeValueDictionary = new RouteValueDictionary(readonlyDictionary); + routeValueDictionary.Add("City", "Redmond"); + + // Assert + Assert.Equal(4, routeValueDictionary.Count); + Assert.Equal("James", routeValueDictionary["Name"]); + Assert.Equal(30, routeValueDictionary["Age"]); + Assert.Equal("Redmond", routeValueDictionary["City"]); + var address = Assert.IsType
(routeValueDictionary["Address"]); + address.State = "Washington"; + Assert.Equal("Washington", ((Address)routeValueDictionary["Address"]).State); + } + private static string GetDuplicateKeyErrorMessage() { // Gets the exception message when duplicate entries are @@ -233,5 +275,12 @@ namespace Microsoft.AspNet.Routing.Tests set { } } } + + private class Address + { + public string City { get; set; } + + public string State { get; set; } + } } }