Catching 404 errors at Application Level

J

JJ

I only want to catch 404 errors at the application level (the rest are will
be handled by the customerrors section of the web.config). How do I check
for the error code in the
Application_Error of Global.asax ?

Thanks,
JJ
 
J

Juan T. Llibre

Sorry about the previous blank reply...

re:
!> How do I check for the error code in the Application_Error of Global.asax ?

Sub Application_Error(ByVal sender As Object, ByVal e As EventArgs)
Server.Transfer("Errors.aspx")
End Sub

Then, in Errors.aspx :
---------------------------------
<html>
<script language="VB" runat="server">
Private Sub Page_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles
MyBase.Load
Dim errMessage As String = ""
Dim appException As System.Exception = Server.GetLastError()
If (TypeOf (appException) Is HttpException) Then
Dim checkException As HttpException = CType(appException, HttpException)
Select Case checkException.GetHttpCode
Case 400
errMessage &= "Bad request. The file size is too large."
Case 401
errMessage &= "You are not authorized to view this page."
Case 403
errMessage &= "You are not allowed to view that page."
Case 404
errMessage &= "The page you have requested can't be found."
Case 408
errMessage &= "The request has timed out."
Case 500
errMessage &= "The server can't fulfill your request."
Case Else
errMessage &= "The server has experienced an error."
End Select
Else
errMessage &= "The following error occurred<BR>" & appException.ToString
End If
ErrorMessage.Text = errMessage & "<BR>We're sorry for the inconvenience."
Server.ClearError()
End Sub
</script>

<body>
<hr>
<asp:label id="ErrorMessage" font-size="12" font-bold="true" runat=server/>
<hr>
<p>Return to <a href="/">Your application's entry page</a>
</body>
</html>
-------------

You don't need to catch all those errors if you don't want to, but why only
catch 404 errors when all the ones listed in the Case statement are available ?




Juan T. Llibre, asp.net MVP
asp.net faq : http://asp.net.do/faq/
foros de asp.net, en español : http://asp.net.do/foros/
======================================
 
M

Mark Rae

Juan T. Llibre said:
Sorry about the previous blank reply...

re:
!> How do I check for the error code in the Application_Error of
Global.asax ?

Sub Application_Error(ByVal sender As Object, ByVal e As EventArgs)
Server.Transfer("Errors.aspx")
End Sub

Then, in Errors.aspx :
---------------------------------
<html>
<script language="VB" runat="server">
Private Sub Page_Load(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles MyBase.Load
Dim errMessage As String = ""
Dim appException As System.Exception = Server.GetLastError()
If (TypeOf (appException) Is HttpException) Then
Dim checkException As HttpException = CType(appException,
HttpException)
Select Case checkException.GetHttpCode
Case 400
errMessage &= "Bad request. The file size is too large."
Case 401
errMessage &= "You are not authorized to view this page."
Case 403
errMessage &= "You are not allowed to view that page."
Case 404
errMessage &= "The page you have requested can't be found."
Case 408
errMessage &= "The request has timed out."
Case 500
errMessage &= "The server can't fulfill your request."
Case Else
errMessage &= "The server has experienced an error."
End Select
Else
errMessage &= "The following error occurred<BR>" &
appException.ToString
End If
ErrorMessage.Text = errMessage & "<BR>We're sorry for the
inconvenience."
Server.ClearError()
End Sub
</script>

<body>
<hr>
<asp:label id="ErrorMessage" font-size="12" font-bold="true"
runat=server/>
<hr>
<p>Return to <a href="/">Your application's entry page</a>
</body>
</html>
-------------

You don't need to catch all those errors if you don't want to, but why
only
catch 404 errors when all the ones listed in the Case statement are
available ?




Juan T. Llibre, asp.net MVP
asp.net faq : http://asp.net.do/faq/
foros de asp.net, en español : http://asp.net.do/foros/
======================================
 
J

Juan T. Llibre

re:
!> Would this still work for something like:
!> http://www.mydomain.com/thispagedoesntexist.htm

No, it wouldn't...unless you add *.htm/*.html to the aspnet_isapi.dll file mappings.

Most asp.net developers don't run .htm/.html files, though.
If they do, adding them will take care of the problem.




Juan T. Llibre, asp.net MVP
asp.net faq : http://asp.net.do/faq/
foros de asp.net, en español : http://asp.net.do/foros/
======================================
 
J

Juan T. Llibre

re:
!> Indeed - was just checking... :)

Much appreciated, as I had not made that clear.

One more thing I should add is that the sample code will *only* catch HttpException errors.

Coding exception catching should still be programmed into the page,
using Try, Catch, Finally syntax.




Juan T. Llibre, asp.net MVP
asp.net faq : http://asp.net.do/faq/
foros de asp.net, en español : http://asp.net.do/foros/
======================================
 
J

JJ

Thanks for that. Unfortunately, it has exposed another problem:

The solution works well for when a user tries to access an aspx page that
does not exist, but when I type a partial directory name in the url like:

http://www.mysite.com/testdirecto

The error page gets displayed, but with no theme and loss of all the
graphics (like the page has lost its reference to the themes folder).
When debugging the Global.asax line 'Server.Transfer("~/Error.aspx")' is run
several times when entring a url like the one above, yet on typing a full
reference to a non existent aspx page the line only gets run once and the
error page displays correctly..

Any ideas what the problem is here?

Many thanks,

JJ
 
J

JJ

I see that, as pointed out by Mark that Server.Transfer doesn't work for non
aspx pages.
This problem raises its head when you try entering a non exisitent url
without the '.aspx'.

I would guess that at the 'Global.asax' level I need to check if the
referring url has a '.aspx' extension on it and if it doesn't, use
Response.Redirect instead.
I'm currently trying to work out how I do that....

I'm beginning to confuse myself as to why using the customErrors section of
the web.config is not enough in itself. I guess this doesn't kick in when an
unhandled expception is encountered...

JJ
 
J

JJ

This is the way I have done it, at least until you more experienced
programmers can tell me how it shoud be done:

In Global.asax I have put:
protected void Application_Error(Object sender, EventArgs e)
{
Exception ex = Server.GetLastError().GetBaseException();
if (ex is HttpException )
{
if (this.Request.Url.ToString().EndsWith(".aspx"))
{
Server.Transfer("~/Error.aspx");
}

}


In order to deal with all the possible urls that are not ending in '.aspx' I
have left the customError section in web.config to 'On', and set it to point
to the same Error.aspx page as in the Global.aspx file.

In the Error.aspx page I check for an exception (as would be received if the
last statement was the 'Server.Transfer("~/Error.aspx")' line in
Global.asax, and if the exception is not null, I proceed with the code
detailed by Juan.

If the Exception is not present, I know we have reached the page by way of
the customErrors section (redirect I guess), and based on the
queryparameter, I can display the appropriate error message.

This is the only way I could get application level exceptions handled AND
cope with weird/non aspx/non existent page requests.

Now someone will tell me there's a much easier way.... ;-)

JJ
 
M

Mark Rae

One more thing I should add is that the sample code will *only* catch
HttpException errors.

Coding exception catching should still be programmed into the page,
using Try, Catch, Finally syntax.

Absolutely!
 
M

Mark Rae

I see that, as pointed out by Mark that Server.Transfer doesn't work for
non aspx pages.

It's not that Server.Transfer doesn't work for non aspx pages per se, but
rather that non aspx pages (e.g. *.htm etc) don't actually get processed by
ASP.NET's ISAPI DLL by default. This can be changed, but that requires
access to IIS on the webserver itself...
This problem raises its head when you try entering a non exisitent url
without the '.aspx'.

Same problem...
I would guess that at the 'Global.asax' level I need to check if the
referring url has a '.aspx' extension on it and if it doesn't, use
Response.Redirect instead.

See above - only files which are "recognised" by the ASP.NET ISAPI will
actually get processed by ASP.NET... If you try to access a missing HTML
file, ASP.NET won't even figure in the equation, so the contents of
Global.asax et al is completely irrelevant...
I'm currently trying to work out how I do that....

I don't think you can, unless you can add the file extension(s) in question
to the ASP.NET ISAPI filter...
I'm beginning to confuse myself as to why using the customErrors section
of the web.config is not enough in itself. I guess this doesn't kick in
when an unhandled expception is encountered...

See above.
 
J

JJ

Hi Mark.

As this will likely be on a shared web server, I won't have access to IIS.

I think I understand, but it seems the method I've used does bypass the
problem (fingers firmly crossed).

The site in question doesn't have any html files, but I do want it to handle
'user' errors, like typing in a non existent url (with or without any
extension).
Using the previous solution wouldn't do this. Typing in
'http://www.myserver.com/areallystupidurl' would cause irratic behaviour
undoubtedly because of the reasons you have detailed.

The code did reach the Application_Error in the Global.asax, even though the
'error' was not from an .aspx page (it was in fact from no existent page).
So I thought that there is where I'd filter out whether to do a
Server.Transfer leave the customErrors section do its Response.Redirect.

So the 'solution' I've detailed, seems to handle non existent urls (of any
extension) and those with no extension at all, without having to access IIS.

(As I say it 'seems' to work but I'd feel more confortable if you would give
it your theoretical 'seal' of approval.... ;-) )

JJ
 
M

Mark Rae

(As I say it 'seems' to work but I'd feel more confortable if you would
give it your theoretical 'seal' of approval.... ;-) )

As I am neither a Microsoft employee nor an MVP, I have no 'seal of
approval' (theoretical or otherwise) to give you... :)
 
J

JJ

Well I'll just have to run with it then... ;-)

Just don't go visiting my site and breaking it.

Thanks yet again,
JJ
 
J

JJ

Its a bit odd, but it turns out that my solution worked ok on my local
machines web servers, but not on the host.
So all I can do is present a polite error message for .aspx pages that are
missing, but if someone types in a url with no .aspx extension, then the
default error pages are presented,

JJ
 
J

Juan T. Llibre

re:
!> So all I can do is present a polite error message for .aspx pages that are
!> missing, but if someone types in a url with no .aspx extension, then the
!> default error pages are presented,

Hi, JJ.

My question to you is : why are you trying to
catch incomplete urls at the Application level ?

I catch "regular" 404's for aspx pages in the Application_Error event,
by using server.transfer to an error.aspx page, but catch incomplete urls
with the standard 404 error page at Drive:\WINDOWS\Help\iisHelp\common.

If you want a "pretty" page for incomplete urls, just modify 404b.htm in that directory.

Check it out :

Try hitting : http://asp.net.do/test/some
....and then try hitting http://asp.net.do/test/some.aspx

The first one has a custom message for you.
The second one is caught by my Application_Error and server.transfer("Errors.aspx") routines.







Juan T. Llibre, asp.net MVP
asp.net faq : http://asp.net.do/faq/
foros de asp.net, en español : http://asp.net.do/foros/
======================================
 
J

JJ

Thanks for that - my personal 404 page in cyberspace ;-)

I guess I was trying the incorrect url entry there because that's where
incorrect .aspx pages were caught - there's logic there somewhere (I think).
I have just tried redirecting IIS's 404 error to the same page, but realise
now that IIS doesn't understand relative links so won't like a page that is
based on a master and is themed....
I guess I have to either use a straight html page or an aspx one with full
paths to images for this ?

Thanks,

JJ

Juan T. Llibre said:
re:
!> So all I can do is present a polite error message for .aspx pages that
are
!> missing, but if someone types in a url with no .aspx extension, then
the
!> default error pages are presented,

Hi, JJ.

My question to you is : why are you trying to
catch incomplete urls at the Application level ?

I catch "regular" 404's for aspx pages in the Application_Error event,
by using server.transfer to an error.aspx page, but catch incomplete urls
with the standard 404 error page at Drive:\WINDOWS\Help\iisHelp\common.

If you want a "pretty" page for incomplete urls, just modify 404b.htm in
that directory.

Check it out :

Try hitting : http://asp.net.do/test/some
...and then try hitting http://asp.net.do/test/some.aspx

The first one has a custom message for you.
The second one is caught by my Application_Error and
server.transfer("Errors.aspx") routines.







Juan T. Llibre, asp.net MVP
asp.net faq : http://asp.net.do/faq/
foros de asp.net, en español : http://asp.net.do/foros/
======================================
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top