6
votes

I'm nearly done doing a major rewrite and redesign/restructuring of an existing website that gets a lot of traffic. I've been using the IIS 7 Url Rewrite Module to enable extension-less and SEO-friendly urls, as well as to redirect requests for old pages to appropriate pages in the new site structure. It's been going well, but I'm looking into how to set up a custom 404 page and am stymied. So far, I've set up the following code in the node of the web.config:

<httpErrors errorMode="Custom" existingResponse="Replace">
  <remove statusCode="404" subStatusCode="-1" />
  <error statusCode="404" prefixLanguageFilePath="" path="/404.htm" responseMode="ExecuteURL" />
</httpErrors>

The thing is, it WORKS, but not quite! If I go to an non-existent URL, I do get served my custom 404 page, but the request get a 200 OK status code in response instead of the desired 404. I've fiddled with various attributes of the httpErrors node but no luck. Does anyone know how to show the custom 404 page AND return an actual 404 status code?

Thanks!

2

2 Answers

3
votes

To get our custom 404 handler working, we had to do the following:

    <customErrors defaultRedirect="ErrorPage.aspx" mode="On">
        <error statusCode="500" redirect="ErrorPage.aspx" />
        <error statusCode="404" redirect="/404.aspx" />
        <error statusCode="403" redirect="ErrorPage.aspx" />
    </customErrors>

AND

    <httpErrors errorMode="Custom">
        <remove statusCode="404" subStatusCode="-1" />
        <error statusCode="404" prefixLanguageFilePath="" path="/404.aspx" responseMode="ExecuteURL" />
    </httpErrors>

I actually think I ran into the same problem, where I specified only the one type of error. This might not work for extensionless -- but hopefully it sets you on the right track.

1
votes

This worked for me, in the code behind of the 404.aspx:

    protected void Page_Load(object sender, EventArgs e)
    {
        this.Response.StatusCode = 404;
        this.Response.StatusDescription = "Not Found";
        this.Response.TrySkipIisCustomErrors = true;
    }