ASP.NET MVC - Co vše může obsahovat ViewModel   otázka

C#, ASP.NET MVC

Ahoj, měl bych dotaz ohledně toho, co vše je vhodné řešit ve ViewModelu. Například je vhodné řešit ve ViewModelu načítání a ukládání z databáze, jako v ukázce níže?

public class PersonViewModel
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public string Surname { get; set; }

        public PersonViewModel()
        {

        }

        public IEnumerable<PersonViewModel> GetAllPersons()
        {
            using (var db = new PersonContext())
            {
                return db.Persons.Select(s => new PersonViewModel()
                {
                    Id = s.Id,
                    Name = s.Name,
                    Surname = s.Surname
                }).ToList();
            }
        }

        public void CreateNewPerson(PersonViewModel dto)
        {
            using (var db = new PersonContext())
            {
                db.Persons.Add(new Person()
                {                    
                    Name = dto.Name,
                    Surname = dto.Surname
                });
                db.SaveChanges();
            }
        }      
    }
nahlásit spamnahlásit spam 0 odpovědětodpovědět

Zdravím,

v žádném případě :-) ViewModel je jen "výcuc" z modelu, který souvisí s konkrétním view, je to tedy ve většině případů pouze přepravka a validace spojené s ní.

Práce s DB patří do nějaké části modelu. U Rich domain modelu je to většinou jedna třída (s čímž nesouhlasim), u aenemic domain modelu (který je občas považován při špatném pochopení za antipattenr), je to v repository

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Vidím tu řadu názorů co "se nesmí" a co "se musí". S většinou z nich nesouhlasím.

Často vidím dogmatický přístup k ASP.NET MVC jako k čisté MVC architektuře. V reálném použití ale tak ASP.NET MVC nemůže efektivně fungovat.

Příkladem může být právě uvedený kód. Osobně s ním mám problém pouze v tom, že bych raději viděl, aby si životní cyklus datového kontextu řídil controller. Ale ani uvedené použití nemusí být nutně špatně.

Výhodou kódu ve ViewModelu (nebo stranou v jiné třídě; to už je jedno) je především znovupoužitelnost. V ASP.NET MVC používáte modely, které jsou modely specifickými pro UI. Musíte následně zajistit nějakým způsobem jejich binding na BL/DL vrstvu. Pokud to budete dělat v controlleru, ztratíte znovupoužitelnost. Pokud to budete dělat v modelu, je to podle ostatních špatně. V BL/DL to dělat taky nemůžete, protože ty nemají mít znalost view modelů z prezentační vrstvy. Ve výsledku na to uděláte službu na úrovni prezentační vrstvy. V tuto chvíli je ale úplně jedno zda to bude v samostatné službě nebo součástí modelu.

Takže ve výsledku nevidím s uvedeným kódem nějaký zásadní problém.

Rád si poslechnu důvody, proč je podle ostatních špatné použití kódu ve ViewModelu.

nahlásit spamnahlásit spam 0 odpovědětodpovědět

To, že by si měl životnost datového kontextu řídit controller je pravda, to mě vůbec nenapadlo. Když si tedy vytvořím třídu DataService, která bude mít v kontejneru nastavený lifestyle na PerWebRequest a bude obsahovat metody GetAllPersons() a CreateNewPerson(), které při vytváření pouze předám PersonViewModel, je to lepší přístup?

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Mno na tenhle "problém" narážím od doby co dělám aplikace v ASP.NET MVC.

S tím příkladem mám vlastně jen dva problémy:

1, funkce CreateNewPerson a GetAllPersons() používá stejný view model. V praxi se mi málo kdy stane, že by šel view model znovupoužít (nebavím se o komponentách)

2, Většinou metody CreateNewPerson nejsou takhle jednoduché, ale vyžadují další závislosti, kterýma dřív nebo později začneme view model zanášet. A jelikož často view modely serializujeme do JSONu, při složitějších konstrukcích nakonec skončíme s circular dependency.

Opravdu se mi vyplatilo jako view modely používat jako anemický model (obyčejné POCO) a zbytek aplikace řešit na úrovni níž. Třeba se nechat inspirovat Jimmy Bogardem: https://lostechies.com/jimmybogard/2015/... nebo Tomášem Hercegem https://www.wug.cz/praha/akce/744-Zajima....

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Ad 1) Někdy ano, někdy ne. Opět to záleží na situaci.

Ad 2) Trochu nechápu smysl tohoto argumentu. Původní dotaz je jen, zda mít ViewModely jako POCO nebo do nich zahrnout metody pro načítání a ukládání (resp komunikaci a mapování s BL/DL). Je pochopitelné, že takové ViewModely mají vlastnosti a strukturu na míru určenou šablonám a pokud obsahují zbytečná data, tak je jejich návrh špatný (z důvodů jaký uvádíte).

Existuje mnoho scénářů, kdy se vyplatí má view model jako POCO. Jen si nemyslím, že je správné to vyzdvihovat jako jedinou správnou možnost.

nahlásit spamnahlásit spam 0 odpovědětodpovědět

OK, puvodni odpoved jsem psal na mobilu a tam se mi nechtelo rozepisovat, tak budu tedy presnejsi a korektnejsi:

S tím, co zmiňujete ale já souhlasím, vy chcete mít ve ViewModelu data, která se týkají Viewcka a k tomu chcete mít logiku, která slouží k převodu mezi nějakým DTO a ViewModel, což je skutečně někde na Controller vrstvě..

Buďto v nějaké službě nebo ve ViewModelu.. ale jsou to prostě jen mapovací metodky, které dělají jen to jedno :

Mapují DTO->ViewModel a ViewModel->DTO. Nemají na starost žádnou složitou logiku aplikace, nedělají žádnou práci, co by jste měl v servise, nebo v repozitáři a už vůbec nemají context...

Tedy namísto automappera, nebo ručného mapování v controlleru / v nějaké službě na úrovni controlleru, to máte přímo ve ViewModelu.

A je jedno jestli je to jako ToMetody, CreateMetody, copy constructor, nebo třeba (explicit) operator. POřád jsou to metody jen pro mapování, žádná jiná logika.

Tedy k úplně první otázce:

GetAllPersons() by jste stejně měl někde v servise a vracela by IEnumerable<Person> a ViewModel by mel v sobe prevod Person->PersonViewModel..

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Chápu co se snažíte popsat, ale pořád nemyslím, že je to jediná správná cesta. Způsob, který popisujete se určitě na mnoho scénářů hodí a také ho používám. Ale píše programátor aplikaci, kde využívá jako BL/DL EntityFramework, pak nevidím důvod, proč bych nemohl uložení napsat rovnou do metod ViewModelu. Pokud by se začal kód duplikovat, tak by jej vyvedl do služeb. Další je rozhodnutí, zda bude mapování a provolávání řešit controller/přímo ViewModel/nějaká další infrastruktura. Je mnoho přístupů a zvlášť u ASP.NET MVC není jeden správný. Nebo mě o tom zatím nikdo nepřesvědčil :-)

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Já souhlasím, každé SOC je vždy za cenu práce navíc, takže je to vždy čas navíc, který v budoucnu zjednoduší rozsiritelnost/ zamezi nutnému refaktoringu.. Takže pokud píší web, který mi sežere 30-40 hodin a vím že ho nebudu v budoucnu tolik upravovat, tak třeba také nepouziji n-tier architekturu a mám prostě jeden projekt mvc v celém solutionu, včetně dal(ef) a coru (servisy). Takže v tomto případě mám prostě logiku jako statickou metodu v query objectu. Takže vždy záleží na situaci. U velké aplikace bych si ale určitě logiku do view modelu nenarval.. Takže se zřejmě shodujeme

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Přesně tak, žádné výpočty, žádná logika. View model nese pouze data a slouží pro transport dat mezi controllerem a view, nic víc v tom nehledejte. Osobně jsem se už naučil praktiku, kdy view modely neobsahují žádné metody, pouze properties a bez veškeré logiky. Případné výpočty z již získaných dat z modelu, přenechte controlleru. :)

R.

nahlásit spamnahlásit spam 1 / 1 odpovědětodpovědět

A co se týče používání EF ve webovém projektu:

Za to bych dotyčného pověsil za určité části mužského těla do průvanu. Nemá tam co dělat a nejlépe ho ani nereferencovat. To, že to tak prezentuje Mrkvosoft je druhá věc. :-)

R.

nahlásit spamnahlásit spam 1 / 1 odpovědětodpovědět

Dobrý den,

a co jiného používat?

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Zdravím, omlouvám se, asi to vyznělo trochu jako nepoužívat EF vůbec, to jsem tím říct nechtěl :-). Tím projektem jsem myslel assembly v rámci solution, tedy MVC Application.

R.

nahlásit spamnahlásit spam 0 odpovědětodpovědět
                       
Nadpis:
Antispam: Komu se občas házejí perly?
Příspěvek bude publikován pod identitou   anonym.
  • Administrátoři si vyhrazují právo komentáře upravovat či mazat bez udání důvodu.
    Mazány budou zejména komentáře obsahující vulgarity nebo porušující pravidla publikování.
  • Pokud nejste zaregistrováni, Vaše IP adresa bude zveřejněna. Pokud s tímto nesouhlasíte, příspěvek neodesílejte.

přihlásit pomocí externího účtu

přihlásit pomocí jména a hesla

Uživatel:
Heslo:

zapomenuté heslo

 

založit nový uživatelský účet

zaregistrujte se

 
zavřít

Nahlásit spam

Opravdu chcete tento příspěvek nahlásit pro porušování pravidel fóra?

Nahlásit Zrušit

Chyba

zavřít

feedback