【问题标题】:Failing ASP.NET MVC route. Is this a bug or corner case?ASP.NET MVC 路由失败。这是错误还是极端情况?
【发布时间】:2011-03-11 22:26:04
【问题描述】:

我有一个 ASP.NET MVC 3 应用程序,用户可以在其中发布“bla bla 如果 yada yada yada 会更好”的建议。 对于建议详细信息页面,我定义了一个不错的 SEO 友好 路线,如下所示:

routes.MapRoute(null, "suggestion/{id}/{it}/would-be-better-if-{if}", 
    new { controller = "suggestion", action = "details" });

如您所见,我希望修复“如果”部分会更好。

这条路线非常适合任何旧的建议,并生成像suggestion/5/this-site/would-be-better-if-it-had-a-iphone-application 这样的链接,点击链接实际上会请求相应的详细信息页面。

具有讽刺意味的是,我的一个朋友恰好是一名测试人员,他无意中发布了一条实际上打破路线的建议:“如果'如果'总是对齐会更好,这个网站会更好在中间”。
为此建议生成的链接是 /suggestion/84/this-site/would-be-better-if-would-be-better-if-was-always-alligned-in-the-middle.

我已经尝试过Phil Haack's Routing Debugger 并确认该路线实际上会一直工作到suggestion/84/this-site/would-be-better-if-would-be-better-if-,所以第二个“如果会更好”实际上被接受了;在此之后添加任何内容实际上会导致 url 不匹配任何路由 (感谢 Omar -see cmets- 的帮助)


请记住,我真的不想更改路由定义,因为我认为它在这种情况下已经尽我所能,就 SEO 而言。

那么,为什么文本等于路由的固定部分会阻止链接匹配路由? 为什么路线中断了?

我实际上对为什么更感兴趣,因为我相信理解为什么会导致解决方案,或者至少是对一个相当有趣的问题的正确理解。

【问题讨论】:

  • 这很有趣。不知道为什么会这样,但如果您想要临时修复,请将-{if} 替换为/{if}。我猜 ASP.NET MVC 对待 / 与其他字符不同。
  • 一些测试表明路由suggestion/84/this-site/would-be-better-if-would-be-better-if-有效;只有在最后一个 - 之后它有任何东西之后才会中断。
  • @Omar - 我真的不想更改路线,尽管您提出的解决方法是完全可以接受的。关于您的第二条评论,谢谢,我完全错过了那条评论……如果您问我,这会让您更加好奇。
  • 我认为这是一个错误,我遇到了类似的问题:stackoverflow.com/questions/4318373/…
  • 我真的不知道 double would-be-better-if 是什么意思。但老实说,您需要使用自定义路线,例如 @Lukáš 或此处 stackoverflow.com/questions/1107507/…

标签: asp.net-mvc asp.net-mvc-3 routes asp.net-mvc-routing system.web.routing


【解决方案1】:

我不确定它为什么会这样,但你可以使用这样的东西:

public interface IRouteRule
{
    object ProcessIncoming(object value);
    object ProcessOutgoing(object value);
}

public class StartsWithRouteRule : IRouteRule
{
    public StartsWithRouteRule(string value)
    {
        Value = value;
    }

    public string Value { get; protected set; }

    public object ProcessIncoming(object value)
    {
        var result = value as string;
        if (result == null)
            return null;

        if (!result.StartsWith(Value))
            return null;

        return result.Substring(Value.Length);
    }

    public object ProcessOutgoing(object value)
    {
        var result = value as string;
        if (result == null)
            return null;

        return Value + result;
    }
}

public class ComplexRoute : Route
{
    public ComplexRoute(string url, object defaults, object rules)
        : this(url, new RouteValueDictionary(defaults), rules)
    { }
    public ComplexRoute(string url, RouteValueDictionary defaults, object rules)
        : base(url, defaults, new MvcRouteHandler())
    {
        Rules = new Dictionary<string, IRouteRule>();
        foreach (var pair in new RouteValueDictionary(rules))
            Rules.Add(pair.Key, (IRouteRule)pair.Value);
    }

    public Dictionary<string, IRouteRule> Rules { get; protected set; }

    public override RouteData GetRouteData(HttpContextBase httpContext)
    {
        var result = base.GetRouteData(httpContext);

        if (result == null)
            return null;

        foreach (var pair in Rules)
        {
            var currentValue = result.Values[pair.Key];
            if (currentValue == null)
                return null;

            var value = pair.Value.ProcessIncoming(currentValue);
            if (value == null)
                return null;

            result.Values[pair.Key] = value;
        }

        return result;
    }

    public override VirtualPathData GetVirtualPath(RequestContext requestContext, RouteValueDictionary values)
    {
        values = new RouteValueDictionary(values);

        foreach (var pair in Rules)
        {
            var currentValue = values[pair.Key];
            if (currentValue == null)
                return null;

            var value = pair.Value.ProcessOutgoing(currentValue);
            if (value == null)
                return null;

            values[pair.Key] = value;
        }

        return base.GetVirtualPath(requestContext, values);
    }
}

用法:

routes.Add(new ComplexRoute(
    "suggestion/{id}/{it}/{if}",
    new { controller = "suggestion", action = "details" },
    new { @if = new StartsWithRouteRule("would-be-better-if-") }));

【讨论】:

  • áš - 这可能有效(尚未尝试过),但我实际上对 为什么 路线中断非常感兴趣。
  • 我倾向于同意它中断的原因是它是一个错误。 MVC 团队中的任何人都运行过这个吗?
  • @Matt - 实际上我没有,但我想我会马上去做。感谢您的提示。
【解决方案2】:

这看起来像是 ASP.NET routing: Literal sub-segment between tokens, and route values with a character from the literal sub-segment 的欺骗,这是一个更简单的错误版本。我建议关闭这个以支持那个。

我回答了这个问题。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-07-30
    • 2016-07-30
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多