Wyświetl widok z innego kontrolera w ASP.NET MVC

248

Czy można wyświetlić widok z innego kontrolera?

Powiedzmy na przykład mam CategoriesControlleri do Category/NotFound.aspxwidzenia. Będąc w CategoriesController, mogę łatwo wrócić View("NotFound").

Teraz powiedz, że mam ProductsControllerakcję i akcję oraz widok, aby dodać produkt. Jednak działanie to wymaga posiadania kategorii, do której można dodać Produkt. Na przykład Products/Add/?catid=10.

Jeśli nie mogę znaleźć kategorii na podstawie catid, chcę wyświetlić NotFoundwidok z kontrolera kategorii zamiast tworzyć CategoryNotFoundwidok pod kontrolerem produktów.

Czy to możliwe, czy też źle układam rzeczy? Czy jest na to dobry sposób?

dtc
źródło

Odpowiedzi:

283

Tak. Domyślnie ASP.NET MVC melduje się najpierw \Views\[Controller_Dir]\, ale potem, jeśli nie znajdzie widoku, melduje się \Views\Shared.

Udostępniony katalog jest przeznaczony specjalnie do udostępniania widoków na wielu kontrolerach. Po prostu dodaj swój widok do podkatalogu Shared i możesz już iść.

Jeśli to zrobisz, return View("~/Views/Wherever/SomeDir/MyView.aspx")możesz zwrócić dowolny widok, który chcesz.

womp
źródło
Dzięki, to brzmi jak rozwiązanie, którego powinienem użyć. Nadal zastanawiam się, czy można wyświetlić Widok z innego kontrolera. Zgaduję, że to narusza jakąś zasadę w MVC?
dtc
1
W sytuacji opisanej powyżej tak, powinieneś używać folderu współdzielonego.
Jonathan Freeland
69
Tak, to jest również możliwe. Jeśli zwrócisz Widok („~ / Views / Wherever / SomeDir / MyView.aspx”) Możesz zwrócić dowolny widok, który chcesz. Nie narusza to żadnej konkretnej reguły per se, jednak w ASP.Net MVC chodzi o „konwencję nad konfiguracją”. Innymi słowy, framework jest zbudowany tak, aby działał automatycznie z wykorzystaniem pewnych konwencji i powinieneś go używać tam, gdzie to możliwe.
womp
1
Dziękuję za wyjaśnienie. Nie wiedziałem, że można tak nazywać Widoki. Udostępniony katalog oczywiście działa idealnie :)
dtc
1
Nie byłem w kontrolerze, więc musiałem użyć new ViewResult { ViewName = "~/Views/Error/Unauthorised.cshtml" };i zadziałało
Nacht - Przywróć Monikę
162

Możesz użyć:

return View("../Category/NotFound", model);

Został przetestowany w ASP.NET MVC 3, ale powinien również działać w ASP.NET MVC 2.

Guillaume86
źródło
3
Pracuje w MVC 2 i okazało się, że jest najczystszym rozwiązaniem dla niecodziennej sytuacji, z którą mam do czynienia.
Todd Menier
3
Resharper zgłosi ten link jako błąd, ale nadal działa.
CodeMonkeyKing
1
@CodeMonkeyKing - Resharper 7 (w VS2012) poprawnie identyfikuje ścieżkę sformatowaną jako "~/Views/Category/NotFound.cshtml".
Richard Ev
Warto zauważyć: to rozwiązanie działa z trybami wyświetlania, np. Jeśli masz widok „/Category/NotFound.Mobile.cshtml”.
BenWillkommen,
55

Tak, to możliwe. Zwróć taką RedirectToAction()metodę:

return RedirectToAction("ActionOrViewName", "ControllerName");
doncadavona
źródło
1
Uważam, że powinno to wyglądać jak RedirectToAction („ActionOrView”, „Controller”, null), ponieważ w przeciwnym razie drugim parametrem jest routeValues
Zoran P.
Ale w tym przypadku musisz napisać akcję w kontrolerze, w przeciwieństwie do rozwiązania View.
tobbenb3
@ tobbenb3 To znacznie lepsze rozwiązanie niż kodowanie wyniku. Tak czy inaczej, nie powinieneś podawać ciągu ścieżki.
perustaja
34

Próbowałeś RedirectToAction?

Paul Johnson
źródło
1
Powiedziałbym, że jest to MVC dla każdego, kto nie chce widoku w udostępnionych folderach, pamiętaj, że dla wszystkich innych rozwiązań (takich jak korzystanie z bezpośrednich ścieżek) każdy, kto próbuje zmienić faktyczne widoki, nie będzie musiał brać pod uwagę że jest również używany w innym kontrolerze, co powoduje nieprzewidziane zachowanie
yoel halb
4
co powiesz na bez przekierowywania?
Luckyy,
znacznie lepsze rozwiązanie niż przenoszenie widoku do folderów współdzielonych
juFo
To rozwiązanie wymaga działania na kontrolerze, View (directPath) renderuje dane wyjściowe bez żadnych działań. Gdy dodasz akcję, musisz pomyśleć, aby ukryć ją przed bezpośrednim dostępem przez adres URL, wygeneruje ona krok w historii przeglądarki itp. Ale tak, to moja droga.
Jan Zahradník
3
RedirectToAction wysyła kod odpowiedzi 302 do przeglądarki. Nie jest to właściwe, gdy próbujesz wyświetlić stronę 404 nie znalezioną. Oznacza to, że to rozwiązanie wydaje się działać, ale dezorientuje wyszukiwarki.
NightOwl888
20

Tak, możesz. Zwróć działanie takie jak to:

return RedirectToAction("View", "Name of Controller");

Przykład:

return RedirectToAction("Details/" + id.ToString(), "FullTimeEmployees");

To podejście wywoła metodę GET

Możesz także przekazać wartości do akcji takiej jak ta:

return RedirectToAction("Details/" + id.ToString(), "FullTimeEmployees", new {id = id.ToString(), viewtype = "extended" });
ignacio chiazzo
źródło
jak mam wysłać obiekt przy takim podejściu?
Djeroen
Spójrz @Djeroen
ignacio chiazzo
5
Nie zwracasz widoku, wywołujesz akcję.
0014
Przede wszystkim było dla mnie pomocne.
anil shrestha
5

Możesz także wywołać dowolny kontroler z JavaScript / jQuery . Załóżmy, że masz kontroler zwracający 404 lub inną kontrolę / stronę użytkownika. Następnie, po pewnym działaniu, z kodu klienta możesz zadzwonić na jakiś adres, który uruchomi kontroler i zwróci wynik w formacie HTML , kod klienta może pobrać ten zwrócony wynik i umieścić go w dowolnym miejscu na stronie ...

Marko
źródło
Nie wiedziałem tego. To brzmi jak coś, czego mógłbym użyć w przyszłości. Tak, mvc rocks :)
dtc
1

Za pomocą tego kodu możesz uzyskać dowolny kontroler:

var controller = DependencyResolver.Current.GetService<ControllerB>();
controller.ControllerContext = new ControllerContext(this.Request.RequestContext, 
controller);
Yair GR
źródło
Tłumaczenie: Za pomocą tego kodu można uzyskać dowolny kontroler: [kod], Pozdrawiam,
Robert Columbia
3
Chociaż ten kod może odpowiedzieć na pytanie, zapewnienie dodatkowego kontekstu dotyczącego tego, jak i / lub dlaczego rozwiązuje problem, poprawiłoby długoterminową wartość odpowiedzi.
Nic3500,