14

Attualmente nella mia applicazione e utilizzando l'unità di modello di lavoro e repository generico, tutti i miei controller contengono tutta la logica aziendale. Sono in procinto di mettere tutto per usare ViewModels al posto del modello dritto.MVC 3 - Controller e ViewModels - Quale dovrebbe contenere la maggior parte della logica aziendale?

Mentre questa è una buona idea, ora arriva una domanda che può significativamente separare la mia logica di business nei controller. Per controller e ViewModels, che dovrebbero contenere la maggior parte della logica aziendale?

Ho provato alcuni modi per ottenere il mio ViewModels per contenere praticamente tutta la logica aziendale. Tuttavia, devo avere un argomento nel costruttore del mio ViewModel che prende un'unità di lavoro. E 'questa una buona idea?

Il mio codice odore mi dice che lo è. Tuttavia, sono solo un po 'preoccupato di come questo sarà coerente con i controller che eseguono azioni che non richiedono ViewModels. In poche parole, azioni che non richiedono il passaggio di un modello/ViewModel a una vista; questo caso si verifica in azioni che reindirizzano ad altre azioni. Il che significa che la mia logica aziendale può rimanere in quell'azione o separare quella logica aziendale in una funzione.

Qual è la migliore pratica qui?

risposta

7

Per i controller e ViewModels, che dovrebbe contenere la maggior parte della logica di business?

Nessuno di quelli.

Ho provato alcuni modi per ottenere il mio ViewModels praticamente contenere tutta la logica di business. Tuttavia, devo avere un argomento nel costruttore del mio ViewModel che prende un'unità di lavoro. E 'questa una buona idea?

imho È una pessima idea. Prima di tutto rompi molti dei principi SOLIDI. Raggruppare tutto il codice nel modello di visualizzazione rende difficile il test. Cosa succede se si desidera utilizzare alcune delle business logic in un'altra vista? Duplicate quel codice?

Qual è la migliore pratica qui?

Torniamo prima al pattern MVC. È una definizione abbastanza ampia, ma sapendo dovrebbe darti un'idea di cosa dovresti piazzare dove.

  • Il "Modello" in MVC è davvero tutto ciò che viene utilizzato per tirare insieme i dati. Può essere un servizio web, un livello aziendale, repository, ecc.

  • La vista è tutto il codice che genera l'HTML (poiché stiamo parlando di web).

  • Il controller deve essere considerato come una colla tra il modello e la vista. Quindi dovrebbe prendere le informazioni dal modello e trasformarlo in qualcosa di utile dalla vista.

Il problema con questa struttura è che è abbastanza facile "perdere" informazioni specifiche del livello nelle altre parti del modello. Quindi Microsoft ha introdotto ViewModels nella loro implementazione di MVC.

In questo modo è possibile rimuovere tutta la logica di rendering dalle viste e inserirla nel ViewModel. Invece di fare questo nella vista:

<span>@(model.Age == 0 ? "n/a" : model.Age)</span> 

si inserisce il codice all'interno del ViewModel, invece, e sufficiente chiamare @model.Age. In questo modo non è necessario duplicare il codice in tutte le viste che utilizzano il modello di visualizzazione.

La risposta alla tua domanda su ViewModel è che dovrebbe contenere solo la logica che viene utilizzata per rendere correttamente le informazioni dal "Modello".

Per quanto riguarda il controller, non inserirò alcuna logica di business. Prima di tutto, rende molto difficile testare la tua logica. Quindi aggiungete più responsabilità ad esso (e facendo così rompere SRP). L'unica logica valida nel controller è prendere le informazioni dal ViewModel e trasformarle in qualcosa utilizzabile dal "Modello" e viceversa.

Spero che risponda alla tua domanda.

Aggiornamento

vorrei creare un progetto separato e aggiungere classi ad esso. Quindi aggiungi un riferimento dal tuo webproject e chiama quelle classi nei controller.

Vorrei anche iniziare a utilizzare l'inversione del contenitore di controllo per ottenere automaticamente quelle dipendenze create per me.

Autofac può sia scoprire i servizi per voi (zero-configurazione) e iniettare se stesso in MVC.

di seguire il modello di interfaccia separato creare i seguenti progetti:

  • YourProject.BusinessLayer < - Aggiungi le tue lezioni qui
  • YourProject.BusinessLayer.Specification < - Aggiungi si interfacce che definisce il vostro livello di business Qui.
  • YourProject.Mvc < - Il progetto MVC.

Il progetto "Specifica" può essere utilizzato per semplificare il test delle cose e facilitare l'implementazione (potrebbero essere solo alcune classi e non necessariamente l'intero livello aziendale). Leggi su "Modello di interfaccia separato"

+1

Buona risposta. Vorrei chiedere dove andrebbe la mia logica aziendale? – TIHan

+0

Leggi il mio aggiornamento. – jgauffin

+0

Grazie. Inizierò a esaminare questo. – TIHan

10

Non posso dire che il mio approccio sia una best practice, ma preferisco inserire qualsiasi logica di business in un livello separato "di servizio".

Tendo ad usare ViewModel per memorizzare solo le proprietà richieste per una vista specifica. Se sono presenti metodi su ViewModel, è probabile che vengano recuperati solo gli insiemi relativi a tale vista.

Mantengo i controller leggeri, cercando di limitare il più possibile alla convalida e al reindirizzamento/visualizzazione delle visualizzazioni.

Quindi, se ho una logica complessa, farò in modo che un comando del controller effettui una chiamata a un servizio separato solo per gestire quella logica. In questo modo la logica è isolata, il che rende più facile testare poiché non è più necessario creare un controller o ViewModel per testarlo. È anche più facile riutilizzare un servizio piuttosto che selezionare un ViewModel.

Speriamo che questo aiuti. In bocca al lupo.

+0

+1 - Questo sembra un approccio ragionevole; ma la mia domanda non ha ancora avuto risposta. Sono consapevole di cosa sia un ViewModel, sto cercando di capire se ViewModel dovrebbe contenere la maggior quantità possibile di logica di business. – TIHan

+2

@TIHan, ha detto che ViewModel contiene solo i dati. Il servizio fa il processo. Il controllore controlla il traffico. –

+0

Il ViewModel dovrebbe essere semplicemente un [poco] (http://en.wikipedia.org/wiki/Plain_Old_CLR_Object) che contiene tutti i dati finali per la vista. Come si ottengono i dati, elaborati, formattati, ecc. Fino a un livello di servizio. –

3

Model-View-View Model (MVVM) è un modello di progettazione per la creazione di interfacce utente. Your View Model è una rappresentazione in puro codice dei dati e delle operazioni su un'interfaccia utente. Quindi dovrebbe contenere la logica relativa a quell'interfaccia utente.

Ad esempio:

se si sta implementando un editor di lista, il tuo modello di vista sarebbe un oggetto che contiene un elenco di voci, e di esporre metodi per aggiungere e rimuovere elementi.

Da Wikipedia:

ViewModel: il ViewModel è un “modello della vista” significa che è un astrazione della vista che serve anche in associazione di dati tra il View e il modello. Potrebbe essere visto come un aspetto specializzato di ciò che sarebbe un controller (nel modello MVC) che funge da raccoglitore/convertitore di dati che modifica le informazioni del modello in Visualizza informazioni e passa i comandi dalla vista al modello. ViewModel espone proprietà pubbliche, comandi e astrazioni.ViewModel è stato paragonato a uno stato concettuale dei dati rispetto allo stato reale dei dati nel modello. [7]

+0

Questo è tutto a posto, ma mi chiedo come funzioni con un repository generico e con il modello dell'unità di lavoro. – TIHan

1

il controller chiama il UoW per ottenere i dati necessari per costruire il tuo viewmodel. puoi chiamare più di 1 metodo del tuo UoW

quindi passare tutti i dati necessari al tuo costruttore viewmodel. (passare l'Uow a de viewmodel sembra davvero pessimo)

Se hai bisogno di qualche "logica" complessa sul tuo controller che richiama molti metodi da UoW, ecc, dovresti prendere in considerazione la creazione di un altro repository o di un livello di logica aziendale che fa tutto il duro lavoro e lo chiami dal tuo controller come

SomeClass something = Uow.BLGoodName.DoSomeFancyStuff(params ..) 
ViewData.model = new ControllerActionViewModel(something); 
Return View(); 
Problemi correlati