Ограничение маршрута ASP.NET MVC2 - необязательный параметр числового идентификатора

У меня есть маршрут по умолчанию, настроенный в моем проекте ASP.NET MVC2, и я хотел бы добавить / изменить его для некоторых других моих контроллеров. Допустим, у меня есть контроллер клиента с ожидаемым действием Details и параметром id (int). Например:

    //
    // GET: /Customer/Details/5
    public ActionResult Details(int id)
    {
      //...
    }

Как я могу добавить маршрут, который будет возвращать 404, если пользователь вводит «не число»? Я попытался добавить следующий маршрут по умолчанию "до", но это не сработало ...

    routes.MapRoute(
        "DefaultDigitsId", // Route name
        "{controller}/{action}/{id}", // URL with parameters
        new { controller = "Home", action = "Index" },
        new { id = @"\d+" }
        );

    routes.MapRoute(
        "Default", // Route name
        "{controller}/{action}/{id}", // URL with parameters
        new { controller = "Home", action = "Index", id = UrlParameter.Optional } // Parameter defaults
        );

Обратите внимание, я хотел бы, если возможно, сохранить маршрут по умолчанию ... Все мои контроллеры используют "Details" и "Edit", где требуется параметр "id" (int). Мне интересно, есть ли способ выполнить это без необходимости указывать несколько маршрутов (то есть что-то общее) ... И, конечно же, цель состоит в том, чтобы, если пользователь вводит что-то вроде "/ Customer / Details / apple", он не выдает ошибку, а переводит их на страницу ошибок .. .

Также есть этот пост, который намекает на установка значения по умолчанию, но я не уверен, как это сделать ...


person zam6ak    schedule 09.12.2010    source источник
comment
Итак, Customer / Details / 1 должен использовать маршрут DefaultDigitsId, а Customer / Details / apple должен выдать вам 404, верно? Какие URL-адреса вы ожидаете использовать для маршрута по умолчанию?   -  person StriplingWarrior    schedule 10.12.2010
comment
Я предполагаю что-то вроде / Customer / Index или /Customer/Create... Я вижу, что вы указываете ... Вы намекаете, что я могу удалить идентификатор из маршрута по умолчанию, поскольку он не будет использоваться?   -  person zam6ak    schedule 10.12.2010
comment
На самом деле я не пытался подчеркнуть: просто поймите, к какому поведению вы стремитесь.   -  person StriplingWarrior    schedule 10.12.2010


Ответы (3)


Я не пробовал это, но вы можете попробовать:

routes.MapRoute(
    "DefaultDetails",
    "{controller}/Details/{id}",
    new { controller = "Home", action = "Details" },
    new { id = @"\d+" }
    );

routes.MapRoute(
    "DefaultEdit",
    "{controller}/Edit/{id}",
    new { controller = "Home", action = "Edit" },
    new { id = @"\d+" }
    );

routes.MapRoute(
    "Default",
    "{controller}/{action}/{id}",
    new { controller = "Home", action = "Index", id = UrlParameter.Optional }
    );

Я ожидал, что «Клиент / Детали / 1» использует первый маршрут (который проверяет идентификатор как число, при вызове «Заказчик / Редактировать / 1» используется второй, который делает то же самое, и вызов «Покупатель / Покупка» / Orange "использует третий маршрут, который не пытается таким образом проверять идентификаторы. Правильно ли я понял, что вы пытаетесь сделать? Сообщите мне, работает ли этот подход.

person StriplingWarrior    schedule 09.12.2010
comment
В порядке. Ваш подход работает немного лучше, чем наличие маршрута с ограничением (такое же, как по умолчанию, но с идентификатором, сопоставленным с регулярным выражением) и наличие маршрута по умолчанию, но удаление из него идентификатора. Спасибо - person zam6ak; 10.12.2010

Добавьте IgnoreRoute после того, который соответствует числовому идентификатору, который будет игнорировать любые запросы к действию Details на контроллере Customer:

routes.MapRoute(
  "DefaultDigitsId", // Route name
  "{controller}/{action}/{id}", // URL with parameters
  new { controller = "Home", action = "Index" },
  new { id = @"\d+" } // match numeric id
);

routes.IgnoreRoute("Customer/Details/{*pathInfo}");

routes.MapRoute(
  "Default", // Route name
  "{controller}/{action}/{id}", // URL with parameters
  new { controller = "Home", action = "Index", id = UrlParameter.Optional } // Parameter defaults
);
person Jason Goemaat    schedule 09.12.2010
comment
Придется ли мне добавлять игнорирование для всех других действий и контроллеров ... Есть около 5 контроллеров, каждый из которых имеет как минимум 2 действия, требующих id ... И он будет расти ... - person zam6ak; 10.12.2010
comment
Если вы хотите принимать идентификатор ТОЛЬКО, если он числовой, просто снимите / {id} с маршрута по умолчанию. - person Jason Goemaat; 10.12.2010
comment
lol :) точно такая же мысль, которая у меня была секунду назад, когда я отвечал на комментарий вверху @StriplingWarrior - person zam6ak; 10.12.2010

Любое значение, которое не может быть преобразовано в строку, сделает значение идентификатора нулевым при вызове, поэтому вы можете перенаправить на страницу с ошибкой, если идентификатор не равен нулю.

Другая возможность - зарегистрировать глобальный фильтр, который проверяет, есть ли параметр с именем id, и если он равен нулю, затем перенаправляет на страницу ошибки.

person Diego    schedule 09.12.2010
comment
Как я могу проверить, является ли параметр id нулевым, если он не объявлен нулевым? Кроме того, я надеюсь, что мне не придется объявлять его как int? id, чтобы я мог проверить, является ли он нулевым (а затем попытаться его разобрать) ... - person zam6ak; 10.12.2010
comment
Вы правы, я этого не заметил. Он использует int? или другие решения, опубликованные выше - person Diego; 10.12.2010
comment
Думаю, объявить параметр как int? будет меньшим из зол, поскольку это позволит системе маршрутизации выполнять свою работу. В вашем контроллере вам нужно будет вернуть ошибку, если значение равно нулю или числовое значение, которое не найдено. Это может быть неплохим подходом, учитывая, что, скорее всего, вам все равно нужно будет проверить значение int, чтобы увидеть, является ли это действительным идентификатором. - person Hector Correa; 10.12.2010
comment
@Hector Я должен с уважением не согласиться с вами :) Пометка параметра как нулевого, чтобы вы могли проверить его достоверность, на мой взгляд, должна быть задачей фреймворка. У меня есть бизнес-сервис, который получает клиента на основе идентификатора, и, если он не найден, выдает бизнес-исключение (CustomerNotFoundException), которое я могу поймать в контроллере. Но это проверка бизнес-уровня, а не проверка параметров mvc ... Отдельные проблемы ... - person zam6ak; 10.12.2010
comment
@ zam6ak Возможно, вы могли бы поделиться этим с ребятами, разрабатывающими фреймворк MVC, я думаю, что ваша точка зрения верна. Например, в Play! Framework (Java MVC Framework), если значение не может быть проанализировано, маршрутизатор возвращает ошибку. - person Diego; 11.12.2010