ASP.NET MVC - Поймать весь маршрут и маршрут по умолчанию

При попытке получить мое приложение для корректной обработки ошибок 404, я выполнил весь маршрут в конце таблицы маршрутов, как показано ниже:

 routes.MapRoute(
            "NotFound", _
           "{*url}", _
           New With {.controller = "Error", .action = "PageNotFound"} _
       )

Однако, чтобы получить это, мне пришлось удалить маршрут по умолчанию:

{controller}/action/{id}

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

Есть ли более простой способ сделать это, а не добавлять маршрут для каждого контроллера/действия?

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

Ответ 1

Использовать ограничения маршрута

В вашем случае вы должны определить свой маршрут по умолчанию {controller}/{action}/{id} и установить ограничение на него. Вероятно, связано с именами контроллеров или, возможно, даже с действиями. Затем поместите уловку за ним, и он должен работать нормально.

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

Итак. Сначала определите маршрут по умолчанию с ограничениями маршрута, а затем поймайте весь маршрут после него:

routes.MapRoute(
    "Default",
    "{controller}/{action}/{id}",
    new { controller = "Home", action = "Index", id = UrlParameter.Optional },
    new { controller = "Home|Settings|General|..." } // this is basically a regular expression
);
routes.MapRoute(
    "NotFound",
    "{*url}",
    new { controller = "Error", action = "PageNotFound" }
);

Ответ 2

//this catches all  requests
routes.MapRoute(
    "Error",
    "{*.}",
     new { controller = "PublicDisplay", action = "Error404" } 
);

добавить этот маршрут в конец таблицы маршрутов

Ответ 3

А, проблема заключается в том, что ваш маршрут по умолчанию захватывает все 3 сегмента URL. Проблема здесь в том, что Routing запускается до того, как мы определим, кто будет обрабатывать запрос. Таким образом, любой URL-адрес из трех сегментов будет соответствовать маршруту по умолчанию, даже если он заканчивается позже, когда нет контроллера для его обработки.

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

Ответ 4

Хорошо, я обнаружил, что нет хорошего способа сделать это. Я установил свойство redirectMode для customErrors в ResponseRewrite.

<customErrors mode="On" defaultRedirect="~/Shared/Error" redirectMode="ResponseRewrite">
    <error statusCode="404" redirect="~/Shared/PageNotFound"/>
</customErrors>

Это дает мне желаемое поведение, но не отображает отформатированную страницу.

Мне это плохо сделано, поскольку SEO идет. Тем не менее, я считаю, что есть решение, которое я пропускаю, поскольку SO делает именно то, что я хочу. URL-адрес остался на странице с ошибкой и выбрасывает 404. Проверьте Firewall в файле stackoverflow.com/fail.

Ответ 5

Я бы рекомендовал это как наиболее читаемую версию. Это необходимо в вашем RouteConfig.cs и контроллере ErrorController.cs, содержащем действие "PageNotFound" . Это может вернуть представление. Создайте файл PageNotFound.cshtml, и он будет возвращен в ответ на 404:

        routes.MapRoute(
            name:  "PageNotFound",
            url:  "{*url}",
            defaults: new { controller = "Error", action = "PageNotFound" }
        );

Как это прочитать:

name: "PageNotFound"

= создать новый шаблон маршрута с произвольным именем "PageNotFound"

url:"{*url}"

= использовать этот шаблон для сопоставления всех других необработанных маршрутов

defaults: new { controller = "Error", action = "PageNotFound" }

= определить действие, на которое будет отображаться неверный путь (метод действия "PageNotFound" в контроллере ошибок). Это необходимо, так как неправильно введенный путь, очевидно, не будет сопоставляться с каким-либо действием

Ответ 6

Вероятно, вам лучше настроить файл ошибки 404 в разделе конфигурации, а затем восстановить маршрут по умолчанию.

FWIW, я думаю, что требование маршрута по умолчанию также задерживается.

Ответ 7

Мое решение - 2 шага.

Первоначально я решил эту проблему, добавив эту функцию в файл Global.asax.cs:

protected void Application_Error(Object sender, EventArgs e)

Где я пробовал кастинг Server.GetLastError() в HttpException, а затем проверил GetHttpCode. Это решение подробно описано здесь:

ASP.NET MVC Пользовательская обработка ошибок Application_Error Global.asax?

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

например, эти URL-адреса отображали страницу 404:

www.site.com/blah

www.site.com/blah/blah

однако, www.site.com/blah/blah/blah просто скажет, что страница не найдена. Добавление вашего трека по всему маршруту ПОСЛЕ всех моих других маршрутов разрешило это:

routes.MapRoute(
            "NotFound",
            "{*url}",
            new { controller = "Errors", action = "Http404" }
        );

Однако маршрут NotFound, похоже, не маршрутизирует запросы, у которых есть расширения файлов. Это работает, когда они захватываются разными маршрутами.