Z tego pytania wynika, że sensowne jest, aby kontroler utworzył model ViewModel, który dokładniej odzwierciedla model, który widok próbuje wyświetlić, ale jestem ciekawy niektórych konwencji (jestem nowy we wzorcu MVC , jeśli nie było to już oczywiste).
Zasadniczo miałem następujące pytania:
- Zwykle lubię mieć jedną klasę / plik. Czy ma to sens w przypadku ViewModel, jeśli jest on tworzony tylko w celu przekazywania danych z kontrolera do widoku?
- Jeśli ViewModel należy do własnego pliku, a ty używasz struktury katalogu / projektu do oddzielenia rzeczy, to gdzie należy plik ViewModel ? W katalogu kontrolerów ?
Na razie tyle. Mogę mieć jeszcze kilka pytań, ale przeszkadza mi to przez ostatnią godzinę i wydaje mi się, że mogę znaleźć spójne wskazówki gdzie indziej.
EDYCJA: Patrząc na przykładową aplikację NerdDinner na CodePlex, wygląda na to, że ViewModels są częścią Kontrolerów , ale nadal sprawia mi to dyskomfort, że nie znajdują się we własnych plikach.
asp.net-mvc
asp.net-mvc-viewmodel
jerhinesmith
źródło
źródło
Odpowiedzi:
Dla każdego widoku tworzę coś, co nazywam „ViewModel”. Umieszczam je w folderze o nazwie ViewModels w moim projekcie MVC Web. Nazywam je po kontrolerze i akcji (lub widoku), które reprezentują. Więc jeśli muszę przekazać dane do widoku SignUp na kontrolerze członkostwa, tworzę klasę MembershipSignUpViewModel.cs i umieszczam ją w folderze ViewModels.
Następnie dodaję niezbędne właściwości i metody, aby ułatwić transfer danych z kontrolera do widoku. Korzystam z Automappera, aby przejść z mojego ViewModel do modelu domeny i wrócić, jeśli to konieczne.
Działa to również dobrze w przypadku złożonych modeli ViewModels, które zawierają właściwości podobne do innych modeli ViewModels. Na przykład, jeśli masz 5 widgetów na stronie indeksu w kontrolerze członkostwa i utworzyłeś ViewModel dla każdego widoku częściowego - w jaki sposób przekazujesz dane z akcji Index do części? Dodajesz właściwość do MembershipIndexViewModel typu MyPartialViewModel, a podczas renderowania częściowej przekazujesz w Model.MyPartialViewModel.
Wykonanie tego w ten sposób pozwala dostosować częściowe właściwości ViewModel bez konieczności zmiany widoku indeksu. Nadal po prostu przechodzi w Model.MyPartialViewModel, więc jest mniejsza szansa, że będziesz musiał przejść przez cały łańcuch części, aby coś naprawić, gdy wszystko, co robisz, to dodawanie właściwości do częściowego ViewModel.
Dodam również przestrzeń nazw „MyProject.Web.ViewModels” do web.config, aby umożliwić mi odwoływanie się do nich w dowolnym widoku bez dodawania wyraźnej instrukcji importu do każdego widoku. Po prostu sprawia, że jest trochę czystszy.
źródło
Rozdzielanie klas według kategorii (kontrolery, modele ViewModels, filtry itp.) To nonsens.
Jeśli chcesz napisać kod dla sekcji Home swojej witryny (/), utwórz folder o nazwie Home i umieść tam HomeController, IndexViewModel, AboutViewModel itp. Oraz wszystkie powiązane klasy używane przez akcje Home.
Jeśli masz wspólne klasy, takie jak ApplicationController, możesz umieścić je w katalogu głównym projektu.
Po co rozdzielać rzeczy powiązane (HomeController, IndexViewModel) i utrzymywać razem rzeczy, które w ogóle nie mają związku (HomeController, AccountController)?
Napisałem post na blogu na ten temat.
źródło
Trzymam swoje klasy aplikacji w podfolderze o nazwie „Core” (lub oddzielnej bibliotece klas) i używam tych samych metod, co KIGG przykładowa aplikacja , ale z pewnymi zmianami, aby moje aplikacje były bardziej SUCHE.
Tworzę klasę BaseViewData w / Core / ViewData /, gdzie przechowuję wspólne właściwości dla całej witryny.
Następnie tworzę również wszystkie moje klasy ViewData widoku w tym samym folderze, które następnie pochodzą z BaseViewData i mają określone właściwości widoku.
Następnie tworzę ApplicationController, z którego pochodzą wszystkie moje kontrolery. ApplicationController ma ogólną metodę GetViewData w następujący sposób:
Wreszcie w mojej akcji kontrolera wykonuję następujące czynności, aby zbudować mój model ViewData
Myślę, że to działa naprawdę dobrze i utrzymuje twoje widoki w porządku i twoje kontrolery są chude.
źródło
Klasa ViewModel służy do kapsułkowania wielu elementów danych reprezentowanych przez instancje klas w jednym łatwym do zarządzania obiekcie, który można przekazać do swojego widoku.
Sensowne byłoby posiadanie klas ViewModel we własnych plikach, we własnym katalogu. W moich projektach mam podfolder folderu Modele o nazwie ViewModels. Tam
ProductViewModel.cs
mieszkają moje modele ViewModels (np. ).źródło
Nie ma dobrego miejsca na przechowywanie modeli. Możesz przechowywać je w osobnym zestawie, jeśli projekt jest duży i istnieje wiele ViewModels (obiektów transferu danych). Możesz także przechowywać je w osobnym folderze projektu witryny. Na przykład w Oxite są one umieszczane w projekcie Oxite, który zawiera również wiele różnych klas. Kontrolery w Oxite są przenoszone do osobnego projektu, a widoki są również w osobnym projekcie.
W CodeCampServer ViewModels mają nazwę * Form i są umieszczane w projekcie interfejsu użytkownika w folderze Modele.
W projekcie MvcPress są one umieszczane w projekcie Data, który zawiera również cały kod do pracy z bazą danych i trochę więcej (ale nie poleciłem tego podejścia, to tylko przykład)
Możesz więc zobaczyć, że jest wiele punktów widzenia. Zazwyczaj trzymam moje ViewModels (obiekty DTO) w projekcie witryny. Ale kiedy mam więcej niż 10 modeli, wolę przenieść je do oddzielnego zestawu. Zwykle w tym przypadku przenoszę również kontrolery do oddzielnego zestawu.
Kolejne pytanie dotyczy łatwego mapowania wszystkich danych z modelu na model ViewModel. Sugeruję zajrzeć do biblioteki AutoMapper . Bardzo mi się podoba, to dla mnie cała brudna robota.
Proponuję także przyjrzeć się projektowi SharpArchitecture . Zapewnia bardzo dobrą architekturę dla projektów i zawiera wiele fajnych ram i wskazówek oraz wspaniałą społeczność.
źródło
Oto fragment kodu z moich najlepszych praktyk:
źródło
Wrzucamy wszystkie nasze ViewModels do folderu Modele (cała nasza logika biznesowa znajduje się w osobnym projekcie ServiceLayer)
źródło
Osobiście sugerowałbym, że jeśli ViewModel nie jest trywialny, użyj osobnej klasy.
Jeśli masz więcej niż jeden model widoku, sugeruję, aby sensowne było podzielenie go na przynajmniej katalog. jeśli model widoku zostanie później udostępniony, wówczas przestrzeń nazw sugerowana w katalogu ułatwia przejście do nowego zestawu.
źródło
W naszym przypadku mamy modele wraz ze sterownikami w projekcie oddzielnym od widoków.
Zasadniczo próbowaliśmy przenieść i uniknąć większości elementów ViewData [„...”] do ViewModel, dlatego unikamy rzutów i magicznych ciągów, co jest dobrą rzeczą.
ViewModel posiada również pewne wspólne właściwości, takie jak informacje o paginacji dla list lub informacje nagłówkowe strony, aby narysować okruszki i tytuły. W tej chwili klasa podstawowa zawiera moim zdaniem zbyt dużo informacji i możemy podzielić ją na trzy części, najbardziej podstawowe i niezbędne informacje dla 99% stron w modelu widoku podstawowego, a następnie model dla list i model dla formularzy, które przechowują określone dane dla tych scenariuszy i dziedziczą po podstawowym.
Wreszcie, wdrażamy model widoku dla każdego podmiotu, aby zająć się konkretnymi informacjami.
źródło
kod w kontrolerze:
kod w widoku modelu:
projektowanie:
DevJet.Web (projekt internetowy ASP.NET MVC)
DevJet.Web.App.Dictionary (oddzielny projekt biblioteki klas)
w tym projekcie stworzyłem kilka folderów takich jak: DAL, BLL, BO, VM (folder do przeglądania modeli)
źródło
Utwórz klasę bazową modelu widoku, która ma zwykle wymagane właściwości, takie jak wynik operacji i dane kontekstowe, można również umieścić bieżące dane użytkownika i role
W klasie kontrolera bazowego istnieje metoda taka jak PopulateViewModelBase (), ta metoda wypełni dane kontekstowe i role użytkownika. HasError i ErrorMessage, ustaw te właściwości, jeśli istnieje wyjątek podczas pobierania danych z usługi / db. Powiąż te właściwości w widoku, aby pokazać błąd. Roli użytkownika można używać do pokazywania ukrytej sekcji w widoku opartym na rolach.
Aby zapełnić modele widoków różnymi działaniami get, można to uczynić spójnym, mając podstawowy kontroler z abstrakcyjną metodą FillModel
W kontrolerach
źródło