private static bool IsValidParameterName(TemplateParserContext context, string parameterName) { if (parameterName.Length == 0) { context.Error = String.Format(CultureInfo.CurrentCulture, Resources.TemplateRoute_InvalidParameterName, parameterName); return(false); } for (var i = 0; i < parameterName.Length; i++) { var c = parameterName[i]; if (c == Separator || c == OpenBrace || c == CloseBrace || c == QuestionMark || c == Asterisk) { context.Error = String.Format(CultureInfo.CurrentCulture, Resources.TemplateRoute_InvalidParameterName, parameterName); return(false); } } if (!context.ParameterNames.Add(parameterName)) { context.Error = String.Format(CultureInfo.CurrentCulture, Resources.TemplateRoute_RepeatedParameter, parameterName); return(false); } return(true); }
internal static string RunViewComponent(ControllerAction controllerAction, TemplateParserContext context) { ControllerClass controllerClass = controllerAction.ControllerClass; if (!controllerClass.IsActionMethod(controllerAction.ActionMethod)) return null; using (ViewComponent component = controllerClass.CreateViewComponent(context)) { try { controllerClass.SetupController(component, context); object returnValue = controllerClass.Run(component, "Run", context); if (returnValue is string) return (string) returnValue; return TemplateUtil.ExtractBody(component.View.Render()); } catch { component.SkipTearDown = true; throw; } } }
public static string RenderComponent(View view, string name, params object[] parameters) { TemplateParserContext newContext = new TemplateParserContext(view, view.ViewTemplate); for (int i = 0; i < parameters.Length ; i+=2) newContext.SetLocal((string) parameters[i], parameters[i+1], parameters[i+1] == null ? typeof(object) : parameters[i+1].GetType()); return WebAppHelper.RunViewComponent(WebAppHelper.GetViewComponent(name), newContext); }
public static RoutePattern Parse(string pattern) { if (pattern == null) { throw new ArgumentNullException(nameof(pattern)); } var trimmedPattern = TrimPrefix(pattern); var context = new TemplateParserContext(trimmedPattern); var segments = new List <RoutePatternPathSegment>(); while (context.MoveNext()) { var i = context.Index; if (context.Current == Separator) { // If we get here is means that there's a consecutive '/' character. // Templates don't start with a '/' and parsing a segment consumes the separator. throw new RoutePatternException(pattern, Resources.TemplateRoute_CannotHaveConsecutiveSeparators); } if (!ParseSegment(context, segments)) { throw new RoutePatternException(pattern, context.Error); } // A successful parse should always result in us being at the end or at a separator. Debug.Assert(context.AtEnd() || context.Current == Separator); if (context.Index <= i) { throw new InvalidProgramException("Infinite loop in the parser. This is a bug."); } } if (IsAllValid(context, segments)) { var builder = RoutePatternBuilder.Create(pattern); for (var i = 0; i < segments.Count; i++) { builder.PathSegments.Add(segments[i]); } return(builder.Build()); } else { throw new RoutePatternException(pattern, context.Error); } }
public void TestTemplateParserContext() { var tpc = new TemplateParserContext("abc", "def"); Assert.Equal("abc", tpc.ExpressionPrefix); Assert.Equal("def", tpc.ExpressionSuffix); Assert.True(tpc.IsTemplate); tpc = new TemplateParserContext(); Assert.Equal("#{", tpc.ExpressionPrefix); Assert.Equal("}", tpc.ExpressionSuffix); Assert.True(tpc.IsTemplate); }
private static bool IsValidLiteral(TemplateParserContext context, string literal) { Debug.Assert(context != null); Debug.Assert(literal != null); if (literal.IndexOf(QuestionMark) != -1) { context.Error = Resources.FormatTemplateRoute_InvalidLiteral(literal); return(false); } return(true); }
private static bool IsValidLiteral(TemplateParserContext context, string literal) { Contract.Assert(context != null); Contract.Assert(literal != null); if (literal.IndexOf(QuestionMark) != -1) { context.Error = String.Format(CultureInfo.CurrentCulture, Resources.TemplateRoute_InvalidLiteral, literal); return(false); } return(true); }
private static bool IsValidParameterName(TemplateParserContext context, string parameterName) { if (parameterName.Length == 0 || parameterName.IndexOfAny(InvalidParameterNameChars) >= 0) { context.Error = Resources.FormatTemplateRoute_InvalidParameterName(parameterName); return(false); } if (!context.ParameterNames.Add(parameterName)) { context.Error = Resources.FormatTemplateRoute_RepeatedParameter(parameterName); return(false); } return(true); }
public static RouteTemplate Parse(string routeTemplate) { if (routeTemplate == null) { routeTemplate = String.Empty; } if (IsInvalidRouteTemplate(routeTemplate)) { throw new ArgumentException(Resources.TemplateRoute_InvalidRouteTemplate, nameof(routeTemplate)); } var context = new TemplateParserContext(routeTemplate); var segments = new List<TemplateSegment>(); while (context.Next()) { if (context.Current == Separator) { // If we get here is means that there's a consecutive '/' character. // Templates don't start with a '/' and parsing a segment consumes the separator. throw new ArgumentException(Resources.TemplateRoute_CannotHaveConsecutiveSeparators, nameof(routeTemplate)); } else { if (!ParseSegment(context, segments)) { throw new ArgumentException(context.Error, nameof(routeTemplate)); } } } if (IsAllValid(context, segments)) { return new RouteTemplate(segments); } else { throw new ArgumentException(context.Error, nameof(routeTemplate)); } }
public static RouteTemplate Parse(string routeTemplate) { if (routeTemplate == null) { routeTemplate = String.Empty; } if (IsInvalidRouteTemplate(routeTemplate)) { throw new ArgumentException(Resources.TemplateRoute_InvalidRouteTemplate, "routeTemplate"); } var context = new TemplateParserContext(routeTemplate); var segments = new List <TemplateSegment>(); while (context.Next()) { if (context.Current == Separator) { // If we get here is means that there's a consecutive '/' character. // Templates don't start with a '/' and parsing a segment consumes the separator. throw new ArgumentException(Resources.TemplateRoute_CannotHaveConsecutiveSeparators, "routeTemplate"); } else { if (!ParseSegment(context, segments)) { throw new ArgumentException(context.Error, "routeTemplate"); } } } if (IsAllValid(context, segments)) { return(new RouteTemplate(segments)); } else { throw new ArgumentException(context.Error, "routeTemplate"); } }
private static bool IsSegmentValid(TemplateParserContext context, TemplateSegment segment) { // If a segment has multiple parts, then it can't contain a catch all. for (var i = 0; i < segment.Parts.Count; i++) { var part = segment.Parts[i]; if (part.IsParameter && part.IsCatchAll && segment.Parts.Count > 1) { context.Error = Resources.TemplateRoute_CannotHaveCatchAllInMultiSegment; return(false); } } // if a segment has multiple parts, then the parameters can't be optional for (var i = 0; i < segment.Parts.Count; i++) { var part = segment.Parts[i]; if (part.IsParameter && part.IsOptional && segment.Parts.Count > 1) { context.Error = Resources.TemplateRoute_CannotHaveOptionalParameterInMultiSegment; return(false); } } // A segment cannot containt two consecutive parameters var isLastSegmentParameter = false; for (var i = 0; i < segment.Parts.Count; i++) { var part = segment.Parts[i]; if (part.IsParameter && isLastSegmentParameter) { context.Error = Resources.TemplateRoute_CannotHaveConsecutiveParameters; return(false); } isLastSegmentParameter = part.IsParameter; } return(true); }
private static bool IsAllValid(TemplateParserContext context, List <TemplateSegment> segments) { // A catch-all parameter must be the last part of the last segment for (var i = 0; i < segments.Count; i++) { var segment = segments[i]; for (var j = 0; j < segment.Parts.Count; j++) { var part = segment.Parts[j]; if (part.IsParameter && part.IsCatchAll && (i != segments.Count - 1 || j != segment.Parts.Count - 1)) { context.Error = Resources.TemplateRoute_CatchAllMustBeLast; return(false); } } } return(true); }
private static bool IsAllValid(TemplateParserContext context, List<TemplateSegment> segments) { // A catch-all parameter must be the last part of the last segment for (var i = 0; i < segments.Count; i++) { var segment = segments[i]; for (var j = 0; j < segment.Parts.Count; j++) { var part = segment.Parts[j]; if (part.IsParameter && part.IsCatchAll && (i != segments.Count - 1 || j != segment.Parts.Count - 1)) { context.Error = Resources.TemplateRoute_CatchAllMustBeLast; return false; } } } return true; }
public static RouteTemplate Parse(string routeTemplate) { if (routeTemplate == null) { routeTemplate = String.Empty; } var trimmedRouteTemplate = TrimPrefix(routeTemplate); var context = new TemplateParserContext(trimmedRouteTemplate); var segments = new List <TemplateSegment>(); while (context.Next()) { if (context.Current == Separator) { // If we get here is means that there's a consecutive '/' character. // Templates don't start with a '/' and parsing a segment consumes the separator. throw new ArgumentException("invlaid segement", nameof(routeTemplate)); } else { if (!ParseSegment(context, segments)) { throw new ArgumentException(context.Error, nameof(routeTemplate)); } } } if (IsAllValid(context, segments)) { return(new RouteTemplate(routeTemplate, segments)); } else { throw new ArgumentException(context.Error, nameof(routeTemplate)); } }
private static bool ParseLiteral(TemplateParserContext context, TemplateSegment segment) { context.Mark(); string encoded; while (true) { if (context.Current == Separator) { encoded = context.Capture(); context.Back(); break; } else if (context.Current == OpenBrace) { if (!context.Next()) { // This is a dangling open-brace, which is not allowed context.Error = Resources.TemplateRoute_MismatchedParameter; return(false); } if (context.Current == OpenBrace) { // This is an 'escaped' brace in a literal, like "{{foo" - keep going. } else { // We've just seen the start of a parameter, so back up and return context.Back(); encoded = context.Capture(); context.Back(); break; } } else if (context.Current == CloseBrace) { if (!context.Next()) { // This is a dangling close-brace, which is not allowed context.Error = Resources.TemplateRoute_MismatchedParameter; return(false); } if (context.Current == CloseBrace) { // This is an 'escaped' brace in a literal, like "{{foo" - keep going. } else { // This is an unbalanced close-brace, which is not allowed context.Error = Resources.TemplateRoute_MismatchedParameter; return(false); } } if (!context.Next()) { encoded = context.Capture(); break; } } var decoded = encoded.Replace("}}", "}").Replace("{{", "}"); if (IsValidLiteral(context, decoded)) { segment.Parts.Add(TemplatePart.CreateLiteral(decoded)); return(true); } else { return(false); } }
internal static object[] CreateParameters(MethodInfo method, TemplateParserContext context) { ParameterInfo[] parameters = method.GetParameters(); object[] parameterValues = new object[parameters.Length]; int i = 0; foreach (ParameterInfo parameter in parameters) { ClientDataAttribute[] attributes = (ClientDataAttribute[])parameter.GetCustomAttributes(typeof(ClientDataAttribute), true); ClientDataAttribute mapAttribute; if (attributes.Length > 0) mapAttribute = attributes[0]; else mapAttribute = new GetOrPostAttribute(parameter.Name); object value; Type type; if (context != null && context.Get(parameter.Name, out value, out type)) parameterValues[i++] = TypeHelper.ConvertType(value, parameter.ParameterType); else parameterValues[i++] = GetClientValue(mapAttribute, parameter.ParameterType); //TODO: add IObjectBinder support for complex objects } return parameterValues; }
private static bool IsValidLiteral(TemplateParserContext context, string literal) { Debug.Assert(context != null); Debug.Assert(literal != null); if (literal.IndexOf(QuestionMark) != -1) { context.Error = String.Format(CultureInfo.CurrentCulture, Resources.TemplateRoute_InvalidLiteral, literal); return false; } return true; }
public object Run(Controller controller, string methodName, TemplateParserContext context) { ActionMethod actionMethod = _actionMethods[methodName]; if (actionMethod.DefaultLayoutName != null) controller.View.LayoutName = actionMethod.DefaultLayoutName; if (actionMethod.DefaultViewName != null) controller.View.ViewName = actionMethod.DefaultViewName; object returnValue = actionMethod.Invoke(controller, context); if (returnValue is StringBuilder) return returnValue.ToString(); return returnValue; }
private static bool ParseSegment(TemplateParserContext context, List <TemplateSegment> segments) { Debug.Assert(context != null); Debug.Assert(segments != null); var segment = new TemplateSegment(); while (true) { if (context.Current == OpenBrace) { if (!context.Next()) { // This is a dangling open-brace, which is not allowed context.Error = Resources.TemplateRoute_MismatchedParameter; return(false); } if (context.Current == OpenBrace) { // This is an 'escaped' brace in a literal, like "{{foo" context.Back(); if (!ParseLiteral(context, segment)) { return(false); } } else { // This is the inside of a parameter if (!ParseParameter(context, segment)) { return(false); } } } else if (context.Current == Separator) { // We've reached the end of the segment break; } else { if (!ParseLiteral(context, segment)) { return(false); } } if (!context.Next()) { // We've reached the end of the string break; } } if (IsSegmentValid(context, segment)) { segments.Add(segment); return(true); } else { return(false); } }
private static bool IsSegmentValid(TemplateParserContext 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.IsParameter && ((RoutePatternParameter)part).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.IsParameter && ((RoutePatternParameter)part).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 = string.Format( Resources.TemplateRoute_OptionalParameterCanbBePrecededByPeriod, RoutePatternPathSegment.DebuggerToString(parts), ((RoutePatternParameter)part).Name, parts[i - 1].DebuggerToString()); return(false); } else if (previousPart is RoutePatternLiteral 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 = string.Format( Resources.TemplateRoute_OptionalParameterCanbBePrecededByPeriod, RoutePatternPathSegment.DebuggerToString(parts), ((RoutePatternParameter)part).Name, parts[i - 1].DebuggerToString()); return(false); } parts[i - 1] = RoutePatternPart.CreateSeparatorFromText(previousPart.RawText, ((RoutePatternLiteral)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 = string.Format( Resources.TemplateRoute_OptionalParameterHasTobeTheLast, RoutePatternPathSegment.DebuggerToString(parts), ((RoutePatternParameter)part).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); }
public void OnStart(TemplateParserContext context) { }
public void OnLeftCurlyBrace(TemplateParserContext context, int pos) { }
internal void TearDownController(Controller controller, TemplateParserContext context) { try { foreach (MethodInfo method in _teardownMethods) method.Invoke(controller, WebAppHelper.CreateParameters(method, context)); } catch (TargetInvocationException ex) { throw ExceptionHelper.ResolveTargetInvocationException(ex); } }
internal void SetupController(Controller controller, TemplateParserContext context) { try { foreach (MethodInfo method in _setupMethods) method.Invoke(controller, WebAppHelper.CreateParameters(method, context)); } catch (TargetInvocationException ex) { throw ExceptionHelper.ResolveTargetInvocationException(ex); } RegisterAjaxMethods(controller); }
public void OnEnd(TemplateParserContext context) { }
private static bool ParseSegment(TemplateParserContext context, List <RoutePatternPathSegment> segments) { Debug.Assert(context != null); Debug.Assert(segments != null); var parts = new List <RoutePatternPart>(); while (true) { var i = context.Index; if (context.Current == OpenBrace) { if (!context.MoveNext()) { // This is a dangling open-brace, which is not allowed context.Error = Resources.TemplateRoute_MismatchedParameter; return(false); } if (context.Current == OpenBrace) { // This is an 'escaped' brace in a literal, like "{{foo" context.Back(); if (!ParseLiteral(context, parts)) { return(false); } } else { // This is a parameter context.Back(); if (!ParseParameter(context, parts)) { return(false); } } } else { if (!ParseLiteral(context, parts)) { return(false); } } if (context.Current == Separator || context.AtEnd()) { // We've reached the end of the segment break; } if (context.Index <= i) { throw new InvalidProgramException("Infinite loop in the parser. This is a bug."); } } if (IsSegmentValid(context, parts)) { segments.Add(new RoutePatternPathSegment(null, parts.ToArray())); return(true); } else { return(false); } }
private static bool IsSegmentValid(TemplateParserContext context, TemplateSegment segment) { // If a segment has multiple parts, then it can't contain a catch all. for (var i = 0; i < segment.Parts.Count; i++) { var part = segment.Parts[i]; if (part.IsParameter && part.IsCatchAll && segment.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 < segment.Parts.Count; i++) { var part = segment.Parts[i]; if (part.IsParameter && part.IsOptional && segment.Parts.Count > 1) { // This optional parameter is the last part in the segment if (i == segment.Parts.Count - 1) { Debug.Assert(segment.Parts[i - 1].IsLiteral); // the optional parameter is preceded by a period if (segment.Parts[i - 1].Text == PeriodString) { segment.Parts[i - 1].IsOptionalSeperator = true; } else { // The optional parameter is preceded by a literal other than period // Example of error message: // "In the complex segment {RouteValue}-{param?}, the optional parameter 'param'is preceded // by an invalid segment "-". Only valid literal to precede an optional parameter is a // period (.). context.Error = string.Format( Resources.TemplateRoute_OptionalParameterCanbBePrecededByPeriod, segment.DebuggerToString(), part.Name, segment.Parts[i - 1].Text); return false; } } 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 ')' var nextPart = segment.Parts[i + 1]; var invalidPartText = nextPart.IsParameter ? nextPart.Name : nextPart.Text; context.Error = string.Format( Resources.TemplateRoute_OptionalParameterHasTobeTheLast, segment.DebuggerToString(), segment.Parts[i].Name, invalidPartText ); return false; } } } // A segment cannot contain two consecutive parameters var isLastSegmentParameter = false; for (var i = 0; i < segment.Parts.Count; i++) { var part = segment.Parts[i]; if (part.IsParameter && isLastSegmentParameter) { context.Error = Resources.TemplateRoute_CannotHaveConsecutiveParameters; return false; } isLastSegmentParameter = part.IsParameter; } return true; }
internal ViewComponent CreateViewComponent(TemplateParserContext context) { ViewComponent controller = (ViewComponent) Activator.CreateInstance(_classType); controller.Initialize(this, context); return controller; }
public void OnRightCurlyBrace(TemplateParserContext context, int pos) { context.AddProp(pos); context.SetState(TemplateParserContext.Waiting); }
private static bool IsSegmentValid(TemplateParserContext context, TemplateSegment segment) { // If a segment has multiple parts, then it can't contain a catch all. for (var i = 0; i < segment.Parts.Count; i++) { var part = segment.Parts[i]; if (part.IsParameter && part.IsCatchAll && segment.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 < segment.Parts.Count; i++) { var part = segment.Parts[i]; if (part.IsParameter && part.IsOptional && segment.Parts.Count > 1) { // This is the last part if (i == segment.Parts.Count - 1) { Debug.Assert(segment.Parts[i - 1].IsLiteral); if (segment.Parts[i - 1].Text == PeriodString) { segment.Parts[i - 1].IsOptionalSeperator = true; } else { context.Error = Resources.TemplateRoute_CanHaveOnlyLastParameterOptional_IfFollowingOptionalSeperator; return(false); } } else { context.Error = Resources.TemplateRoute_CanHaveOnlyLastParameterOptional_IfFollowingOptionalSeperator; return(false); } } } // A segment cannot contain two consecutive parameters var isLastSegmentParameter = false; for (var i = 0; i < segment.Parts.Count; i++) { var part = segment.Parts[i]; if (part.IsParameter && isLastSegmentParameter) { context.Error = Resources.TemplateRoute_CannotHaveConsecutiveParameters; return(false); } isLastSegmentParameter = part.IsParameter; } return(true); }
public void OnEnd(TemplateParserContext context) { context.Finish(); context.SetState(TemplateParserContext.Finished); }
private static bool ParseParameter(TemplateParserContext context, TemplateSegment segment) { context.Mark(); while (true) { if (context.Current == OpenBrace) { // This is an open brace inside of a parameter, it has to be escaped if (context.Next()) { if (context.Current != OpenBrace) { // If we see something like "{p1:regex(^\d{3", we will come here. context.Error = Resources.TemplateRoute_UnescapedBrace; return(false); } } else { // This is a dangling open-brace, which is not allowed // Example: "{p1:regex(^\d{" context.Error = Resources.TemplateRoute_MismatchedParameter; return(false); } } else if (context.Current == CloseBrace) { // When we encounter Closed brace here, it either means end of the parameter or it is a closed // brace in the parameter, in that case it needs to be escaped. // Example: {p1:regex(([}}])\w+}. First pair is escaped one and last marks end of the parameter if (!context.Next()) { // This is the end of the string -and we have a valid parameter context.Back(); break; } if (context.Current == CloseBrace) { // This is an 'escaped' brace in a parameter name } else { // This is the end of the parameter context.Back(); break; } } if (!context.Next()) { // This is a dangling open-brace, which is not allowed context.Error = Resources.TemplateRoute_MismatchedParameter; return(false); } } var rawParameter = context.Capture(); var decoded = rawParameter.Replace("}}", "}").Replace("{{", "{"); // At this point, we need to parse the raw name for inline constraint, // default values and optional parameters. var templatePart = InlineRouteParameterParser.ParseRouteParameter(decoded); if (templatePart.IsCatchAll && templatePart.IsOptional) { context.Error = Resources.TemplateRoute_CatchAllCannotBeOptional; return(false); } if (templatePart.IsOptional && templatePart.DefaultValue != null) { // Cannot be optional and have a default value. // The only way to declare an optional parameter is to have a ? at the end, // hence we cannot have both default value and optional parameter within the template. // A workaround is to add it as a separate entry in the defaults argument. context.Error = Resources.TemplateRoute_OptionalCannotHaveDefaultValue; return(false); } var parameterName = templatePart.Name; if (IsValidParameterName(context, parameterName)) { segment.Parts.Add(templatePart); return(true); } else { return(false); } }
private static bool ParseParameter(TemplateParserContext context, TemplateSegment segment) { context.Mark(); while (true) { if (context.Current == OpenBrace) { // This is an open brace inside of a parameter, it has to be escaped if (context.Next()) { if (context.Current != OpenBrace) { // If we see something like "{p1:regex(^\d{3", we will come here. context.Error = Resources.TemplateRoute_UnescapedBrace; return false; } } else { // This is a dangling open-brace, which is not allowed // Example: "{p1:regex(^\d{" context.Error = Resources.TemplateRoute_MismatchedParameter; return false; } } else if (context.Current == CloseBrace) { // When we encounter Closed brace here, it either means end of the parameter or it is a closed // brace in the parameter, in that case it needs to be escaped. // Example: {p1:regex(([}}])\w+}. First pair is escaped one and last marks end of the parameter if (!context.Next()) { // This is the end of the string -and we have a valid parameter context.Back(); break; } if (context.Current == CloseBrace) { // This is an 'escaped' brace in a parameter name } else { // This is the end of the parameter context.Back(); break; } } if (!context.Next()) { // This is a dangling open-brace, which is not allowed context.Error = Resources.TemplateRoute_MismatchedParameter; return false; } } var rawParameter = context.Capture(); var decoded = rawParameter.Replace("}}", "}").Replace("{{", "{"); // At this point, we need to parse the raw name for inline constraint, // default values and optional parameters. var templatePart = InlineRouteParameterParser.ParseRouteParameter(decoded); if (templatePart.IsCatchAll && templatePart.IsOptional) { context.Error = Resources.TemplateRoute_CatchAllCannotBeOptional; return false; } if (templatePart.IsOptional && templatePart.DefaultValue != null) { // Cannot be optional and have a default value. // The only way to declare an optional parameter is to have a ? at the end, // hence we cannot have both default value and optional parameter within the template. // A workaround is to add it as a separate entry in the defaults argument. context.Error = Resources.TemplateRoute_OptionalCannotHaveDefaultValue; return false; } var parameterName = templatePart.Name; if (IsValidParameterName(context, parameterName)) { segment.Parts.Add(templatePart); return true; } else { return false; } }
private static bool IsSegmentValid(TemplateParserContext context, TemplateSegment segment) { // If a segment has multiple parts, then it can't contain a catch all. for (var i = 0; i < segment.Parts.Count; i++) { var part = segment.Parts[i]; if (part.IsParameter && part.IsCatchAll && segment.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 < segment.Parts.Count; i++) { var part = segment.Parts[i]; if (part.IsParameter && part.IsOptional && segment.Parts.Count > 1) { // This optional parameter is the last part in the segment if (i == segment.Parts.Count - 1) { if (!segment.Parts[i - 1].IsLiteral) { // The optional parameter is preceded by something that is not a literal. // 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 = string.Format( Resources.TemplateRoute_OptionalParameterCanbBePrecededByPeriod, segment.DebuggerToString(), part.Name, segment.Parts[i - 1].DebuggerToString()); return(false); } else if (segment.Parts[i - 1].Text != 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 = string.Format( Resources.TemplateRoute_OptionalParameterCanbBePrecededByPeriod, segment.DebuggerToString(), part.Name, segment.Parts[i - 1].Text); return(false); } segment.Parts[i - 1].IsOptionalSeperator = true; } 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 ')' var nextPart = segment.Parts[i + 1]; var invalidPartText = nextPart.IsParameter ? nextPart.Name : nextPart.Text; context.Error = string.Format( Resources.TemplateRoute_OptionalParameterHasTobeTheLast, segment.DebuggerToString(), segment.Parts[i].Name, invalidPartText); return(false); } } } // A segment cannot contain two consecutive parameters var isLastSegmentParameter = false; for (var i = 0; i < segment.Parts.Count; i++) { var part = segment.Parts[i]; if (part.IsParameter && isLastSegmentParameter) { context.Error = Resources.TemplateRoute_CannotHaveConsecutiveParameters; return(false); } isLastSegmentParameter = part.IsParameter; } return(true); }
private static bool ParseLiteral(TemplateParserContext context, TemplateSegment segment) { context.Mark(); string encoded; while (true) { if (context.Current == Separator) { encoded = context.Capture(); context.Back(); break; } else if (context.Current == OpenBrace) { if (!context.Next()) { // This is a dangling open-brace, which is not allowed context.Error = Resources.TemplateRoute_MismatchedParameter; return false; } if (context.Current == OpenBrace) { // This is an 'escaped' brace in a literal, like "{{foo" - keep going. } else { // We've just seen the start of a parameter, so back up and return context.Back(); encoded = context.Capture(); context.Back(); break; } } else if (context.Current == CloseBrace) { if (!context.Next()) { // This is a dangling close-brace, which is not allowed context.Error = Resources.TemplateRoute_MismatchedParameter; return false; } if (context.Current == CloseBrace) { // This is an 'escaped' brace in a literal, like "{{foo" - keep going. } else { // This is an unbalanced close-brace, which is not allowed context.Error = Resources.TemplateRoute_MismatchedParameter; return false; } } if (!context.Next()) { encoded = context.Capture(); break; } } var decoded = encoded.Replace("}}", "}").Replace("{{", "{"); if (IsValidLiteral(context, decoded)) { segment.Parts.Add(TemplatePart.CreateLiteral(decoded)); return true; } else { return false; } }
public object Invoke(object target, TemplateParserContext parserContext) { return Invoke(target, WebAppHelper.CreateParameters(_methodInfo,parserContext)); }
private static bool IsValidParameterName(TemplateParserContext context, string parameterName) { if (parameterName.Length == 0) { context.Error = String.Format(CultureInfo.CurrentCulture, Resources.TemplateRoute_InvalidParameterName, parameterName); return false; } for (var i = 0; i < parameterName.Length; i++) { var c = parameterName[i]; if (c == Separator || c == OpenBrace || c == CloseBrace || c == QuestionMark || c == Asterisk) { context.Error = String.Format(CultureInfo.CurrentCulture, Resources.TemplateRoute_InvalidParameterName, parameterName); return false; } } if (!context.ParameterNames.Add(parameterName)) { context.Error = String.Format(CultureInfo.CurrentCulture, Resources.TemplateRoute_RepeatedParameter, parameterName); return false; } return true; }
private static bool ParseParameter(TemplateParserContext context, TemplateSegment segment) { context.Mark(); while (true) { if (context.Current == Separator) { // This is a dangling open-brace, which is not allowed context.Error = Resources.TemplateRoute_MismatchedParameter; return(false); } else if (context.Current == OpenBrace) { // If we see a '{' while parsing a parameter name it's invalid. We'll just accept it for now // and let the validation code for the name find it. } else if (context.Current == CloseBrace) { if (!context.Next()) { // This is the end of the string - and we have a valid parameter context.Back(); break; } if (context.Current == CloseBrace) { // This is an 'escaped' brace in a parameter name, which is not allowed. // We'll just accept it for now and let the validation code for the name find it. } else { // This is the end of the parameter context.Back(); break; } } if (!context.Next()) { // This is a dangling open-brace, which is not allowed context.Error = Resources.TemplateRoute_MismatchedParameter; return(false); } } var rawParameter = context.Capture(); // At this point, we need to parse the raw name for inline constraint, // default values and optional parameters. var templatePart = InlineRouteParameterParser.ParseRouteParameter(rawParameter); if (templatePart.IsCatchAll && templatePart.IsOptional) { context.Error = Resources.TemplateRoute_CatchAllCannotBeOptional; return(false); } if (templatePart.IsOptional && templatePart.DefaultValue != null) { // Cannot be optional and have a default value. // The only way to declare an optional parameter is to have a ? at the end, // hence we cannot have both default value and optional parameter within the template. // A workaround is to add it as a separate entry in the defaults argument. context.Error = Resources.TemplateRoute_OptionalCannotHaveDefaultValue; return(false); } var parameterName = templatePart.Name; if (IsValidParameterName(context, parameterName)) { segment.Parts.Add(templatePart); return(true); } else { return(false); } }
private static bool ParseSegment(TemplateParserContext context, List<TemplateSegment> segments) { Debug.Assert(context != null); Debug.Assert(segments != null); var segment = new TemplateSegment(); while (true) { if (context.Current == OpenBrace) { if (!context.Next()) { // This is a dangling open-brace, which is not allowed context.Error = Resources.TemplateRoute_MismatchedParameter; return false; } if (context.Current == OpenBrace) { // This is an 'escaped' brace in a literal, like "{{foo" context.Back(); if (!ParseLiteral(context, segment)) { return false; } } else { // This is the inside of a parameter if (!ParseParameter(context, segment)) { return false; } } } else if (context.Current == Separator) { // We've reached the end of the segment break; } else { if (!ParseLiteral(context, segment)) { return false; } } if (!context.Next()) { // We've reached the end of the string break; } } if (IsSegmentValid(context, segment)) { segments.Add(segment); return true; } else { return false; } }
public void OnLeftCurlyBrace(TemplateParserContext context, int pos) { context.AddConst(pos); context.SetState(TemplateParserContext.Prop); }