asp.net-mvc - page - custom error mvc 5 web config
Página de error personalizada de ASP.NET MVC 5 (5)
Estoy utilizando un atributo de autorización personalizado en una aplicación ASP.NET MVC 5 como la siguiente:
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);
}
}
}
En la sección system.web
de mi web.config mencioné las rutas de error como:
<system.web>
<customErrors mode="On" defaultRedirect="/Error/Error">
<error statusCode="403" redirect="/Error/NoPermissions"/>
</customErrors>
</system.web>
Pero nunca soy redirigido a mi página de error personalizada en /Error/NoPermissions
. En su lugar, el navegador muestra la página de error general que dice "Error HTTP 403.0 - Prohibido" .
Gracias a todos, pero el problema no es con el código 403. En realidad, el problema estaba en la forma en que intentaba devolver 403. Acabo de cambiar mi código para lanzar una HttpException
lugar de devolver HttpStatusCodeResult
y todo funciona ahora. Puedo devolver cualquier código de estado HTTP lanzando la excepción HttpException
y la configuración de mis customErrors
los captura a todos. Puede ser que HttpStatusCodeResult
no esté haciendo el trabajo exacto que esperaba que hiciera.
Acabo de reemplazar
context.Result = new System.Web.Mvc.HttpStatusCodeResult((int)System.Net.HttpStatusCode.Forbidden);
con
throw new HttpException((int)System.Net.HttpStatusCode.Forbidden, "Forbidden");
Eso es.
Feliz codificacion
También tuve este problema. El código en la pregunta del OP funciona perfectamente, excepto el código de error personalizado en la sección <system.web>
en el archivo web.config
. Para solucionar el problema, lo que debo hacer es agregar el siguiente código a <system.webServer>
. Tenga en cuenta que ''webserver''
lugar de ''web''
.
<httpErrors errorMode="Custom" existingResponse="Replace">
<remove statusCode="403" />
<error statusCode="403" responseMode="ExecuteURL" path="/Error/UnAuthorized" />
</httpErrors>
Si alguien está utilizando el siguiente entorno, aquí está la solución completa:
El entorno:
- Visual Studio 2013 Update 4
- Microsoft .NET Framework 4.5.1 con ASP.NET MVC 5
- Proyecto: aplicación web ASP.NET con MVC y autenticación: plantilla de cuenta de usuario individual
Clase de atributo personalizado:
Agregue la siguiente clase al espacio de nombres predeterminado de su sitio web. La razón explicada aquí en la pregunta de desbordamiento de pila de respuesta aceptada : ¿Por qué AuthorizeAttribute se redirige a la página de inicio de sesión por fallas de autenticación y autorización?
[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);
}
}
}
Luego agrega el siguiente código al archivo web.config
<system.webServer>
<httpErrors errorMode="Custom" existingResponse="Replace">
<remove statusCode="403" />
<error statusCode="403" responseMode="ExecuteURL" path="/Error/UnAuthorized" />
</httpErrors>
</system.webServer>
El siguiente artículo explica más sobre esto: ASP.NET MVC: Mejorando el atributo de autorización (403 prohibido)
Y httpErrors en la sección web.config de este artículo: dusted.codes/…
Luego agregue el ErrorController.cs a la carpeta de Controladores
public class ErrorController : Controller
{
// GET: UnAuthorized
public ActionResult UnAuthorized()
{
return View();
}
public ActionResult Error()
{
return View();
}
}
Luego agregue un UnAuthorized.cshtml a la carpeta Ver / Compartida
@{
ViewBag.Title = "Your Request Unauthorized !"; //Customise as required
}
<h2>@ViewBag.Title.</h2>
Esto mostrará una página de error personalizada en lugar de la página de error generada por el navegador.
También tenga en cuenta que para el entorno anterior, no es necesario comentar el código dentro del método RegisterGlobalFilters
agregado por la plantilla como se sugiere en una de las respuestas.
Tenga en cuenta que acabo de cortar y pegar el código de mi proyecto de trabajo, por lo tanto, utilicé los NoPermissions
no Unauthorized
OP en lugar del código anterior.
[1]: Eliminar todos los ''customErrors'' y ''httpErrors'' de Web.config
[2]: verifica que ''App_Start / FilterConfig.cs'' tiene este aspecto:
public class FilterConfig
{
public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
filters.Add(new HandleErrorAttribute());
}
}
[3]: en ''Global.asax'' agrega este método:
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]: Agregar ''Controllers / ErrorPageController.cs''
public class ErrorPageController : Controller
{
public ActionResult Error(int statusCode, Exception exception)
{
Response.StatusCode = statusCode;
ViewBag.StatusCode = statusCode + " Error";
return View();
}
}
[5]: en ''Vistas / Compartido / 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
:RE
ya que me encontré con un problema muy similar, quise arrojar más luz sobre él.
customErrors solo capturará excepciones http reales lanzadas en su aplicación ASP.NET. El HttpStatusCodeResult no lanza una excepción sin embargo. Simplemente escribe una respuesta con el código de estado correspondiente, lo que tiene más sentido en su ejemplo.
Si está ejecutando en IIS 7.0 o superior, debería usar httpErrors ahora, ya que esto le mostrará páginas de error personalizadas en todos los casos. Esta es una configuración de nivel IIS.
Escribí un blog completo sobre esto para explicar las diferencias: dusted.codes/…
Actualizar
Solo necesitas hacer esa redirección especial para errores 403. Todos los otros 500 errores deberían surtir efecto a través de su defaultRedirect="/Error/Error"
en customErrors
. Sin embargo, debe eliminar o comentar el registro HandleErrorAttribute en el archivo App_Start / FilterConfig.cs para que los errores personalizados realmente funcionen. De lo contrario, ese atributo redirigirá todos los errores al archivo Error.cshtml en el directorio Vistas / Compartido.
public class FilterConfig
{
public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
// remove this line below
//filters.Add(new HandleErrorAttribute());
}
}
Respuesta original
Por lo que sé, no puede usar customErrors en web.config para manejar 403 errores por alguna razón. Siento tu dolor, ya que parece ser algo que debería ser tan simple como el código que ya tienes, pero aparentemente los errores 403 se tratan como un problema del servidor web.
Lo que puede hacer en su lugar es simplemente redirigir al usuario a la página deseada de "No Permissions":
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);
}
}
}
La solicitud tendrá un código de estado 200 en lugar de un 403, pero si puedes vivir con eso, esta es una solución fácil.
Aquí hay una pregunta SO similar para obtener más información: Devolución de errores personalizados .
Además, este artículo explica cómo recorrer la ruta de IIS: http://kitsula.com/Article/MVC-Custom-Error-Pages