Как исправить 404 с помощью маршрутов в ASP.NET MVC?

У меня возникла проблема с попыткой получить маршрутизацию для работы с ASP.NET MVC 3.0. У меня объявлены следующие маршруты:

public static void RegisterRoutes(RouteCollection routes)
{
    routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

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

    routes.MapRoute(
        "TestRoute",
        "{id}",
        new { controller = "Product", action = "Index3", id = UrlParameter.Optional }
    );

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

Когда я посещаю:

http://localhost

Сайт работает правильно, и он попадает в маршрут Default.

Когда я посещаю:

http://localhost/1

Я получаю 404:

Ошибка сервера в приложении "/".

Ресурс не найден. Описание: HTTP 404. Ресурс, который вы ищете (или его зависимости), мог быть удален, изменилось его имя или Временно недоступен. Просмотрите следующий URL-адрес и сделайте что это правильно написано.

Запрошенный URL:/1

Ниже перечислены действия, которые соответствуют этим маршрутам:

public ActionResult Index3(int? id)
{
    Product myProduct = new Product
    {
        ProductID = 1,
        Name = "Product 1 - Index 3",
        Description = "A boat for one person",
        Category = "Watersports",
        Price = 275M
    };

    Product myProduct2 = new Product
    {
        ProductID = 2,
        Name = "Product 2 - Index 3",
        Description = "A boat for one person",
        Category = "Watersports",
        Price = 275M
    };

    ViewBag.ProcessingTime = DateTime.Now.ToShortTimeString();

    if (id == 1)
        return View("index", myProduct);
    else
        return View("index", myProduct2);
}

Как мне структурировать маршруты, чтобы все три метода действий попали правильно?

Ответ 1

ASP.NET MVC Routing оценивает маршруты сверху вниз. Таким образом, если два маршрута совпадают, первый из них попадает (тот, который ближе к "вершине" метода RegisterRoutes) будет иметь приоритет над последующим.

С учетом этого вам нужно сделать две вещи, чтобы исправить вашу проблему:

  • Ваш маршрут по умолчанию должен быть внизу.
  • В ваших маршрутах должны быть ограничения на них, если они содержат одинаковое количество сегментов:

Какая разница между:

example.com/1

и

example.com/index

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

Чтобы исправить это, вы должны убедиться, что маршруты, использующие ProductIds, принимают ограничения:

routes.MapRoute(
    "TestRoute",
    "{id}",
    new { controller = "Product", action = "Index3", id = UrlParameter.Optional },
    new { id = @"\d+" } //one or more digits only, no alphabetical characters
);

Есть и другие проблемы с вашей настройкой, но это две вещи, которые приходят на ум сразу с места.

Ответ 2

Ваши маршруты MapRoute Значение по умолчанию должно быть последним.

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

Ответ 3

Настройте самый общий маршрут до последней из цепочки вызовов MapRoute.

Попробуйте следующее:

public static void RegisterRoutes(RouteCollection routes)
{
        routes.IgnoreRoute("{resource}.axd/{*pathInfo}");


        routes.MapRoute(
                "TestRoute",
                "{id}",
                new { controller = "Product", action = "Index3", id = UrlParameter.Optional }
        );

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


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

}

Ответ 4

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

Ответ 5

В моем случае ответ на ту же проблему заключался в необходимости "включать в проект" соответствующие контроллеры и представления вместо неправильных правил маршрутизации.

Когда мои были созданы, они по какой-то причине не включались автоматически. Эта проблема была выявлена ​​после закрытия и повторного открытия решения.

{+ 1 ненависть}, присужденная Visual Studio за ее ошибочную гипер-автоматизацию, отправив мне копать файлы Web.Config, пытаясь зацепиться за расширения, и даже пытаться (и терпеть неудачу) взломать приличный ErrorController.