示例#1
0
        private static bool IsSegmentValid(Context context, List <RoutePatternPart> parts)
        {
            // If a segment has multiple parts, then it can't contain a catch all.
            for (var i = 0; i < parts.Count; i++)
            {
                var part = parts[i];
                if (part is RoutePatternParameterPart parameter && parameter.IsCatchAll && parts.Count > 1)
                {
                    context.Error = Resources.TemplateRoute_CannotHaveCatchAllInMultiSegment;
                    return(false);
                }
            }

            // if a segment has multiple parts, then only the last one parameter can be optional
            // if it is following a optional seperator.
            for (var i = 0; i < parts.Count; i++)
            {
                var part = parts[i];

                if (part is RoutePatternParameterPart parameter && parameter.IsOptional && parts.Count > 1)
                {
                    // This optional parameter is the last part in the segment
                    if (i == parts.Count - 1)
                    {
                        var previousPart = parts[i - 1];

                        if (!previousPart.IsLiteral && !previousPart.IsSeparator)
                        {
                            // The optional parameter is preceded by something that is not a literal or separator
                            // Example of error message:
                            // "In the segment '{RouteValue}{param?}', the optional parameter 'param' is preceded
                            // by an invalid segment '{RouteValue}'. Only a period (.) can precede an optional parameter.
                            context.Error = Resources.FormatTemplateRoute_OptionalParameterCanbBePrecededByPeriod(
                                RoutePatternPathSegment.DebuggerToString(parts),
                                parameter.Name,
                                parts[i - 1].DebuggerToString());

                            return(false);
                        }
                        else if (previousPart is RoutePatternLiteralPart literal && literal.Content != PeriodString)
                        {
                            // The optional parameter is preceded by a literal other than period.
                            // Example of error message:
                            // "In the segment '{RouteValue}-{param?}', the optional parameter 'param' is preceded
                            // by an invalid segment '-'. Only a period (.) can precede an optional parameter.
                            context.Error = Resources.FormatTemplateRoute_OptionalParameterCanbBePrecededByPeriod(
                                RoutePatternPathSegment.DebuggerToString(parts),
                                parameter.Name,
                                parts[i - 1].DebuggerToString());

                            return(false);
                        }

                        parts[i - 1] = RoutePatternFactory.SeparatorPart(((RoutePatternLiteralPart)previousPart).Content);
                    }
                    else
                    {
                        // This optional parameter is not the last one in the segment
                        // Example:
                        // An optional parameter must be at the end of the segment. In the segment '{RouteValue?})',
                        // optional parameter 'RouteValue' is followed by ')'
                        context.Error = Resources.FormatTemplateRoute_OptionalParameterHasTobeTheLast(
                            RoutePatternPathSegment.DebuggerToString(parts),
                            parameter.Name,
                            parts[i + 1].DebuggerToString());

                        return(false);
                    }
                }
            }

            // A segment cannot contain two consecutive parameters
            var isLastSegmentParameter = false;

            for (var i = 0; i < parts.Count; i++)
            {
                var part = parts[i];
                if (part.IsParameter && isLastSegmentParameter)
                {
                    context.Error = Resources.TemplateRoute_CannotHaveConsecutiveParameters;
                    return(false);
                }

                isLastSegmentParameter = part.IsParameter;
            }

            return(true);
        }