Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

For a helpful not-found page that still tells browsers and search engines the requested URL is missing, keep the HTTP 404 response and render the page at the original URL. In ASP.NET Core, use UseStatusCodePagesWithReExecute; in classic ASP.NET Framework, map status code 404 with system.web/customErrors. A browser redirect is different: it changes the address bar and returns a redirect status first. Which option works also depends on whether ASP.NET or IIS handles the request.

Choose what should happen to the missing URL

A custom 404 page is usually a presentation for a not-found response, not a replacement destination. Keep these outcomes distinct: rendering a page while preserving 404, internally running an error endpoint, and telling the browser to navigate somewhere else.

Option Address bar Response behavior Best fit
Status-code response with a custom body Original missing URL Returns 404 with a body A not-found message without a separate error endpoint
ASP.NET Core re-execution Original missing URL Runs an error endpoint internally and preserves the original status A shared MVC or Razor error view that still returns 404
ASP.NET Core redirect Changes to the error endpoint First sends 302; the destination may then return 200 Another application owns presentation or client navigation is intentional
IIS redirect Changes to the destination Can send 301, 302, 307, or 308 A known URL has moved or should route elsewhere
IIS custom error handling Depends on configuration IIS handles a server-level error The request does not reach the ASP.NET application

For an unknown URL with no replacement, prefer a genuine 404 page over sending every visitor to the home page. A redirect is appropriate when there is a deliberate destination, such as a known replacement for a retired URL.

ASP.NET Core: render a page and preserve 404

ASP.NET Core does not provide a status-code page by default for HTTP errors such as 404. Without status-code-pages middleware, the response to an unmatched endpoint may be browser-dependent. To return a useful body, configure status-code pages before request-handling middleware that may set the error status. Microsoft documents the status-code middleware and its behavior in Handle errors in ASP.NET Core.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Use internal re-execution for a shared error endpoint

UseStatusCodePagesWithReExecute processes the request again at another path without asking the browser to navigate there. The original address remains visible and the original status code is retained. The target path must begin with /. Configure the middleware before routing so the error endpoint can be routed.

app.UseStatusCodePagesWithReExecute("/Error/{0}");

app.UseRouting();
app.UseEndpoints(endpoints =>
{
    endpoints.MapControllers();
    endpoints.MapRazorPages();
});

Here, a 404 is internally re-executed at /Error/404. Add an endpoint that handles that path and renders a page with useful navigation, search, or a way to report a broken link. The error endpoint can inspect IStatusCodeReExecuteFeature to access the original path and query when it needs to explain or log what was requested.

Write the response body directly when no endpoint is needed

UseStatusCodePages can write a response body directly or use a delegate. This can suit a small, deliberately simple response. Microsoft notes that the basic text-only handler is not generally useful to end users in production; a designed endpoint or view is usually more helpful.

ASP.NET Core: redirect only when the browser should navigate

UseStatusCodePagesWithRedirects sends a 302 response to the client, which then requests the error endpoint. The browser address bar changes, and the destination endpoint commonly responds with 200. As a result, the initial response is not the original 404. Use this behavior when the client really should navigate to another endpoint, not simply to display a not-found message. See Microsoft’s ASP.NET Core error-handling documentation.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Status-code pages handle HTTP status responses; they do not catch exceptions. Microsoft states, “The status code pages middleware does not catch exceptions.” Configure exception-handling middleware or an error handler for exceptions rather than expecting a 404 page to handle them.

Classic ASP.NET Framework: map 404 with customErrors

For applications built on the older System.Web stack, add a status-specific entry to customErrors in Web.config. For example:

<customErrors mode="RemoteOnly" defaultRedirect="~/ErrorPages/Oops.aspx">
  <error statusCode="404" redirect="~/ErrorPages/404.aspx" />
</customErrors>

Create 404.aspx to explain that the requested resource was not found and offer sensible next steps, such as navigation or search. Microsoft’s custom error page tutorial also describes suggesting likely replacement pages based on known broken URLs; that is application logic, not a built-in feature.

This configuration only applies when a request is handled by the ASP.NET engine. Static resources such as images or HTML files may be served directly by IIS, so a missing static file can bypass the ASP.NET error page.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

IIS: handle server-level errors and genuine redirects

Use httpErrors when IIS owns the request

If IIS handles a missing file or rejects a request before it reaches ASP.NET, inspect IIS error handling rather than relying on application middleware or customErrors. IIS httpErrors settings control server error responses, including the error path and mode; verify the effective configuration and whether it replaces an application response. See Microsoft’s documentation for Adding HTTP Errors.

Reserve redirects for moved URLs

IIS httpRedirect supports permanent status codes 301 and 308 and temporary status codes 302 and 307. Choose permanent when the move is intended to last and temporary when it is not. These are redirect responses that send the client to a destination, not a way to display a 404 while retaining its status. Microsoft documents the available settings in HTTP Redirects <httpRedirect>.

Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Diagnose which 404 you are seeing

Not every 404 means an application route simply failed to match. IIS distinguishes substatuses that can point to different causes. Its documented examples include:

  • 404.0: not found.
  • 404.1: site not found.
  • 404.2: ISAPI/CGI restriction.
  • 404.3: MIME type restriction.
  • 404.4: no handler.
  • 404.5: request filtering.
  • 404.6: verb denied.

Check the IIS logs and the specific substatus before routing all failures to the same page; a server restriction may need a configuration fix, not an application-level not-found view. Microsoft’s IIS HTTP status code overview lists these cases.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Keep URL rewriting separate from 404 presentation

URL rewriting is a broader mechanism for changing or redirecting request paths; it is not synonymous with showing a not-found page. ASP.NET Core provides URL rewriting middleware for rewrite and redirect rules, but Microsoft recommends server-based rewrite technologies when available and suitable because the middleware does not support every feature offered by IIS, Apache, or Nginx modules. See URL rewriting middleware in ASP.NET Core.

Implementation checklist

  • Identify the target: ASP.NET Core uses middleware; classic ASP.NET Framework uses system.web/customErrors.
  • Decide whether the original URL should remain in the address bar and whether the response should remain 404.
  • In ASP.NET Core, add status-code pages before request handlers; put re-execution before routing.
  • Ensure the configured error path is handled by an endpoint and gives visitors a useful next step.
  • For classic ASP.NET, confirm the request reaches the ASP.NET engine; configure IIS handling separately for requests IIS owns.
  • When IIS returns an error, check its status subcode and effective httpErrors configuration.
  • Use redirects for known replacement destinations, not as a blanket treatment for unknown paths.

The cited Microsoft error-handling page is a view for ASP.NET Core 5.0, a legacy release; check current guidance and hosting details against the version your project targets. The classic ASP.NET configuration applies to the System.Web generation, not ASP.NET Core. IIS behavior depends on hosting and effective server configuration.

Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.