Маршрутизация для настраиваемой страницы ошибок ASP.NET MVC 404

Я пытаюсь создать настраиваемую страницу ошибки HTTP 404, когда кто-то вводит URL-адрес, который не вызывает допустимое действие или контроллер в ASP.NET MVC, вместо того, чтобы отображать общую ошибку ASP.NET «Ресурс не найден».

Я не хочу использовать web.config для этого.

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

Обновление. Я попробовал дать ответ, но все равно получаю неприятное сообщение «Ресурс не найден».

Еще одно обновление: Хорошо, по-видимому, что-то изменилось в RC1. Я даже пробовал специально отлавливать 404 на HttpException, но он все равно выдает мне страницу «Ресурс не найден».

Я даже использовал функцию ресурса MvcContrib и ничего - та же проблема. Любые идеи?


comment
Дублируйте stackoverflow.com/questions/310580/   -  person Craig Stuntz    schedule 16.02.2009
comment
@Peter Это решение, которое я добавил, наряду с переопределением HandleUnknownAction, чтобы отображать представление страницы, не найденной, когда действие не существует, а затем встроенный пользовательский обработчик ошибок ASP.net для обработки чего-либо другого, что пользователи могут вводить .   -  person dswatik    schedule 10.10.2009
comment
@pete Это тоже работает stackoverflow.com/questions/619895/   -  person dswatik    schedule 10.10.2009
comment
Я ненавижу, когда другие пользователи самонадеянны и говорят что-то вроде: «Зачем вам это нужно?» Просто сделайте это ... Но я бы посоветовал, если ничто не мешает вам использовать подход web.config и он удовлетворяет ваши потребности, это стандартный и элегантный подход. Любые отзывы об этом подходе приветствуются, так как вполне могут возникнуть проблемы, о которых я не знаю.   -  person Sean    schedule 25.01.2012
comment
По теме: Как правильно обрабатывать 404 в ASP.NET MVC?   -  person kenorb    schedule 25.05.2015
comment
См .: Пользовательская страница ошибок с ASP .Net MVC 4   -  person kenorb    schedule 25.05.2015
comment
Это дублированный вопрос, так как основной принятый ответ фактически указывает на эту страницу, так что это своего рода ответ только по ссылке без какого-либо значимого решения.   -  person kenorb    schedule 25.05.2015


Ответы (10)


Просто добавьте маршрут перехвата всех маршрутов в конец таблицы маршрутов и отобразите с ним любую страницу, которую хотите.

См .: Как сделать маршрут перехвата всех запросов для обработки запросов типа« 404 страница не найдена »для ASP.NET MVC?

person Alex Reitbort    schedule 16.02.2009
comment
Я пробовал это, однако, я все еще получаю уродливое сообщение о том, что ресурс не найден по умолчанию в ASP.NET .. - person dswatik; 16.02.2009
comment
Я не нашел окончательного (и гибкого !!) решения этой проблемы ни в этом ответе, ни по предоставленной ссылке. - person Peter; 09.10.2009
comment
Я тоже ... это похоже на хакерский ответ. Я больше ищу способ заставить customErrors вести себя так же, как в WebForms. Любые идеи? - person JC Grubbs; 04.05.2010
comment
Это и не работает, и плохо в принципе. Не работает, потому что не будет обнаруживать плохие URL-адреса, которые соответствуют одному из предыдущих шаблонов маршрутизации. Плохо в принципе, потому что преобразует то, что должно быть ошибкой, в ошибку. Перенаправление на страницу с именем Error отличается от перенаправления на страницу с ошибкой. Вы хотите сохранить это как ошибку, зарегистрировать ошибку, а затем обработать ее как ошибку. Ошибки - ценная информация. - person Matthew; 14.10.2015

Я пытался включить настраиваемые ошибки на производственном сервере в течение 3 часов, кажется, я нашел окончательное решение, как это сделать в ASP.NET MVC без каких-либо маршрутов.

Для включения настраиваемых ошибок в приложении ASP.NET MVC нам потребуется (IIS 7+):

  1. Настройте пользовательские страницы в веб-конфигурации в разделе system.web:

    <customErrors mode="RemoteOnly"  defaultRedirect="~/error">
        <error statusCode="404" redirect="~/error/Error404" />
        <error statusCode="500" redirect="~/error" />
    </customErrors>
    

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

  2. Установите параметр волшебного ответа и код состояния ответа (в модуле обработки ошибок или в атрибуте дескриптора ошибки)

      HttpContext.Current.Response.StatusCode = 500;
      HttpContext.Current.Response.TrySkipIisCustomErrors = true;
    
  3. Установите еще один волшебный параметр в веб-конфигурации в разделе system.webServer:

    <httpErrors errorMode="Detailed" />
    

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

person Andrew Orsich    schedule 16.09.2011
comment
Это все еще не идеальное решение. Он не дает вам правильных кодов ответа HTTP. Использование customErrors приводит к перенаправлению 302 только для загрузки страницы с ошибкой. - person Justin Helgerson; 15.04.2014
comment
@ Ek0nomik Идеальных решений не видел :) - person Andrew Orsich; 20.04.2014
comment
@JustinHelgerson Я настраиваю ErrorController для каждого кода состояния и устанавливаю коды ответа внутри этих действий, и он устанавливает правильные коды ответа. Я тестировал с Fiddler и кодами состояния 404 ответ 404, а страницы с 500 ошибками отвечают 500. И в обоих случаях обслуживаются мои пользовательские просмотры ошибок - person Shane Neuville; 04.07.2014
comment
мой товарищ по команде только что удалил представление ошибок в общей папке, чтобы сделать ошибку времени выполнения с кодом состояния 500 для перенаправления на страницу пользовательской ошибки, как указано здесь и здесь. Надежда кому-то помогает. - person Shaiju T; 16.06.2016

Я заставил свою обработку ошибок работать, создав ErrorController, который возвращает представления в этой статье. Мне также пришлось добавить «Catch All» к маршруту в global.asax.

Я не вижу, как он попадет на любую из этих страниц с ошибками, если его нет в Web.config ..? Мой Web.config должен был указать:

customErrors mode="On" defaultRedirect="~/Error/Unknown"

а затем я также добавил:

error statusCode="404" redirect="~/Error/NotFound"
person Jack Smit    schedule 17.08.2009
comment
Спасибо, это помогло мне через 2 года! Что делать, если вам нужна только пользовательская ошибка 404, и ничего больше? - person Shaul Behr; 12.08.2011
comment
@Shaul еще через год ... не устанавливайте defaultRedirect, полностью исключите атрибут. - person NJE; 29.10.2012

Источник

NotFoundMVC - предоставляет удобную для пользователя страницу 404, когда контроллер, действие или маршрут не найдены в вашем приложении ASP.NET MVC3. Представление с именем NotFound отображается вместо страницы ошибок ASP.NET по умолчанию.

Вы можете добавить этот плагин через nuget, используя: Install-Package NotFoundMvc

NotFoundMvc автоматически устанавливается при запуске веб-приложения. Он обрабатывает все различные способы, которыми ASP.NET MVC обычно генерирует исключение 404 HttpException. Это включает в себя отсутствующий контроллер, действие и маршрут.

Пошаговое руководство по установке:

1 - Щелкните правой кнопкой мыши свой проект и выберите "Управление пакетами Nuget" ...

2 - Найдите NotFoundMvc и установите его. введите описание изображения здесь

3 - После завершения установки в ваш проект будут добавлены два файла. Как показано на скриншотах ниже.

введите описание изображения здесь

4 - Откройте только что добавленный NotFound.cshtml в папке Views / Shared и измените его по своему желанию. Теперь запустите приложение и введите неправильный URL-адрес, и вы увидите удобную для пользователя страницу 404.

введите описание изображения здесь

Нет, пользователи получат сообщение об ошибке типа Server Error in '/' Application. The resource cannot be found.

Надеюсь это поможет :)

P.S: Престижность Эндрю Дэви за создание такого замечательного плагина.

person Yasser Shaikh    schedule 03.11.2012
comment
@niico Судя по исходному коду, кажется, что код ответа установлен на 404, так что да. - person Will Dean; 05.02.2018

Попробуйте это в web.config, чтобы заменить страницы ошибок IIS. Я думаю, это лучшее решение, и оно также отправляет правильный код состояния.

<system.webServer>
  <httpErrors errorMode="Custom" existingResponse="Replace">
    <remove statusCode="404" subStatusCode="-1" />
    <remove statusCode="500" subStatusCode="-1" />
    <error statusCode="404" path="Error404.html" responseMode="File" />
    <error statusCode="500" path="Error.html" responseMode="File" />
  </httpErrors>
</system.webServer>

Дополнительная информация на сайте Tipila - Использование настраиваемых страниц ошибок ASP.NET MVC

person Amila    schedule 15.03.2012
comment
+1. Это единственное, что казалось мне стабильно работающим в MVC5 с несколькими областями. - person hawkke; 25.04.2014
comment
Это самое простое решение. Однако вы не можете использовать синтаксис бритвы на странице ошибки. - person edgarian; 12.03.2016

Это решение не требует изменений файла web.config или универсальных маршрутов.

Сначала создайте такой контроллер;

public class ErrorController : Controller
{
    public ActionResult Index()
    {
        ViewBag.Title = "Regular Error";
        return View();
    }

    public ActionResult NotFound404()
    {
        ViewBag.Title = "Error 404 - File not Found";
        return View("Index");
    }
}

Затем создайте представление в «Views / Error / Index.cshtml» как;

 @{
      Layout = "~/Views/Shared/_Layout.cshtml";
  }                     
  <p>We're sorry, page you're looking for is, sadly, not here.</p>

Затем добавьте следующее в файл Global asax, как показано ниже:

protected void Application_Error(object sender, EventArgs e)
{
        // Do whatever you want to do with the error

        //Show the custom error page...
        Server.ClearError(); 
        var routeData = new RouteData();
        routeData.Values["controller"] = "Error";

        if ((Context.Server.GetLastError() is HttpException) && ((Context.Server.GetLastError() as HttpException).GetHttpCode() != 404))
        {
            routeData.Values["action"] = "Index";
        }
        else
        {
            // Handle 404 error and response code
            Response.StatusCode = 404;
            routeData.Values["action"] = "NotFound404";
        } 
        Response.TrySkipIisCustomErrors = true; // If you are using IIS7, have this line
        IController errorsController = new ErrorController();
        HttpContextWrapper wrapper = new HttpContextWrapper(Context);
        var rc = new System.Web.Routing.RequestContext(wrapper, routeData);
        errorsController.Execute(rc);

        Response.End();
}

Если после этого вы по-прежнему получаете настраиваемую страницу ошибок IIS, убедитесь, что следующие разделы закомментированы (или пусты) в файле веб-конфигурации:

<system.web>
   <customErrors mode="Off" />
</system.web>
<system.webServer>   
   <httpErrors>     
   </httpErrors>
</system.webServer>
person Sujeewa    schedule 19.03.2013
comment
Я не думаю, что этот подход будет работать во всех случаях, поскольку сообщение 404 часто перехватывается веб-сервером и поэтому никогда не обрабатывается на уровне приложения. - person Chris Halcrow; 07.02.2016
comment
Я хочу добавить, что если вы воспользуетесь этим подходом, я бы рекомендовал добавить Response.End(); в конец вашего обработчика Application_Error. Без этого для данного сеанса запускается только первое возникновение ошибки, что является проблемой, если у вас, например, есть настраиваемая регистрация ошибок в обработчике Application_Error. - person Keith; 18.12.2017

Если вы работаете в MVC 4, вы можете посмотреть это решение, оно сработало у меня.

Добавьте в мой Global.asax следующий метод Application_Error:

protected void Application_Error(object sender, EventArgs e)
{
    Exception exception = Server.GetLastError();
    Server.ClearError();

    RouteData routeData = new RouteData();
    routeData.Values.Add("controller", "Error");
    routeData.Values.Add("action", "Index");
    routeData.Values.Add("exception", exception);

    if (exception.GetType() == typeof(HttpException))
    {
        routeData.Values.Add("statusCode", ((HttpException)exception).GetHttpCode());
    }
    else
    {
        routeData.Values.Add("statusCode", 500);
    }

    IController controller = new ErrorController();
    controller.Execute(new RequestContext(new HttpContextWrapper(Context), routeData));
    Response.End();

Сам контроллер действительно прост:

public class ErrorController : Controller
{
    public ActionResult Index(int statusCode, Exception exception)
    {
        Response.StatusCode = statusCode;
        return View();
    }
}

Проверьте полный исходный код Mvc4CustomErrorPage на GitHub.

person Duc Hoang    schedule 25.05.2015

У меня была та же проблема, что вам нужно сделать, это вместо добавления атрибута customErrors в файл web.config в папке Views вы должны добавить его в файл web.config в корневой папке ваших проектов.

person SmokeIT    schedule 27.12.2009

Вот верный ответ, который позволяет полностью настроить страницу с ошибкой в ​​одном месте. Не нужно изменять web.config или создавать отдельный код.

Также работает в MVC 5.

Добавьте этот код в контроллер:

        if (bad) {
            Response.Clear();
            Response.TrySkipIisCustomErrors = true;
            Response.Write(product + I(" Toodet pole"));
            Response.StatusCode = (int)HttpStatusCode.NotFound;
            //Response.ContentType = "text/html; charset=utf-8";
            Response.End();
            return null;
        }

На основе http://www.eidias.com/blog/2014/7/2/mvc-custom-error-pages

person Andrus    schedule 22.07.2016

Я расскажу о некоторых конкретных случаях,

если вы используете метод PageNotFound в HomeController, как показано ниже

[Route("~/404")]
public ActionResult PageNotFound()
{
  return MyView();
}

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

//[Route("~/404")]
public ActionResult PageNotFound()
{
  return MyView();
}

И если вы измените его как имя метода в web.config, он работает. Однако не забудьте выполнить код, как показано ниже, в web.config

<customErrors mode="On">
  <error statusCode="404" redirect="~/PageNotFound" /> 
 *// it is not "~/404" because it is not accepted url in Route Tag like [Route("404")]*
</customErrors>
person Furkan ozturk    schedule 11.03.2019