Revert "Fix for issue 85 - Dictionary types should return null on key not found"
This is causing issues with routing functional tests in CoreCLR. Suspect
CoreCLR compat issue.
This reverts commit ae65001e84.
This commit is contained in:
parent
ae65001e84
commit
0e826e69e6
|
|
@ -2,48 +2,21 @@
|
||||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections;
|
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
|
|
||||||
namespace Microsoft.AspNet.Routing
|
namespace Microsoft.AspNet.Routing
|
||||||
{
|
{
|
||||||
/// <summary>
|
public class RouteValueDictionary : Dictionary<string, object>
|
||||||
/// An <see cref="IDictionary{string, object}"/> type for route values.
|
|
||||||
/// </summary>
|
|
||||||
public class RouteValueDictionary : IDictionary<string, object>
|
|
||||||
{
|
{
|
||||||
private readonly Dictionary<string, object> _dictionary;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Creates an empty RouteValueDictionary.
|
|
||||||
/// </summary>
|
|
||||||
public RouteValueDictionary()
|
public RouteValueDictionary()
|
||||||
|
: base(StringComparer.OrdinalIgnoreCase)
|
||||||
{
|
{
|
||||||
_dictionary = new Dictionary<string, object>(StringComparer.OrdinalIgnoreCase);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Creates a RouteValueDictionary initialized with the provided input values.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="values">Input values to copy into the dictionary.</param>
|
|
||||||
public RouteValueDictionary([NotNull] IDictionary<string, object> values)
|
|
||||||
{
|
|
||||||
_dictionary = new Dictionary<string, object>(values, StringComparer.OrdinalIgnoreCase);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Creates a RouteValueDictionary initialized with the provided input values.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="values">Input values to copy into the dictionary.</param>
|
|
||||||
/// <remarks>
|
|
||||||
/// 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.
|
|
||||||
/// </remarks>
|
|
||||||
public RouteValueDictionary(object obj)
|
public RouteValueDictionary(object obj)
|
||||||
: this()
|
: base(StringComparer.OrdinalIgnoreCase)
|
||||||
{
|
{
|
||||||
if (obj != null)
|
if (obj != null)
|
||||||
{
|
{
|
||||||
|
|
@ -73,162 +46,9 @@ namespace Microsoft.AspNet.Routing
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
public RouteValueDictionary(IDictionary<string, object> other)
|
||||||
public object this[[NotNull] string key]
|
: base(other, StringComparer.OrdinalIgnoreCase)
|
||||||
{
|
{
|
||||||
get
|
|
||||||
{
|
|
||||||
object value;
|
|
||||||
_dictionary.TryGetValue(key, out value);
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
set
|
|
||||||
{
|
|
||||||
_dictionary[key] = value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the comparer for this dictionary.
|
|
||||||
/// </summary>
|
|
||||||
/// <remarks>
|
|
||||||
/// This will always be a reference to <see cref="StringComparer.OrdinalIgnoreCase"/>
|
|
||||||
/// </remarks>
|
|
||||||
public IEqualityComparer<string> Comparer
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return _dictionary.Comparer;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
public int Count
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return _dictionary.Count;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
bool ICollection<KeyValuePair<string, object>>.IsReadOnly
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return ((ICollection<KeyValuePair<string, object>>)_dictionary).IsReadOnly;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
public Dictionary<string, object>.KeyCollection Keys
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return _dictionary.Keys;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
ICollection<string> IDictionary<string, object>.Keys
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return _dictionary.Keys;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
public Dictionary<string, object>.ValueCollection Values
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return _dictionary.Values;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
ICollection<object> IDictionary<string, object>.Values
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return _dictionary.Values;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
void ICollection<KeyValuePair<string, object>>.Add(KeyValuePair<string, object> item)
|
|
||||||
{
|
|
||||||
((ICollection<KeyValuePair<string, object>>)_dictionary).Add(item);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
public void Add([NotNull] string key, object value)
|
|
||||||
{
|
|
||||||
_dictionary.Add(key, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
public void Clear()
|
|
||||||
{
|
|
||||||
_dictionary.Clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
bool ICollection<KeyValuePair<string, object>>.Contains(KeyValuePair<string, object> item)
|
|
||||||
{
|
|
||||||
return ((ICollection<KeyValuePair<string, object>>)_dictionary).Contains(item);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
public bool ContainsKey([NotNull] string key)
|
|
||||||
{
|
|
||||||
return _dictionary.ContainsKey(key);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
void ICollection<KeyValuePair<string, object>>.CopyTo(
|
|
||||||
[NotNull] KeyValuePair<string, object>[] array,
|
|
||||||
int arrayIndex)
|
|
||||||
{
|
|
||||||
((ICollection<KeyValuePair<string, object>>)_dictionary).CopyTo(array, arrayIndex);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
public Dictionary<string, object>.Enumerator GetEnumerator()
|
|
||||||
{
|
|
||||||
return _dictionary.GetEnumerator();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
IEnumerator<KeyValuePair<string, object>> IEnumerable<KeyValuePair<string, object>>.GetEnumerator()
|
|
||||||
{
|
|
||||||
return _dictionary.GetEnumerator();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
IEnumerator IEnumerable.GetEnumerator()
|
|
||||||
{
|
|
||||||
return _dictionary.GetEnumerator();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
bool ICollection<KeyValuePair<string, object>>.Remove(KeyValuePair<string, object> item)
|
|
||||||
{
|
|
||||||
return ((ICollection<KeyValuePair<string, object>>)_dictionary).Remove(item);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
public bool Remove([NotNull] string key)
|
|
||||||
{
|
|
||||||
return _dictionary.Remove(key);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
public bool TryGetValue([NotNull] string key, out object value)
|
|
||||||
{
|
|
||||||
return _dictionary.TryGetValue(key, out value);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -147,7 +147,7 @@ namespace Microsoft.AspNet.Routing.Template
|
||||||
|
|
||||||
// Add any ambient values that don't match parameters - they need to be visible to constraints
|
// Add any ambient values that don't match parameters - they need to be visible to constraints
|
||||||
// but they will ignored by link generation.
|
// but they will ignored by link generation.
|
||||||
var combinedValues = new RouteValueDictionary(context.AcceptedValues);
|
var combinedValues = new Dictionary<string, object>(context.AcceptedValues, StringComparer.OrdinalIgnoreCase);
|
||||||
if (ambientValues != null)
|
if (ambientValues != null)
|
||||||
{
|
{
|
||||||
foreach (var kvp in ambientValues)
|
foreach (var kvp in ambientValues)
|
||||||
|
|
@ -292,6 +292,7 @@ namespace Microsoft.AspNet.Routing.Template
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Compares two objects for equality as parts of a case-insensitive path.
|
/// Compares two objects for equality as parts of a case-insensitive path.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
@ -341,8 +342,8 @@ namespace Microsoft.AspNet.Routing.Template
|
||||||
{
|
{
|
||||||
private readonly IDictionary<string, object> _defaults;
|
private readonly IDictionary<string, object> _defaults;
|
||||||
|
|
||||||
private readonly RouteValueDictionary _acceptedValues;
|
private readonly Dictionary<string, object> _acceptedValues;
|
||||||
private readonly RouteValueDictionary _filters;
|
private readonly Dictionary<string, object> _filters;
|
||||||
|
|
||||||
public TemplateBindingContext(IDictionary<string, object> defaults, IDictionary<string, object> values)
|
public TemplateBindingContext(IDictionary<string, object> defaults, IDictionary<string, object> values)
|
||||||
{
|
{
|
||||||
|
|
@ -353,20 +354,20 @@ namespace Microsoft.AspNet.Routing.Template
|
||||||
|
|
||||||
_defaults = defaults;
|
_defaults = defaults;
|
||||||
|
|
||||||
_acceptedValues = new RouteValueDictionary();
|
_acceptedValues = new Dictionary<string, object>(StringComparer.OrdinalIgnoreCase);
|
||||||
|
|
||||||
if (_defaults != null)
|
if (_defaults != null)
|
||||||
{
|
{
|
||||||
_filters = new RouteValueDictionary(defaults);
|
_filters = new Dictionary<string, object>(defaults, StringComparer.OrdinalIgnoreCase);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public RouteValueDictionary AcceptedValues
|
public Dictionary<string, object> AcceptedValues
|
||||||
{
|
{
|
||||||
get { return _acceptedValues; }
|
get { return _acceptedValues; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public RouteValueDictionary Filters
|
public Dictionary<string, object> Filters
|
||||||
{
|
{
|
||||||
get { return _filters; }
|
get { return _filters; }
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -32,10 +32,10 @@ namespace Microsoft.AspNet.Routing.Template
|
||||||
|
|
||||||
if (defaults == null)
|
if (defaults == null)
|
||||||
{
|
{
|
||||||
defaults = new RouteValueDictionary();
|
defaults = new Dictionary<string, object>(StringComparer.OrdinalIgnoreCase);
|
||||||
}
|
}
|
||||||
|
|
||||||
var values = new RouteValueDictionary();
|
var values = new Dictionary<string, object>(StringComparer.OrdinalIgnoreCase);
|
||||||
|
|
||||||
for (var i = 0; i < requestSegments.Length; i++)
|
for (var i = 0; i < requestSegments.Length; i++)
|
||||||
{
|
{
|
||||||
|
|
@ -175,7 +175,7 @@ namespace Microsoft.AspNet.Routing.Template
|
||||||
private bool MatchComplexSegment(TemplateSegment routeSegment,
|
private bool MatchComplexSegment(TemplateSegment routeSegment,
|
||||||
string requestSegment,
|
string requestSegment,
|
||||||
IDictionary<string, object> defaults,
|
IDictionary<string, object> defaults,
|
||||||
RouteValueDictionary values)
|
Dictionary<string, object> values)
|
||||||
{
|
{
|
||||||
Contract.Assert(routeSegment != null);
|
Contract.Assert(routeSegment != null);
|
||||||
Contract.Assert(routeSegment.Parts.Count > 1);
|
Contract.Assert(routeSegment.Parts.Count > 1);
|
||||||
|
|
|
||||||
|
|
@ -42,7 +42,7 @@ namespace Microsoft.AspNet.Routing.Template
|
||||||
_target = target;
|
_target = target;
|
||||||
_routeTemplate = routeTemplate ?? string.Empty;
|
_routeTemplate = routeTemplate ?? string.Empty;
|
||||||
Name = routeName;
|
Name = routeName;
|
||||||
_defaults = defaults ?? new RouteValueDictionary();
|
_defaults = defaults ?? new Dictionary<string, object>(StringComparer.OrdinalIgnoreCase);
|
||||||
_constraints = RouteConstraintBuilder.BuildConstraints(constraints, _routeTemplate) ??
|
_constraints = RouteConstraintBuilder.BuildConstraints(constraints, _routeTemplate) ??
|
||||||
new Dictionary<string, IRouteConstraint>();
|
new Dictionary<string, IRouteConstraint>();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -23,7 +23,7 @@ namespace Microsoft.AspNet.Routing.Template.Tests
|
||||||
|
|
||||||
// PathString in HttpAbstractions guarantees a leading slash - so no value in testing other cases.
|
// PathString in HttpAbstractions guarantees a leading slash - so no value in testing other cases.
|
||||||
[Fact]
|
[Fact]
|
||||||
public async Task Match_Success_LeadingSlash()
|
public async void Match_Success_LeadingSlash()
|
||||||
{
|
{
|
||||||
// Arrange
|
// Arrange
|
||||||
var route = CreateRoute("{controller}/{action}");
|
var route = CreateRoute("{controller}/{action}");
|
||||||
|
|
@ -40,7 +40,7 @@ namespace Microsoft.AspNet.Routing.Template.Tests
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public async Task Match_Success_RootUrl()
|
public async void Match_Success_RootUrl()
|
||||||
{
|
{
|
||||||
// Arrange
|
// Arrange
|
||||||
var route = CreateRoute("");
|
var route = CreateRoute("");
|
||||||
|
|
@ -55,7 +55,7 @@ namespace Microsoft.AspNet.Routing.Template.Tests
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public async Task Match_Success_Defaults()
|
public async void Match_Success_Defaults()
|
||||||
{
|
{
|
||||||
// Arrange
|
// Arrange
|
||||||
var route = CreateRoute("{controller}/{action}", new { action = "Index" });
|
var route = CreateRoute("{controller}/{action}", new { action = "Index" });
|
||||||
|
|
@ -72,7 +72,7 @@ namespace Microsoft.AspNet.Routing.Template.Tests
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public async Task Match_Fails()
|
public async void Match_Fails()
|
||||||
{
|
{
|
||||||
// Arrange
|
// Arrange
|
||||||
var route = CreateRoute("{controller}/{action}");
|
var route = CreateRoute("{controller}/{action}");
|
||||||
|
|
@ -86,7 +86,7 @@ namespace Microsoft.AspNet.Routing.Template.Tests
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public async Task Match_RejectedByHandler()
|
public async void Match_RejectedByHandler()
|
||||||
{
|
{
|
||||||
// Arrange
|
// Arrange
|
||||||
var route = CreateRoute("{controller}", accept: false);
|
var route = CreateRoute("{controller}", accept: false);
|
||||||
|
|
@ -102,20 +102,6 @@ namespace Microsoft.AspNet.Routing.Template.Tests
|
||||||
Assert.NotNull(context.RouteData.Values);
|
Assert.NotNull(context.RouteData.Values);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
|
||||||
public async Task Match_RouteValuesDoesntThrowOnKeyNotFound()
|
|
||||||
{
|
|
||||||
// Arrange
|
|
||||||
var route = CreateRoute("{controller}/{action}");
|
|
||||||
var context = CreateRouteContext("/Home/Index");
|
|
||||||
|
|
||||||
// Act
|
|
||||||
await route.RouteAsync(context);
|
|
||||||
|
|
||||||
// Assert
|
|
||||||
Assert.Null(context.RouteData.Values["1controller"]);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static RouteContext CreateRouteContext(string requestPath)
|
private static RouteContext CreateRouteContext(string requestPath)
|
||||||
{
|
{
|
||||||
var request = new Mock<HttpRequest>(MockBehavior.Strict);
|
var request = new Mock<HttpRequest>(MockBehavior.Strict);
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue