Почему этот маршрут не совпадает - PullRequest
5 голосов
/ 03 января 2012

У меня проблемы с поиском подходящих маршрутов.

Я использую int в кодировке base-32 в качестве коротких ссылок на слайд-шоу в веб-приложении. Есть 5 разных версий каждого слайд-шоу, и я использую начальное письмо, чтобы различать каждую версию.

Маршруты всегда совпадают, за исключением случаев, когда первый символ в base-32 в кодировке int совпадает с символом, обозначающим версию слайд-шоу. Эта аномалия существует для всех 5 букв префикса: n, f, c, x и h.

Что из-за первых двух одинаковых символов эти маршруты не совпадают? Я затрудняюсь понять, что здесь происходит (когда маршруты не совпадают, они просто переходят к значениям по умолчанию).

Маршрутные совпадения (/na0): route for na0

Маршрут не соответствует (/nn0): route for nn0

Маршрутные совпадения (/nfg): route for nfg

Маршрут не соответствует (/ffg): route for ffg

Я ошеломлен. Вот код маршрутизации, если он не понятен в таблицах RouteDebug на скриншотах:

        routes.MapRoute(
            "NonBrandedSlideshow",
            "n{id}",
            MVC.Slideshow.NonBranded(), null,
            new { id = Settings.Base32Regex }
        );

        routes.MapRoute(
            "FullSlideshow",
            "f{id}",
            MVC.Slideshow.Full(), null,
            new { id = Settings.Base32Regex }
        );

        routes.MapRoute(
            "CompactSlideshow",
            "c{id}",
            MVC.Slideshow.Compact(), null,
            new { id = Settings.Base32Regex }
        );

        routes.MapRoute(
            "FlexibleSlideshow",
            "x{id}",
            MVC.Slideshow.Flexible(), null,
            new { id = Settings.Base32Regex }
        );

        routes.MapRoute(
            "Html5Slideshow",
            "h{id}",
            MVC.Slideshow.NonBrandedHtml5(), null,
            new { id = Settings.Base32Regex }
        );

Здесь следует отметить, что я использую T4MVC (см. Раздел 2.2.5), и эти MapRoute методы являются расширениями, добавленными T4MVC. Методы MapRoute, которые я использую, эквивалентны стандартным методам, и я попытался использовать метод не-T4MVC MapRoute с тем же результатом:

        routes.MapRoute(
            "Html5Slideshow",
            "h{id}",
            new { controller = "Slideshow", action = "NonBrandedHtml5" },
            new { id = Settings.Base32Regex }
        );

Вот Base32Regex, хотя я пробовал его с этим ограничением и без него (используемая реализация Base32 предполагает, что I и O равны 1 и 0, например).

public static partial class Settings
{
    public static string Base32Regex
    {
        get { return @"[0-9ABCDEFGHJKMNPQRSTVWXYZ]+"; }
    }
}

Ответы [ 5 ]

3 голосов
/ 07 января 2012

Ну, я такой же ошеломленный. Я выполнил несколько других тестов, и, насколько я вижу, это должно быть некоторой ошибкой в ​​способе проверки маршрутов, когда константа перед параметром маршрута имеет такой же повторяющийся символ. Некоторые другие ошеломляющие примеры:

"nn{id}"
route matches (/nna0)
route doesn't match (/nnn0)

"nnn{id}"
route matches (/nnna0)
route doesn't match (/nnnn0)

как только константа не повторяет один и тот же символ, все хорошо

"mn{id}"
route matches (/mna0)
route matches (/mnn0)
route matches (/mnmn)

Это может быть не совсем то, что вы ищете. Но, учитывая странность ситуации, это было единственное, что я мог придумать. Добавьте константу в ограничение и удалите ее из URL. Затем в вашем контроллере (эта часть мне не понравилась) вам нужно будет удалить эту константу из параметра id. Надеюсь, это сработает, или, по крайней мере, поможет найти другое решение.

routes.MapRoute(
    "NonBrandedSlideshow",
    "{id}",
    MVC.Slideshow.NonBranded(), null,
    new { id = "n"+Settings.Base32Regex }
);

UPDATE:

Я думаю, это известная проблема , спасибо @ max-toro

3 голосов
/ 07 января 2012

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

2 голосов
/ 03 января 2012

У меня не было большого успеха в получении маршрутов для сопоставления с префиксом константы к параметру маршрута, например "const{param}".Вы пытались использовать свой префикс в качестве полного сегмента маршрута, например "const/{param}"?Будет ли это соответствовать вашим требованиям?

routes.MapRoute(

    "NonBrandedSlideshow",
    "n/{id}",
    MVC.Slideshow.NonBranded(), null,
    new { id = Settings.Base32Regex }
);

routes.MapRoute(
    "FullSlideshow",
    "f/{id}",
    MVC.Slideshow.Full(), null,
    new { id = Settings.Base32Regex }
);

... и т. Д.

Обновление после комментария № 1

Понятно.Единственное, что я могу попробовать, это сделать параметр id параметром catchall.Посмотрите, работает ли это:

routes.MapRoute(

    "NonBrandedSlideshow",
    "n{*id}",
    MVC.Slideshow.NonBranded(), null,
    new { id = Settings.Base32Regex }
);

routes.MapRoute(
    "FullSlideshow",
    "f{*id}",
    MVC.Slideshow.Full(), null,
    new { id = Settings.Base32Regex }
);

Однако эти маршруты должны быть зарегистрированы поздно, чтобы контроллер не заканчивал маршрутизацией любого URL с префиксом n, f и т. Д. Для этих действий контроллера.

1 голос
/ 11 января 2012

Это обходной путь. Странный, я думаю ...

Поскольку ваши правила маршрутизации довольно просты, вы можете создать пользовательский ControllerFactory и проверить URL. если URL соответствует вашему пути, вы можете определить, какой контроллер и действие использовать, и установить параметр id на основе URL. Если нет, просто оставьте обычное поведение.

Я знаю, он не будет использовать готовую маршрутизацию, но так как она не работает ... Хорошая новость: как только она исправлена, вы можете обновить маршруты, удалить Custom ControllerFactory и продолжить без обходного пути.

1 голос
/ 07 января 2012

вы пытались сопоставить их без ограничения маршрута в конце?

РЕДАКТИРОВАТЬ: извините за половину ответа прервано

вам нужно попробовать это для ограничения маршрута

     routes.MapRoute(
            "NSlideshow",
            "{id}",
            new { controller = "SlideShow", action = "N", id = UrlParameter.Optional },
            new
            {
                id = @"^[n]{1}[0-9ABCDEFGHJKMNPQRSTVWXYZ]+"
            }
        );

     routes.MapRoute(
            "GSlideshow",
            "{id}",
            new { controller = "SlideShow", action = "G", id = UrlParameter.Optional },
            new
            {
                id = @"^[g]{1}[0-9ABCDEFGHJKMNPQRSTVWXYZ]+"
            }
        );

промыть и повторить для каждого случая, в вашем методе действия уберите первый символ с передней части id

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...