Неудачный маршрут ASP.NET MVC. Это ошибка или угловой случай? - PullRequest
13 голосов
/ 12 марта 2011

У меня есть приложение ASP.NET MVC 3, в котором пользователи могут публиковать предложения в духе "бла бла , было бы лучше, если бы 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.

Я попробовал Отладчик маршрутизации Фила Хаака и подтвердил, что маршрут на самом деле будет работать до suggestion/84/this-site/would-be-better-if-would-be-better-if-, поэтому второй вариант "будет лучше, если" действительно будет принят; добавление чего-либо после этого фактически приведет к тому, что URL не будет совпадать ни с одним маршрутом (спасибо Омару - см. комментарии- за помощь) .


Пожалуйста, имейте в виду, что Я действительно не хочу менять определение маршрута , так как я думаю, что это так хорошо, как я могу управлять в этом случае, с точки зрения SEO.

Итак, Почему , имеющий текст, равный фиксированной части маршрута, не позволяет ссылке соответствовать маршруту? почему нарушает маршрут?

Меня на самом деле больше интересует почему , так как я верю, что понимание причины приведет к решению или, по крайней мере, правильному пониманию довольно интересной проблемы.

Ответы [ 2 ]

5 голосов
/ 12 марта 2011

Я не уверен, почему он так себя ведет, но вы можете использовать что-то вроде этого:

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-") }));
2 голосов
/ 19 сентября 2011

Это похоже на обман Маршрутизация ASP.NET: буквенный подсегмент между токенами и значения маршрута с символом из буквального подсегмента , что является гораздо более простой версией ошибки. Я бы рекомендовал закрыть этот в пользу этого.

Я ответил на этот вопрос.

...