23

我希望将所有 401 错误重定向到自定义错误页面。我最初在我的 web.config 中设置了以下条目。

<customErrors defaultRedirect="ErrorPage.aspx" mode="On">
  <error statusCode="401" redirect="~/Views/Shared/AccessDenied.aspx" />
</customErrors>

使用 IIS Express 时,我收到了常见的 IIS Express 401 错误页面。

如果我不使用 IIS Express,则会返回空白页。使用 Google Chrome 的网络选项卡检查响应,我看到当页面为空白时,标题中返回 401 状态

到目前为止,我尝试使用此 SO 答案中的建议,因为我使用的是 IIS Express,但无济于事。我尝试使用组合<custom errors><httpErrors>没有运气 - 仍然显示标准错误或空白页。

根据上述 SO 问题的链接,该httpErrors部分目前看起来像这样(我还找到了另一个非常有希望的答案,但是没有运气 - 空白回复)

<system.webServer>
  <httpErrors  errorMode="DetailedLocalOnly" existingResponse="PassThrough" >
    <remove statusCode="401"  />
    <error statusCode="401" path="/Views/Shared/AccessDenied.htm" />
  </httpErrors>

 <!-- 
 <httpErrors  errorMode="Custom" 
             existingResponse="PassThrough" 
             defaultResponseMode="ExecuteURL">
      <remove statusCode="401"  />
  <error statusCode="401" path="~/Views/Shared/AccessDenied.htm" 
         responseMode="File" />
 </httpErrors>
 -->
</system.webServer>

我什至根据来自iis.netapplicationhost.config的信息修改了文件并修改为。在我努力的过程中,我还设法偶然发现了这个错误,如另一个 SO question中所述。<httpErrors lockAttributes="allowAbsolutePathsWhenDelegated,defaultPath"><httpErrors lockAttributes="allowAbsolutePathsWhenDelegated">

如何在 Asp.Net Mvc 3 中显示自定义错误页面?

附加信息

以下控制器操作已使用Authorize特定用户的属性进行修饰。

[HttpGet]
[Authorize(Users = "domain\\userXYZ")]
public ActionResult Edit() 
{
   return GetSettings();
}

[HttpPost]
[Authorize(Users = "domain\\userXYZ")]
public ActionResult Edit(ConfigurationModel model, IList<Shift> shifts)
{
    var temp = model;
    model.ConfiguredShifts = shifts;
    EsgConsole config = new EsgConsole();

    config.UpdateConfiguration(model.ToDictionary());
    return RedirectToAction("Index");
}
4

4 回答 4

34

我使用这些步骤:

// in Global.asax.cs:
        protected void Application_Error(object sender, EventArgs e) {

            var ex = Server.GetLastError().GetBaseException();

            Server.ClearError();
            var routeData = new RouteData();
            routeData.Values.Add("controller", "Error");
            routeData.Values.Add("action", "Index");

            if (ex.GetType() == typeof(HttpException)) {
                var httpException = (HttpException)ex;
                var code = httpException.GetHttpCode();
                routeData.Values.Add("status", code);
            } else {
                routeData.Values.Add("status", 500);
            }

            routeData.Values.Add("error", ex);

            IController errorController = new Kavand.Web.Controllers.ErrorController();
            errorController.Execute(new RequestContext(new HttpContextWrapper(Context), routeData));
        }

        protected void Application_EndRequest(object sender, EventArgs e) {
            if (Context.Response.StatusCode == 401) { // this is important, because the 401 is not an error by default!!!
                throw new HttpException(401, "You are not authorised");
            }
        }

和:

// in Error Controller:
    public class ErrorController : Controller {

        public ActionResult  Index(int status, Exception error) {
            Response.StatusCode = status;
            return View(status);
        }

        protected override void Dispose(bool disposing) {
            base.Dispose(disposing);
        }
    }

和错误文件夹中的索引视图:

@* in ~/Views/Error/Index.cshtml: *@

@model Int32    
@{
    Layout = null;
}    
<!DOCTYPE html>    
<html>
<head>
    <title>Kavand | Error</title>
</head>
<body>
    <div>
        There was an error with your request. The error is:<br />
        <p style=" color: Red;">
        @switch (Model) {
            case 401: {
                    <span>Your message goes here...</span>
                }
                break;
            case 403: {
                    <span>Your message goes here...</span>
                }
                break;
            case 404: {
                    <span>Your message goes here...</span>
                }
                break;
            case 500: {
                    <span>Your message goes here...</span>
                }
                break;
            //and more cases for more error-codes...
            default: {
                    <span>Unknown error!!!</span>
                }
                break;
        }
        </p>
    </div>
</body>
</html>

和 - 最后一步:

<!-- in web.config: -->

<customErrors mode="Off"/>
于 2011-09-08T01:36:59.883 回答
11

我永远无法让 web.config 和 MVC 中的 CustomErrors 一起玩得很好,所以我放弃了。我这样做。

在 global.asax 中:

protected void Application_Error()
    {
        var exception = Server.GetLastError();
        var httpException = exception as HttpException;
        Response.Clear();
        Server.ClearError();
        var routeData = new RouteData();
        routeData.Values["controller"] = "Errors";
        routeData.Values["action"] = "General";
        routeData.Values["exception"] = exception;
        Response.StatusCode = 500;
        if (httpException != null)
        {
            Response.StatusCode = httpException.GetHttpCode();
            switch (Response.StatusCode)
            {
                case 403:
                    routeData.Values["action"] = "Http403";
                    break;
                case 404:
                    routeData.Values["action"] = "Http404";
                    break;
            }
        }
        // Avoid IIS7 getting in the middle
        Response.TrySkipIisCustomErrors = true;
        IController errorsController = new GNB.LG.StrategicPlanning.Website.Controllers.ErrorsController();
        HttpContextWrapper wrapper = new HttpContextWrapper(Context);
        var rc = new RequestContext(wrapper, routeData);
        errorsController.Execute(rc);
    }

在错误控制器中:

public class ErrorsController
{
    public ActionResult General(Exception exception)
    {
        // log the error here
        return View(exception);
    }

    public ActionResult Http404()
    {
        return View("404");
    }

    public ActionResult Http403()
    {
        return View("403");
    }
}

在 web.config 中:

<customErrors mode="Off" />

无论在何处或如何创建错误,这对我都有效。401 现在没有在那里处理,但你可以很容易地添加它。

于 2011-07-18T12:52:10.817 回答
9

也许我遗漏了一些东西,但 MVC 有一个ErrorHandlerAttribute使用自定义错误的默认全局。这在这里解释得很好。

public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
    filters.Add(new HandleErrorAttribute());
}

您需要做的就是custom errors在配置中打开,然后设置自定义错误重定向,最好是静态HTML文件(以防应用程序出现错误)。

<customErrors mode="On" defaultRedirect="errors.htm">
    <error statusCode="404" redirect="errors404.htm"/>
</customErrors>

如果您愿意,也可以指向一个自定义Controller来显示错误。在下面的示例中,我刚刚使用了到 named 的默认路由、一个Controller名为Error的操作和一个名为的Index字符串参数id(用于接收错误代码)。您当然可以使用您想要的任何路由。您的示例不起作用,因为您试图直接链接到Views目录而不通过Controller. MVC .NET 不Views直接向文件夹提供请求。

<customErrors mode="On" defaultRedirect="/error/index/500">
    <error statusCode="404" redirect="/error/index/404"/>
</customErrors>

ErrorHandlerAttribute也可以广泛用于将Controllers/Actions错误重定向到ViewsController. 例如,要在发生类型异常时显示View命名,您可以使用:MyArgumentErrorArgumentException

[ControllerAction,ExceptionHandler("MyArgumentError",typeof(ArgumentException))]
public void Index()
{
   // some code that could throw ArgumentExcepton
}

当然,另一种选择是更新股票Error页面Shared

于 2011-09-09T23:28:56.997 回答
0

在那里查看 web.config 的第一部分,您直接指向 .aspx 页面。当我设置错误页面时,我直接指向控制器和操作。例如:

<customErrors mode="On" defaultRedirect="~/Error/UhOh">
  <error statusCode="404" redirect="~/Error/NotFound" />
  <error statusCode="403" redirect="~/Error/AccessDenied" />
</customErrors>

我有一个包含所有必需操作的错误控制器。我认为 MVC 不能很好地直接调用 .aspx 页面。

于 2011-09-14T00:31:39.413 回答