2009-03-13 11 views
9

Metoda "RenderPartial()" w ASP.NET MVC oferuje bardzo niski poziom funkcjonalności. Nie zapewnia ani nie próbuje dostarczyć prawdziwego modelu "kontrolera podrzędnego".ModelFactory w środowisku ASP.NET MVC w celu rozwiązania problemu "RenderPartial"

Mam coraz większą liczbę formantów renderowanych za pomocą "RenderPartial()". Dzielą się one na 3 główne kategorie:

1) mechanizmy kontroli, które są bezpośrednimi potomkowie konkretnej strony, że modela takiej strony

2) parametry, które są bezpośrednimi potomkowie konkretnej strony, że użytkowania ten model strony z additional key of some type. Pomyśl o implementacji "DataRepeater".

3) Elementy sterujące reprezentujące niepowiązaną funkcję na stronie, na której się pojawiają na. Może to być wszystko, od rotatora banerów , do formularza opinii, lokalizator sklepu, rejestracja listy adresowej. Kluczową sprawą jest to, że nie ma znaczenia, która strona zostanie umieszczona.

Ze względu na sposób model ViewData pracuje tam istnieje tylko jeden model obiektu na żądanie - który jest cokolwiek powiedzieć na subcontrols potrzeba musi być obecny w modelu widoku.

Ostatecznie zespół MVC będzie miał nadzieję, że wyjdzie z prawdziwym modelem "kontrolera podrzędnego", ale do tej pory dodaję tylko coś do głównego modelu strony, który potrzebne są także formanty podrzędne.

W przypadku (3) powyżej oznacza to, że mój model "ProductModel" może zawierać pole dla modelu "MailingListSignup". Oczywiście nie jest to idealne, ale zaakceptowałem to przy najlepszym kompromisie z obecnymi ramami - i najprawdopodobniej "zamykać drzwi" do przyszłego modelu subkontrolera.

Kontroler powinien być odpowiedzialny za uzyskanie danych dla modelu, ponieważ model powinien być po prostu głupią strukturą danych, która nie wie, skąd pochodzą jej dane. Ale nie chcę, aby kontroler musiał tworzyć model w kilku różnych miejscach.

Co zacząłem robić to stworzenie fabryki, która stworzy mi model. Ta fabryka jest wywoływana przez kontroler (model nie wie o fabryce).

public static class JoinMailingListModelFactory { 

     public static JoinMailingListModel CreateJoinMailingListModel() { 

      return new JoinMailingListModel() 
      { 
       MailingLists = MailingListCache.GetPartnerMailingLists(); 
      }; 
     } 
    } 

Moje pytanie brzmi: jak inne osoby z tym samym problemem faktycznie tworzą modele. Jakie będzie najlepsze podejście do przyszłej kompatybilności z nowymi funkcjami MVC?


  • UWAGA: Są problemy z RenderAction() że nie będę wchodzić tutaj - zwłaszcza, że ​​jej tylko w MvcContrib i nie będzie w wersji RTM ASP.NET-MVC. Inne problemy spowodowały, że zdecydowałem się go nie używać. Tak więc udawajmy, że istnieje tylko RenderPartial() - lub przynajmniej to, co postanowiłem użyć.

Odpowiedz

2

Jednym ze sposobów, jakie widziałem w tym scenariuszu, jest użycie filtru akcji do zapełnienia danych dla widoku częściowego - tj.podklasa ActionFilterAttribute. W polu OnActionExecuting dodaj dane do danych ViewData. Wtedy po prostu trzeba ozdobić różne działania, które użytku że częściowy widok z filtrem.

+0

tym bardziej myślałem o tym mniej podobało mi się ten pomysł. to im więcej myślałem o tym, tym bardziej im się to podobało. głównie dlatego, że łatwiej jest każdemu dodać kontrolę do strony - wystarczy dodać atrybut i RenderPartial i gotowe. –

+0

To brzmi jak dużo myślenia; -p –

+0

skończyło się używaniem tego podejścia w kilku miejscach w mojej aplikacji. sprawia, że ​​znacznie czystsze jest stosowanie pewnych rzeczy do modeli na całym świecie. Używam go zarówno do "modelu podstawowego", który odpowiada stronie wzorcowej, jak i "modeli obszarowych" dla różnych obszarów w witrynie. dość elastyczny i chociaż nie jestem całkowicie zakochany w wstrzykiwaniu rzeczy do moich modeli to działa całkiem dobrze –

1

Jest renderPartial przeciążenie Używam który pozwala ci określić nową ViewData i modelu:

RenderPartial code

Jeśli spojrzeć na tego linka kodu źródłowego MVC, a także następujące (poszukaj metoda RenderPartialInternal):

RenderPartialInternal code

widać, że jeśli w zasadzie kopiuje ViewData zdać tworzenia nowego słownika i ustawia model do wykorzystania w kontrola. Tak więc strona może mieć model, ale następnie przekazać inny model do pod-kontroli.

Jeśli sub-kontrole nie są określane bezpośrednio z głównego widoku modelu, można rade Marc Gravell wspomina dodać niestandardową logikę.

5

Zamiast dodawania rzeczy jak MailingListSignup jako własność swoimi ProductModel, hermetyzacji zarówno na tym samym poziomie w klasie jak ProductViewModel, który wygląda tak:

public class ProductViewModel() { 
    public ProductModel productModel; 
    public MailingListSignup signup; 
} 

następnie dostać Państwa zdanie jest silnie wpisany do ProductViewModel klasa. Możesz uzyskać dostęp do ProductModel wywołując Model.productModel, można uzyskać dostęp do klasy rejestracyjny korzystając Model.signup.

Jest to luźna interpretacja "Modelu prezentacji" Fowlera (http://martinfowler.com/eaaDev/PresentationModel.html), ale widziałem, że jest używana przez niektórych twórców Microsoft, takich jak Rob Conery i Stephen Walther.

+1

Często odwołuję się do asp.net MVC jako MVVC :) –

+0

To jest ogólnie podejście, które biorę, ale wciąż pachnie jakby dla mnie śmieszne.Nie podoba mi się to, że zewnętrznemu widokowi dostarczono dane, których nie potrzebuje. Użyłem Html.RenderAction (), który wydaje się być lepszy niż Html.RenderPartial() jako proxy dla prawdziwych podkontrolerów, ale wciąż jest nieco słaby. –

+0

@ James, robię to na swój sposób, gdzie productModel i SignUpModel są rzeczywistymi modelami danych. Ale tracę zalety adnotacji walidacyjnych. Używam Fluent Validation do sprawdzania poprawności rzeczy na poziomie domeny, wydaje się w porządku. – Tom

0

Jednym ze sposobów próbowałem było użyć silnie typami częściowy widok z interfejsem. W większości przypadków lepszy jest agregowany ViewModel, ale nadal chcę to udostępnić.

<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<IMailingListSignup>" %> 

ViewModel implementuje interfejs

public class ProductViewModel:IMailingListSignup 

ów nie idealny w ogóle, ale rozwiązuje kilka problemów: Nadal można łatwo mapować właściwości od swojej drodze do modelu. Nie jestem shure, jeśli w przeciwnym razie możesz mieć mapę parametrów trasy do właściwości MailingListSignup.

Nadal masz problem z napełnieniem model. Jeśli nie spóźnię się, wolę zrobić to w OnActionExecuted. Nie widzę sposobu, w jaki można wypełnić model w OnActionExecuting.

Powiązane problemy