Mam witrynę internetową, która ma układ strony. Jednak ta strona układu zawiera dane, które model wszystkich stron musi zawierać taki tytuł strony, nazwę strony i lokalizację, w której faktycznie się znajdujemy, dla pomocnika HTML, który wykonałem, który wykonał jakąś akcję. Każda strona ma również własne właściwości modeli widoku.
W jaki sposób mogę to zrobić? Wygląda na to, że wpisywanie układu jest złym pomysłem, ale jak mam przekazać te informacje?
asp.net-mvc-4
Rushino
źródło
źródło
ViewBag
. Być może kwestia preferencji. Głosował jednak za twoim komentarzemOdpowiedzi:
Jeśli musisz przekazać te same właściwości do każdej strony, rozsądne byłoby utworzenie podstawowego modelu widoku, który jest używany przez wszystkie modele widoku. Twoja strona układu może następnie przyjąć ten model podstawowy.
Jeśli za tymi danymi jest wymagana logika, należy je umieścić w podstawowym kontrolerze używanym przez wszystkie kontrolery.
Jest wiele rzeczy, które możesz zrobić, ale ważne podejście polega na tym, aby nie powtarzać tego samego kodu w wielu miejscach.
Edycja: aktualizacja z komentarzy poniżej
Oto prosty przykład, aby zademonstrować tę koncepcję.
Utwórz model widoku bazowego, z którego będą dziedziczyć wszystkie modele widoku.
Twoja strona układu może przyjąć to jako model.
Na koniec ustaw dane w metodzie akcji.
źródło
public class HomeController : BaseController
. W ten sposób wspólny kod wystarczy napisać tylko raz i można go zastosować do wszystkich kontrolerów.Użyłem pomocnika HTML RenderAction dla maszynki do golenia w układzie.
Potrzebowałem go do prostego sznurka. Więc moja akcja zwraca łańcuch i łatwo go zapisuje. Ale jeśli potrzebujesz złożonych danych, możesz zwrócić PartialViewResult i modelować.
Wystarczy, że umieścisz swój model na początku utworzonego widoku częściowego „_maPartialView.cshtml”
Następnie możesz użyć danych w modelu w tym częściowym widoku za pomocą html.
źródło
Inną opcją jest utworzenie oddzielnej klasy LayoutModel ze wszystkimi właściwościami, których będziesz potrzebować w układzie, a następnie włóż wystąpienie tej klasy do ViewBag. Używam metody Controller.OnActionExecuting, aby ją wypełnić. Następnie na początku układu możesz wyciągnąć ten obiekt z powrotem z ViewBag i kontynuować dostęp do tego silnie wpisanego obiektu.
źródło
OnActionExecuting
. Korzystanie z ViewBag oznacza również utratę bezpieczeństwa typu w kontrolerze, co nigdy nie jest dobre.Przypuszczalnie podstawowym przypadkiem użycia tego jest pobranie modelu podstawowego do widoku dla wszystkich (lub większości) akcji kontrolera.
Biorąc to pod uwagę, użyłem kombinacji kilku z tych odpowiedzi, głównie w oparciu o odpowiedź Colina Bacona.
To prawda, że nadal jest to logika kontrolera, ponieważ zapełniamy model widoku, aby powrócić do widoku. Dlatego właściwym miejscem do umieszczenia tego jest kontroler.
Chcemy, aby miało to miejsce na wszystkich kontrolerach, ponieważ używamy tego na stronie układu. Używam go do częściowych widoków renderowanych na stronie układu.
Nadal chcemy również dodatkowej korzyści z silnie wpisanego ViewModel
W ten sposób utworzyłem BaseViewModel i BaseController. Wszystkie kontrolery ViewModels będą dziedziczyć odpowiednio po BaseViewModel i BaseController.
Kod:
BaseController
Zwróć uwagę na użycie OnActionExecuted wzięte z tego postu SO
HomeController
BaseViewModel
HomeViewModel
FooterModel
Layout.cshtml
_Nav.cshtml
Mam nadzieję, że to pomoże.
źródło
Nie musisz majstrować przy akcjach ani zmieniać modelu, po prostu użyj kontrolera podstawowego i rzutuj istniejący kontroler z kontekstu widoku układu.
Utwórz podstawowy kontroler z żądanymi wspólnymi danymi (tytuł / strona / lokalizacja itp.) I inicjalizacją akcji ...
Upewnij się, że każdy kontroler używa kontrolera podstawowego ...
Przerzuć istniejący kontroler podstawowy z kontekstu widoku na twojej
_Layout.cshml
stronie ...Teraz możesz odwoływać się do wartości w kontrolerze podstawowym ze strony układu.
AKTUALIZACJA
Możesz także utworzyć rozszerzenie strony, które pozwoliłoby ci używać
this
.Wtedy musisz tylko pamiętać, aby używać
this.Controller()
kontrolera, gdy chcesz.lub określony kontroler, który dziedziczy po
_BaseController
...źródło
jeśli chcesz przekazać cały model, postępuj tak w układzie:
i dodaj to w kontrolerze:
źródło
Nie sądzę, aby żadna z tych odpowiedzi była wystarczająco elastyczna dla dużej aplikacji na poziomie przedsiębiorstwa. Nie jestem fanem nadużywania ViewBag, ale w tym przypadku dla elastyczności zrobiłbym wyjątek. Oto, co bym zrobił ...
Powinieneś mieć podstawowy kontroler na wszystkich kontrolerach. Dodaj dane układu OnActionExecuting w kontrolerze podstawowym (lub OnActionExecuted, jeśli chcesz to odroczyć) ...
Następnie w swoim _Layout.cshtml ściągnij swój ViewModel z ViewBag ...
Lub...
Nie wpływa to na kodowanie kontrolerów strony ani modeli widoków.
źródło
MyLayoutViewModel
dynamicznie utworzony, jak mogę przekazać niektóre parametry doOnActionExecuting
metody?base.OnActionExecuting(filterContext)
swojejOnActionExecuting
metody !!!Tworzenie widoku podstawowego, który reprezentuje model widoku Układ, jest okropnym podejściem. Wyobraź sobie, że chcesz mieć model, który reprezentuje nawigację zdefiniowaną w układzie. Zrobiłbyś to
CustomersViewModel : LayoutNavigationViewModel
? Czemu? Dlaczego należy przekazywać dane modelu nawigacji przez każdy model widoku znajdujący się w rozwiązaniu?Model widoku układu powinien być dedykowany samodzielnie i nie powinien zmuszać pozostałych modeli widoku do polegania na nim.
Zamiast tego możesz to zrobić w swoim
_Layout.cshtml
pliku:Co najważniejsze, nie musimy tego robić
new LayoutViewModel()
i otrzymamy wszystkie zależności, któreLayoutViewModel
zostały rozwiązane za nas.na przykład
źródło
Scoped
obiekt modelu układu w ASP..Net Core, jak również.Inne odpowiedzi obejmowały prawie wszystko, w jaki sposób możemy przekazać model do naszej strony układu. Ale znalazłem sposób, za pomocą którego można dynamicznie przekazywać zmienne do strony układu, bez korzystania z żadnego modelu lub częściowego widoku w układzie. Powiedzmy, że masz ten model -
I chcesz dynamicznie uzyskiwać miasto i stan. Np
w pliku index.cshtml możesz umieścić te dwie zmienne w ViewBag
Następnie w pliku layout.cshtml możesz uzyskać dostęp do tych zmiennych widoku
źródło
Jest inny sposób, aby sobie z tym poradzić. Może nie jest to najczystszy sposób z architektonicznego punktu widzenia, ale pozwala uniknąć wielu problemów związanych z innymi odpowiedziami. Po prostu wstrzyknij usługę w układzie Razor, a następnie wywołaj metodę, która pobiera niezbędne dane:
Następnie w widoku układu:
Ponownie, nie jest czysty pod względem architektury (oczywiście usługa nie powinna być wstrzykiwana bezpośrednio w widoku), ale wykonuje swoje zadanie.
źródło
@inject
Moim zdaniem najlepszym rozwiązaniem jest używanie .Możesz także skorzystać z RenderSection , który pomoże Ci wprowadzić
Model
dane do_Layout
widoku.Możesz wstrzyknąć
View Model
daneJson
,Script
,CSS
,HTML
etcW tym przykładzie wstrzykuję
Json
z mojegoIndex
widoku doLayout
widoku.Index.chtml
_Layout.cshtml
Eliminuje to potrzebę tworzenia oddzielnej Bazy
View Model
.Nadzieja pomaga komuś.
źródło
to, co zrobiłem, jest bardzo proste i działa
Zadeklaruj właściwość statyczną w dowolnym kontrolerze lub możesz utworzyć klasę danych z wartościami statycznymi, jeśli chcesz w ten sposób:
Wartości te mogą być aktualizowane przez kontrolery na podstawie operacji. później możesz ich użyć w swoim _Layout
W pliku _layout.cshtml
źródło
Dlaczego nikt nie zasugerował metod rozszerzających w ViewData?
Opcja 1
Wydaje mi się zdecydowanie najmniej inwazyjnym i najprostszym rozwiązaniem problemu. Żadnych ciągów zakodowanych na stałe. Brak narzuconych ograniczeń. Żadnego magicznego kodowania. Bez skomplikowanego kodu.
Ustaw dane na stronie
Opcja 2
Inna opcja, ułatwiająca deklarację pola.
Ustaw dane na stronie. Deklaracja jest łatwiejsza niż pierwsza opcja, ale składnia użycia jest nieco dłuższa.
Opcja nr 3
Następnie można to połączyć z zwróceniem pojedynczego obiektu zawierającego wszystkie pola związane z układem z ich wartościami domyślnymi.
Ustaw dane na stronie
Ta trzecia opcja ma kilka zalet i myślę, że w większości przypadków jest najlepszą opcją:
Najprostsza deklaracja pól i wartości domyślnych.
Najprostsza składnia użycia podczas ustawiania wielu pól.
Umożliwia ustawienie różnego rodzaju danych w ViewData (np. Layout, Header, Navigation).
Zezwala na dodatkowy kod i logikę w klasie LayoutData.
PS Nie zapomnij dodać przestrzeni nazw ViewDataExtensions w _ViewImports.cshtml
źródło
Możesz utworzyć plik razor w folderze App_Code, a następnie uzyskać do niego dostęp ze stron widoku.
Projekt> Repozytorium / IdentityRepository.cs
Projekt> App_Code / IdentityRepositoryViewFunctions.cshtml:
Projekt> Widoki / Shared / _Layout.cshtml (lub dowolny inny plik .cshtml)
źródło
zamiast przechodzić przez to, zawsze możesz zastosować inne podejście, które również jest szybkie
utwórz nowy widok częściowy w katalogu udostępnionym i nazwij swój widok częściowy w układzie jako
w częściowym widoku możesz zadzwonić do swojej bazy danych i wykonać to, co chcesz
zakładając, że dodano bazę danych Entity Framework
źródło
To niesamowite, że nikt tego tutaj nie powiedział. Przekazywanie modelu widoku przez podstawowy kontroler to bałagan. Używamy oświadczeń użytkowników, aby przekazywać informacje do strony układu (na przykład do wyświetlania danych użytkownika na pasku nawigacyjnym). Jest jeszcze jedna zaleta. Dane są przechowywane za pomocą plików cookie, więc nie ma potrzeby pobierania danych w każdym żądaniu za pośrednictwem częściowych. Po prostu wyszukaj w Google „oświadczenia o tożsamości netto”.
źródło
Możesz użyć w ten sposób:
źródło