2011-06-22 23 views
7

od wewnątrz na zewnątrz, są to nasi MVC warstwy aplikacji:ASP.NET MVC: Gdzie można utworzyć model widoku dla widoku?

  1. MS SQL/Stoły/views/Przechowywane Procs
  2. Entity Framework 4.1 (ORM) z POCO generacji
  3. Repository
  4. Service (odzyskać) oraz Funkcje sterujące (SAVE)
  5. Routing -> Sterownik -> Razor Zobacz
  6. (klient) JQuery Ajax z Knockout.js (MVVM)

Wszystko jest w porządku, dopóki nie trzeba tworzyć pojedynczą ViewModel do kroku 5, aby nakarmić zarówno widok Razor jak również JSON/Knockout ViewModel:

  • nagłówek, który zawiera wszystkie Rozwijanej opcje listy i wybory do pola poniżej
  • Items - tablica cokolwiek wysłać do klienta, który staje ViewModel

Ponieważ kontroler nie będzie mieć dostęp do repozytorium bezpośrednio to znaczy utworzyć usługę dla każdego za nd każdy widok, który umożliwia edycję treści? Będę musiał pobrać POCO z repozytorium oraz wszystkie opcje dla każdego typu pola w razie potrzeby.

Po prostu wydaje się zbędne tworzenie oddzielnych usług dla każdego widoku. Na przykład viewModel do edycji adresu i oddzielnego viewModel do edycji nieruchomości, która również ma adres. Możemy mieć tuzin formularzy, które edytują ten sam adres POCO.

Aby ułatwić udzielenie odpowiedzi na to pytanie, czy kontroler ma bezpośredni dostęp do repozytoriów z powodu nieszczelnej abstrakcji?

+0

Czy lubisz nokauty? zawsze chciałem znaleźć powód, aby go użyć i nigdy nie miałem. –

+0

@nathan Powinieneś sprawdzić ten film http://channel9.msdn.com/events/mix/mix11/frm08. Pomoże znaleźć powody, by z niego skorzystać. Zmniejsza to kod do około połowy. –

Odpowiedz

1

Cóż, czy twoje kontrolery będą miały kod, który tłumaczy POCO z Entity Framework na osobne obiekty modelu widoku?

Jeśli tak, powinieneś przenieść ten kod do oddzielnej klasy i postępować zgodnie z zasadą jednej odpowiedzialności. To, czy ta klasa jest w "warstwie usług", czy nie, należy do Ciebie. Niezależnie od tego, czy korzystasz z AutoMapper, czy nie, wszystko zależy od Ciebie. Ale ten rodzaj data mappers nie powinien być częścią logiki sterownika; kontrolerzy powinni być tak głupi, jak to tylko możliwe.


OK, teraz zignorujmy problem mapowania danych i udawaj, że zawsze możesz używać swoich POCO bezpośrednio jako modeli widoku.Wtedy byś nadal chcą warstwę usług, ponieważ byłoby to tłumaczyć między

userService.GetByUserName("bob") 

w niemym kontrolera i realizacji, które w specyficzny sposób, wracając

userRepository.Users.Single(u => u.UserName == "bob") 


Umieszczenie ich razem, Twój UserController kończy się przyjmowaniem zależności IUserService i IUserDataMapper, a kod jest super-głupi, zgodnie z życzeniem:

public ActionResult ShowUserPage(string userName) 
{ 
    var user = userService.GetByUserName(userName); 
    var viewModel = userDataMapper.MakeViewModel(user); 

    return View(viewModel); 
} 

Możesz teraz przetestować kontroler za pomocą kodów pośredniczących dla obu zależności lub wyodrębnić IUserDataMapper podczas kpiny IUserService lub na odwrót. Twój kontroler ma bardzo małą logikę i has only one axis of change. To samo można powiedzieć dla klasy danych użytkownika i klasy usługi użytkownika.


Dziś rano czytałem artykuł, który może ci się przydać w tych sprawach architektonicznych. Jest, nieco protekcjonalnie, zatytułowany "Software Development Fundamentals, Part 2: Layered Architecture." Prawdopodobnie nie będzie możliwe przejście z modelu aplikacji bazy danych do modelu trwałego ignorancji, który opisuje i sugeruje artykuł. Ale może wskazać ci właściwy kierunek.

+0

To jest ta część, której mi brakowało, aby oddzielić Usługę, która pobiera Elementy od mechanika, który tworzy viewModel z kolekcji encji. Zakładam, że 'userDataMapper.MakeViewModel' będzie w stanie zapytać bazę danych o możliwe opcje rozwijanej listy, na przykład, aby umieścić ją w nagłówku viewModel? –

+0

Cóż, to zależy - czy chcesz móc przetestować program odwzorowujący dane bez żywej bazy danych? Jeśli tak, to program odwzorowujący dane powinien zostać prawdopodobnie wyposażony w coś w rodzaju 'IOptionsConfiguration' lub' IOptionsRepository'. Następnie powiązany kod w programie odwzorowującym dane staje się po prostu 'options.GetUserTypes()' lub czymkolwiek, a twoje testy mogą w razie potrzeby wywołać ten interfejs. – Domenic

0

Osobiście zawsze wprowadzam repozytorium/repozytoria do kontrolera. nie jestem pewien, dlaczego chcesz mieć warstwę usługi między repozytorium i kontrolerem. jeśli cokolwiek, użyłbyś specyfikacji.

kiedy już to zrobisz, sprawdź automapper. jest maperem, który po odpowiednim skonfigurowaniu może zmapować twój model domeny do twojego viewmodelu iz powrotem.

+0

Ostrożnie, twoja wzmianka o specyfikacjach sprawia, że ​​myślę, że mówisz o repozytoriach _Domain Driven Design_, podczas gdy pytanie OP wydaje się wskazywać, że działa głównie z anemiczną warstwą DTO i koncepcją repozytorium. – Domenic

Powiązane problemy