Come gestire viste complesse (costituite da più parti) nell'applicazione web MVC

8

Diciamo che sto scrivendo un'applicazione web del blog usando il pattern MVC. Il layout tipico per la pagina principale dell'applicazione blog è - una sorta di indice di post nella parte principale, e a parte alcune parti aggiuntive, come la timeline, il pannello di navigazione dei tag, il pannello di sottoscrizione, ecc. Questi controlli appaiono anche su un singolo post vista, e potrebbe apparire su altre viste che ho.

La mia domanda è: come devo gestire questi pannelli da parte mia nei miei punti di vista e controller. Vedo tre approcci qui:

  1. Crea una grande classe viewmodel che contenga tutte le informazioni richiesto per il rendering della vista (indice o singolo post). In quel caso potrei rendere questi pannelli a parte un punto di vista parziale, e chiamandoli dalla vista che si sta facendo passare una parte di quella grande ViewModel. Lo svantaggio è - avrò il codice di riempimento viewmodel diffuso tra i vari metodi di controllo, il che significa che il codice è duplicato. Il che è abbastanza brutto.

  2. Crea un altro livello di rendering della vista. Dì, lo strato più in alto di il rendering restituisce parti alfine di rendering html o funzioni che quando chiamato emette un html. Lo strato sotto questa "combinazione" strato parziale "darebbe solo viste parziali per ogni pannello che voglio, includere il contenuto principale. Lo svantaggio qui - l'uso della memoria. La maggior parte dei framework moderni esegue il rendering di html direttamente sul flusso di output, ma in questo approccio le viste parziali verranno rese prima in oggetti stringa, il che comporta un sovraccarico della memoria.

  3. Usa qualcosa come "RenderAction" da asp.net mvc, che chiama a metodo del controller da una vista. Penso che questa sia la peggiore soluzione di 3 dato, perché elimina un approccio MVC.

La domanda non è legata a nessun quadro specifico, voglio capire il modo generale di fare cose del genere.

Aggiorna

Dopo aver dato una risposta, ho scoperto che il post non è chiaro. Quindi aggiornamento ragionevole qui:

Alla voce viewmodel capisco un oggetto che contiene tutti i dati necessari per eseguire il rendering di una vista particolare.

Tutti e tre gli approcci implicano la costruzione di viste parziali con il proprio modello di visualizzazione. Ad esempio (usando la sintassi C #):

class SinglePostViewModel {
  string Text {get;set;}
  string Title {get;set;}
  string Slug {get;set;}
  DateTime PublishedDate {get;set;}
  ...
}

class TagNavigationPanelViewModel {
  string TagText {get;set;}
  int PostsCount {get;set;}
}

class CalendarNavigationPanelViewModel {
  DateTime YearAndMonth {get;set;}
  int PostsCount {get;set;} 
}

La mia domanda è: come combinare bene quelle viste parziali.

    
posta Hedin 07.08.2013 - 21:10
fonte

3 risposte

1

Vedo un altro metodo che, a meno che non abbia frainteso il tuo post, non sia stato menzionato:

La vista principale, post , avrebbe il suo modello. Questo modello consisterebbe in SOLO le proprietà necessarie per visualizzare questo post ( author , title , body , ecc.). Quindi, ogni pezzo della visualizzazione post a cui è possibile pensare ( timeline , tag navigation panel , subscribing panel , ecc.), Verrà suddiviso nelle proprie viste e ognuno avrà il proprio modello. In questo modo, puoi costruire quei modelli nel tuo controller quando ne hai bisogno.

Potrebbe sembrare una quantità inutile di lavoro extra per dividerli in questo modo, ma si presta al principio di responsabilità singola . Mantieni ogni "vista / modello" focalizzata su se stesso in modo che possa essere riutilizzato ovunque sia necessario.

Se ritieni che il tuo codice stia iniziando a duplicarsi, a seconda della tua situazione, dovresti prendere in considerazione di scrivere una sorta di "classe di supporto". Questa classe helper gestirà tutto il build-up del modello in un unico posto e tutti gli altri codici duplicati verrebbero ridotti a una chiamata di classe helper.

    
risposta data 08.08.2013 - 06:49
fonte
1

Quello che sto facendo è una variazione / combinazione dei tuoi punti 1 e 3. Combino i viewmodels in una classe contenitore, e li uso come un "viewmodel" principale. Passa le parti come modelli ai parziali.

Seguendo il tuo esempio, vorrei creare questo modello di visualizzazione per la pagina predefinita:

class DefaultViewModel {
  public List<SinglePostViewModel> Posts ...
  public TagNavigationPanelViewModel Tags ...
  public CalendarNavigationPanelViewModel Calendar ...
  ...
}

In Default.cshtml

@model DefaultViewModel
...html for rendering the default page...


@Html.Partial("_TagNavigationPanel", Model.Tags)
...etc...

In _TagNavigationPanel.cshtml

@model TagNavigationPanelViewModel
...html+razor for rendering the tags...

Quindi, segui lo stesso approccio per una singola pagina post:

class SinglePostPageViewModel {
  public SinglePostViewModel Post ...
  // no tags in single view, for example..
  // public TagNavigationPanelViewModel Tags ...
  public CalendarNavigationPanelViewModel Calendar ...
  // But a list of related, perhaps?
  public List<RelatedPosts> RelatedPosts
  ...
}

E costruisci le tue viste (cshtml (s)) di conseguenza

    
risposta data 08.08.2013 - 10:06
fonte
0

Puoi creare una singola vista "container" con tutte e tre le subviews - SinglePostView , TagNavigationPanelView e CalendarNavigationPanelView . Puoi anche sostituire SinglePostView con qualsiasi altra vista richiesta da una pagina. In questo modo è sufficiente sostituire la vista "centrale" (post) per pagine diverse con un altro tipo di vista (ad esempio l'elenco di post) e le altre viste devono solo essere aggiornate con i dati corrispondenti, non sostituiti.

La vista del contenitore (ad esempio MyView ) dovrebbe contenere riferimenti a tutte le visualizzazioni secondarie. Può avere diversi metodi di update utilizzati per aggiornare sottoview diverse. Ad esempio: updateCalendar(CalendarNavigationPanelViewModel calendarData) o updatePost(SinglePostViewModel postData) . O anche un singolo update(IViewModel modelData) - allora dovrai controllare il tipo di (e lanciare) il modelData per determinare quale vista aggiornare

    
risposta data 08.08.2013 - 11:32
fonte

Leggi altre domande sui tag