2011-04-14 33 views
8

La pregunta es: ¿Por qué el manejo de errores personalizados no funciona para rutas/directorios no existentes?Manejo de errores personalizados en web.config/Global.asax no maneja el directorio inexistente

Actualizado con código fijo (gracias a todos por que de entrada):

* Código de Actualización de web.config y Global.asax *

<httpErrors errorMode="Custom"> 
     <remove statusCode="500" subStatusCode="-1" /> 
     <remove statusCode="404" subStatusCode="-1" /> 
     <error statusCode="404" subStatusCode="-1" prefixLanguageFilePath="" path="/*****.aspx" responseMode="ExecuteURL" /> 
     <error statusCode="500" subStatusCode="-1" prefixLanguageFilePath="" path="/*****.aspx" responseMode="ExecuteURL"/> 
    </httpErrors> 

    added this to the global.asax to stop IIS from handling my 500 errors 
    after @Kev's suggestions IIS handled my 500's these lines fixed that 
    HttpApplication myApplication = new HttpApplication(); 
    myApplication.Response.TrySkipIisCustomErrors = true; 

Tenemos un sitio configuración con manejo de error personalizado en web.config y global.asax (la configuración se muestra a continuación). Somos capaces de manejar todos los 404 y 500 sin problemas. Los errores se detectan en el Application_Error en el global.asax, se registra en un DB y luego usando HttpContext configuramos el código de estado y usamos Server.Transfer() para mover al usuario a la página de error apropiada (los redireccionamientos causan un 302 y perjudican al SEO).

El problema es cuando el usuario escribe en http://www.example.com/whatever aparece una página en blanco en Firefox y en IE muestra la página IE 404. Firebug no muestra ningún código de estado que se active, y cuando depuro la solución, no se tocan los puntos de interrupción que he establecido en el global.asax. Lo curioso es que un usuario puede ingresar http://www.example.com/whatever/hmm.aspx y se producirá un error. Parece que solo está trabajando en páginas no existentes y no en rutas/directorios que no existen.

A continuación se muestra mi código web.config para los errores y mi código global.asax para error de aplicación.

He añadido el * * para ocultar información, tienen válidos .aspx páginas en ellos:

de configuración Web:

<customErrors defaultRedirect="~/******.aspx" mode="On" 
       redirectMode="ResponseRewrite"> 
    <error statusCode="500" redirect="~/*****.aspx" /> 
    <error statusCode="404" redirect="~/*****.aspx" /> 
</customErrors> 

    <httpErrors errorMode="Custom"> 
     <remove statusCode="500" subStatusCode="-1" /> 
     <remove statusCode="404" subStatusCode="-1" /> 
     <error statusCode="404" subStatusCode="-1" prefixLanguageFilePath="" path="/*****.aspx" responseMode="ExecuteURL" /> 
     <error statusCode="500" subStatusCode="-1" prefixLanguageFilePath="" path="/*****.aspx" responseMode="ExecuteURL"/> 
    </httpErrors> 

Código:

protected void Application_Error(Object sender, EventArgs e) 
{ 
    // At this point we have information about the error 
    HttpContext ctx = HttpContext.Current; 

    // set the exception to the Context 
    Exception exception = ctx.Server.GetLastError(); 

    // get the status code of the Error 
    int httpCode = ((HttpException)exception).GetHttpCode(); 

    // get the IP Address 
    String strHostName = string.Empty; 
    String ipAddress_s = string.Empty; 
    strHostName = System.Net.Dns.GetHostName(); 

    System.Net.IPHostEntry ipEntry = System.Net.Dns.GetHostByName(strHostName); 
    System.Net.IPAddress[] addr = ipEntry.AddressList; 

    for (int i = 0; i < addr.Length; i++) 
    { 
     ipAddress_s += "IP Address {" + (i + 1) + "} " + 
          addr[i].ToString() + Environment.NewLine; 
    } 

    // setup the error info one for user display and one for the DB Insert 
    string errorInfo = 
     "<br /><b>Error Location:</b> " + ctx.Request.Url.ToString() + 
     "<br /><br /><b>Error Source:</b> " + exception.Source + 
     "<br /><br /><b>Error Try/Catch:</b> " + exception.InnerException + 
     "<br /><br /><b>Error Info:</b> " + exception.Message + 
     "<br /><br /><b>Status Code:</b> " + httpCode + 
     "<br /><br /><b>Stack trace:</b> " + exception.StackTrace; 
    string errorInfoDB = 
     "||Error Location: " + ctx.Request.Url.ToString() + 
     "||Error Source: " + exception.Source + 
     "||Error Try/Catch: " + exception.InnerException + 
     "||Error Info: " + exception.Message + 
     "||HttpErrorCode: " + httpCode + 
     "||Stack trace: " + exception.StackTrace + 
     "||IP Address: " + ipAddress_s; 

    // clean the input befor you put it in the DB 
    char quote = (char)34; 
    char filler = (char)124; 
    char tick = (char)39; 
    char greaterThan = (char)60; 
    char lessThan = (char)62; 
    errorInfo = errorInfo.Replace(quote, filler); 
    errorInfo = errorInfo.Replace(tick, filler); 
    errorInfo = errorInfo.Replace(greaterThan, filler); 
    errorInfo = errorInfo.Replace(lessThan, filler); 

    errorInfoDB = errorInfoDB.Replace(quote, filler); 
    errorInfoDB = errorInfoDB.Replace(tick, filler); 
    errorInfoDB = errorInfoDB.Replace(greaterThan, filler); 
    errorInfoDB = errorInfoDB.Replace(lessThan, filler); 

    string pattern = string.Empty; 
    string replacement = "sQueEl"; 
    pattern = "/cookie|SELECT|UPDATE|INSERT|INTO|DELETE|FROM|NOT IN|WHERE|TABLE|DROP|script*/ig"; 
    errorInfoDB = Regex.Replace(errorInfoDB, pattern, replacement); 

    pattern = "/cookie|select|update|insert|into|delete|from|not in|where|table|drop|script*/ig"; 
    errorInfoDB = Regex.Replace(errorInfoDB, pattern, replacement); 


    if (httpCode == 404) 
    { 
     InSert_To_DB_Class(*****, *****, *****, *****, *****, errorInfoDB); 
    } 
    else 
    { 
     InSert_To_DB_Class(*****, *****, *****, *****, *****, errorInfoDB); 
    } 

    // set the error info to the session variable to display to the allowed users 
    Application["AppError"] = errorInfo; 

    // clear the error now that is has been stored to a session 
    ctx.Server.ClearError(); 
    ctx.Response.ClearHeaders(); 
    // set the status code so we can return it for SEO 
    ctx.Response.StatusCode = httpCode; 
    ctx.Response.TrySkipIisCustomErrors = true; 
    HttpApplication myApplication = new HttpApplication(); 
    myApplication.Response.TrySkipIisCustomErrors = true; 
    try 
    { 
     if (ctx.Request.RawUrl.Contains("/*****")) 
     { 
      // redirect to the error page 
      ctx.Server.Transfer("~/*****.aspx", false); 
     } 
     else if(ctx.Request.RawUrl.Contains("/*****")) 
     { 
      ctx.Server.Transfer("~/*****/*****.aspx", false); 
     } 
     else 
     { 
      // check the httpCode 
      if (httpCode == 404) 
      { 
       // set the page name they were trying to find to a session variable 
       // this will be cleared in the ****** page 
       Application["404_page"] = exception.Message; 
       // redirect to the 404 page 
       ctx.Server.Transfer("~/*****", false); 
      } 
      else 
      { 
       // redirect to the error page 
       ctx.Server.Transfer("~/*****", false); 
      } 
     } 
    } 
} 
+0

Tu muestra de configuración no es válida, publica _actual_ snippets menos los datos confidenciales. –

Respuesta

25

de este comentario a Sr. Decepción:

Gracias, estoy usando IIS 7 local e IIS 7.5 en vivo. Avísame cuando encuentres el material.

Si su aplicación se ejecuta en un grupo de aplicaciones configurado para ejecutarse en el modo de canalización clásica, entonces el contenido no destinado para ASP.NET no afectará el tiempo de ejecución de ASP.NET. es decir, carpetas que no existen. Estos serán manejados directamente por IIS.

tienes un par de opciones:

  1. Establecer el grupo de aplicaciones a modo de canalización integrada. También puede ser necesario para establecer la siguiente configuración si el tratamiento de errores de IIS "come" el ASP.NET 404 y 500 del código de estado ASP.NET:

    <configuration> 
        <system.webServer> 
        <httpErrors existingResponse="PassThrough" /> 
        </system.webServer> 
    </configuration> 
    
  2. Si la solicitud no se comporta bien en la "canalización integrada" el modo, pero no eres más preocupados por conseguir una página que se muestra para una respuesta 404 a continuación, configure lo siguiente:

    <system.webServer> 
        <httpErrors> 
        <remove statusCode="404" subStatusCode="-1" /> 
        <error statusCode="404" prefixLanguageFilePath="" 
          path="/404.aspx" responseMode="ExecuteURL" /> 
        </httpErrors> 
    </system.webServer> 
    

    se necesitaría establecer el código de 404 estado en la página, de lo contrario sólo va a devolver un 200 .

    Si utiliza una página estática, por ejemplo:

    <error statusCode="404" prefixLanguageFilePath="" 
         path="404.html" responseMode="File" /> 
    

    Esto devolverá un 404.

  3. Si la aplicación no se comporta bien en el modo "Integrated Pipeline" AND debe pasar errores 404 a través de su manejador de errores, puede que tenga que mapear manualmente el contenido comodín en el HttpHandler de ASP.NET para que la tubería. Esta sería una solución subóptima.

+0

Gracias Kev. He hecho algunas de sus sugerencias y ahora obtengo la página IIS 404.0 para una ruta/directorio inexistente. He eliminado el , que ahora muestra la página de IIS. Todavía estoy teniendo problemas para disparar en ASP.NET. He intentado con las sugerencias en http://learn.iis.net/page.aspx/508/wildcard-script-mapping-and-iis-7-integrated-pipeline/ pero parecen no tener ningún efecto. Una vez más todo el manejo de mis errores está hecho, en el archivo global.asax no estoy usando ningún módulo personalizado para esto. Parece que solo necesito una parte más para que IIS no se encargue de la solicitud. – Kaos

+0

@Kaos - está funcionando su grupo en modo de canalización clásica o integrada – Kev

+1

@Kev Parece que está funcionando ahora. A continuación se muestra lo que hice en el Web.config. Kaos

4

ASP. NET nunca es invocado por IIS. IIS maneja la solicitud de página, ve que la página no existe y ASP.NET nunca se carga.

Si desea cargar ASP.NET independientemente de si el archivo existe, debe cambiar su configuración de IIS. ¿Estás usando IIS6 o IIS7/7.5?

+0

Gracias, estoy usando IIS 7 local e IIS 7.5 en los servidores en vivo – Kaos

+0

¿Cómo lo configuro para que ASP.net se cargue sin importar – Kaos

+2

Aquí hay alguna información sobre el manejo de todas las solicitudes, comienza la información de IIS7/7.5 sobre la mitad de la página: [link] (http://learn.iis.net/page.aspx/508/wildcard-script-mapping-and-iis-7-integrated-pipeline/) Lo importante parte está al final; necesita 'runAllManagedModulesForAllRequests' establecido en' True'. –

0

no puedo encontrar la fuente de material para esto, pero creo que el problema radica en el hecho de que es el manejo de error personalizado páginas y no caminos.

investigación sugiere que usted vino a través de este, ya que:

www.mysite.com/nonexistingpath/nonexistingpage.aspx 

Esto debe golpear la página de error correcto. El siguiente no:

www.mysite.com/nonexistingpath/ 

Este tipo de reitera que ya responder a su propia pregunta, pero voy a ver si puedo encontrar el material de referencia. En última instancia, no es una solicitud de página, por lo que no existe un manejo de ISAPI a través de los controladores adecuados.

+0

Gracias, estoy usando IIS 7 local e IIS 7.5 en vivo. Avísame cuando encuentres el material. – Kaos

+0

@Kaos: ¿No tuvo éxito ninguno de los enlaces provistos por Crunchy/Charlie? Ofrecen _how_, incluso si no _por qué_. –

+0

el enlace proporcionado por Crunchy/Charlie ayudó a algunos, pero no me ayudó con la solución que necesitaba. – Kaos

3

Usted necesidad de establecer asignación de comodín para que todas las peticiones pasan por .Net

si el uso de IIS6 el siguiente enlace pueden serle de ayuda:

http://professionalaspnet.com/archive/2007/07/27/Configure-IIS-for-Wildcard-Extensions-in-ASP.NET.aspx

asignación de script comodín y IIS 7 canalización integrada:

http://learn.iis.net/page.aspx/508/wildcard-script-mapping-and-iis-7-integrated-pipeline/

+0

Gracias estoy usando IIS 7 en local e IIS 7.5 en vivo. – Kaos