Как определить этот маршрут в ASP.NET MVC? - PullRequest
1 голос
/ 16 января 2010

У меня есть контроллер с именем Movie, с действием с именем ByYear, который принимает год в качестве параметра:

    public ActionResult ByYear(int year)
    {
        ViewData["Title"] = string.Format("Movies released in {0}", year);
        var repository = MvcApplication.GetRepository();
        var movies = repository.Medias
                                .OfType<Movie>()
                                .Where(m => m.Year == year);
        return View("Index", movies);
    }

Я хотел бы получить доступ к этому действию по следующему URL: / Movie / ByYear / {year} , но единственный действительный маршрут для этого действия: / Movie / ByYear? год = {год} .

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

Может кто-нибудь сказать мне, как этого добиться?

Примечание: на самом деле это очень похоже на этот вопрос , но ответ не был принят, и ответ с наибольшим количеством голосов не имеет смысла для меня, поскольку я совершенно новичок в MVC ...

Ответы [ 3 ]

9 голосов
/ 16 января 2010

Измените имя вашего параметра year на id, и это будет соответствовать маршруту по умолчанию, который MVC добавляет в ваш проект.

Итак, для дальнейшего пояснения, давайте посмотрим на маршрут по умолчанию, добавленный ASP.NET MVC:

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

На этом маршруте вы можете увидеть три токена, которые названы специально для controller, action, а третий токен, который передается действию, - id. Когда запрос поступает в ваше приложение, ASP.NET MVC проанализирует маршруты, которые в настоящее время сопоставлены, и попытается найти сигнатуру метода, которая соответствует им, используя отражение против ваших контроллеров.

Когда он смотрит на ваш контроллер Movie, он видит действие с именем ByYear, однако этот метод принимает целое число с именем year, а не id. Вот почему у вас получается что-то вроде /Movie/ByYear?year={year}, когда вы создаете ActionLink для этого конкретного действия. Итак, чтобы исправить это, у вас есть два варианта:

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

Второй метод - добавить другой маршрут, соответствующий сигнатуре этого метода. Для этого вам нужно открыть ваш Global.asax и просто добавить следующее (не проверено, но должно работать):

routes.MapRoute(
    "MoviesByYear",
    "Movies/ByYear/{year}",
    new { controller = "Movie", action = "ByYear" }
);

Этот маршрут жестко закодирован, да, но он не нарушит другие маршруты в вашей системе и позволит вам вызвать параметр метода year.

РЕДАКТИРОВАТЬ 2: Следует также отметить, что механизм маршрутизации остановится на первом найденном маршруте, который соответствует вашему запросу, поэтому любые пользовательские маршруты, подобные этому, следует добавить до маршрута по умолчанию, чтобы уверен, что они будут найдены.

4 голосов
/ 16 января 2010

ОК, я только что узнал, как это сделать. Мне просто нужно было создать новый маршрут до маршрута по умолчанию ... Я не думал, что заказ имел какое-то значение

        routes.MapRoute(
            "MovieByYear",                                          // Route name
            "Movie/ByYear/{year}",                                  // URL with parameters
            new { controller = "Movie", action = "ByYear" }         // Parameter defaults
        );

РЕДАКТИРОВАТЬ: Есть ли более простой способ? (без переименования параметров). Я хотел бы иметь возможность сделать что-то подобное:

[Route("/Movie/ByYear/{year}")]
public ActionResult ByYear(int year)
{
    ...
2 голосов
/ 16 января 2010

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

routes.MapRoute(
     "MovieByYear",                        // Route name
     "Movie/ByYear/{year}",       // URL with parameters
     new { controller = "Movie", action = "ByYear" },
     new { year = @"\d+" }                 // Parameter defaults
);
...