C# 使用花括号时,管线变换不起作用

C# 使用花括号时,管线变换不起作用,c#,asp.net-core-mvc,.net-5,C#,Asp.net Core Mvc,.net 5,我有以下代码 Startup.cs public void配置服务(IServiceCollection服务) { services.AddMvc(选项=> { options.Conventions.Add(新的RouteTokenTransformerConvention(新的SlugifyParameterTransformer()); }); } 其中slagifyParameterTransformer实现IOutboundParameterTransformer并将URL转换为SE

我有以下代码

Startup.cs

public void配置服务(IServiceCollection服务)
{
services.AddMvc(选项=>
{
options.Conventions.Add(新的RouteTokenTransformerConvention(新的SlugifyParameterTransformer());
});
}
其中
slagifyParameterTransformer
实现
IOutboundParameterTransformer
并将URL转换为SEO友好的URL

在我的
家庭控制器中
,我有这些

public IActionResult Index()
{
返回视图();
}
[路由(“{controller}/{action}”)]//路由转换仅在使用方括号时有效。
公共IActionResult SomeTestPage()
{
返回视图();
}
在我的
Index.cshtml
中,我有这些

@addTagHelper*,Microsoft.AspNetCore.Mvc.TagHelpers
一些测试页面
在构建和运行网站时,
SomeTestPage
的URL是
localhost\Home\SomeTestPage
,而不是通过
slagifyParameterTransformer
转换。但是,在我将
RouteAttribute
装饰
SomeTestPage
操作方法中的花括号替换为方括号后,URL被正确地转换为
localhost\home\SomeTestPage

使用属性路由定义路由模板时,花括号和方括号之间有什么区别

使用属性路由定义路由模板时,花括号和方括号之间有什么区别

在中,我们可以发现它通常使用带有方括号的
[controller]
[action]
[area]
作为控制器名称、操作名称和区域名称,并使用
{id}
等作为属性路由中的其他通用路由参数

此外,正如中提到的@serpent5,当与属性路由一起使用时,
IOutboundParameterTransformer
似乎只处理
[
]

使用提供的值和路由令牌转换器替换模板中的令牌

//
///使用提供的值和路由令牌转换器替换模板中的令牌。
/// 
///模板。
///要使用的标记值。
///路由令牌转换器。
///包含替换值的新字符串。
公共静态字符串替换令牌(字符串模板、IDictionary值、IOOutboundParameterTransformer routeTokenTransformer)
{
var builder=新的StringBuilder();
var state=TemplateParserState.Plaintext;
int?tokenStart=null;
var范围=0;
//我们将使用'null'额外运行一次循环,以检测字符串的结尾。

对于(var i=0;i您的项目的.NET Core版本是哪个?@FeiHan我使用ASP.NET Core 5.0感谢您将问题提交给github。我碰巧使用了花括号作为路由模板,因为我在属性路由之前在学习路径上偶然发现了传统路由。传统路由似乎不支持方括号,所以我坚持使用c我想知道ASP.NET核心团队是否可以使其更加一致?Hi@NoctisTong,我们可以发现Rick确实帮助我报告的github问题添加了
文档增强
标记,我们可以跟踪问题并检查文档团队是否会帮助更新文档。Hi@NoctisTong,关于此官方文档中的“路由模板[controller]、[action]、[area]中的令牌替换”已更新:为方便起见,属性路由通过将令牌括在方括号中来支持令牌替换(
[
]
)。
/// <summary>
/// Replaces the tokens in the template with the provided values and route token transformer.
/// </summary>
/// <param name="template">The template.</param>
/// <param name="values">The token values to use.</param>
/// <param name="routeTokenTransformer">The route token transformer.</param>
/// <returns>A new string with the replaced values.</returns>
public static string ReplaceTokens(string template, IDictionary<string, string> values, IOutboundParameterTransformer routeTokenTransformer)
{
    var builder = new StringBuilder();
    var state = TemplateParserState.Plaintext;

    int? tokenStart = null;
    var scope = 0;

    // 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 == '[')
                {
                    scope++;
                    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 == ']')
                {
                    --scope;
                    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 == ']' && scope == 0)
                {
                    // 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;
                    }

                    scope = 0;
                    tokenStart = null;
                    break;
                }
        }
    }

    return builder.ToString();
}