In my ASP.NET MVC application I want to have a generic error page that is showed together with returning HTTP 500. Something like this page on Stack Overflow.
Of course I'd like to reuse as much code as possible so that the page is styled the same way as other pages in my application, so I want to have an ASP.NET page reusing the master pages, not a plain HTML file. However if I do so I have a page that contains some server-side executable code for creating actual HTML served to the client. In case of Stack Overflow generic error page it's the code checking whether the user is registered, retrieving his rep, etc, and inserting elements for that into HTML.
That code can fail and if that happens the page isn't properly constructed and an exception is thrown in the server.
How do I handle that situation (error when building HTML for the error page) gracefully? What's the typical approach?
You can handle default errors at the application level either by modifying your application's configuration or by adding an Application_Error handler in the Global. asax file of your application. You can handle default errors and HTTP errors by adding a customErrors section to the Web. config file.
The “Server error in '/' application” can occur when a file extension does not have permission to run on the server. When exploring a solution to a “Server error in '/' application”, first ensure that you are using the correct file name.
I like to start by categorize the possible errors.
To now show the error page, but only in rare cases.
So when user make actions with out page, we try to capture all wrong input of the user, and show him what to do to continue with out any error.
You can start by capture on global.asax
all errors using the void Application_Error(object sender, EventArgs e)
void Application_Error(object sender, EventArgs e)
{
try
{
Exception LastOneError = Server.GetLastError();
if (LastOneError != null)
{
Debug.Fail("Unhandled error: " + LastOneError.ToString());
if (!(EventLog.SourceExists(SourceName)))
EventLog.CreateEventSource(SourceName, LogName);
EventLog MyLog = new EventLog();
MyLog.Source = SourceName;
StringBuilder cReportMe = new StringBuilder();
cReportMe.Append("[Error come from ip:");
cReportMe.Append(GetRemoteHostIP());
cReportMe.Append("] ");
cReportMe.Append("Last Error:");
cReportMe.Append(LastOneError.ToString());
if (LastOneError.ToString().Contains("does not exist."))
{
// page not found
MyLog.WriteEntry(cReportMe.ToString(), EventLogEntryType.Warning, 998);
}
else
{
MyLog.WriteEntry(cReportMe.ToString(), EventLogEntryType.Error, 999);
}
}
}
catch (Exception ex)
{
Debug.Fail("Unhandled error: " + GlobalFun.GetErrorMessage(ex));
}
string cTheFile = HttpContext.Current.Request.Path;
// to avoid close loop and stackoverflow
if(!cTheFile.EndsWith("error.aspx"))
Server.Transfer("~/error.aspx");
}
This global error handle have one main goal, to tell me whats is not working and fail to handle it before reach here, so I log it (not manner the way of log it) and fix it soon. When I debug my code I did not make the server transfer to be able to locate the error fast.
In this case is better to now show any error but just reload the page by making a redirect. How to know if its trying to hack the page ?
If on post back you get some CRC/hach error of your parameters you know that. Look that answer https://stackoverflow.com/a/2551810/159270 to see an example of a viewstate error and how to handle it.
I know that MVC did not have viewstate, but you may have other encrypted string on your code, or some kind of security that you can know when its broken. This is the general idea:
if(IsPostBack && HashErrorOnParametres)
{
LogIt();
Responce.Redirect(Request.RawUrl, true);
return;
}
Let say that your database is not open at all, then all users start to see the error page from the general handler. There you may have an extra option to restart the pool, or stop the pages after 20 errors in the last 5 minute, or something similar, and send you email to run and fix this very hard error.
I think that all the possible known errors must be handled inside the page using try/catch and show to the user a message for what go wrong, if this error is from the user, and of course log it to see it and fix it.
Breaking the page in parts, maybe one part is throw the error and the rest working good, if this is not so important you can simple hide this part, and show the rest, until you fix it. For example if you just show information's about a product, and a part that speak about one part is throw an error, you can simple hide this part and see it on the log and fix it.
Some time I was try to handle the error per page, using protected override void OnError(EventArgs e)
but this is not help me, and I remove it. I handle the errors per action, and if they are not critical I hide them until I fix them.
The rest normal errors is shown on the user, eg is not entered the correct data... a message for that and tell them what to fix.
As I say, my goal is to not show the error page at all.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With