MVC: маршрут 404 не работает должным образом в производстве - PullRequest
5 голосов
/ 18 октября 2011

У меня есть следующий маршрут внизу моего global.asax:

//404 ERRORS:
routes.MapRoute(
    "404-PageNotFound",
    "{*url}",
    new { controller = "Error", action = "PageNotFound" }
);

Что отлично работает в Visual Studio, но в процессе работы я получаю страницу ошибки IIS.

Не должен ли этот маршрут перехватить какой-либо URL-адрес, который не был перехвачен другими, следовательно, никаких 404-х с точки зрения IIS? Что еще мне нужно сделать в web.config?

Примечание: я не хочу перенаправить на определенный URL-адрес 404; скорее я показываю страницу с ошибкой 404 по запрошенному URL-адресу (я считаю, что это правильный подход с точки зрения удобства использования).

UPDATE
В моем контроллере ошибок я устанавливаю Response.StatusCode = 404;, что, похоже, является проблемой. Когда я удаляю это и снова развертываю в производство, я снова получаю дружественные страницы ошибок. Однако я считаю, что действительно нужен статус 404 в заголовке HTTP - для целей SEO - поэтому мой вопрос теперь звучит так:

ПЕРЕСМОТРЕННЫЙ ВОПРОС
Как / почему IIS перехватывает ответ и отправляет сообщение об ошибке 404 «из коробки» и как мне предотвратить это?

** РЕШЕНИЕ **
Доммер получает приз за предложение Response.TrySkipIisCustomErrors=true;, которое (я думаю) было необходимо. Но было еще 2 ключевых детали:

  • пользовательских ошибок должно быть на в web.config (duh!) И
  • действие 404 должно иметь атрибут [HandleErrors].

заставить его работать везде
Поскольку некоторые URL-адреса могут отображаться на маршруты, отличные от «404-PageNotFound», но содержащие недопустимые параметры, и поскольку я не хочу перенаправлять на страницу 404, я создал это действие в своем базовом контроллере:

[HandleError]
public ActionResult NotFound()
{
    Response.StatusCode = 404;
    Response.TrySkipIisCustomErrors = true;     
    return View("PageNotFound", SearchUtilities.GetPageNotFoundModel(HttpContext.Request.RawUrl));          
}

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

return NotFound();

примечание: Не RedirectToAction ()

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

Ответы [ 2 ]

4 голосов
/ 18 октября 2011

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

// This will match too many things, so let's constrain it to those we know are valid
   routes.MapRoute(
    "Default",
    "{controller}/{action}/{id}",
    new { controller = "Home", action = "Index", id = UrlParameter.Optional },
    new { controller = "Home|OtherController|AnotherController|..." } // regular expression matching all valid controllers
);

//404 ERRORS:
routes.MapRoute(
    "404-PageNotFound",
    "{*url}",
    new { controller = "Error", action = "PageNotFound" }
);

Если вы хотите получить более полный ответ, посмотрите на это: Как правильно обработать 404 в ASP.NET MVC?

РЕДАКТИРОВАТЬ:

Чтобы избавиться от пользовательской ошибки IIS, попробуйте изменить свой контроллер ошибок следующим образом:

Response.StatusCode = 404;
Response.TrySkipIisCustomErrors=true; // add this line

MSDN документ: http://msdn.microsoft.com/en-us/library/system.web.httpresponse.tryskipiiscustomerrors.aspx

0 голосов
/ 18 октября 2011

Пожалуйста, попробуйте вот так

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


routes.MapRoute(
                        "404-PageNotFound", // Route name
                        "{*url}", 
                        new { controller = "Error", action = "PageNotFound", id = UrlParameter.Optional } // Parameter defaults
                    );
...