2009-07-23 31 views
5

que tienen un sitio asp.net mvc 1.0 que sirve algo de contenido a partir de una jerarquía de nivel 2 /categoría/artículoCómo manejar 'Ver no encontrado' InvalidOperationException en asp.net mvc?

Cuando las cosas funcionan bien los mapas de artículo para una vista y la vista consigue prestados. Sin embargo, cuando la url cumple con la condición de enrutamiento pero la vista no existe, se genera una excepción que no puedo atrapar en la acción del Controlador.

enrutamiento:

routes.MapRoute(
    "Article", 
    "{category}/{article}.aspx", 
    new { controller = "MyController", action = "Article" } 
); 

myController Acción:

public ActionResult Article(string category, string article) 
{ 
    string path = string.Format("~/Views/{0}/{1}.aspx", category, article); 
    ViewResult vr = View(path); 
    return vr; 
} 

Sin embargo, cuando no se encuentra el punto de vista, un System.InvalidOperationException se genera que no puedo coger en la acción del controlador.

Detalles de excepciones: System.InvalidOperationException: La vista '~/Vistas/mi-categoría/mi-artículo-con-largo name.aspx' o su maestro no podía ser encontrada. Los siguientes lugares se realizaron búsquedas: ~/Vistas/mi-categoría/mi-artículo-con-largo name.aspx

que pueda interceptar el error en el método Application_Error() en global.asax.cs pero:

  1. no sé cómo redireccionar a la vista de error desde allí
  2. pregunto si hay un lugar mejor cerca de donde está la excepción planteada.

Respuesta

7

xandy, Greg, Agradezco tus respuestas. Este artículo (Strategies For Resource Based 404 Errors in aspnet mvc) me ayudó a obtener la solución que estaba buscando de una manera bastante limpia. Todo lo que necesito hacer es anular el controlador.OnException. Como solo tengo un controlador donde necesito el comportamiento, solo tengo que anular OnException en ese controlador.

Habiendo dicho eso, mi solución trata los síntomas no la enfermedad y, como ambos sugieren, sería mejor verificar la existencia del archivo antes de invocar esto. Ver en un camino.

Aquí está el código que usa para tratar los síntomas :)

protected override void OnException(ExceptionContext filterContext) 
{ 
    //InvalidOperationException is thrown if the path to the view 
    // cannot be resolved by the viewengine 
    if (filterContext.Exception is InvalidOperationException) 
    { 
     filterContext.ExceptionHandled = true; 
     filterContext.Result = View("~/Views/Error/NotFound.aspx"); 
     filterContext.HttpContext.Response.StatusCode = 404; 
    } 

    base.OnException(filterContext); 
} 

Un problema que no podía resolver es cómo mostrar el NotFound Vista de una manera limpia. Por lo general, se accede a través de ErrorController NotFound Action. Tuve que codificar el camino hacia él. Puedo vivir con esto, pero me gustaría saber si es posible sin el camino de HC.

+0

He intentado y me gusta la solución. El único problema es que si obtiene una InvalidOperationException debido a un motivo diferente, se producirá un 404. Tuve una excepción al intentar serializar algo. – Bealer

0

Creo que el mejor lugar para comprobar si la vista existe estaría dentro del controlador. Si encapsula el constructor de la vista que no funciona, entonces es posible que ASP.net difiera la creación de instancias de Vista fuera del constructor (no estoy seguro de si lo está).

Pero una cosa que puede intentar es verificar manualmente si la ruta existe o no, usando Server.MapPath() para obtener la ruta absoluta del archivo y verificar si ya existe.

0

Me gustaría simplemente devolver una vista por defecto, tal vez una respuesta 404 sería apropiado. Por supuesto, para que esto funcione, tendrá que cambiar un poco su arquitectura.

AFAIK necesitará tener algún código para verificar si el archivo existe, como en su archivo ASPX si no desea el comportamiento predeterminado del marco de trabajo. Debería usar ResolveURL or Url.Content para resolver la ruta desde su ruta de aplicación.

Como nota, en general, no es exactamente seguro hacer su dominio (los nombres de los archivos) expuestos al mundo. Si los ASPX son solo datos, entonces debe poner el texto en una base de datos o archivos de texto simples, no ejecutables. Si está creando algún tipo de CMS (es decir, si realmente desea una forma de 'instalar' la funcionalidad), entonces podría considerar usar una vista ASPX para contener vistas parciales para encapsular los fragmentos del código ASP.NET.

En cuanto a llegar a la página 404, this answer podría ayudar.

3

Hay un lugar adecuado para manejar esto. Si implementa su propio ViewEngine, puede anular el método "FileExists".

public class ViewEngine : RazorViewEngine 
{ 
    protected override bool FileExists(ControllerContext context, string path) 
    { 
     if(!base.FileExists(context, path)) 
      throw new NotFoundException(); 

     return true; 
    } 

}

Sólo tiene que registrar el motor de vista en su Global.asax como tal,

ViewEngines.Engines.Clear(); 
ViewEngines.Engines.Add(new ViewEngine()); 

En Application_Error se puede implementar un controlador que atrapa NotFoundExceptions, los registra, a continuación, devuelve un mensaje amigable mediante la ejecución de un ErrorController.

Cuestiones relacionadas