ASP。NET MVC 5自定义错误页面

时间:2022-10-07 17:05:08

I am using a custom authorize attribute in a ASP.NET MVC 5 application like following:

我正在使用一个ASP中的自定义授权属性。NET MVC 5应用程序如下:

public class CustomAuthorizeAttribute : AuthorizeAttribute
{
    protected override void HandleUnauthorizedRequest(AuthorizationContext context)
    {
        if (context.HttpContext.Request.IsAuthenticated)
        {
            context.Result = new System.Web.Mvc.HttpStatusCodeResult((int)System.Net.HttpStatusCode.Forbidden);                
        }
        else
        {
            base.HandleUnauthorizedRequest(context);
        }
    }
}

In system.web section of my web.config I mentioned error paths like:

在系统。我的网页的网页。我提到的配置错误路径如下:

<system.web>
    <customErrors mode="On" defaultRedirect="/Error/Error">
      <error statusCode="403" redirect="/Error/NoPermissions"/>
    </customErrors>
</system.web>

But I am never redirected to my custom error page at /Error/NoPermissions. Instead the browser display the general error page saying "HTTP Error 403.0 - Forbidden".

但是我永远不会被重定向到我的自定义错误页面at / error / nopermission。相反,浏览器显示一般的错误页面,显示“HTTP错误403.0 -禁止”。

5 个解决方案

#1


40  

[1]: Remove all 'customErrors' & 'httpErrors' from Web.config

[1]:从Web.config中删除所有的“customErrors”和“httpErrors”

[2]: Check 'App_Start/FilterConfig.cs' looks like this:

[2]:检查FilterConfig App_Start /。cs的看起来像这样:

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

[3]: in 'Global.asax' add this method:

[3]:在“全球。asax”添加这个方法:

public void Application_Error(Object sender, EventArgs e)
{
    Exception exception = Server.GetLastError();
    Server.ClearError();

    var routeData = new RouteData();
    routeData.Values.Add("controller", "ErrorPage");
    routeData.Values.Add("action", "Error");
    routeData.Values.Add("exception", exception);

    if (exception.GetType() == typeof(HttpException))
    {
        routeData.Values.Add("statusCode", ((HttpException)exception).GetHttpCode());
    }
    else
    {
        routeData.Values.Add("statusCode", 500);
    }

    Response.TrySkipIisCustomErrors = true;
    IController controller = new ErrorPageController();
    controller.Execute(new RequestContext(new HttpContextWrapper(Context), routeData));
    Response.End();
}

[4]: Add 'Controllers/ErrorPageController.cs'

[4]:添加“控制器/ ErrorPageController.cs”

public class ErrorPageController : Controller
{
    public ActionResult Error(int statusCode, Exception exception)
    {
         Response.StatusCode = statusCode;
         ViewBag.StatusCode = statusCode + " Error";
         return View();
    }
}

[5]: in 'Views/Shared/Error.cshtml'

[5]:在“视图/共享/ Error.cshtml”

@model System.Web.Mvc.HandleErrorInfo
@{
    ViewBag.Title = (!String.IsNullOrEmpty(ViewBag.StatusCode)) ? ViewBag.StatusCode : "500 Error";
}

<h1 class="error">@(!String.IsNullOrEmpty(ViewBag.StatusCode) ? ViewBag.StatusCode : "500 Error"):</h1>

//@Model.ActionName
//@Model.ControllerName
//@Model.Exception.Message
//@Model.Exception.StackTrace

:D

:D

#2


15  

Thanks everyone, but problem is not with 403 code. Actually the problem was with the way i was trying to return 403. I just changed my code to throw an HttpException instead of returning the HttpStatusCodeResult and every things works now. I can return any HTTP status code by throwing HttpException exception and my customErrors configuration catches all of them. May be HttpStatusCodeResult is not doing the exact job I expected it to do.

谢谢大家,但问题不在于403代码。实际上问题是我返回403的方式。我只是更改了代码以抛出HttpException,而不是返回HttpStatusCodeResult,现在一切都正常了。我可以通过抛出HttpException返回任何HTTP状态代码,我的customErrors配置捕获所有的HTTP状态代码。可能是HttpStatusCodeResult没有做我预期的工作。

I just replaced

我只是代替

context.Result = new System.Web.Mvc.HttpStatusCodeResult((int)System.Net.HttpStatusCode.Forbidden);

with

throw new HttpException((int)System.Net.HttpStatusCode.Forbidden, "Forbidden");

That's it.

就是这样。

Happy coding.

快乐的编码。

#3


12  

I also had this issue. Code in the OP’s question is perfectly working except the custom error code in <system.web> section in the web.config file. To fix the issue what I need to do was add the following code to <system.webServer>. Note that ‘webserver’ instead of ‘web’.

我也有这个问题。OP问题中的代码除了 部分在web上。配置文件。为了解决这个问题,我需要将以下代码添加到 。注意“webserver”而不是“web”。 中的自定义错误代码外,运行良好。web>

<httpErrors errorMode="Custom" existingResponse="Replace">
  <remove statusCode="403" />
  <error statusCode="403" responseMode="ExecuteURL" path="/Error/UnAuthorized" />
</httpErrors>

If someone is using following environment, here is the complete solution:

如果有人正在使用以下环境,以下是完整的解决方案:

The Environment:

环境:

  • Visual Studio 2013 Update 4
  • Visual Studio 2013更新4
  • Microsoft .NET Framework 4.5.1 with ASP.NET MVC 5
  • 微软。net框架4.5.1与ASP。净MVC 5
  • Project: ASP.NET Web Application with MVC & Authentication: Individual User Account template
  • 项目:ASP。NET Web应用程序与MVC &身份验证:个人用户帐户模板。

Custom Attribute class:

自定义属性类:

Add the following class to your web site’s default namespace. The reason explained here in the accepted answer Stack Overflow question: Why does AuthorizeAttribute redirect to the login page for authentication and authorization failures?

将以下类添加到web站点的默认名称空间中。为什么AuthorizeAttribute会重定向到登录页面进行身份验证和授权失败?

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, Inherited = true, AllowMultiple = true)]
public class AuthorizeAttribute : System.Web.Mvc.AuthorizeAttribute
{
    protected override void HandleUnauthorizedRequest(System.Web.Mvc.AuthorizationContext filterContext)
    {
        if (filterContext.HttpContext.Request.IsAuthenticated)
        {
            filterContext.Result = new System.Web.Mvc.HttpStatusCodeResult((int)System.Net.HttpStatusCode.Forbidden);

        }
        else
        {
            base.HandleUnauthorizedRequest(filterContext);
        }
    }
} 

Then add the following code the web.config file

然后在web上添加以下代码。配置文件

<system.webServer>
   <httpErrors errorMode="Custom" existingResponse="Replace">
      <remove statusCode="403" />
      <error statusCode="403" responseMode="ExecuteURL" path="/Error/UnAuthorized" />
   </httpErrors>
</system.webServer>

Following article explain more about this: ASP.NET MVC: Improving the Authorize Attribute (403 Forbidden)

下面的文章将对此进行更多的解释:ASP。NET MVC:改进授权属性(403禁止)

And httpErrors in web.config section in this article: Demystifying ASP.NET MVC 5 Error Pages and Error Logging

并在web httpErrors。本文中的配置部分:解构ASP。NET MVC 5错误页面和错误日志

Then add the ErrorController.cs to Controllers folder

然后加入ErrorController。cs控制器文件夹

public class ErrorController : Controller
{
    // GET: UnAuthorized
    public ActionResult UnAuthorized()
    {
        return View();
    }

    public ActionResult Error()
    {
        return View();
    }

}

Then add a UnAuthorized.cshtml to View/Shared folder

然后添加一个未经授权的。cshtml视图/共享文件夹

@{
    ViewBag.Title = "Your Request Unauthorized !"; //Customise as required
 }
 <h2>@ViewBag.Title.</h2> 

This will show customised error page instead of browser generated error page.

这将显示定制的错误页面,而不是浏览器生成的错误页面。

Also note that for the above environment, it is not required to comment the code inside RegisterGlobalFilters method added by the template as suggested in one of the answers.

还请注意,对于上面的环境,不需要注释模板中添加的RegisterGlobalFilters方法中的代码,正如其中一个答案中所建议的那样。

Please note that I just cut and paste code from my working project therefore I used Unauthorized instead OP’s NoPermissions in the above code.

请注意,我只是从我的工作项目中剪切和粘贴代码,因此我在上面的代码中使用了未授权的OP的nopermission。

#4


1  

since I ran into a very similar issue I wanted to shed more light on it.

由于我遇到了一个非常相似的问题,我想对它进行更多的阐述。

customErrors will only capture actual http exceptions thrown in your ASP.NET application. The HttpStatusCodeResult doesn't throw an exception though. It just writes a response with the according status code, which makes more sense in your example.

customErrors只会捕获在ASP中抛出的实际http异常。网络应用程序。但HttpStatusCodeResult并没有抛出异常。它只使用根据状态代码编写响应,这在您的示例中更有意义。

If you are running on IIS 7.0 or higher you should be using httpErrors now, as this will show you custom error pages in all cases. This is an IIS level setting.

如果您在IIS 7.0或更高版本上运行,您现在应该使用httpErrors,因为这将向您显示所有情况下的自定义错误页面。这是IIS级别设置。

I wrote a whole blog post about this to explain the differences: http://dusted.codes/demystifying-aspnet-mvc-5-error-pages-and-error-logging

我写了一篇关于这一点的博文来解释它们的区别:http://dusted.codes/demystifying-aspnet-mvc-5 error-page -error- error-logging

#5


0  

Update

更新

You only need to do that special redirect for 403 errors. All other 500 errors should take effect through your defaultRedirect="/Error/Error" setting in customErrors. However, you need to remove or comment out the HandleErrorAttribute registration in the App_Start/FilterConfig.cs file for custom errors to actually work. Otherwise, that attribute will redirect all errors to the Error.cshtml file in the Views/Shared directory.

对于403个错误,只需要进行特殊的重定向。所有其他500个错误应该通过您的defaultRedirect="/Error/Error"设置在customErrors中。但是,您需要删除或注释App_Start/FilterConfig中的HandleErrorAttribute注册。cs文件的自定义错误,以实际工作。否则,该属性将把所有错误重定向到错误。视图/共享目录中的cshtml文件。

public class FilterConfig
{
    public static void RegisterGlobalFilters(GlobalFilterCollection filters)
    {
        // remove this line below
        //filters.Add(new HandleErrorAttribute());
    }
}

Original Answer

原来的答案

As far as I know, you cannot use customErrors in the web.config to handle 403 errors for some reason. I feel your pain as it seems like something that should be as simple as the code you already have, but apparently 403 errors are treated as a web server concern.

据我所知,您不能在web中使用定制错误。由于某种原因,配置处理403个错误。我感觉您的痛苦似乎应该像您已经拥有的代码一样简单,但是显然有403个错误被当作web服务器关注。

What you can do instead is just redirect the user to your desired "NoPermissions" page like this:

你所能做的只是将用户重定向到你想要的“nopermission”页面,就像这样:

public class CustomAuthorizeAttribute : AuthorizeAttribute
{
    protected override void HandleUnauthorizedRequest(AuthorizationContext context)
    {
        if (context.HttpContext.Request.IsAuthenticated)
        {
            context.Result = new RedirectToRouteResult(new RouteValueDictionary(new
            {
                action = "NoPermissions",
                controller = "Error",
                area = ""
            }));
        }
        else
        {
            base.HandleUnauthorizedRequest(context);
        }
    }
}

The request will have a 200 status code instead of a 403, but if you can live with that, this is an easy workaround.

这个请求将有一个200的状态码而不是403,但是如果你能接受,这是一个简单的解决方案。

Here is a similar SO question for more info: Returning custom errors.

关于更多信息,这里有一个类似的问题:返回自定义错误。

Also, this article explains how to go the IIS route: http://kitsula.com/Article/MVC-Custom-Error-Pages

此外,本文还解释了如何使用IIS路径:http://kitsula.com/article/mvc自定义错误页面

#1


40  

[1]: Remove all 'customErrors' & 'httpErrors' from Web.config

[1]:从Web.config中删除所有的“customErrors”和“httpErrors”

[2]: Check 'App_Start/FilterConfig.cs' looks like this:

[2]:检查FilterConfig App_Start /。cs的看起来像这样:

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

[3]: in 'Global.asax' add this method:

[3]:在“全球。asax”添加这个方法:

public void Application_Error(Object sender, EventArgs e)
{
    Exception exception = Server.GetLastError();
    Server.ClearError();

    var routeData = new RouteData();
    routeData.Values.Add("controller", "ErrorPage");
    routeData.Values.Add("action", "Error");
    routeData.Values.Add("exception", exception);

    if (exception.GetType() == typeof(HttpException))
    {
        routeData.Values.Add("statusCode", ((HttpException)exception).GetHttpCode());
    }
    else
    {
        routeData.Values.Add("statusCode", 500);
    }

    Response.TrySkipIisCustomErrors = true;
    IController controller = new ErrorPageController();
    controller.Execute(new RequestContext(new HttpContextWrapper(Context), routeData));
    Response.End();
}

[4]: Add 'Controllers/ErrorPageController.cs'

[4]:添加“控制器/ ErrorPageController.cs”

public class ErrorPageController : Controller
{
    public ActionResult Error(int statusCode, Exception exception)
    {
         Response.StatusCode = statusCode;
         ViewBag.StatusCode = statusCode + " Error";
         return View();
    }
}

[5]: in 'Views/Shared/Error.cshtml'

[5]:在“视图/共享/ Error.cshtml”

@model System.Web.Mvc.HandleErrorInfo
@{
    ViewBag.Title = (!String.IsNullOrEmpty(ViewBag.StatusCode)) ? ViewBag.StatusCode : "500 Error";
}

<h1 class="error">@(!String.IsNullOrEmpty(ViewBag.StatusCode) ? ViewBag.StatusCode : "500 Error"):</h1>

//@Model.ActionName
//@Model.ControllerName
//@Model.Exception.Message
//@Model.Exception.StackTrace

:D

:D

#2


15  

Thanks everyone, but problem is not with 403 code. Actually the problem was with the way i was trying to return 403. I just changed my code to throw an HttpException instead of returning the HttpStatusCodeResult and every things works now. I can return any HTTP status code by throwing HttpException exception and my customErrors configuration catches all of them. May be HttpStatusCodeResult is not doing the exact job I expected it to do.

谢谢大家,但问题不在于403代码。实际上问题是我返回403的方式。我只是更改了代码以抛出HttpException,而不是返回HttpStatusCodeResult,现在一切都正常了。我可以通过抛出HttpException返回任何HTTP状态代码,我的customErrors配置捕获所有的HTTP状态代码。可能是HttpStatusCodeResult没有做我预期的工作。

I just replaced

我只是代替

context.Result = new System.Web.Mvc.HttpStatusCodeResult((int)System.Net.HttpStatusCode.Forbidden);

with

throw new HttpException((int)System.Net.HttpStatusCode.Forbidden, "Forbidden");

That's it.

就是这样。

Happy coding.

快乐的编码。

#3


12  

I also had this issue. Code in the OP’s question is perfectly working except the custom error code in <system.web> section in the web.config file. To fix the issue what I need to do was add the following code to <system.webServer>. Note that ‘webserver’ instead of ‘web’.

我也有这个问题。OP问题中的代码除了 部分在web上。配置文件。为了解决这个问题,我需要将以下代码添加到 。注意“webserver”而不是“web”。 中的自定义错误代码外,运行良好。web>

<httpErrors errorMode="Custom" existingResponse="Replace">
  <remove statusCode="403" />
  <error statusCode="403" responseMode="ExecuteURL" path="/Error/UnAuthorized" />
</httpErrors>

If someone is using following environment, here is the complete solution:

如果有人正在使用以下环境,以下是完整的解决方案:

The Environment:

环境:

  • Visual Studio 2013 Update 4
  • Visual Studio 2013更新4
  • Microsoft .NET Framework 4.5.1 with ASP.NET MVC 5
  • 微软。net框架4.5.1与ASP。净MVC 5
  • Project: ASP.NET Web Application with MVC & Authentication: Individual User Account template
  • 项目:ASP。NET Web应用程序与MVC &身份验证:个人用户帐户模板。

Custom Attribute class:

自定义属性类:

Add the following class to your web site’s default namespace. The reason explained here in the accepted answer Stack Overflow question: Why does AuthorizeAttribute redirect to the login page for authentication and authorization failures?

将以下类添加到web站点的默认名称空间中。为什么AuthorizeAttribute会重定向到登录页面进行身份验证和授权失败?

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, Inherited = true, AllowMultiple = true)]
public class AuthorizeAttribute : System.Web.Mvc.AuthorizeAttribute
{
    protected override void HandleUnauthorizedRequest(System.Web.Mvc.AuthorizationContext filterContext)
    {
        if (filterContext.HttpContext.Request.IsAuthenticated)
        {
            filterContext.Result = new System.Web.Mvc.HttpStatusCodeResult((int)System.Net.HttpStatusCode.Forbidden);

        }
        else
        {
            base.HandleUnauthorizedRequest(filterContext);
        }
    }
} 

Then add the following code the web.config file

然后在web上添加以下代码。配置文件

<system.webServer>
   <httpErrors errorMode="Custom" existingResponse="Replace">
      <remove statusCode="403" />
      <error statusCode="403" responseMode="ExecuteURL" path="/Error/UnAuthorized" />
   </httpErrors>
</system.webServer>

Following article explain more about this: ASP.NET MVC: Improving the Authorize Attribute (403 Forbidden)

下面的文章将对此进行更多的解释:ASP。NET MVC:改进授权属性(403禁止)

And httpErrors in web.config section in this article: Demystifying ASP.NET MVC 5 Error Pages and Error Logging

并在web httpErrors。本文中的配置部分:解构ASP。NET MVC 5错误页面和错误日志

Then add the ErrorController.cs to Controllers folder

然后加入ErrorController。cs控制器文件夹

public class ErrorController : Controller
{
    // GET: UnAuthorized
    public ActionResult UnAuthorized()
    {
        return View();
    }

    public ActionResult Error()
    {
        return View();
    }

}

Then add a UnAuthorized.cshtml to View/Shared folder

然后添加一个未经授权的。cshtml视图/共享文件夹

@{
    ViewBag.Title = "Your Request Unauthorized !"; //Customise as required
 }
 <h2>@ViewBag.Title.</h2> 

This will show customised error page instead of browser generated error page.

这将显示定制的错误页面,而不是浏览器生成的错误页面。

Also note that for the above environment, it is not required to comment the code inside RegisterGlobalFilters method added by the template as suggested in one of the answers.

还请注意,对于上面的环境,不需要注释模板中添加的RegisterGlobalFilters方法中的代码,正如其中一个答案中所建议的那样。

Please note that I just cut and paste code from my working project therefore I used Unauthorized instead OP’s NoPermissions in the above code.

请注意,我只是从我的工作项目中剪切和粘贴代码,因此我在上面的代码中使用了未授权的OP的nopermission。

#4


1  

since I ran into a very similar issue I wanted to shed more light on it.

由于我遇到了一个非常相似的问题,我想对它进行更多的阐述。

customErrors will only capture actual http exceptions thrown in your ASP.NET application. The HttpStatusCodeResult doesn't throw an exception though. It just writes a response with the according status code, which makes more sense in your example.

customErrors只会捕获在ASP中抛出的实际http异常。网络应用程序。但HttpStatusCodeResult并没有抛出异常。它只使用根据状态代码编写响应,这在您的示例中更有意义。

If you are running on IIS 7.0 or higher you should be using httpErrors now, as this will show you custom error pages in all cases. This is an IIS level setting.

如果您在IIS 7.0或更高版本上运行,您现在应该使用httpErrors,因为这将向您显示所有情况下的自定义错误页面。这是IIS级别设置。

I wrote a whole blog post about this to explain the differences: http://dusted.codes/demystifying-aspnet-mvc-5-error-pages-and-error-logging

我写了一篇关于这一点的博文来解释它们的区别:http://dusted.codes/demystifying-aspnet-mvc-5 error-page -error- error-logging

#5


0  

Update

更新

You only need to do that special redirect for 403 errors. All other 500 errors should take effect through your defaultRedirect="/Error/Error" setting in customErrors. However, you need to remove or comment out the HandleErrorAttribute registration in the App_Start/FilterConfig.cs file for custom errors to actually work. Otherwise, that attribute will redirect all errors to the Error.cshtml file in the Views/Shared directory.

对于403个错误,只需要进行特殊的重定向。所有其他500个错误应该通过您的defaultRedirect="/Error/Error"设置在customErrors中。但是,您需要删除或注释App_Start/FilterConfig中的HandleErrorAttribute注册。cs文件的自定义错误,以实际工作。否则,该属性将把所有错误重定向到错误。视图/共享目录中的cshtml文件。

public class FilterConfig
{
    public static void RegisterGlobalFilters(GlobalFilterCollection filters)
    {
        // remove this line below
        //filters.Add(new HandleErrorAttribute());
    }
}

Original Answer

原来的答案

As far as I know, you cannot use customErrors in the web.config to handle 403 errors for some reason. I feel your pain as it seems like something that should be as simple as the code you already have, but apparently 403 errors are treated as a web server concern.

据我所知,您不能在web中使用定制错误。由于某种原因,配置处理403个错误。我感觉您的痛苦似乎应该像您已经拥有的代码一样简单,但是显然有403个错误被当作web服务器关注。

What you can do instead is just redirect the user to your desired "NoPermissions" page like this:

你所能做的只是将用户重定向到你想要的“nopermission”页面,就像这样:

public class CustomAuthorizeAttribute : AuthorizeAttribute
{
    protected override void HandleUnauthorizedRequest(AuthorizationContext context)
    {
        if (context.HttpContext.Request.IsAuthenticated)
        {
            context.Result = new RedirectToRouteResult(new RouteValueDictionary(new
            {
                action = "NoPermissions",
                controller = "Error",
                area = ""
            }));
        }
        else
        {
            base.HandleUnauthorizedRequest(context);
        }
    }
}

The request will have a 200 status code instead of a 403, but if you can live with that, this is an easy workaround.

这个请求将有一个200的状态码而不是403,但是如果你能接受,这是一个简单的解决方案。

Here is a similar SO question for more info: Returning custom errors.

关于更多信息,这里有一个类似的问题:返回自定义错误。

Also, this article explains how to go the IIS route: http://kitsula.com/Article/MVC-Custom-Error-Pages

此外,本文还解释了如何使用IIS路径:http://kitsula.com/article/mvc自定义错误页面