I'm having an issue with custom errors on an ASP.NET MVC app I've deployed on my shared host. I've created an ErrorController and added the following code to Global.asax to catch unhandled exceptions, log them, and then transfer control to the ErrorController to display custom errors. This code is taken from here:
protected void Application_Error(object sender, EventArgs e)
{
Exception ex = Server.GetLastError();
Response.Clear();
HttpException httpEx = ex as HttpException;
RouteData routeData = new RouteData();
routeData.Values.Add("controller", "Error");
if (httpEx == null)
{
routeData.Values.Add("action", "Index");
}
else
{
switch (httpEx.GetHttpCode())
{
case 404:
routeData.Values.Add("action", "HttpError404");
break;
case 500:
routeData.Values.Add("action", "HttpError500");
break;
case 503:
routeData.Values.Add("action", "HttpError503");
break;
default:
routeData.Values.Add("action", "Index");
break;
}
}
ExceptionLogger.LogException(ex); // <- This is working. Errors get logged
routeData.Values.Add("error", ex);
Server.ClearError();
IController controller = new ErrorController();
// The next line doesn't seem to be working
controller.Execute(new RequestContext(new HttpContextWrapper(Context), routeData));
}
Application_Error is definitely firing because the logging works fine, but instead of displaying my custom error pages, I get the Go Daddy generic ones. From the title of the blog post the above code is taken from, I notice that it uses Release Candidate 2 of the MVC framework. Did something change in 1.0 that makes the last line of code not work? As usual it works great on my machine.
Any suggestions will be greatly appreciated.
Edit: Forgot to mention that I've tried all 3 possiblities for the customErrors mode in Web.config (Off, On, and RemoteOnly). Same results regardless of this setting.
Edit 2: And I've also tried it with and without the [HandleError] decoration on the Controller classes.
Update: I've figured out and fixed the 404s. There is a section of the Settings panel in Go Daddy's Hosting Control Center where 404 behavior can be controlled and the default is to show their generic page, and apparently this overrides any Web.config settings. So my custom 404 page is now showing as intended. However, 500s and 503s are still not working. I've got code in the HomeController to grab a static text version of the content if Sql Server throws an exception as follows:
public ActionResult Index()
{
CcmDataClassesDataContext dc = new CcmDataClassesDataContext();
// This might generate an exception which will be handled in the OnException override
HomeContent hc = dc.HomeContents.GetCurrentContent();
ViewData["bodyId"] = "home";
return View(hc);
}
protected override void OnException(ExceptionContext filterContext)
{
// Only concerned here with SqlExceptions so an HTTP 503 message can
// be displayed in the Home View. All others will bubble up to the
// Global.asax.cs and be handled/logged there.
System.Data.SqlClient.SqlException sqlEx =
filterContext.Exception as System.Data.SqlClient.SqlException;
if (sqlEx != null)
{
try
{
ExceptionLogger.LogException(sqlEx);
}
catch
{
// couldn't log exception, continue without crashing
}
ViewData["bodyId"] = "home";
filterContext.ExceptionHandled = true;
HomeContent hc = ContentHelper.GetStaticContent();
if (hc == null)
{
// Couldn't get static content. Display friendly message on Home View.
Response.StatusCode = 503;
this.View("ContentError").ExecuteResult(this.ControllerContext);
}
else
{
// Pass the static content to the regular Home View
this.View("Index", hc).ExecuteResult(this.ControllerContext);
}
}
}
Here's the code that attempts to fetch the static content:
public static HomeContent GetStaticContent()
{
HomeContent hc;
try
{
string path = Configuration.CcmConfigSection.Config.Content.PathToStaticContent;
string fileText = File.ReadAllText(path);
string regex = @"^[^#]([^\r\n]*)";
MatchCollection matches = Regex.Matches(fileText, regex, RegexOptions.Multiline);
hc = new HomeContent
{
ID = Convert.ToInt32(matches[0].Value),
Title = matches[1].Value,
DateAdded = DateTime.Parse(matches[2].Value),
Body = matches[3].Value,
IsCurrent = true
};
}
catch (Exception ex)
{
try
{
ExceptionLogger.LogException(ex);
}
catch
{
// couldn't log exception, continue without crashing
}
hc = null;
}
return hc;
}
I've verified that if I change the connection string to generate a SqlException, the code properly logs the error and then grabs and displays the static content. But if I also change the path to the static text file in Web.config to test the 503 version of the Home View, what I get instead is a page with nothing other than "service unavailable". That's it. No custom 503 message with the look and feel of the site.
Does anyone have any suggestions on improvements to the code that might help? Would it help to add different headers to the HttpResponse? Or is Go Daddy heavy-handedly hijacking the 503s?