aspnetcore/src/Microsoft.AspNet.Routing/InlineRouteParameterParser.cs

92 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.Diagnostics;
using System.Text.RegularExpressions;
using Microsoft.AspNet.Routing.Template;
namespace Microsoft.AspNet.Routing
{
public static class InlineRouteParameterParser
{
// One or more characters, matches "id"
private const string ParameterNamePattern = @"(?<parameterName>.+?)";
// Zero or more inline constraints that start with a colon followed by zero or more characters
// Optionally the constraint can have arguments within parentheses
// - necessary to capture characters like ":" and "}"
// Matches ":int", ":length(2)", ":regex(\})", ":regex(:)" zero or more times
private const string ConstraintPattern = @"(:(?<constraint>.*?(\(.*?\))?))*";
// A default value with an equal sign followed by zero or more characters
// Matches "=", "=abc"
private const string DefaultValueParameter = @"(?<defaultValue>(=.*?))?";
private static readonly Regex _parameterRegex = new Regex(
"^" + ParameterNamePattern + ConstraintPattern + DefaultValueParameter + "$",
RegexOptions.CultureInvariant | RegexOptions.IgnoreCase);
public static TemplatePart ParseRouteParameter([NotNull] string routeParameter)
{
var isCatchAll = routeParameter.StartsWith("*", StringComparison.Ordinal);
var isOptional = routeParameter.EndsWith("?", StringComparison.Ordinal);
routeParameter = isCatchAll ? routeParameter.Substring(1) : routeParameter;
routeParameter = isOptional ? routeParameter.Substring(0, routeParameter.Length - 1) : routeParameter;
var parameterMatch = _parameterRegex.Match(routeParameter);
if (!parameterMatch.Success)
{
return TemplatePart.CreateParameter(name: string.Empty,
isCatchAll: isCatchAll,
isOptional: isOptional,
defaultValue: null,
inlineConstraints: null);
}
var parameterName = parameterMatch.Groups["parameterName"].Value;
// Add the default value if present
var defaultValueGroup = parameterMatch.Groups["defaultValue"];
var defaultValue = GetDefaultValue(defaultValueGroup);
// Register inline constraints if present
var constraintGroup = parameterMatch.Groups["constraint"];
var inlineConstraints = GetInlineConstraints(constraintGroup);
return TemplatePart.CreateParameter(parameterName,
isCatchAll,
isOptional,
defaultValue,
inlineConstraints);
}
private static string GetDefaultValue(Group defaultValueGroup)
{
if (defaultValueGroup.Success)
{
var defaultValueMatch = defaultValueGroup.Value;
// Strip out the equal sign at the beginning
Debug.Assert(defaultValueMatch.StartsWith("=", StringComparison.Ordinal));
return defaultValueMatch.Substring(1);
}
return null;
}
private static IEnumerable<InlineConstraint> GetInlineConstraints(Group constraintGroup)
{
var constraints = new List<InlineConstraint>();
foreach (Capture capture in constraintGroup.Captures)
{
constraints.Add(new InlineConstraint(capture.Value));
}
return constraints;
}
}
}