public void Accept(string key, object value)
 {
     if (!_acceptedValues.ContainsKey(key))
     {
         _acceptedValues.Add(key, value);
     }
 }
        public void ContainsKey_PropertyStorage_True_CaseInsensitive()
        {
            // Arrange
            var dict = new DispatcherValueCollection(new { key = "value" });

            // Act
            var result = dict.ContainsKey("kEy");

            // Assert
            Assert.True(result);
            Assert.IsType <DispatcherValueCollection.PropertyStorage>(dict._storage);
        }
        public void ContainsKey_PropertyStorage_False()
        {
            // Arrange
            var dict = new DispatcherValueCollection(new { key = "value" });

            // Act
            var result = dict.ContainsKey("other");

            // Assert
            Assert.False(result);
            Assert.IsType <DispatcherValueCollection.PropertyStorage>(dict._storage);
        }
        public void ContainsKey_EmptyStorage()
        {
            // Arrange
            var dict = new DispatcherValueCollection();

            // Act
            var result = dict.ContainsKey("key");

            // Assert
            Assert.False(result);
            Assert.IsType <DispatcherValueCollection.EmptyStorage>(dict._storage);
        }
        public void ContainsKey_ListStorage_True_CaseInsensitive()
        {
            // Arrange
            var dict = new DispatcherValueCollection()
            {
                { "key", "value" },
            };

            // Act
            var result = dict.ContainsKey("kEy");

            // Assert
            Assert.True(result);
            Assert.IsType <DispatcherValueCollection.ListStorage>(dict._storage);
        }
        public void ContainsKey_ListStorage_False()
        {
            // Arrange
            var dict = new DispatcherValueCollection()
            {
                { "key", "value" },
            };

            // Act
            var result = dict.ContainsKey("other");

            // Assert
            Assert.False(result);
            Assert.IsType <DispatcherValueCollection.ListStorage>(dict._storage);
        }
Exemple #7
0
        public void TryMatch_DoesNotSetOptionalParameter_EmptyString()
        {
            // Arrange
            var route = CreateMatcher("{controller?}");
            var url   = "";

            var values = new DispatcherValueCollection();

            // Act
            var match = route.TryMatch(url, values);

            // Assert
            Assert.True(match);
            Assert.Empty(values);
            Assert.False(values.ContainsKey("controller"));
        }
Exemple #8
0
        public void TryMatch_DoesNotSetOptionalParameter()
        {
            // Arrange
            var route = CreateMatcher("{controller}/{action?}");
            var url   = "/Home";

            var values = new DispatcherValueCollection();

            // Act
            var match = route.TryMatch(url, values);

            // Assert
            Assert.True(match);
            Assert.Single(values);
            Assert.Equal("Home", values["controller"]);
            Assert.False(values.ContainsKey("action"));
        }
Exemple #9
0
        public void TryMatch_MultipleOptionalParameters()
        {
            // Arrange
            var route = CreateMatcher("{controller}/{action?}/{id?}");
            var url   = "/Home/Index";

            var values = new DispatcherValueCollection();

            // Act
            var match = route.TryMatch(url, values);

            // Assert
            Assert.True(match);
            Assert.Equal(2, values.Count);
            Assert.Equal("Home", values["controller"]);
            Assert.Equal("Index", values["action"]);
            Assert.False(values.ContainsKey("id"));
        }
        public bool TryMatch(PathString path, DispatcherValueCollection values)
        {
            if (values == null)
            {
                throw new ArgumentNullException(nameof(values));
            }

            var i             = 0;
            var pathTokenizer = new PathTokenizer(path);

            // Perf: We do a traversal of the request-segments + route-segments twice.
            //
            // For most segment-types, we only really need to any work on one of the two passes.
            //
            // On the first pass, we're just looking to see if there's anything that would disqualify us from matching.
            // The most common case would be a literal segment that doesn't match.
            //
            // On the second pass, we're almost certainly going to match the URL, so go ahead and allocate the 'values'
            // and start capturing strings.
            foreach (var stringSegment in pathTokenizer)
            {
                if (stringSegment.Length == 0)
                {
                    return(false);
                }

                var pathSegment = i >= RoutePattern.PathSegments.Count ? null : RoutePattern.PathSegments[i];
                if (pathSegment == null && stringSegment.Length > 0)
                {
                    // If pathSegment is null, then we're out of route segments. All we can match is the empty
                    // string.
                    return(false);
                }
                else if (pathSegment.IsSimple && pathSegment.Parts[0] is RoutePatternParameter parameter && parameter.IsCatchAll)
                {
                    // Nothing to validate for a catch-all - it can match any string, including the empty string.
                    //
                    // Also, a catch-all has to be the last part, so we're done.
                    break;
                }
                if (!TryMatchLiterals(i++, stringSegment, pathSegment))
                {
                    return(false);
                }
            }

            for (; i < RoutePattern.PathSegments.Count; i++)
            {
                // We've matched the request path so far, but still have remaining route segments. These need
                // to be all single-part parameter segments with default values or else they won't match.
                var pathSegment = RoutePattern.PathSegments[i];
                Debug.Assert(pathSegment != null);

                if (!pathSegment.IsSimple)
                {
                    // If the segment is a complex segment, it MUST contain literals, and we've parsed the full
                    // path so far, so it can't match.
                    return(false);
                }

                var part = pathSegment.Parts[0];
                if (part.IsLiteral || part.IsSeparator)
                {
                    // If the segment is a simple literal - which need the URL to provide a value, so we don't match.
                    return(false);
                }

                var parameter = (RoutePatternParameter)part;
                if (parameter.IsCatchAll)
                {
                    // Nothing to validate for a catch-all - it can match any string, including the empty string.
                    //
                    // Also, a catch-all has to be the last part, so we're done.
                    break;
                }

                // If we get here, this is a simple segment with a parameter. We need it to be optional, or for the
                // defaults to have a value.
                if (!_hasDefaultValue[i] && !parameter.IsOptional)
                {
                    // There's no default for this (non-optional) parameter so it can't match.
                    return(false);
                }
            }

            // At this point we've very likely got a match, so start capturing values for real.
            i = 0;
            foreach (var requestSegment in pathTokenizer)
            {
                var pathSegment = RoutePattern.PathSegments[i++];
                if (SavePathSegmentsAsValues(i, values, requestSegment, pathSegment))
                {
                    break;
                }
                if (!pathSegment.IsSimple)
                {
                    if (!MatchComplexSegment(pathSegment, requestSegment.ToString(), Defaults, values))
                    {
                        return(false);
                    }
                }
            }

            for (; i < RoutePattern.PathSegments.Count; i++)
            {
                // We've matched the request path so far, but still have remaining route segments. We already know these
                // are simple parameters that either have a default, or don't need to produce a value.
                var pathSegment = RoutePattern.PathSegments[i];
                Debug.Assert(pathSegment != null);
                Debug.Assert(pathSegment.IsSimple);

                var part = pathSegment.Parts[0];
                Debug.Assert(part.IsParameter);

                // It's ok for a catch-all to produce a null value
                if (part is RoutePatternParameter parameter && (parameter.IsCatchAll || _hasDefaultValue[i]))
                {
                    // Don't replace an existing value with a null.
                    var defaultValue = _defaultValues[i];
                    if (defaultValue != null || !values.ContainsKey(parameter.Name))
                    {
                        values[parameter.Name] = defaultValue;
                    }
                }
            }

            // Copy all remaining default values to the route data
            foreach (var kvp in Defaults)
            {
                if (!values.ContainsKey(kvp.Key))
                {
                    values.Add(kvp.Key, kvp.Value);
                }
            }

            return(true);
        }