Как заставить действие MVC вернуть 404


142

У меня есть действие, которое принимает строку, которая используется для получения некоторых данных. Если эта строка не приводит к возврату данных (возможно, потому, что она была удалена), я хочу вернуть 404 и отобразить страницу с ошибкой.

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

Как лучше всего это сделать?

Это так же просто, как установить Response.StatusCode = 404?


вы также должны сохранить Response.TrySkipIisCustomErrors = true; Ответ @ganders спас жизнь ...
Thunder

Ответы:


112

Есть несколько способов сделать это,

  1. Вы правы в общем коде aspx, который может быть назначен вашим указанным способом
  2. throw new HttpException(404, "Some description");

1
Следует обратить внимание на то, что если у вас есть страница customError, настроенная для обработки 404, эта страница с ошибкой вернет 200 (не найденная страница была найдена ... :-(). Я склонен генерировать исключение, скажем, BlogController и укажите в действии NotFound правильный код ответа.
Найджел Сэмпсон,

20
В итоге я сделал: Response.StatusCode = 404; Response.TrySkipIisCustomErrors = true; return View ("MyCustomView"); Это отлично работает в моей ситуации.
Пол Хайлс

@PaulHiles: Это ответ для меня в MVC3. Хотел бы я проголосовать за это как за ответ, а не как комментарий.
Valamas

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

@AndyBrown, он работает как для IIS, так и для IIS Express, вам необходимо проверить свою конфигурацию IIS (консоль администратора)
Dewfy

151

В ASP.NET MVC 3 и выше вы можете вернуть HttpNotFoundResult из контроллера.

return new HttpNotFoundResult("optional description");

4
использование:return new HttpNotFoundResult("optional description");
Valamas

6
Если вы возвращаетесь из контроллера, также вызывается удобный метод HttpNotFound(). Чтобы вы могли вернуться return HttpNotFound("optional description")вместо этого.
Луис Перес,

1
В 2012 году все было не так удобно ;-)
Стефан Пол Ноак

61

В MVC 4 и выше вы можете использовать встроенные HttpNotFoundвспомогательные методы:

if (notWhatIExpected)
{
    return HttpNotFound();
}

или

if (notWhatIExpected)
{
    return HttpNotFound("I did not find message goes here");
}

26

Код:

if (id == null)
{
  throw new HttpException(404, "Your error message");//RedirectTo NoFoundPage
}

Web.config

<customErrors mode="On">
  <error statusCode="404" redirect="/Home/NotFound" />
</customErrors>

Кроме того, все доступные коды состояния существуют в этом перечислении: HttpStatusCode.
user2173353 02

12

Я использовал это:

Response.StatusCode = 404;
return null;

Спасибо. Это выглядит намного лучше, чем создание дорогостоящего исключения на сервере. Интересно, будет ли 404 регистрироваться в журналах IIS ... в идеале это было бы.
fozylet

1
Но в asp.net этот метод не лучшее решение, верно? поскольку на веб-странице будет отображаться вся соответствующая конфиденциальная информация о сервере.
lzlstyle

1
Обработка одного исключения займет меньше миллисекунды. По сравнению с несколькими сотнями миллисекунд, просто чтобы выполнить HTTP-соединение, это бессмысленно. бросить HttpException или вернуть HttpNotFoundResult, вручную установить код состояния и вернуть null - это ужасно.
Джордж


5

Например, в NerdDinner. Попробуйте это

public ActionResult Details(int? id) {
    if (id == null) {
        return new FileNotFoundResult { Message = "No Dinner found due to invalid dinner id" };
    }
    ...
}

Спасибо, но за кулисами это вызывает исключение HttpException, подобное предложению номер два в сообщении Dewfy. Мне нужно немного больше контроля, чтобы я мог отображать красивую страницу с ошибкой, относящуюся к действию, а не просто перенаправлять на страницу контроллера / глобальной 404. Похоже, что установка кода состояния и возврат к пользовательскому представлению - это выход в моей ситуации.
Пол Хайлс

4

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

public ActionResult FourOhFour()
{
    Response.StatusCode = 404;
    Response.TrySkipIisCustomErrors = true; // this line made it work
    return View();
}

2
Вы серьезно говорите мне, что простое return HttpNotFound();не работает для вас? Сколько лет вашей системе?
Gone Coding

1
Вы пробовали return HttpNotFound();? Он отлично работает с MVC 4 и выше. msdn.microsoft.com/en-us/library/… "Свойство TrySkipIisCustomErrors используется только в том случае, если ваше приложение размещено в IIS 7.0. При работе в классическом режиме в IIS 7.0 значение свойства TrySkipIisCustomErrors по умолчанию равно true. При работе в интегрированном режиме , для свойства TrySkipIisCustomErrors по умолчанию установлено значение false. "
Gone Coding

2

Я использую:

Response.Status = "404 NotFound";

У меня это работает :-)


2

В .NET Core 1.1:

return new NotFoundObjectResult(null);

1
Если вы не возвращаете объект, то более подходящим вариантом является return NotFound (), но в любом случае вы не получите удобную страницу с ошибкой, если не обработаете ее чем-то вроде StatusCodePagesWithReExecute. См. Devtrends.co.uk/blog/handling-404-not-found-in-asp.net-core
Пол


-1

Пожалуйста, попробуйте следующий демонстрационный код:

public ActionResult Test()

{
  return new HttpStatusCodeResult (404,"Not found");
}
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.