My question is what's the "best practice" means to accomplish what I
described. Should I handle Application_Error in global.asax and do
those things? Are other folks doing something different?
Thanks,
Donnie
The best practice would be to use Elmah as-is and to configure a custom
error page in the web.config file.
Elmah will catch errors and log them without any interference on the rest
of the application. If you want a custom error page, that can easily be
set up in the standard ASP.NET web.config CustomErrors section. Neither
will affect the operation of the other.
Regards,
Scott
> Should I handle Application_Error in global.asax and do
> those things?
Yes, do a Server.Execute to your custom error page within there. You can use the GetHttpCode method of the HttpException object to find out which custom error page to display (for example, 404.aspx, 500.aspx, etc.). One problem I've noticed with ASP.NET is that Server.Execute resets the status code of the HTTP response so you have to tuck that away in a local variable on the stack and set it back on Response.StatusCode once your Server.Execute returns. Finally, you can issue a Server.ClearError before Application_Error returns. Fortunately, none of this affects ELMAH's ability to log the exception at the same time.
- Atif
void Application_Error(object sender, EventArgs e)
{
Exception uncaught = Server.GetLastError();
if (uncaught is HttpUnhandledException && uncaught.InnerException !
= null)
{
uncaught = uncaught.InnerException;
}
int origCode = ((HttpException) uncaught).GetHttpCode();
Server.Execute("~/MyCustomErrorPage.aspx");
HttpContext.Current.Response.StatusCode = origCode;
Server.ClearError():
}
Is that about right? One thing I really want to make sure of is that
we stop getting unhandled error entries in the system event log.
I appreciate the input.
Donnie
Yep, some simplifications aside, that's about right.
Unfortunately, Server.Execute is throwing a spurious error about
"Cannot use a leading .. to exit above the top directory" when I
execute the error page. If I run this same page normally (via
browser), it works fine. Based on the URL being resolved in the
callstack, I've proven that the page refers to the URL as "~/images/
whatever.jpg" but by the time it gets to the .net method in question,
it looks like "/../images/whatever.jpg". If I get rid of the leading
'~' (since my app is at the root, it would work), sure enough the
error goes away but then shows up for any other URL in the app of the
form "~/someotherfile.ext" (obviously there are zillions of those).
Assuredly as asp.net bug with the weird situation of Server.Execute in
the middle of handling an error for a page that had been executing in
a standard context.
Oh well - will have to revisit it later.
Donnie
object o = BuildManager.CreateInstanceFromVirtualPath(
"~/ErrorPage.aspx", typeof(IHttpHandler));
StringWriter sw = new StringWriter();
Server.Execute((IHttpHandler) o, sw, false);
HttpContext.Current.Response.Clear();
HttpContext.Current.Response.StatusCode = // Code from
Server.LastError();
HttpContext.Current.Response.Write(sw.ToString());
Server.ClearError();
That code seems to be working well, and accomplishes the two goals I
had: a) Preventing entries in the system event log; b) adhering to
Atif's recommendation that the error page return a semantically
accurate HTTP status code. Note that the customErrors mode in
Web.config must be "Off" for Application_Error to get called in the
first place.
FWIW...
Donnie
It's a working example of what I was talking about that's deployed in production. I'm not sure I see why you had to go through the BuildManager rather than being able to rely on just Server.Execute, but perhaps having the above code may help shed some light.
- Atif
-----Original Message-----
From: el...@googlegroups.com [mailto:el...@googlegroups.com] On Behalf Of soccerdad
Sent: Tuesday, October 02, 2007 8:36 PM
To: ELMAH
Subject: [ELMAH] Re: ELMAH and custom error page
Interesting. It's not been my observation at all. Are we using the same ASP.NET here considering all the discrepancies? :) AFAIK, Application_Error has always been called unconditionally. In all my apps, I've left the customError mode to remoteOnly.
- Atif
-----Original Message-----
From: el...@googlegroups.com [mailto:el...@googlegroups.com] On Behalf Of soccerdad
Sent: Tuesday, October 02, 2007 8:36 PM
To: ELMAH
Subject: [ELMAH] Re: ELMAH and custom error page
The rationale under the section, "Custom Error Handling in ASP.NET and Status Codes," seems plain wrong to me. Rich seems to be hitting the right note here in response:
http://professionalaspnet.com/archive/2007/09/30/Properly-Using-Custom-Error-Pages-in-ASP.NET.aspx#395
The following blog post is a nice eye-opener into just how much of what we assume and do is wrong or misunderstood:
http://coderjournal.com/2007/04/world-of-http11-status-codes/
- Atif
-----Original Message-----
From: el...@googlegroups.com [mailto:el...@googlegroups.com] On Behalf Of soccerdad
Sent: Tuesday, October 02, 2007 8:36 PM
To: ELMAH
Subject: [ELMAH] Re: ELMAH and custom error page
- Eric
http://forums.asp.net/t/1165013.aspx
I was in contact with a number of people, including Scott Guthrie and
another developer at MS, about Server.Execute. They basically
confirmed that calling Server.Execute in the context of a different
relative path than the currently executing page could / would cause
problems. Rick Strahl also confirmed this expectation. The MS
developer said that the BuildManager approach was a sound one and that
it shouldn't have any issues in a medium-trust environment.
FWIW...
Donnie
On Oct 2, 3:18 pm, Atif Aziz <Atif.A...@skybow.com> wrote:
> Thanks for sharing your findings, Donnie. Incidentally, I checked-in some code into the DotNetKicks project that returns custom error pages as I had suggested earlier in our thread. You might want to check out Application_Error in Global.asax.cs over at:http://dotnetkicks.googlecode.com/svn/trunk/DotNetKicks/Incremental.K...
I do agree with you - a 302 / 200 is not an appropriate response to a
real error. I may check MS' issues site and open a case suggesting
that customErrors be enhanced to behave the way we've developed based
on new attributes in the Web.config, e.g. 'preserveStatusCode="true"'.
Thanks for all the feedback and links on this topic.
Donnie
On Oct 2, 3:18 pm, Atif Aziz <Atif.A...@skybow.com> wrote:
> Thanks for sharing your findings, Donnie. Incidentally, I checked-in some code into the DotNetKicks project that returns custom error pages as I had suggested earlier in our thread. You might want to check out Application_Error in Global.asax.cs over at:http://dotnetkicks.googlecode.com/svn/trunk/DotNetKicks/Incremental.K...
OK, I can imagine this could turn out to be an issue because I've simply come across such oddities in ASP.NET before, but I can't seem to reproduce it for the life of me. Want to take a crack at the attached plain-vanilla solution? It has the setup (I think) you described in your ASP.NET Forums thread and Server.Execute seems to be working fine along with image references.
If you mean submitting it as a bug (and a bug it is) over at http://connect.microsoft.com/VisualStudio then you'll get my vote. :)
>>
The final task of Application_Error is to execute the Redirect() or Transfer(). From the discussion of configuring behavior above, you already know that which of these you choose is tied to how the Exception is stored, and that some combinations work while others don't.
<<
The decision to use Redirect or Transfer is very fundamental to what you're communicating to the user agent from the point of view of the HTTP protocol and nothing to do with how the Exception is stored.
>>
The features of the storage methods usually drive the decision. But occasionally, features of Redirect() and Transfer() drive the decision.
<<
Again, the features don't drive the decision here, but the protocol. And this part gets interesting where the rationale comes in...
>>
If this seems to be an argument in favor of Transfer, it isn't. The built-in customErrors feature uses Redirect and not Transfer for a reason. The rationale of the ASP.NET development team is that Redirect accurately displays the URL of the custom error page, while Server.Transfer is intended for "switchboard"-style pages (as on content management sites) where the true URL is preferably hidden.
<<
Redirect accurately displays the URL of the custom error page? Who cares about the URL or the error page? That's precisely what you want to hide! It's an implementation detail of your server-side.
- Atif
-----Original Message-----
From: el...@googlegroups.com [mailto:el...@googlegroups.com] On Behalf Of Eric
Sent: Tuesday, October 02, 2007 10:47 PM
To: ELMAH
Subject: [ELMAH] Re: ELMAH and custom error page
Thanks for your answer.
If I understand it correctly, only Redirect will send something to the
agent (Redirect Code). Transfer/Execute will not violate the
protocol.
I agree that in the article has the wrong 'feature' view.
I think the reason for his article was the problem with the built-in
customErrors feature,
where you loose all the exception information in the error page.
So he build a vehicle around the different transfer/redirect methods
and for transfering the error infos via context/session/querystring
etc
to show a full featured error page.
Exaggerated, but I was blended too.
Eric