Маршрут для спеціальної сторінки помилок ASP.NET MVC 404


116

Я намагаюся створити користувальницьку сторінку помилок HTTP 404, коли хтось вводить URL-адресу, яка не викликає дійсну дію чи контролер в ASP.NET MVC, замість цього відображає загальну помилку ASP.NET "Ресурс не знайдено".

Я не хочу використовувати web.config для цього.

Чи є якась магія маршрутизації, яку я можу зробити, щоб зловити недійсні URL-адреси?

Оновлення: Я спробував відповідь, але я все ще отримую некрасиве повідомлення "Ресурс не знайдено".

Ще одне оновлення: Гаразд, очевидно, що в RC1 щось змінилося. Я навіть намагався спеціально захопити 404 на HttpExceptionі все ще просто дає мені сторінку "ресурс не знайдений".

Я навіть використав функцію ресурсу MvcContrib і нічого - та сама проблема. Будь-які ідеї?



@Peter Це рішення, яке я додав, що поряд із переосмисленням HandleUnknownAction для відображення сторінки не знайдено, коли дія не існує, а потім вбудований в ASP.net користувальницький обробник помилок для обробки будь-якого іншого вибагливого, що можуть вводити користувачі .
dswatik

@pete це працює, а stackoverflow.com/questions/619895 / ...
dswatik

8
Я ненавиджу це, коли інші користувачі нахабні і говорять такі речі, як "чому б ти хотів це зробити? Просто зроби це ..." Але я б запропонував, що якщо нічого не заважає тобі використовувати підхід web.config і це задовольняє ваші потреби, це стандартний і елегантний підхід. Будь-який відгук про цей підхід оцінюється, оскільки там дуже добре може бути якесь питання, про яке я не знаю.
Шон

Відповіді:


10

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

Див.: Як я можу зробити спійманий весь маршрут для обробки запитів "404 сторінки не знайдено" для ASP.NET MVC?


Я спробував це, однак, я все ще отримую потворне повідомлення ASP.NET за замовчуванням Не знайдено повідомлення ..
dswatik

3
Я не знаходжу остаточного (і гнучкого !!) рішення цієї проблеми ні в цій відповіді, ні в наданому посиланні.
Пітер

4
Ні я ... це здається наче хитра відповідь. Я шукаю більше способу змусити customErrors вести себе так, як це роблять у WebForms. Будь-які ідеї?
JC Grubbs

1
Це обоє не працює і в принципі погано. Не працює, тому що не буде вловлювати погані URL-адреси, які відповідають одному з попередніх шаблонів маршрутів. Погано в принципі, оскільки він перетворює те, що має бути помилкою, а не помилкою. Перенаправлення на сторінку, яку ви назвали "Помилка", відрізняється від перенаправлення на сторінку помилки. Ви хочете зберегти це як помилку, записуйте помилку, а потім обробляйте її як помилку. Помилки - цінна інформація.
Метью

105

Я намагався включити власні помилки на виробничому сервері протягом 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" />

Це було остаточне, що я знайшов, і після цього я бачу власні помилки на виробничому сервері.


8
Це все ще не ідеальне рішення. Він не отримує належних кодів відповідей HTTP. Використання customErrorsрезультатів у переадресації 302 просто для завантаження вашої сторінки помилок.
Джастін Гельгерсон

@ Ek0nomik Я ніколи не бачив ідеальних рішень :)
Андрій Оршич

2
@JustinHelgerson Я встановлюю ErrorController для кожного коду статусу і встановлюю коди відповідей усередині цих дій, і він встановлює нормальні коди відповідей. Я перевірив, що з кодами статусу Fiddler та 404 відповідають 404, а сторінки з 500 помилками відповідають на 500. І в обох випадках подаються мої власні уявлення про помилки
Шейн Новілл,

мій товариш по команді щойно видалив Помилка перегляду під загальною папкою, щоб зробити помилку виконання за допомогою 500 кодів стану для переадресації на користувальницьку сторінку помилок, як згадується тут і тут . Надія комусь допомагає.
shaijut

41

Я отримав свою роботу з помилками, створивши ErrorController, який повертає думки в цій статті. Мені також довелося додати "Зловити всіх" до маршруту в global.asax.

Я не бачу, як він потрапить на будь-яку з цих сторінок помилок, якщо її немає у Web.config ..? Мій Web.config повинен був вказати:

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

а потім я також додав:

error statusCode="404" redirect="~/Error/NotFound"

2
Спасибі - що мені допомогло через 2 роки! Що робити, якщо вам потрібна лише власна помилка 404, нічого іншого?
Shaul Behr

1
@Shaul ще через рік ... не встановлюйте defaultRedirect, виключайте атрибут взагалі.
NJE

27

Джерело

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

Ви можете додати цей плагін через nuget, використовуючи: Install-Package NotFoundMvc

NotFoundMvc автоматично встановлюється під час запуску веб-додатків. Він обробляє всі різні способи 404 HttpException, як правило, кидається ASP.NET MVC. Сюди входить відсутній контролер, дія та маршрут.

Покрокове керівництво по встановленню:

1 - Клацніть правою кнопкою миші на своєму проекті та оберіть Manage Nuget Packages ...

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

3 - Після завершення встановлення до вашого проекту будуть додані два файли. Як показано на скріншотах нижче.

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

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

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

Більше не буде, чи отримуватимуть користувачі повідомлення про помилки Server Error in '/' Application. The resource cannot be found.

Сподіваюся, це допомагає :)

PS: Кудо Ендрю Дейві за створення такого дивовижного плагіна.


@niico Переглядаючи вихідний код, схоже, встановити код відповіді на 404, так, так.
Буде Дін

20

Спробуйте це в 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


1
+1. Це єдине, що, здається, працювало для мене на MVC5 з кількома областями.
Хоукке

Це найпростіше рішення. Ви не можете використовувати синтаксис бритви на своїй сторінці помилок.
highace

15

Це рішення не потребує змін файлів 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>

Я не думаю, що такий підхід буде працювати у всіх випадках, оскільки 404 часто перехоплюється веб-сервером і тому ніколи не обробляється на рівні програми.
Кріс Халькроу

Я хочу додати, що якщо ви користуєтеся цим підходом, я рекомендую додати в Response.End();кінець вашого обробника Application_Error. Без цього за перший сеанс спрацьовує лише перше виникнення помилки, що є проблемою, якщо у вас є, наприклад, користувальницький журнал помилок у обробнику Application_Error.
Кіт

6

Якщо ви працюєте в MVC 4, ви можете подивитися це рішення, воно працювало для мене.

Додайте до мене такий метод Application_Error Global.asax:

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 .


0

У мене була така ж проблема, що вам потрібно зробити, це замість того, щоб додавати атрибут customErrors у файл web.config у папці Views, ви повинні додати його у файл web.config у кореневій папці ваших проектів.


0

Ось справжня відповідь, яка дозволяє повністю налаштувати сторінку помилок в одному місці. Не потрібно змінювати 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


0

Я розповім про деякі конкретні випадки,

якщо ви використовуєте метод «PageNotFound» в HomeController, як показано нижче

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

це б не працювало. Але ви повинні очистити теги маршруту, як показано нижче,

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

І якщо ви зміните його як метод Name в 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>
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.