Mi amigo y yo estábamos experimentando el mismo problema con las zonas en ASP.NET MVC 2. Encontramos un "hack" que, hasta ahora, parece estar funcionando. Para la versión de tl; dr, vea la parte inferior de esta respuesta.
usted probablemente tiene algo similar a la siguiente en la clase "AdminAreaRegistration.cs" su zona "administrador" de:
// Web/Areas/Admin/AdminAreaRegistration.cs
public override void RegisterArea(AreaRegistrationContext context) {
context.MapRoute(
"Admin_default",
"Admin/{controller}/{action}/{id}",
new { action = "Index", id = UrlParameter.Optional }
);
}
Por lo tanto, debe tener sentido de que cuando se hace una petición de "http://website/Abstract" , la ruta "Admin_default" no coincide con la solicitud. Entonces, por diseño, el marco MVC intenta hacer coincidir la solicitud con cualquier otra ruta definida. Si utilizó las herramientas de MVC en Visual Studio para crear su proyecto web, tendrá una ruta "Predeterminada" definida en su archivo "Global.asax" (en la raíz de su proyecto web). Debe tener un aspecto similar a este:
// Web/Global.asax.cs
public static void RegisterRoutes(RouteCollection routes) {
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
"Default",
"{controller}/{action}/{id}",
new {controller = "Home", action = "Index", id = UrlParameter.Optional}
);
}
La ruta "por defecto" tiene éxito en la adecuación de la solicitud de "http://website/Abstract", con "controlador" = "acción" "Resumen" = (valor por defecto) "Índice", e "id" = UrlParameter.Optional (valor predeterminado). Esta es la conducta correcta y prevista ... hasta ahora.
Ahora, la estructura MVC intentará cargar el Controlador "Abstracto". Por diseño, MVC buscará una clase llamada "AbstractController" que extienda "Controller" en cualquier lugar dentro de la jerarquía de archivos/espacios de nombres del proyecto web. Es importante tener en cuenta que la ubicación del archivo y el espacio de nombres de un Controlador no afectan la capacidad de MVC para encontrarlo; en otras palabras, solo porque ha colocado el "AbstractController" dentro de una carpeta llamada "Areas \ Admin \ Controllers" y ha cambiado el espacio de nombres para que sea "Web.Areas.Admin.Controllers" en lugar de, digamos, "Web.Controllers" , no significa que MVC no lo usará.
Cuando MVC ejecuta la acción "Index" en "AbstractController" que, muy probablemente, simplemente devuelva "View()", entonces MVC se confunde porque no sabe dónde encontrar la vista "Index". Como MVC ha coincidido con una ruta que no es de área (la ruta "Predeterminada" en Global.asax), cree que la vista coincidente debe ubicarse en carpetas que no sean de área. De este modo se obtiene el mensaje de error conocido:
The view 'Index' or its master was not found. The following locations were searched:
~/Views/Abstract/Index.aspx
~/Views/Abstract/Index.ascx
~/Views/Shared/Index.aspx
~/Views/Shared/Index.ascx
Nosotros, al igual que usted, no quería que las solicitudes de "http://website/Abstract" para resolver a "AbstractController" zona "administrador" de; solo "http://website/Admin/Abstract" debería funcionar. No puedo pensar por qué alguien querría este comportamiento.
Una solución simple es eliminar la ruta "Predeterminada" en Global.asax, pero esto romperá cualquier Controlador/Vistas regular que no sea de área. Probablemente esta no sea una opción para la mayoría de las personas ...
Por lo tanto, pensamos que podría restringir el conjunto de controladores que MVC usaría para solicitudes coincidentes por la ruta "por defecto" en Global.asax:
// Web/Global.asax.cs
public static void RegisterRoutes(RouteCollection routes) {
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
"Default",
"{controller}/{action}/{id}",
new {controller = "Home", action = "Index", id = UrlParameter.Optional},
new[] {"Web.Controllers"} // Added this line
);
}
Nop. Una solicitud para "http://website/Abstract" será todavía use "AbstractController" dentro del área "Administrador", aunque el espacio de nombres "AbstractController" sea "Web.Areas.Admin.Controllers" y (claramente) no "Web.Controllers" . Esto es completamente confuso; parece que esta lista blanca no tiene efecto diferible en la resolución del controlador MVC.
- tl; dr respuesta comienza aquí -
Después de algún piratería, nos dimos cuenta de cómo forzar MVC utilizar sólo los controladores dentro del espacio de nombres (s) de la lista blanca.
// Web/Global.asax.cs
public static void RegisterRoutes(RouteCollection routes) {
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
"Default",
"{controller}/{action}/{id}",
new {controller = "Home", action = "Index", id = UrlParameter.Optional},
new[] {"Web.Controllers"}
).DataTokens["UseNamespaceFallback"] = false; // Added this line
}
establecer la clave "UseNamespaceFallback" del diccionario DataTokens en la ruta "por defecto" false. Ahora, cuando realizamos una solicitud de "http://website/Abstract", la ruta "Predeterminada" seguirá coincidiendo (¡esto es un comportamiento válido!) Pero MVC no utilizará ningún Controlador que no esté dentro del (los) espacio (s) de nombre definidos; en este caso, solo los Controladores dentro del espacio de nombres "Web.Controllers" son válidos. ¡Finalmente, esta es la funcionalidad que estábamos buscando! No podemos entender por qué este no es el comportamiento predeterminado. Extraño, ¿eh?
Espero que esto ayude.
¿qué piensan todos de esto: http://stackoverflow.com/questions/2314524/asp-net-mvc-2-rc-2-returns-area-specific-controller-when-no-area-specified es básicamente decir que mi problema es por diseño y la única forma de evitarlo es codificar las rutas a cada controlador en el espacio de nombres predeterminado. – Bryan
arriba el enlace al comentario de haack es incorrecto. una correcta: http://stackoverflow.com/questions/1639971/mvc-2-arearegistration-routes-order/1640825#1640825 – Bryan
Sin ver las rutas que ha definido tanto en su área como en su sitio principal, es imposible contar. – Haacked