2010-02-22 13 views
5

Mam podstawową witrynę MVC 2 (RC2) z jednym kontrolerem poziomu bazowego ("Dom") i jednym obszarem ("Admin") z jeden kontroler ("Streszczenie"). Kiedy zadzwonię pod numer http://website/Abstract - kontroler abstrakcyjny w obszarze administracyjnym zostanie wywołany, mimo że nie określiłem obszaru w adresie URL. Co gorsza - nie wydaje się, aby wiedzieć, że jest pod Admin, ponieważ nie może znaleźć skojarzony widok i po prostu zwraca:ASP.NET MVC 2 RC 2 zwraca specyficzny dla obszaru kontroler, gdy nie określono obszaru

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 

robię coś źle? Czy to błąd? Cecha?

+0

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

+0

Powyższy link do komentarza haack'a jest błędny. poprawne: http://stackoverflow.com/questions/1639971/mvc-2-arearegistration-routes-order/1640825#1640825 – Bryan

+0

Nie widząc tras, które zdefiniowałeś zarówno w swoim obszarze, jak i na głównej stronie, nie można powiedzieć. – Haacked

Odpowiedz

11

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.

+0

dzięki za szczegółową odpowiedź. najlepsza odpowiedź, jaką widziałem. Słyszałem tylko trudne kody dla wszystkich moich administratorów root. – Bryan

+0

to jest świetna odpowiedź. Właśnie spotkałem to samo zachowanie i naprawdę byłem tym zaskoczony. –

1

Czy poprawnie skonfigurowałeś trasę? Podczas korzystania z obszarów musisz ręcznie zmienić kod routingu, aby MVC wyświetlało się w odpowiednich obszarach nazw.

http://haacked.com/archive/2010/01/12/ambiguous-controller-names.aspx

+0

Artykuł Haacka dotyczy głównie usuwania problemów związanych z duplikowaniem nazw kontrolerów. Próbowałem dodać domyślną przestrzeń nazw kontrolera do mojej domyślnej trasy, ale to nie pomaga. Wydaje się, że jest trochę zamieszania co do tego, co tak naprawdę jest: http://stackoverflow.com/questions/721700/asp-net-mvc-controller-namespace-array Niektórzy ludzie uważają, że to tylko nadaje priorytet pewnemu obszarowi nazw - ale wszystkie inne wciąż są przeszukiwane. – Bryan

Powiązane problemy