/// <summary> /// Creates a new instance of <see cref="RouteTokenTransformerConvention"/> with the specified <see cref="IOutboundParameterTransformer"/>. /// </summary> /// <param name="parameterTransformer">The <see cref="IOutboundParameterTransformer"/> to use with attribute routing token replacement.</param> public RouteTokenTransformerConvention(IOutboundParameterTransformer parameterTransformer) { if (parameterTransformer == null) { throw new ArgumentNullException(nameof(parameterTransformer)); } _parameterTransformer = parameterTransformer; }
public ControllerRouteTokenTransformerConvention(Type controllerType, IOutboundParameterTransformer parameterTransformer) { if (parameterTransformer == null) { throw new ArgumentNullException(nameof(parameterTransformer)); } _controllerType = controllerType; _parameterTransformer = parameterTransformer; }
public CustomPageRouteTransformerConvention(IOutboundParameterTransformer parameterTransformer) : base(parameterTransformer) { }
public static string ReplaceTokens(string template, IDictionary <string, string> values, IOutboundParameterTransformer routeTokenTransformer) { var builder = new StringBuilder(); var state = TemplateParserState.Plaintext; int?tokenStart = null; // We'll run the loop one extra time with 'null' to detect the end of the string. for (var i = 0; i <= template.Length; i++) { var c = i < template.Length ? (char?)template[i] : null; switch (state) { case TemplateParserState.Plaintext: if (c == '[') { state = TemplateParserState.SeenLeft; break; } else if (c == ']') { state = TemplateParserState.SeenRight; break; } else if (c == null) { // We're at the end of the string, nothing left to do. break; } else { builder.Append(c); break; } case TemplateParserState.SeenLeft: if (c == '[') { // This is an escaped left-bracket builder.Append(c); state = TemplateParserState.Plaintext; break; } else if (c == ']') { // This is zero-width parameter - not allowed. var message = Resources.FormatAttributeRoute_TokenReplacement_InvalidSyntax( template, Resources.AttributeRoute_TokenReplacement_EmptyTokenNotAllowed); throw new InvalidOperationException(message); } else if (c == null) { // This is a left-bracket at the end of the string. var message = Resources.FormatAttributeRoute_TokenReplacement_InvalidSyntax( template, Resources.AttributeRoute_TokenReplacement_UnclosedToken); throw new InvalidOperationException(message); } else { tokenStart = i; state = TemplateParserState.InsideToken; break; } case TemplateParserState.SeenRight: if (c == ']') { // This is an escaped right-bracket builder.Append(c); state = TemplateParserState.Plaintext; break; } else if (c == null) { // This is an imbalanced right-bracket at the end of the string. var message = Resources.FormatAttributeRoute_TokenReplacement_InvalidSyntax( template, Resources.AttributeRoute_TokenReplacement_ImbalancedSquareBrackets); throw new InvalidOperationException(message); } else { // This is an imbalanced right-bracket. var message = Resources.FormatAttributeRoute_TokenReplacement_InvalidSyntax( template, Resources.AttributeRoute_TokenReplacement_ImbalancedSquareBrackets); throw new InvalidOperationException(message); } case TemplateParserState.InsideToken: if (c == '[') { state = TemplateParserState.InsideToken | TemplateParserState.SeenLeft; break; } else if (c == ']') { state = TemplateParserState.InsideToken | TemplateParserState.SeenRight; break; } else if (c == null) { // This is an unclosed replacement token var message = Resources.FormatAttributeRoute_TokenReplacement_InvalidSyntax( template, Resources.AttributeRoute_TokenReplacement_UnclosedToken); throw new InvalidOperationException(message); } else { // This is a just part of the parameter break; } case TemplateParserState.InsideToken | TemplateParserState.SeenLeft: if (c == '[') { // This is an escaped left-bracket state = TemplateParserState.InsideToken; break; } else { // Unescaped left-bracket is not allowed inside a token. var message = Resources.FormatAttributeRoute_TokenReplacement_InvalidSyntax( template, Resources.AttributeRoute_TokenReplacement_UnescapedBraceInToken); throw new InvalidOperationException(message); } case TemplateParserState.InsideToken | TemplateParserState.SeenRight: if (c == ']') { // This is an escaped right-bracket state = TemplateParserState.InsideToken; break; } else { // This is the end of a replacement token. var token = template .Substring(tokenStart.Value, i - tokenStart.Value - 1) .Replace("[[", "[") .Replace("]]", "]"); if (!values.TryGetValue(token, out var value)) { // Value not found var message = Resources.FormatAttributeRoute_TokenReplacement_ReplacementValueNotFound( template, token, string.Join(", ", values.Keys.OrderBy(k => k, StringComparer.OrdinalIgnoreCase))); throw new InvalidOperationException(message); } if (routeTokenTransformer != null) { value = routeTokenTransformer.TransformOutbound(value); } builder.Append(value); if (c == '[') { state = TemplateParserState.SeenLeft; } else if (c == ']') { state = TemplateParserState.SeenRight; } else if (c == null) { state = TemplateParserState.Plaintext; } else { builder.Append(c); state = TemplateParserState.Plaintext; } tokenStart = null; break; } } } return(builder.ToString()); }