Czy warstwa usług powinna zwracać modele wyświetlania aplikacji MVC?

Powiedz, że masz ASP.NET projekt MVC i używają warstwy usług, takiej jak w tym poradniku menedżera kontaktów na asp.net Strona: http://www.asp.net/mvc/tutorials/iteration-4-make-the-application-loosely-coupled-cs

Jeśli masz viewmodele dla swoich widoków, czy warstwa usług jest odpowiednim miejscem, aby zapewnić każdy viewmodel? Na przykład w próbce kodu warstwy usług znajduje się metoda

    public IEnumerable<Contact> ListContacts()
    {
        return _repository.ListContacts();
    }

Jeśli zamiast tego chcesz mieć liczbę mnogą, czy powinna ona wejść w warstwa serwisowa, czy gdzieś indziej jest to" właściwe " miejsce?

Być może lepiej, jeśli masz osobny model widoku dla każdego widoku skojarzonego z ContactController, czy ContactManagerService powinien mieć osobną metodę zwracania każdego widoku? Jeśli warstwa usługowa nie jest właściwym miejscem, to gdzie należy zainicjować obiekty viewmodel do użycia przez kontroler?

Author: tereško, 2010-06-09

5 answers

Ogólnie nie.

Modele widoków mają na celu dostarczanie informacji do i z widoków i powinny być specyficzne dla aplikacji, w przeciwieństwie do domeny ogólnej. Kontrolery powinny koordynować interakcję z repozytoriami, usługami (tutaj wprowadzam pewne założenia definicji usługi), itp. oraz obsługiwać budowanie i walidację modeli widoków, a także zawierać logikę określania widoków do renderowania.

Przeciekając modele widoku do warstwy "usługi", jesteś rozmycie warstw i teraz mają możliwość zastosowania i prezentacji specyficznych zmieszanych z tym, co powinno koncentrować się na obowiązkach na poziomie domeny.

 42
Author: captaintom,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-06-09 00:18:43

Nie, Nie sądzę. Usługi powinny dbać tylko o domenę problemu, a nie widok, który renderuje wyniki. Zwracane wartości powinny być wyrażane w kategoriach obiektów domeny, a nie widoków.

 21
Author: duffymo,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-06-09 00:07:07

Zgodnie z tradycyjnym podejściem lub teorią, ViewModel powinien być częścią warstwy interfejsu użytkownika. Przynajmniej nazwa Tak mówi.

Ale kiedy przejdziesz do implementacji za pomocą Entity Framework, MVC, repozytorium itp., to zdasz sobie sprawę z czegoś innego.

Ktoś musi mapować modele Entity / DB za pomocą ViewModels (Dto wspomniane na końcu). Czy należy to zrobić w [a] warstwie interfejsu użytkownika (przez kontroler), czy w [B] warstwie usługi?

Wybieram opcję B. opcja A to nie nie ze względu na prosty fakt, że kilka modeli jednostek łączy się ze sobą tworząc model ViewModel. Nie możemy przekazywać niepotrzebnych danych do warstwy UI, podczas gdy w opcji B usługa może bawić się danymi i przekazać tylko wymagane/minimum do warstwy UI po mapowaniu (do ViewModel).

Ponownie, przejdźmy do opcji A, umieść ViewModel w warstwie interfejsu użytkownika (a model encji w warstwie usługi).

Jeśli warstwa usługowa musi mapować do modelu widoku, to warstwa usługowa musi uzyskać dostęp do modelu widoku w warstwie UI. Która biblioteka / projekt? Model widoku powinien znajdować się w oddzielnym projekcie w warstwie interfejsu użytkownika, a do tego projektu należy odwoływać się warstwą usługi. Jeśli ViewModel nie jest w oddzielnym projekcie, to nie ma odniesienia okrągłe, więc nie ma go. Wygląda to niezręcznie mieć warstwę Usług dostęp do warstwy UI, ale nadal możemy sobie z tym poradzić.

Ale co jeśli jest inna aplikacja UI korzystająca z tej usługi? Co zrobić, jeśli istnieje aplikacja mobilna? Jak różny może być ViewModel? Czy dostęp do usługi ten sam projekt modelu widoku? Czy wszystkie projekty interfejsu użytkownika uzyskają dostęp do tego samego projektu ViewModel, czy też mają swój własny?

Po tych rozważaniach moją odpowiedzią byłoby umieszczenie projektu Viewmodel w warstwie usług. Każda warstwa interfejsu użytkownika musi i tak uzyskać dostęp do warstwy usług! I może być wiele podobnych Viewmodeli, z których wszyscy mogliby korzystać (dlatego mapowanie staje się łatwiejsze dla warstwy usług). Mapowania są obecnie wykonywane przez linq, co jest kolejnym plusem.

Wreszcie jest ta dyskusja o DTO. A także o adnotacji danych w modelach widoku. ViewModels with data adnotations (Microsoft.Www.Mvc.DataAnnotations.dll) nie mogą znajdować się w warstwie usługi, zamiast tego znajdują się w warstwie interfejsu użytkownika (ale ComponentModel.DataAnnotations.dll może znajdować się w warstwie usług). Jeśli wszystkie projekty są w jednym rozwiązaniu(.sln), wtedy nie ma znaczenia, którą warstwę położysz. W aplikacjach korporacyjnych każda warstwa będzie miała własne rozwiązanie.

Więc DTO faktycznie jest Viewmodelem, bo przeważnie będzie taki na jedno mapowanie pomiędzy nimi (powiedzmy z Automapperem). Ponownie DTO nadal ma logikę potrzebną dla interfejsu użytkownika (lub wielu aplikacji) i znajduje się w warstwie usług. Oraz Ui layer ViewModel(jeśli korzystamy z Microsoft.Www.Mvc.DataAnnotations.dll) jest po prostu skopiować dane z DTO, z niektórych 'zachowanie' / atrybuty dodane do niego.

[teraz ta dyskusja przybiera ciekawy obrót Czytaj dalej...: I]

I nie myśl, że atrybuty adnotacji danych są tylko dla interfejsu użytkownika. Jeśli ograniczysz walidację za pomocą System.ComponentModel.DataAnnotations.dll następnie ten sam ViewModel może być również używany do walidacji front-end & backend(usuwając w ten sposób UI-Residency-ViewModel-copy-of-DTO). Ponadto atrybuty mogą być również używane w modelach jednostek. Na przykład: używając .tt, Modele danych Entity Framework mogą być autogenerowane z atrybutami walidacji, aby wykonać niektóre walidacje DB, takie jak max-length przed wysłaniem do back endu. Kolejną zaletą jest to, że jeśli Walidacja backend zmienia się w DB then. tt (odczytuje specyfikę DB i tworzy atrybut dla klasy encji) automatycznie to odbierze. Może to wymusić również niepowodzenie testów jednostkowych walidacji interfejsu użytkownika, co jest dużym plusem(więc możemy to poprawić i poinformować wszystkich użytkowników / konsumentów zamiast przypadkowo zapomnieć i zawieść). Tak, dyskusja zmierza w kierunku dobrego projektu RAM. Jak widać wszystko jest powiązane: Walidacja pod względem poziomów, strategia testów jednostkowych, strategia buforowania itp.

Choć nie związane bezpośrednio z pytaniem. "ViewModel" warto też obejrzeć Kanał 9 link . Zaczyna się dokładnie w 11 minut 49 sekund w filmie. Ponieważ byłby to kolejny krok / myśl, gdy twoje obecne pytanie podane powyżej zostanie rozwiązane: "jak zorganizować ViewModels?'

Również w twoim przykładzie " _repository.ListContacts ()" zwraca model widoku z repozytorium. To nie jest dojrzały sposób. Repozytoria powinny dostarczać modele jednostek lub modele baz danych. To zostanie przekonwertowane do modeli widoku i to właśnie ten model widoku jest zwracane przez warstwę serwisową.

 19
Author: Blue Clouds,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-06-25 13:06:45

Przypuszczam, że to zależy od tego, co uważasz za "usługi". Nigdy nie podobał mi się termin usługa w kontekście jednej klasy; jest on niewiarygodnie niejasny i nie mówi wiele o rzeczywistym celu klasy.

Jeśli "warstwa usług" jest warstwą fizyczną, taką jak usługa internetowa, to absolutnie nie; Usługi w kontekście SOA powinny ujawniać operacje domenowe/biznesowe, a nie Dane i logikę prezentacji. Ale jeśli usługa {[2] } jest używana tylko jako abstrakcyjna koncepcja dla dalszego poziomu enkapsulacji, nie widzę problemu z używaniem jej w sposób, w jaki ją opisujesz.

Tylko nie mieszaj pojęć. Jeśli Twoja usługa zajmuje się modelami widoku, powinna to być usługa prezentacji i powinna być nałożona na wierzch modelu , nigdy nie dotykając bezpośrednio bazy danych ani żadnej logiki biznesowej.

 5
Author: Aaronaught,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-06-08 23:49:26

To było trochę "to zależy", gdzie pracuję - Zwykle mieliśmy kontroler zużywający niektóre usługi - a następnie łącząc zwrócone DTO w "ViewModel", który następnie byłby przekazywany do Klienta - albo poprzez wynik JSON, albo związany w szablonie Razor.

Rzecz w tym, że około 80% czasu-mapowanie DTO do ViewModel było 1-1. Zaczynamy poruszać się w kierunku " tam, gdzie jest to potrzebne, po prostu skonsumuj Dto bezpośrednio, ale kiedy DTO i to, czego potrzebujemy w naszym kliencie / widoku nie dopasowuj się - następnie tworzymy model widoku i wykonujemy mapowanie między obiektami w razie potrzeby'.

Chociaż nadal nie jestem przekonany, że jest to najlepsze lub właściwe rozwiązanie-ponieważ kończy się to gorącymi dyskusjami na temat " czy dodajemy tylko X do DTO, aby zaspokoić potrzeby widoku?'

 4
Author: e82,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-07-25 14:42:53