ViewModele w ASP.NET MVC
Nawiązując do poprzedniego wpisu i po części do tematu, w którym brałem udział na jednym z forów opiszę dzisiaj krótko czym są właściwie ViewModele i jak się tego używa.
ViewModel mimo trochę dziwnej nazwy nie jest niczym dziwnym ani trudnym ponieważ jest to… zwykła klasa. Więc dlaczego taka nazwa? Ponieważ klasa taka służy do „opakowywania” modeli (czyli obiektów reprezentujących dane w logice biznesowej, a więc najczęściej obiektów reprezentujących rekordy w bazie danych) w celu przesłania ich do widoku i wyświetlenia użytkownikowi. W tym momencie niektórzy zaznajomieni już trochę z technologią ASP.NET zaprotestują i powiedzą, że przecież bez problemu można przesłać do widoku także same modele, w końcu one też są zwykłymi klasami. To prawda, jednak tylko w sytuacji gdy chcemy w widoku użyć jednego modelu. A co w sytuacji gdy potrzebujemy na jednej stronie wyświetlić informację o aktualnym użytkowniku i jakąś np. listę wszystkich miejsc dostępnych w systemie? W takiej sytuacji część programistów do przesłania obiektu użytkownika posłuży się obiektem ViewBag. Ale poprzednio opisałem czemu użycie go nie jest dobrym rozwiązaniem. Dużo lepiej jest stworzyć nową klasę, która dla powyższego przykładu może wyglądać tak:
public class ViewModel { public User User {get; set; } public IEnumerable<Place> Places { get; set; } }
W kontrolerze tworzymy obiekt takiej klasy i uzupełniamy go danymi, a następnie w pliku widoku korzystamy z niej jak ze zwykłego modelu:
@model ViewModel ... @Model.User.Name @foreach(var place in Model.Places) { ... }
W tym prostym przykładzie gdzie użyte obiekty są bezpośrednio wzięte z np. bazy danych główną przewagą ViewModelu nad ViewBagiem jest wsparcie ze strony IDE jeśli chodzi o sprawdzanie poprawności kodu i podpowiadanie składni.
Ale są sytuacje kiedy ViewModel jest właściwie jedynym sensownym i możliwym rozwiązaniem. Mianowicie chodzi o wyświetlanie wszelkiego rodzaju raportów i z agregowanych danych. Wyobraź sobie, że musisz wyświetlić użytkownikowi wyniki finansowe z całego roku dodatkowo pokazując sumy za każdy miesiąc. W bazie takich danych zazwyczaj nie trzymasz bezpośrednio tylko są one wyliczane przy zapytaniu więc przesłanie bezpośrednio modelu odpada. Jeśli chcesz być tą osobą, której nie lubi reszta programistów, frontendowcy i przyszli pracownicy to możesz spróbować przesłać wszystko przy użyciu ViewBag. Da się. Tylko ilość kodu i błędów jaką możesz popełnić jest spora. Poza tym w ViewModelu możesz zawrzeć dodatkowe funkcje, które np. będą coś liczyć lub uzupełniać co też będzie dużą korzyścią jeśli te same dane musisz przesłać w kilku miejscach.
Mam nadzieję, że tymi kilkoma słowami chodzić trochę zachęciłem Cię do spróbowania zamienienia luźno przesyłanych w różnych ViewBagach i innych tymczasowych kontenerach albo co gorsza zmiennych globalnych danych na rzecz klas łączących je w logiczną i biznesową całość. Nie bój się dużej liczby dodatkowych plików i klas, bój się raczej bałaganu jaki zostawisz rozrzucając obiekty.
Czesc Marku, a powiedz mi czy ViewModel skladajacy sie z 2+ modeli potrzebuje nowy DbContext dla swojego ViewModel kontrolera?