Jak uzyskać akcję MVC, aby zwrócić 404

142

Mam akcję, która przyjmuje ciąg, który jest używany do pobierania niektórych danych. Jeśli ten ciąg nie powoduje zwrócenia żadnych danych (być może dlatego, że zostały usunięte), chcę zwrócić 404 i wyświetlić stronę błędu.

Obecnie używam po prostu powrotu specjalnego widoku, który wyświetla przyjazny komunikat o błędzie specyficzny dla tej akcji, informujący, że element nie został znaleziony. Działa to dobrze, ale najlepiej byłoby zwrócić kod stanu 404, aby wyszukiwarki wiedziały, że ta treść już nie istnieje i mogą ją usunąć z wyników wyszukiwania.

Jaki jest najlepszy sposób rozwiązania tego problemu?

Czy jest to tak proste, jak ustawienie Response.StatusCode = 404?

Paul Hiles
źródło
musisz także zachować Response.TrySkipIisCustomErrors = true; Odpowiedź @ganders uratowała życie ...
Grzmot

Odpowiedzi:

111

Można to zrobić na wiele sposobów,

  1. Masz rację we wspólnym kodzie aspx, który można przypisać w określony sposób
  2. throw new HttpException(404, "Some description");
Dewfy
źródło
1
Jedną rzeczą, na którą należy zwrócić uwagę, jest to, że jeśli masz stronę CustomError skonfigurowaną do obsługi 404, ta strona błędu zwróci 200 (nie znaleziono strony ... :-(). Zwykle zgłaszam wyjątek od powiedz BlogController i niech akcja NotFound ustawi właściwy kod odpowiedzi
Nigel Sampson
20
Skończyło się na zrobieniu: Response.StatusCode = 404; Response.TrySkipIisCustomErrors = true; return View ("MyCustomView"); Działa to doskonale w mojej sytuacji.
Paul Hiles
@PaulHiles: To jest odpowiedź dla mnie w MVC3. Chciałbym móc zagłosować jako odpowiedź, a nie komentarz.
Valamas,
Myślę, że to nie działa, jeśli używasz IIS. Na mojej stronie testowej działa dobrze, ale w witrynie aktywnej uruchamia się niestandardowa strona błędu.
Andy Brown
@AndyBrown działa zarówno dla IIS, jak i IIS Express, musisz przejrzeć swoją konfigurację IIS (konsola administracyjna)
Dewfy
150

W ASP.NET MVC 3 i nowszych można zwrócić HttpNotFoundResult z kontrolera.

return new HttpNotFoundResult("optional description");
Stefan Paul Noack
źródło
4
użycie:return new HttpNotFoundResult("optional description");
Valamas
6
Jeśli wracasz z poziomu kontrolera, istnieje również wygodna metoda o nazwie HttpNotFound(). Więc możesz return HttpNotFound("optional description")zamiast tego wrócić .
Luis Perez
1
W 2012 roku nie było już tak wygodnie ;-)
Stefan Paul Noack
61

W MVC 4 i nowszych możesz użyć wbudowanych HttpNotFoundmetod pomocniczych:

if (notWhatIExpected)
{
    return HttpNotFound();
}

lub

if (notWhatIExpected)
{
    return HttpNotFound("I did not find message goes here");
}
Gone Coding
źródło
26

Kod :

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

Web.config

<customErrors mode="On">
  <error statusCode="404" redirect="/Home/NotFound" />
</customErrors>
Sinan BARAN
źródło
Ponadto wszystkie dostępne kody stanu istnieją w tym wyliczeniu: HttpStatusCode.
user2173353
12

Użyłem tego:

Response.StatusCode = 404;
return null;
Wout
źródło
Dziękuję Ci. Wygląda to o wiele lepiej niż rzucenie kosztownego wyjątku na serwer. Zastanawiam się, czy 404 byłby zalogowany w dziennikach IIS ... Idealnie byłoby.
fozylet
1
Ale w asp.net ta metoda nie jest dobrym rozwiązaniem, prawda? ponieważ strona internetowa wyświetlałaby wszystkie powiązane poufne informacje serwera.
lzlstyle
1
Obsługa jednego wyjątku zajmie mniej niż milisekundę. W porównaniu z kilkuset milisekundami, które wystarczyło na wykonanie połączenia HTTP w górę iz powrotem, jest to bez znaczenia. throw HttpException lub return HttpNotFoundResult, ręczne ustawienie kodu stanu i zwrócenie wartości null jest straszne.
George,
10

Jeśli pracujesz z .NET Core, możesz return NotFound()

Robert Paulsen
źródło
5

W NerdDinner np. Spróbuj go

public ActionResult Details(int? id) {
    if (id == null) {
        return new FileNotFoundResult { Message = "No Dinner found due to invalid dinner id" };
    }
    ...
}
cem
źródło
Dzięki, ale za kulisami generuje HttpException podobny do sugestii numer dwa w poście Dewfy. Szukam nieco większej kontroli, aby móc wyświetlić ładną stronę błędu specyficzną dla akcji, a nie tylko przekierowującą do kontrolera / globalnej strony 404. Wygląda na to, że ustawienie kodu stanu i powrót do widoku niestandardowego jest sposobem na rozwiązanie mojej sytuacji.
Paul Hiles
4

Żaden z powyższych przykładów nie działał dla mnie, dopóki nie dodałem środkowej linii poniżej:

public ActionResult FourOhFour()
{
    Response.StatusCode = 404;
    Response.TrySkipIisCustomErrors = true; // this line made it work
    return View();
}
ganders
źródło
2
Naprawdę mówisz mi, że prostota return HttpNotFound();nie działa dla ciebie? Ile lat ma Twój system?
Gone Coding
1
Próbowałeś return HttpNotFound();? Działa dobrze z MVC 4 w górę. msdn.microsoft.com/en-us/library/… "Właściwość TrySkipIisCustomErrors jest używana tylko wtedy, gdy aplikacja jest hostowana w usługach IIS 7.0. W przypadku uruchamiania w trybie klasycznym w usługach IIS 7.0 wartością domyślną właściwości TrySkipIisCustomErrors jest true. Podczas pracy w trybie zintegrowanym , domyślną wartością właściwości TrySkipIisCustomErrors jest false. "
Gone Coding
2

Używam:

Response.Status = "404 NotFound";

To działa dla mnie :-)

bruno
źródło
2

W .NET Core 1.1:

return new NotFoundObjectResult(null);
feedthedogs
źródło
1
Jeśli nie zwracasz obiektu, wtedy właściwsze jest zwrócenie NotFound (), ale w obu przypadkach nie otrzymasz przyjaznej strony błędu, chyba że obsłużysz ją za pomocą czegoś takiego jak StatusCodePagesWithReExecute. Zobacz devtrends.co.uk/blog/handling-404-not-found-in-asp.net-core
Paul Hiles
0

Możesz też:

        if (response.Data.IsPresent == false)
        {
            return StatusCode(HttpStatusCode.NoContent);
        }
Christof Mehlstäubler
źródło
-1

Wypróbuj następujący kod demonstracyjny:

public ActionResult Test()

{
  return new HttpStatusCodeResult (404,"Not found");
}
user4326800
źródło