aspnetcore/src/Microsoft.AspNet.Mvc.Core/KnownRouteValueConstraint.cs

102 lines
3.9 KiB
C#

// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.AspNet.Http;
using Microsoft.AspNet.Mvc.Core;
using Microsoft.AspNet.Routing;
using Microsoft.Framework.DependencyInjection;
using Microsoft.Framework.Internal;
namespace Microsoft.AspNet.Mvc
{
public class KnownRouteValueConstraint : IRouteConstraint
{
private RouteValuesCollection _cachedValuesCollection;
public bool Match([NotNull] HttpContext httpContext,
[NotNull] IRouter route,
[NotNull] string routeKey,
[NotNull] IDictionary<string, object> values,
RouteDirection routeDirection)
{
object value;
if (values.TryGetValue(routeKey, out value))
{
var valueAsString = value as string;
if (valueAsString != null)
{
var allValues = GetAndCacheAllMatchingValues(routeKey, httpContext);
var match = allValues.Any(existingRouteValue =>
existingRouteValue.Equals(
valueAsString,
StringComparison.OrdinalIgnoreCase));
return match;
}
}
return false;
}
private string[] GetAndCacheAllMatchingValues(string routeKey, HttpContext httpContext)
{
var actionDescriptors = GetAndValidateActionDescriptorsCollection(httpContext);
var version = actionDescriptors.Version;
var valuesCollection = _cachedValuesCollection;
if (valuesCollection == null ||
version != valuesCollection.Version)
{
var routeValueCollection = actionDescriptors
.Items
.Select(ad => ad.RouteConstraints
.FirstOrDefault(
c => c.RouteKey == routeKey &&
c.KeyHandling == RouteKeyHandling.RequireKey))
.Where(rc => rc != null)
.Select(rc => rc.RouteValue)
.Distinct()
.ToArray();
valuesCollection = new RouteValuesCollection(version, routeValueCollection);
_cachedValuesCollection = valuesCollection;
}
return _cachedValuesCollection.Items;
}
private static ActionDescriptorsCollection GetAndValidateActionDescriptorsCollection(HttpContext httpContext)
{
var provider = httpContext.RequestServices
.GetRequiredService<IActionDescriptorsCollectionProvider>();
var descriptors = provider.ActionDescriptors;
if (descriptors == null)
{
throw new InvalidOperationException(
Resources.FormatPropertyOfTypeCannotBeNull("ActionDescriptors",
provider.GetType()));
}
return descriptors;
}
private class RouteValuesCollection
{
public RouteValuesCollection(int version, string[] items)
{
Version = version;
Items = items;
}
public int Version { get; private set; }
public string[] Items { get; private set; }
}
}
}