如何在ASP中创建自定义错误页面。Net MVC 4

我想为500、404和403显示一个自定义错误页面。以下是我所做的:

  1. 启用web中的自定义错误。配置如下:

    <customErrors mode="On"
    defaultRedirect="~/Views/Shared/Error.cshtml">
    
    
    <error statusCode="403"
    redirect="~/Views/Shared/UnauthorizedAccess.cshtml" />
    
    
    <error statusCode="404"
    redirect="~/Views/Shared/FileNotFound.cshtml" />
    
    
    </customErrors>
    
  2. Registered HandleErrorAttribute as a global action filter in the FilterConfig class as follows:

    public static void RegisterGlobalFilters(GlobalFilterCollection filters)
    {
    filters.Add(new CustomHandleErrorAttribute());
    filters.Add(new AuthorizeAttribute());
    }
    
  3. Created a custom error page for each of the above messages. The default one for 500 was already available out of the box.

  4. Declared in each custom error page view that the model for the page is System.Web.Mvc.HandleErrorInfo

For 500, it shows the custom error page. For others, it doesn't.

Is there something I am missing?

It does look like this is not all there is to displaying custom errors as I read through the code in the OnException method of the HandleErrorAttribute class and it is handling only 500.

What do I have to do to handle other errors?

313093 次浏览

我目前的设置(在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");
}
}

视图就是你实现它们的方式。不过,我倾向于添加一些逻辑,以便在应用程序处于调试模式时显示堆栈跟踪和错误信息。所以错误。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>

我建议使用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
{
}
}

我做过pablo解决方案,我总是有错误(MVC4)

未找到视图'Error'或其主视图或没有视图引擎支持搜索位置。

要摆脱这个,删除线条 .

 filters.Add(new HandleErrorAttribute());

在FilterConfig.cs

我做了一些比其他解决方案需要更少的编码。

首先,在我的网里。配置,我有以下:

<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 = "Oops! Error Encountered"; }


<section id="Page">
<div class="col-xs-12 well">
<table cellspacing="5" cellpadding="3" style="background-color:#fff;width:100%;" class="table-responsive">
<tbody>
<tr>
<td valign="top" align="left" id="tableProps">
<img width="25" height="33" src="~/Images/PageError.gif" id="pagerrorImg">
</td>
<td width="360" valign="middle" align="left" id="tableProps2">
<h1 style="COLOR: black; FONT: 13pt/15pt verdana" id="errortype"><span id="errorText">@Response.Status</span></h1>
</td>
</tr>
<tr>
<td width="400" colspan="2" id="tablePropsWidth"><font style="COLOR: black; FONT: 8pt/11pt verdana">Possible causes:</font>
</td>
</tr>
<tr>
<td width="400" colspan="2" id="tablePropsWidth2">
<font style="COLOR: black; FONT: 8pt/11pt verdana" id="LID1">
<hr>
<ul>
<li id="list1">
<span class="infotext">
<strong>Baptist explanation: </strong>There
must be sin in your life. Everyone else opened it fine.<br>
</span>
</li>
<li>
<span class="infotext">
<strong>Presbyterian explanation: </strong>It's
not God's will for you to open this link.<br>
</span>
</li>
<li>
<span class="infotext">
<strong> Word of Faith explanation:</strong>
You lack the faith to open this link. Your negative words have prevented
you from realizing this link's fulfillment.<br>
</span>
</li>
<li>
<span class="infotext">
<strong>Charismatic explanation: </strong>Thou
art loosed! Be commanded to OPEN!<br>
</span>
</li>
<li>
<span class="infotext">
<strong>Unitarian explanation:</strong> All
links are equal, so if this link doesn't work for you, feel free to
experiment with other links that might bring you joy and fulfillment.<br>
</span>
</li>
<li>
<span class="infotext">
<strong>Buddhist explanation:</strong> .........................<br>
</span>
</li>
<li>
<span class="infotext">
<strong>Episcopalian explanation:</strong>
Are you saying you have something against homosexuals?<br>
</span>
</li>
<li>
<span class="infotext">
<strong>Christian Science explanation: </strong>There
really is no link.<br>
</span>
</li>
<li>
<span class="infotext">
<strong>Atheist explanation: </strong>The only
reason you think this link exists is because you needed to invent it.<br>
</span>
</li>
<li>
<span class="infotext">
<strong>Church counselor's explanation:</strong>
And what did you feel when the link would not open?
</span>
</li>
</ul>
<p>
<br>
</p>
<h2 style="font:8pt/11pt verdana; color:black" id="ietext">
<img width="16" height="16" align="top" src="~/Images/Search.gif">
HTTP @Response.StatusCode - @Response.StatusDescription <br>
</h2>
</font>
</td>
</tr>
</tbody>
</table>
</div>
</section>

就是这么简单。它可以很容易地扩展以提供更详细的错误信息,但是ELMAH为我处理了这些信息。状态码&statusDescription是我通常需要的。

这是我的解决方案。在我看来使用[ExportModelStateToTempData] / [ImportModelStateFromTempData]是不舒服的。

~ /视图/ 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();
}


...
}

~ /控制器/ 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);
}
}

~ /控制器/ 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.");
}
}
}

祝你们项目成功;-)

我已经设置好了一切,但仍然无法在登台服务器上看到状态代码500的正确错误页面,尽管在本地开发服务器上一切正常。

我从Rick Strahl找到了帮助我的这篇博文

我需要将Response.TrySkipIisCustomErrors = true;添加到自定义错误处理代码中。

这里似乎有许多步骤混杂在一起。我会把我从头开始做的事情说出来。

  1. 创建ErrorPage控制器

    public class ErrorPageController : Controller
    {
    public ActionResult Index()
    {
    return View();
    }
    
    
    public ActionResult Oops(int id)
    {
    Response.StatusCode = id;
    return View();
    }
    }
    
  2. Add views for these two actions (right click -> Add View). These should appear in a folder called ErrorPage.

  3. Inside App_Start open up FilterConfig.cs and comment out the error handling filter.

    public static void RegisterGlobalFilters(GlobalFilterCollection filters)
    {
    // Remove this filter because we want to handle errors ourselves via the ErrorPage controller
    //filters.Add(new HandleErrorAttribute());
    }
    
  4. Inside web.config add the following <customerErrors> entries, under System.Web

    <customErrors mode="On" defaultRedirect="~/ErrorPage/Oops">
    <error redirect="~/ErrorPage/Oops/404" statusCode="404" />
    <error redirect="~/ErrorPage/Oops/500" statusCode="500" />
    </customErrors>
    
  5. Test (of course). Throw an unhandled exception in your code and see it go to the page with id 500, and then use a URL to a page that does not exist to see 404.

基于maxspan发布的答案,我已经组合了一个最小的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
}
}

虽然实现起来非常简单,但我发现这种方法的一个缺点是使用querystring将异常信息传递到目标错误页面。

你可以得到正确工作的错误,而不入侵global.cs,扰乱HandleErrorAttribute,做响应。TrySkipIisCustomErrors,连接Application_Error,或者别的什么:

在系统。Web(只是平常的,开/关)

<customErrors mode="On">
<error redirect="/error/401" statusCode="401" />
<error redirect="/error/500" statusCode="500" />
</customErrors>

在system.webServer中

<httpErrors existingResponse="PassThrough" />

现在事情的表现应该和预期的一样了,您可以使用ErrorController来显示您需要的任何东西。

看来我来晚了,但你最好也看看这个。

因此,在system.web中缓存应用程序中的异常,例如返回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响应代码的友好页面。

在网络上。在系统下添加此配置。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();
}
}

加上他们受人尊敬的观点,我想这对所有人都肯定有效。

这个解决方案我发现它从:海王星世纪