mio amico ed io stavano vivendo lo stesso problema con le aree in ASP.NET MVC 2. Abbiamo trovato un "hack" che, finora, sembra funzionare. Per la versione tl; dr, vedi la parte inferiore di questa risposta.
probabilmente si sono qualcosa di simile a quanto segue in classe "AdminAreaRegistration.cs" la vostra zona "Admin":
// 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 }
);
}
Quindi, dovrebbe avere un senso che quando si effettua una richiesta per "http://website/Abstract" , la route "Admin_default" non corrisponde alla richiesta. Pertanto, in base alla progettazione, il framework MVC tenta di abbinare la richiesta a qualsiasi altra route definita. Se hai utilizzato gli strumenti MVC in Visual Studio per creare il tuo progetto web, avrai una route "predefinita" definita nel tuo file "Global.asax" (nella radice del tuo progetto web). Esso dovrebbe essere simile a questo:
// 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}
);
}
Il percorso "Default" riesce a corrispondenza alla richiesta di "http://website/Abstract", con =, "azione" "controller" "astratta" = "Index" (valore di default), e "id" = UrlParameter.Optional (valore predefinito). Questo è il comportamento corretto e inteso ... finora.
Ora, il framework MVC tenterà di caricare il controller "Astratto". In base alla progettazione, MVC cerca una classe denominata "AbstractController" che estende "Controller" ovunque all'interno della gerarchia di file/spazio dei nomi del progetto Web. È importante notare che l'ubicazione e lo spazio dei nomi di un controller non influiscono sulla capacità di MVC di trovarlo; in altre parole, solo perché hai inserito "AbstractController" all'interno di una cartella denominata "Aree \ Admin \ Controller" e modificato lo spazio dei nomi in "Web.Areas.Admin.Controllers" anziché, ad esempio, "Web.Controllers" , non significa che MVC non lo userà.
Quando MVC esegue l'azione "Index" in "AbstractController" che, molto probabilmente, solo restituisce "View()", quindi MVC si confonde perché non sa dove trovare l ' "Indice" vista. Poiché MVC ha trovato una corrispondenza non di area (la route "Predefinita" in Global.asax), ritiene che la vista corrispondente debba trovarsi nelle cartelle di visualizzazione non dell'area. Così si ottiene il messaggio di errore familiare:
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
Noi, proprio come voi, non volevi richieste di "http://website/Abstract" per risolvere a "AbstractController" "Admin" del territorio; solo "http://website/Admin/Abstract" dovrebbe funzionare. Non riesco a pensare perché qualcuno vorrebbe questo comportamento.
Una soluzione semplice consiste nell'eliminare la route "Predefinita" in Global.asax, ma in questo modo interromperà qualsiasi controller/vista normale non area. Questa probabilmente non è un'opzione per la maggior parte delle persone ...
Così, abbiamo pensato che avremmo potuto limitare il set di controllori che MVC avrebbe usato per richieste con corrispondenza per via "Default" in 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
);
}
Nope. Una richiesta per "http://website/Abstract" sarà ancora usa "AbstractController" nell'area "Admin", anche se lo spazio dei nomi di "AbstractController" è "Web.Areas.Admin.Controllers" e (chiaramente) non "Web.Controllers" . Questo è completamente confuso; sembra che questa white-list non abbia alcun effetto visibile sulla risoluzione del controller di MVC.
- tl; dr risposta inizia qui -
Dopo un po 'di hacking, abbiamo capito come forzare MVC utilizzare solo controllori all'interno del namespace (s) white list.
// 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
}
impostare la chiave "UseNamespaceFallback" del dizionario DataTokens sulla rotta "Default" su false. Ora, quando facciamo una richiesta per "http://website/Abstract", la route "Default" sarà ancora abbinata (questo è un comportamento valido!) Ma MVC sarà non utilizzare qualsiasi Controller che non rientra nei namespace definiti; in questo caso, solo i controller all'interno dello spazio dei nomi "WebControllers" sono validi. Finalmente, questa è la funzionalità che stavamo cercando! Non riusciamo a capire perché questo non sia il comportamento predefinito. Strano, eh?
Spero che questo aiuti.
cosa ne pensate di questo: http://stackoverflow.com/questions/2314524/asp-net-mvc-2-rc-2-returns-area-specific-controller-when-no-area-specified è fondamentalmente un errore dire che il mio problema è di progettazione e l'unico modo per aggirarlo è quello di instradare il codice su ogni controller nello spazio dei nomi predefinito? – Bryan
sopra il link al commento di haack è sbagliato. correggi uno: http://stackoverflow.com/questions/1639971/mvc-2-arearegistration-routes-order/1640825#1640825 – Bryan
Senza vedere i percorsi che hai definito sia nella tua area che nel tuo sito principale, è impossibile raccontare. – Haacked