我想要为 500、404 和 403 显示自定义错误页面。这是我所做的:
在 web.config 中启用自定义错误,如下所示:
对于 500,它显示自定义错误页面。对于其他人,它没有。
有什么我想念的吗?
当我阅读 HandleErrorAttribute
类的 OnException
方法中的代码时,看起来这并不是显示自定义错误的全部,它只处理 500 个。
我该怎么做才能处理其他错误?
我当前的设置(在 MVC3 上,但我认为它仍然适用)依赖于 ErrorController
,所以我使用:
<system.web>
<customErrors mode="On" defaultRedirect="~/Error">
<error redirect="~/Error/NotFound" statusCode="404" />
</customErrors>
</system.web>
控制器包含以下内容:
public class ErrorController : Controller
{
public ViewResult Index()
{
return View("Error");
}
public ViewResult NotFound()
{
Response.StatusCode = 404; //you may want to set this to 200
return View("NotFound");
}
}
以及您实现它们的方式的视图。不过,我倾向于添加一些逻辑,以在应用程序处于调试模式时显示堆栈跟踪和错误信息。所以 Error.cshtml 看起来像这样:
@model System.Web.Mvc.HandleErrorInfo
@{
Layout = "_Layout.cshtml";
ViewBag.Title = "Error";
}
<div class="list-header clearfix">
<span>Error</span>
</div>
<div class="list-sfs-holder">
<div class="alert alert-error">
An unexpected error has occurred. Please contact the system administrator.
</div>
@if (Model != null && HttpContext.Current.IsDebuggingEnabled)
{
<div>
<p>
<b>Exception:</b> @Model.Exception.Message<br />
<b>Controller:</b> @Model.ControllerName<br />
<b>Action:</b> @Model.ActionName
</p>
<div style="overflow:scroll">
<pre>
@Model.Exception.StackTrace
</pre>
</div>
</div>
}
</div>
我已经完成了 pablo 解决方案,但我总是遇到错误(MVC4)
未找到视图“错误”或其主视图,或者没有视图引擎支持搜索的位置。
要摆脱这种情况,请删除该行
filters.Add(new HandleErrorAttribute());
在 FilterConfig.cs 中
我做的事情比发布的其他解决方案需要更少的编码。
首先,在我的 web.config 中,我有以下内容:
<customErrors mode="On" defaultRedirect="~/ErrorPage/Oops">
<error redirect="~/ErrorPage/Oops/404" statusCode="404" />
<error redirect="~/ErrorPage/Oops/500" statusCode="500" />
</customErrors>
控制器(/Controllers/ErrorPageController.cs)包含以下内容:
public class ErrorPageController : Controller
{
public ActionResult Oops(int id)
{
Response.StatusCode = id;
return View();
}
}
最后,视图包含以下内容(为简单起见已删除,但它可以包含:
@{ ViewBag.Title = "糟糕!遇到错误"; }
@Response.Status
可能原因: tr>
HTTP @Response.StatusCode - @Response.StatusDescription
就这么简单。它可以轻松扩展以提供更详细的错误信息,但 ELMAH 会为我处理这些状态码 & statusDescription 是我通常需要的。
这里似乎有许多步骤混杂在一起。我会提出我从头开始做的事情。
创建 ErrorPage 控制器 public class ErrorPageController : Controller { public ActionResult Index() { return View(); } 公共 ActionResult Oops(int id) { Response.StatusCode = id;返回视图(); } } 为这两个动作添加视图(右键单击 -> 添加视图)。这些应该出现在名为 ErrorPage 的文件夹中。在 App_Start 中打开 FilterConfig.cs 并注释掉错误处理过滤器。 public static void RegisterGlobalFilters(GlobalFilterCollection filters) { // 移除这个过滤器,因为我们想通过 ErrorPage 控制器自己处理错误 //filters.Add(new HandleErrorAttribute());在 web.config 中添加以下
An exception occurred while processing your request. Additionally, another exception occurred while executing the custom error page for the first exception. The request has been terminated.
我从您的代码中获取的所有内容都在 web.config 文件中,我添加了 <error redirect = "~/ControllerName/ActionName" statusCode="404"/>
并且它运行良好:) 其余代码来自@Pablo 的答案。我正在使用 MVC 5 和实体框架 6。我没有从 FilterConfig.cs
中删除 filters.Add(new HandleErrorAttribute())
我会推荐使用 Global.asax.cs 文件。
protected void Application_Error(Object sender, EventArgs e)
{
var exception = Server.GetLastError();
if (exception is HttpUnhandledException)
{
Server.Transfer("~/Error.aspx");
}
if (exception != null)
{
Server.Transfer("~/Error.aspx");
}
try
{
// This is to stop a problem where we were seeing "gibberish" in the
// chrome and firefox browsers
HttpApplication app = sender as HttpApplication;
app.Response.Filter = null;
}
catch
{
}
}
基于 maxspan 发布的答案,我整理了一个最小的 sample project on GitHub,显示了所有工作部分。
基本上,我们只需向 global.asax.cs 添加一个 Application_Error
方法来拦截异常并让我们有机会重定向(或更准确地说,传输请求)到自定义错误页面。
protected void Application_Error(Object sender, EventArgs e)
{
// See http://stackoverflow.com/questions/13905164/how-to-make-custom-error-pages-work-in-asp-net-mvc-4
// for additional context on use of this technique
var exception = Server.GetLastError();
if (exception != null)
{
// This would be a good place to log any relevant details about the exception.
// Since we are going to pass exception information to our error page via querystring,
// it will only be practical to issue a short message. Further detail would have to be logged somewhere.
// This will invoke our error page, passing the exception message via querystring parameter
// Note that we chose to use Server.TransferRequest, which is only supported in IIS 7 and above.
// As an alternative, Response.Redirect could be used instead.
// Server.Transfer does not work (see https://support.microsoft.com/en-us/kb/320439 )
Server.TransferRequest("~/Error?Message=" + exception.Message);
}
}
错误控制器:
/// <summary>
/// This controller exists to provide the error page
/// </summary>
public class ErrorController : Controller
{
/// <summary>
/// This action represents the error page
/// </summary>
/// <param name="Message">Error message to be displayed (provided via querystring parameter - a design choice)</param>
/// <returns></returns>
public ActionResult Index(string Message)
{
// We choose to use the ViewBag to communicate the error message to the view
ViewBag.Message = Message;
return View();
}
}
错误页面视图:
<!DOCTYPE html>
<html>
<head>
<title>Error</title>
</head>
<body>
<h2>My Error</h2>
<p>@ViewBag.Message</p>
</body>
</html>
除了在 FilterConfig.cs 中禁用/删除 filters.Add(new HandleErrorAttribute())
之外,不涉及其他任何内容
public class FilterConfig
{
public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
//filters.Add(new HandleErrorAttribute()); // <== disable/remove
}
}
虽然实现起来非常简单,但我在这种方法中看到的一个缺点是使用查询字符串将异常信息传递到目标错误页面。
我已经完成了所有设置,但在我们的暂存服务器上仍然看不到状态代码 500 的正确错误页面,尽管事实上在本地开发服务器上一切正常。
我从 Rick Strahl 那里找到了对我有帮助的 this blog post。
我需要将 Response.TrySkipIisCustomErrors = true;
添加到我的自定义错误处理代码中。
这是我的解决方案。在我看来,使用 [ExportModelStateToTempData] / [ImportModelStateFromTempData] 不舒服。
~/Views/Home/Error.cshtml:
@{
ViewBag.Title = "Error";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<h2>Error</h2>
<hr/>
<div style="min-height: 400px;">
@Html.ValidationMessage("Error")
<br />
<br />
<button onclick="Error_goBack()" class="k-button">Go Back</button>
<script>
function Error_goBack() {
window.history.back()
}
</script>
</div>
~/控制器/HomeController.sc:
public class HomeController : BaseController
{
public ActionResult Index()
{
return View();
}
public ActionResult Error()
{
return this.View();
}
...
}
~/Controllers/BaseController.sc:
public class BaseController : Controller
{
public BaseController() { }
protected override void OnActionExecuted(ActionExecutedContext filterContext)
{
if (filterContext.Result is ViewResult)
{
if (filterContext.Controller.TempData.ContainsKey("Error"))
{
var modelState = filterContext.Controller.TempData["Error"] as ModelState;
filterContext.Controller.ViewData.ModelState.Merge(new ModelStateDictionary() { new KeyValuePair<string, ModelState>("Error", modelState) });
filterContext.Controller.TempData.Remove("Error");
}
}
if ((filterContext.Result is RedirectResult) || (filterContext.Result is RedirectToRouteResult))
{
if (filterContext.Controller.ViewData.ModelState.ContainsKey("Error"))
{
filterContext.Controller.TempData["Error"] = filterContext.Controller.ViewData.ModelState["Error"];
}
}
base.OnActionExecuted(filterContext);
}
}
~/Controllers/MyController.sc:
public class MyController : BaseController
{
public ActionResult Index()
{
return View();
}
public ActionResult Details(int id)
{
if (id != 5)
{
ModelState.AddModelError("Error", "Specified row does not exist.");
return RedirectToAction("Error", "Home");
}
else
{
return View("Specified row exists.");
}
}
}
祝你项目成功;-)
您可以在不破解 global.cs、弄乱 HandleErrorAttribute、执行 Response.TrySkipIisCustomErrors、连接 Application_Error 或其他任何事情的情况下正常工作的错误:
在 system.web 中(只是通常,开/关)
<customErrors mode="On">
<error redirect="/error/401" statusCode="401" />
<error redirect="/error/500" statusCode="500" />
</customErrors>
并在 system.webServer
<httpErrors existingResponse="PassThrough" />
现在事情应该按预期运行,您可以使用 ErrorController 来显示您需要的任何内容。
在 web.config 中添加如下 system.webserver 标签,
<system.webServer>
<httpErrors errorMode="Custom" existingResponse="Replace">
<remove statusCode="404"/>
<remove statusCode="500"/>
<error statusCode="404" responseMode="ExecuteURL" path="/Error/NotFound"/>
<error statusCode="500" responseMode="ExecuteURL"path="/Error/ErrorPage"/>
</httpErrors>
并添加一个控制器,
public class ErrorController : Controller
{
//
// GET: /Error/
[GET("/Error/NotFound")]
public ActionResult NotFound()
{
Response.StatusCode = 404;
return View();
}
[GET("/Error/ErrorPage")]
public ActionResult ErrorPage()
{
Response.StatusCode = 500;
return View();
}
}
并加上他们尊重的观点,我想这肯定会奏效。
我从以下位置找到了这个解决方案:Neptune Century
看来我来晚了,但你最好也检查一下。
所以在 system.web
中用于缓存应用程序中的异常,例如 return HttpNotFound()
<system.web>
<customErrors mode="RemoteOnly">
<error statusCode="404" redirect="/page-not-found" />
<error statusCode="500" redirect="/internal-server-error" />
</customErrors>
</system.web>
并在 system.webServer
中用于捕获 IIS 捕获但未进入 asp.net 框架的错误
<system.webServer>
<httpErrors errorMode="DetailedLocalOnly">
<remove statusCode="404"/>
<error statusCode="404" path="/page-not-found" responseMode="Redirect"/>
<remove statusCode="500"/>
<error statusCode="500" path="/internal-server-error" responseMode="Redirect"/>
</system.webServer>
在最后一个中,如果您担心客户端响应,请将 responseMode="Redirect"
更改为 responseMode="File"
并提供静态 html 文件,因为这将显示一个带有 200 响应代码的友好页面。
CustomerErrors
元素上有redirectMode="ResponseRewrite"
//you may want to set this to 200
的注释。不要那样做!