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

发布于 2024-11-25 08:43:26 字数 2865 浏览 3 评论 0 原文

我希望将所有 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 状态

到目前为止我所尝试的是使用 这个答案,因为我使用的是 IIS Express 但无济于事。我尝试使用 的组合,但没有成功 - 仍然显示标准错误或空白页面。

httpErrors 部分目前基于 来自 href="https://stackoverflow.com/questions/2480006/what-is-the-difference- Between-customerrors-and-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>

我什至修改了 applicationhost.config 文件并将 修改为 基于来自 iis.net。在我的努力过程中,我还偶然发现了这个错误,如另一个SO问题中所述

如何在 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");
}

I want all 401 errors to be be redirected to a custom error page. I have initially setup the following entry in my web.config.

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

When using IIS Express I receive the stock IIS Express 401 error page.

In the event when I do not use IIS Express a blank page is returned. Using Google Chrome's Network tab to inspect the response, I see that while the page is blank a 401 status is returned in the headers

What I have tried thus far is using suggestions from this SO answer since I am using IIS Express but to no avail. I have tried using a combination <custom errors> and <httpErrors> with no luck - the standard error or blank page is still displayed.

The httpErrors section looks like this at the moment based on the link from the above SO question ( I also found another very promising answer however no luck - blank response)

<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>

I have even modified the applicationhost.config file and modified <httpErrors lockAttributes="allowAbsolutePathsWhenDelegated,defaultPath"> to <httpErrors lockAttributes="allowAbsolutePathsWhenDelegated"> based on information from iis.net. During the course of my endeavours I also managed to stumbled upon this error as described in another SO question.

How do I display custom error pages in Asp.Net Mvc 3?

Additional info

The following controller actions have been decorated with the Authorize attribute for a specific user.

[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");
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

岁月无声 2024-12-02 08:43:26

我使用以下步骤:

// 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");
            }
        }

AND:

// 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);
        }
    }

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

@* 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>

AND - 最后一步:

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

<customErrors mode="Off"/>

I use these steps:

// 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");
            }
        }

AND:

// 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);
        }
    }

AND the index view in Error folder:

@* 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>

AND -the final step:

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

<customErrors mode="Off"/>
凹づ凸ル 2024-12-02 08:43:26

我始终无法让 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);
    }

在 ErrorsController 中:

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,但您可以很容易地添加它。

I was never able to get CustomErrors in a web.config and MVC to play nice together, so I gave up. I do this instead.

In 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);
    }

In ErrorsController:

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");
    }
}

In web.config:

<customErrors mode="Off" />

That's worked for me no matter where or how the error is created. 401 isn't handled there right now but you could add it pretty easily.

很酷不放纵 2024-12-02 08:43:26

也许我遗漏了一些东西,但 MVC 有一个默认的全局 ErrorHandlerAttribute 使用自定义错误。 此处对此进行了很好的解释。

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

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

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

如果您愿意,还可以指向自定义控制器来显示错误。在下面的示例中,我刚刚使用了到名为 ErrorController 的默认路由,其中​​包含名为 Index 的操作和名为 < code>id(接收错误代码)。您当然可以使用您想要的任何路由。您的示例不起作用,因为您尝试直接链接到 Views 目录,而不通过 Controller。 MVC .NET 不直接向 Views 文件夹提供请求。

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

ErrorHandlerAttribute 还可以广泛与 Controllers/Actions 一起使用,将错误重定向到与该操作相关的命名Views控制器。例如,要在发生 ArgumentException 类型的异常时显示名为 MyArgumentErrorView,您可以使用:

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

当然,另一个选项是更新 stock < Shared 中的 code>Error 页面。

Maybe I'm missing something, but MVC has a default global ErrorHandlerAttribute that uses custom errors. This is explained quite well here.

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

All you need to do is turn on custom errors in the config, and then setup custom error redirects, preferably to a static HTML file (in case there's errors with the app).

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

If you prefer could also point to a custom Controller to display the errors. In the following example I've just used the default routing to a Controller named Error, with an action called Index, and string parameter named id (to receive the errorcode). You could of course use any routing you desire. Your example isn't working because you are trying to link directly into the Views directory without going via a Controller. MVC .NET doesn't serve requests to the Views folder directly.

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

The ErrorHandlerAttribute can also be used extensively with Controllers/Actions to redirect errors to named Views related to the Controller. For example to show the View named MyArgumentError when a exception of type ArgumentException occurs you could use:

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

Of course another option is to update the stock Error page in Shared.

别挽留 2024-12-02 08:43:26

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

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

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

Looking at the first part of your web.config there, you're pointing to an .aspx page directly. When I setup my error pages I pointed directly to a controller and action. For example:

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

And I had an Error controller with all the required actions. I don't think MVC plays well with direct calls to .aspx pages.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文