我在共享主机上部署的 ASP.NET MVC 应用程序上遇到自定义错误问题。我创建了一个 ErrorController 并将以下代码添加到 Global.asax 以捕获未处理的异常,记录它们,然后将控制权转移到 ErrorController 以显示自定义错误。此代码取自此处:
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 肯定会触发,因为日志记录工作正常,但我没有显示我的自定义错误页面,而是获得了 Go Daddy 通用错误页面。从博客文章的标题中,我注意到它使用了 MVC 框架的 Release Candidate 2。1.0 中是否发生了一些变化,导致最后一行代码不起作用?像往常一样,它在我的机器上运行良好。
任何建议将不胜感激。
编辑:忘了提到我已经尝试了 Web.config 中 customErrors 模式的所有 3 种可能性(Off、On 和 RemoteOnly)。无论此设置如何,结果都相同。
编辑 2:我也尝试过在控制器类上使用和不使用 [HandleError] 装饰。
更新:我已经弄清楚并修复了 404。Go Daddy 的主机控制中心的设置面板中有一个部分可以控制 404 行为,并且默认显示它们的通用页面,显然这会覆盖任何 Web.config 设置。所以我的自定义 404 页面现在按预期显示。但是,500s 和 503s 仍然无法正常工作。如果 Sql Server 抛出异常,我在 HomeController 中有代码来获取内容的静态文本版本,如下所示:
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);
}
}
}
这是尝试获取静态内容的代码:
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;
}
我已经验证,如果我更改连接字符串以生成 SqlException,代码会正确记录错误,然后抓取并显示静态内容。但是,如果我还更改了 Web.config 中静态文本文件的路径以测试 503 版本的主视图,那么我得到的是一个除了“服务不可用”之外什么都没有的页面。就是这样。没有具有网站外观的自定义 503 消息。
有没有人对可能有帮助的代码改进有任何建议?向 HttpResponse 添加不同的标头会有所帮助吗?还是 Go Daddy 强硬地劫持了 503?