Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the proper way to send an HTTP 404 response from an ASP.NET MVC action?

If given the route:

{FeedName}/{ItemPermalink}

ex: /Blog/Hello-World

If the item doesn't exist, I want to return a 404. What is the right way to do this in ASP.NET MVC?

like image 619
Daniel Schaffer Avatar asked Jan 31 '09 23:01

Daniel Schaffer


People also ask

Which is the correct way to give a 404 status code?

Redirect the page: The easiest and most simple way to fix a 404 error is to redirect the page to another one, using a "301" redirect. A 301 is a response code that signals to a user's browser that your content has moved to a new url.

What action result helper method on a controller will return an HTTP status code 404?

How to return 404 status code from a MVC application. First way is to instantiate HttpNotFoundResult class and return the object. Next alternative is to makes use of HttpNotFound() helper method of the Controller class which returns the HttpNotFoundResult instance.

What do you mean by 404 in asp net?

Best web development and SEO practices dictate that any webpage which does not exist, return an HTTP response code of 404, or Not Found. Basically, this response code means that the URL that you're requesting does not exist.

How does web API handle 404 error?

A simple solution is to check for the HTTP status code 404 in the response. If found, you can redirect the control to a page that exists. The following code snippet illustrates how you can write the necessary code in the Configure method of the Startup class to redirect to the home page if a 404 error has occurred.


3 Answers

Shooting from the hip (cowboy coding ;-)), I'd suggest something like this:

Controller:

public class HomeController : Controller
{
    public ActionResult Index()
    {
        return new HttpNotFoundResult("This doesn't exist");
    }
}

HttpNotFoundResult:

using System;
using System.Net;
using System.Web;
using System.Web.Mvc;

namespace YourNamespaceHere
{
    /// <summary>An implementation of <see cref="ActionResult" /> that throws an <see cref="HttpException" />.</summary>
    public class HttpNotFoundResult : ActionResult
    {
        /// <summary>Initializes a new instance of <see cref="HttpNotFoundResult" /> with the specified <paramref name="message"/>.</summary>
        /// <param name="message"></param>
        public HttpNotFoundResult(String message)
        {
            this.Message = message;
        }

        /// <summary>Initializes a new instance of <see cref="HttpNotFoundResult" /> with an empty message.</summary>
        public HttpNotFoundResult()
            : this(String.Empty) { }

        /// <summary>Gets or sets the message that will be passed to the thrown <see cref="HttpException" />.</summary>
        public String Message { get; set; }

        /// <summary>Overrides the base <see cref="ActionResult.ExecuteResult" /> functionality to throw an <see cref="HttpException" />.</summary>
        public override void ExecuteResult(ControllerContext context)
        {
            throw new HttpException((Int32)HttpStatusCode.NotFound, this.Message);
        }
    }
}
// By Erik van Brakel, with edits from Daniel Schaffer :)

Using this approach you comply to the framework standards. There already is a HttpUnauthorizedResult in there, so this would simply extend the framework in the eyes of another developer maintaining your code later on (you know, the psycho who knows where you live).

You could use reflector to take a look into the assembly to see how the HttpUnauthorizedResult is achieved, because I don't know if this approach misses anything (it seems too simple almost).


I did use reflector to take a look at the HttpUnauthorizedResult just now. Seems they're setting the StatusCode on the response to 0x191 (401). Although this works for 401, using 404 as the new value I seem to be getting just a blank page in Firefox. Internet Explorer shows a default 404 though (not the ASP.NET version). Using the webdeveloper toolbar I inspected the headers in FF, which DO show a 404 Not Found response. Could be simply something I misconfigured in FF.


This being said, I think Jeff's approach is a fine example of KISS. If you don't really need the verbosity in this sample, his method works fine as well.

like image 99
Erik van Brakel Avatar answered Oct 21 '22 23:10

Erik van Brakel


We do it like so; this code is found in BaseController

/// <summary>
/// returns our standard page not found view
/// </summary>
protected ViewResult PageNotFound()
{
    Response.StatusCode = 404;
    return View("PageNotFound");
}

called like so

public ActionResult ShowUserDetails(int? id)
{        
    // make sure we have a valid ID
    if (!id.HasValue) return PageNotFound();
like image 47
Jeff Atwood Avatar answered Oct 21 '22 21:10

Jeff Atwood


throw new HttpException(404, "Are you sure you're in the right place?");
like image 19
yfeldblum Avatar answered Oct 21 '22 21:10

yfeldblum