Mój przyjaciel i ja przeżywa ten sam problem z dziedzin, w ASP.NET MVC 2. Znaleźliśmy „hack”, które, jak dotąd, wydaje się działać. W przypadku wersji tl; dr, spójrz na dół tej odpowiedzi.
Pewnie coś podobnego do następującego w swojej klasie „admin” obszaru „AdminAreaRegistration.cs”:
// 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 }
);
}
Zatem powinien on mieć sens, że kiedy złożyć wniosek o „http://website/Abstract” , trasa "Admin_default" nie pasuje do zapytania. Tak więc, zgodnie z projektem, środowisko MVC próbuje dopasować żądanie do innych zdefiniowanych tras. Jeśli używałeś narzędzi MVC w Visual Studio do stworzenia swojego projektu internetowego, będziesz mieć zdefiniowaną "Domyślną" trasę w pliku "Global.asax" (w katalogu głównym projektu WWW). Powinno to wyglądać mniej więcej tak:
// 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}
);
}
"default" Trasa udaje się dopasowanie żądanie "http://website/Abstract", z "kontrolera" = "streszczenie", "działania" = "Index" (wartość domyślna), i "id" = UrlParameter.Optional (wartość domyślna). To jest prawidłowe i zamierzone zachowanie ... do tej pory.
Teraz platforma MVC spróbuje załadować kontroler "abstrakcyjny". Zgodnie z projektem, MVC wyszuka klasę o nazwie "AbstractController", która rozszerza "Kontroler" w dowolnym miejscu w hierarchii plików/przestrzeni projektu projektu internetowego. Ważne jest, aby pamiętać, że lokalizacja pliku sterownika i przestrzeń nazw nie wpływają na zdolność MVC do jego znalezienia; innymi słowy, tylko dlatego, że umieściliście "AbstractController" w folderze o nazwie "Areas \ Admin \ Controllers" i zmienili przestrzeń nazw na "Web.Areas.Admin.Controllers" zamiast, powiedzmy, "Web.Controllers" , nie oznacza, że MVC z niego nie skorzysta.
Kiedy MVC wykonuje akcję "Index" w "AbstractController", która najprawdopodobniej po prostu zwraca "View()", wtedy MVC zostaje zdezorientowany, ponieważ nie wie, gdzie znaleźć widok "Index". Ponieważ MVC pasuje do trasy innej niż obszar (trasa "Domyślna" w pliku Global.asax), uważa, że pasujący widok powinien znajdować się w folderach widoku poza obszarem. W ten sposób można dostać znajomy komunikat o błędzie:
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
My, tak jak ty, nie chciał żądania „http://website/Abstract” rozwiązania na „AbstractController” „admin” obszaru; tylko "http://website/Admin/Abstract" powinno działać. Nie mogę myśleć, dlaczego ktokolwiek chciałby tego zachowania.
Prostym rozwiązaniem jest usunięcie trasy "domyślnej" w pliku Global.asax, , ale spowoduje to zerwanie wszystkich zwykłych kontrolerów/widoków spoza obszaru. To chyba nie jest opcja dla większości ludzi ...
więc myśleliśmy, że możemy ograniczyć zestaw kontrolerów MVC korzystać żądań dopasowane przez „default” trasy w 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
);
}
Nie. Żądanie "http://website/Abstract" nadal będzie mieć wartość i nadal będzie używać "AbstractController" w obszarze "Admin", nawet jeśli przestrzeń "AbstractController" to "Web.Areas.Admin.Controllers" i (wyraźnie) nie "Web.Controllers" . To jest całkowicie mylące; wygląda na to, że ta biała lista nie ma wpływu na rozdzielczość kontrolera MVC.
- tl; dr odpowiedź zaczyna się tutaj -
Po pewnym hacking, zorientowaliśmy się, jak zmusić MVC używać tylko Kontrolery wewnątrz białej liście nazw (y).
// 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
}
Ustawienie klawisza "UseNamespaceFallback" słownika DataTokens na "Domyślnej" trasie na false. Teraz, gdy złożymy wniosek o "http://website/Abstract", trasa "Domyślna" będzie nadal dopasowana (to jest prawidłowe zachowanie!), Ale MVC będzie , a nie używać dowolnego kontrolera, który nie znajduje się w zdefiniowanych obszarach nazw; w tym przypadku tylko kontrolery w przestrzeni nazw "Web.Controllers" są prawidłowe. Wreszcie, to jest funkcja, której szukaliśmy! Nie możemy zrozumieć, dlaczego nie jest to domyślne zachowanie. Dziwne, co?
Mam nadzieję, że to pomoże.
co o tym wszystkim sądzisz: http://stackoverflow.com/questions/2314524/asp-net-mvc-2-rc-2-return-area-specific-controller-wtedy-no-area-specified jest w gruncie rzeczy mówiąc, że mój problem jest z założenia, a jedynym sposobem, w jaki jest to możliwe, jest trudne kodowanie tras do każdego kontrolera w domyślnej przestrzeni nazw? – Bryan
Powyższy link do komentarza haack'a jest błędny. poprawne: http://stackoverflow.com/questions/1639971/mvc-2-arearegistration-routes-order/1640825#1640825 – Bryan
Nie widząc tras, które zdefiniowałeś zarówno w swoim obszarze, jak i na głównej stronie, nie można powiedzieć. – Haacked