2

I want to be able to generate IIS's standard 404 response, not a custom 404 page, in response to an error condition in a code-behind class. My Page_Load method looks like this:

protected void Page_Load(object sender, System.EventArgs e)
{
    this.a = ...
    ...
    if (this.a == null) ... // *** generate a 404
}

So if a is not null the .aspx file renders, etc, but if a is null I want the standard "The resource cannot be found" page to be shown with a 404 response code.

If I use:

if (a == null) Response.StatusCode = 404;

(which is what seems to be the correct method according to what I can find) the page continues to render (and gives a NullReferenceException with a response code of 500 when it tries to use a).

If I use:

if (a == null) throw new HttpException(404, "Not found");

The response code is 404 but the page content is ASP.NET's unhandled exception page showing the HttpException (which is then shown as the generic "Runtime Error" when customErrors is On).

I want to show IIS's 404 page because the users will understand that, but they probably won't check the response code of the page if it shows a server error.

EDIT: It looks like I can't do this exactly. Given @Smudge202's answer I let my code-behind throw the HttpException and added code to Global.Application_Error() to handle those exceptions:

void Application_Error(object sender, EventArgs e)
{
var exception = Server.GetLastError();

    if (exception is HttpException)
    {
        var httpException = (HttpException)exception;
        if (httpException.GetHttpCode() == 404)
        {
            var context = HttpContext.Current;
            context.Response.Clear();
            context.Response.StatusCode = 404;
            context.Response.StatusDescription = "Not Found";
            context.Response.Write("<h1>404 Not Found</h1>");
            context.Server.ClearError();
        }
    }
    // ...
}

This lets me set my own response to the exception. This approach has two drawbacks:

  • What I really wanted to do was revert control back to IIS and let it display its default 404 response, I can't find a way to do that
  • The new response (written by context.Response.Write()) is shown for every 404, not just ones generated in code

So it looks like I will need to either:

  • From the code-behind, redirect to a bespoke page explaining that the 'thing' can't be found (which also sets the 404 response code), or
  • Set up a custom global 404 page
Rebecca Scott
  • 2,421
  • 2
  • 25
  • 39

3 Answers3

1

How about a redirect to a non-existent page.

JNappi
  • 1,495
  • 1
  • 14
  • 24
  • That could work. It gives a 302 redirect then a 404 on the non-existent page, which probably would present issues for search engines but that isn't my priority. I was hoping for something that wasn't such a kludge but I think I'm going to be disappointed. Thanks. – Rebecca Scott May 26 '11 at 05:50
1

I doubt this is a clean solution, but it might work...

If you combine this post (and several similar I'm sure). It seems from global asax writing a 404 out to the response stream bypasses the custom errors.

With that in mind, you could intentionally raise a custom exception in your code behind. Check for that custom exception in Application_Error, and respond with 404 from there? That will prevent the page from rendering, and everything should work as you've asked?

EDIT:

If this is shown for every 404 exception and you don't want it to be, create a custom exception for your original code behind to fire. Only catch that particular exception in Application_Error, allow the others to pass through as normal?

I also found this thread where the OP was trying, like you, to raise the actual 404 page, and not a mock-up of it. There are a couple suggestions on there on how to do it, no idea if any of them work, but probably worth trying quickly.

Community
  • 1
  • 1
Smudge202
  • 4,689
  • 2
  • 26
  • 44
  • Thanks for the link @Smudge202 but the best I can get from the suggestion in the thread is a blank page. Possibly it has something to do with IIS, I'm actually just using Cassini or whatever VS2008 uses, so I'll test on a real server to see. Cheers! – Rebecca Scott May 26 '11 at 11:22
  • @Ben Most welcome. Here's one more link for you in case you hadn't come across it. He's trying to do the opposite to what you want, so maybe you can reverse the process? [IIS 7 Error Pages](http://www.west-wind.com/weblog/posts/2009/Apr/29/IIS-7-Error-Pages-taking-over-500-Errors) – Smudge202 May 26 '11 at 12:03
  • :-( still no good. I'm just going to give up and redirect to my own error page. It looks like the only way IIS gets control back is by allowing Application_Error to run through without clearing the error, which results in the 500 server error. Thanks for your help! – Rebecca Scott May 27 '11 at 05:13
0

@Ben Scott as JNappi said, his approach is a good work around based on JNappi's idea, I think I can suggest you one think.

When ever you encounter a 404 error try to show a navigate to the custom 404 error message page, but make sure that no such custom 404 error page exists on the server. This will automatically throws the default 404 error message for you.

In that way you can avoid 302 re-direction message.

But I feel still this is solution as work around but hope it helps you.

SAI BALAJI
  • 31
  • 3