page net mvc log handling errors error custom asp application_error all asp.net iis-6 custom-errors redirectmode

asp.net - net - CustomErrors no funciona al configurar redirectMode="ResponseRewrite"



custom error mvc 5 web config (9)

En un sitio antiguo, estaba cambiando la forma en que funciona CustomErrors agregando redirectMode="ResponseRewrite" (nuevo en 3.5 SP1):

<customErrors mode="RemoteOnly" defaultRedirect="Error.aspx" redirectMode="ResponseRewrite"> <error statusCode="404" redirect="404.aspx" /> </customErrors>

El caso es que me muestra la página de error genérico (la que customErrors cuando no configura customErrors . Si customErrors la parte redirectMode="ResponseRewrite" , funciona bien.

Estoy seguro de que 3.5 SP1 está instalado en el servidor, porque utilizo la misma configuración en otros sitios alojados en el mismo servidor.

¿Algunas ideas?


Creé una página de error en aspx que transfiere la consulta a un controlador ASP.NET MVC. Puede volver a escribir la consulta en esta página aspx y transferirá la consulta a su controlador personalizado.

protected void Page_Load(object sender, EventArgs e) { //Get status code var queryStatusCode = Request.QueryString.Get("code"); int statusCode; if (!int.TryParse(queryStatusCode, out statusCode)) { var lastError = Server.GetLastError(); HttpException ex = lastError as HttpException; statusCode = ex == null ? 500 : ex.GetHttpCode(); } Response.StatusCode = statusCode; // Execute a route RouteData routeData = new RouteData(); string controllerName = Request.QueryString.Get("controller") ?? "Errors"; routeData.Values.Add("controller", controllerName); routeData.Values.Add("action", Request.QueryString.Get("action") ?? "Index"); var requestContext = new RequestContext(new HttpContextWrapper(Context), routeData); IController controller = ControllerBuilder.Current.GetControllerFactory().CreateController(requestContext, controllerName); controller.Execute(requestContext); }

Encuentre más detalles aquí: https://.com/a/27354140/143503


Debido a la dependencia de Server.Transfer , parece que la implementación interna de ResponseRewrite no es compatible con MVC.

Esto me parece un agujero de funcionalidad deslumbrante, así que decidí volver a implementar esta característica usando un módulo HTTP, para que simplemente funcione . La solución a continuación le permite manejar los errores redireccionando a cualquier ruta MVC válida (incluidos los archivos físicos) tal como lo haría normalmente.

<customErrors mode="RemoteOnly" redirectMode="ResponseRewrite"> <error statusCode="404" redirect="404.aspx" /> <error statusCode="500" redirect="~/MVCErrorPage" /> </customErrors>

Esto ha sido probado en las siguientes plataformas;

  • MVC4 en modo de canalización integrada (IIS Express 8)
  • MVC4 en modo clásico (VS Development Server, Cassini)
  • MVC4 en modo clásico (IIS6)

namespace Foo.Bar.Modules { /// <summary> /// Enables support for CustomErrors ResponseRewrite mode in MVC. /// </summary> public class ErrorHandler : IHttpModule { private HttpContext HttpContext { get { return HttpContext.Current; } } private CustomErrorsSection CustomErrors { get; set; } public void Init(HttpApplication application) { System.Configuration.Configuration configuration = WebConfigurationManager.OpenWebConfiguration("~"); CustomErrors = (CustomErrorsSection)configuration.GetSection("system.web/customErrors"); application.EndRequest += Application_EndRequest; } protected void Application_EndRequest(object sender, EventArgs e) { // only handle rewrite mode, ignore redirect configuration (if it ain''t broke don''t re-implement it) if (CustomErrors.RedirectMode == CustomErrorsRedirectMode.ResponseRewrite && HttpContext.IsCustomErrorEnabled) { int statusCode = HttpContext.Response.StatusCode; // if this request has thrown an exception then find the real status code Exception exception = HttpContext.Error; if (exception != null) { // set default error status code for application exceptions statusCode = (int)HttpStatusCode.InternalServerError; } HttpException httpException = exception as HttpException; if (httpException != null) { statusCode = httpException.GetHttpCode(); } if ((HttpStatusCode)statusCode != HttpStatusCode.OK) { Dictionary<int, string> errorPaths = new Dictionary<int, string>(); foreach (CustomError error in CustomErrors.Errors) { errorPaths.Add(error.StatusCode, error.Redirect); } // find a custom error path for this status code if (errorPaths.Keys.Contains(statusCode)) { string url = errorPaths[statusCode]; // avoid circular redirects if (!HttpContext.Request.Url.AbsolutePath.Equals(VirtualPathUtility.ToAbsolute(url))) { HttpContext.Response.Clear(); HttpContext.Response.TrySkipIisCustomErrors = true; HttpContext.Server.ClearError(); // do the redirect here if (HttpRuntime.UsingIntegratedPipeline) { HttpContext.Server.TransferRequest(url, true); } else { HttpContext.RewritePath(url, false); IHttpHandler httpHandler = new MvcHttpHandler(); httpHandler.ProcessRequest(HttpContext); } // return the original status code to the client // (this won''t work in integrated pipleline mode) HttpContext.Response.StatusCode = statusCode; } } } } } public void Dispose() { } } }

Uso

Incluya esto como el módulo HTTP final en su web.config

<system.web> <httpModules> <add name="ErrorHandler" type="Foo.Bar.Modules.ErrorHandler" /> </httpModules> </system.web> <!-- IIS7+ --> <system.webServer> <modules> <add name="ErrorHandler" type="Foo.Bar.Modules.ErrorHandler" /> </modules> </system.webServer>


Descubrí que si usa redirectMode = "ResponseRewrite", entonces necesita agregar algo en el área de reescritura del archivo web.config. ¡El problema es cuando tu sitio está roto! No puede reescribir la URL ya que su sitio no puede llamar al "virtual.aspx" que maneja su reescritura.


En mi caso particular, mi página de error tenía una página maestra que tenía un control de usuario que intentó usar Session. Si Session no está disponible, obtiene una HttpException: "El estado de la sesión solo se puede usar cuando enableSessionState se establece en verdadero, ya sea en un archivo de configuración o en la directiva de la página". La solución más fácil es cambiar a html estático, la segunda solución más fácil es usar una página de error más simple, la solución más difícil es asegurarse increíblemente de que su página de error no hace suposiciones en ninguna parte (como esa sesión no lanzará una excepción, por ejemplo) y no es posible que salga el error.


Encontré que el problema estaba en Error.aspx. Todavía no se puede encontrar cuál fue el error real en error.aspx que causa el problema.

Cambiar la página a un archivo html estático solucionó el problema.


Es importante tener en cuenta que cualquiera que intente hacer esto en una aplicación MVC que ResponseRewrite utiliza Server.Transfer detrás de las escenas. Por lo tanto, defaultRedirect debe corresponder a un archivo legítimo en el sistema de archivos. Aparentemente, Server.Transfer no es compatible con las rutas MVC, por lo tanto, si su página de error es servida por una acción del controlador, Server.Transfer buscará / Error / Lo que sea, no lo encontrará en el sistema de archivos, y devolverá un nombre genérico. ¡Página de error 404!


La única forma que funcionó perfectamente para mí es desactivar los errores personalizados y reemplazar las páginas de error de iis a través de web.config. Envía el código de estado correcto con la respuesta y tiene el beneficio de no pasar por el mvc.

aquí está el código

  1. Desactivar errores personalizados

    <customErrors mode="Off" />

  2. Reemplazar páginas de error

    <httpErrors errorMode="Custom" existingResponse="Replace"> <remove statusCode="404" subStatusCode="-1" /> <remove statusCode="500" subStatusCode="-1" /> <error statusCode="404" path="Error404.html" responseMode="File" /> <error statusCode="500" path="Error.html" responseMode="File" /> </httpErrors>

Nota. Utilice responsemode="file" si la url es un enlace directo a un archivo

info: http://tipila.com/tips/use-custom-error-pages-aspnet-mvc


Lo que sucede es que IIS está viendo el código de estado de error y presentando su propia página de error en lugar de la tuya. Para resolverlo, debe configurarlo en el código detrás de la página de su página de error para evitar que IIS haga esto:

Response.TrySkipIisCustomErrors = true;

Esto solo funcionará en IIS7 o superior, para versiones anteriores de IIS necesitarás jugar con la configuración de la página de error.


Sé que esta pregunta es un poco vieja, pero pensé que debería señalar que no es necesario que sea un archivo estático para que funcione.

Me encontré con algo similar, y es solo cuestión de encontrar ese error en su Error.aspx, en nuestro caso fue porque la página maestra en uso se basó en una parte de los datos de la sesión y cuando se configuró ResponseRewrite la sesión no está disponible para nuestra página Error.aspx.

Todavía no he resuelto si esta falta de disponibilidad se debe a nuestra configuración de aplicación específica o a una parte "por diseño" de ASP.net.