Passaggio di dati alla pagina master in ASP.NET MVC


102

Qual è il tuo modo di passare i dati alla pagina master (utilizzando ASP.NET MVC) senza infrangere le regole MVC?

Personalmente, preferisco codificare un controller astratto (controller di base) o una classe base che viene passata a tutte le viste.


1
Ho scritto una guida su come ho gestito questo: britishdeveloper.co.uk/2010/06/… dovrebbe aiutare
BritishDeveloper

Risposte:


77

Se preferisci che le tue visualizzazioni abbiano classi di dati di visualizzazione fortemente tipizzate, questo potrebbe funzionare per te. Altre soluzioni sono probabilmente più corrette ma questo è un buon equilibrio tra design e praticità IMHO.

La pagina master accetta una classe di dati di visualizzazione fortemente tipizzata contenente solo informazioni ad essa rilevanti:

public class MasterViewData
{
    public ICollection<string> Navigation { get; set; }
}

Ogni visualizzazione che utilizza quella pagina master accetta una classe di dati di visualizzazione fortemente tipizzata contenente le sue informazioni e derivante dai dati di visualizzazione delle pagine master:

public class IndexViewData : MasterViewData
{
    public string Name { get; set; }
    public float Price { get; set; }
}

Dal momento che non voglio che i singoli controller sappiano nulla su come mettere insieme i dati delle pagine master, incapsulo quella logica in una fabbrica che viene passata a ciascun controller:

public interface IViewDataFactory
{
    T Create<T>()
        where T : MasterViewData, new()
}

public class ProductController : Controller
{
    public ProductController(IViewDataFactory viewDataFactory)
    ...

    public ActionResult Index()
    {
        var viewData = viewDataFactory.Create<ProductViewData>();

        viewData.Name = "My product";
        viewData.Price = 9.95;

        return View("Index", viewData);
    }
}

L'ereditarietà corrisponde al master per visualizzare bene la relazione, ma quando si tratta di rendering di parziali / controlli utente comporrò i loro dati di visualizzazione nei dati di visualizzazione delle pagine, ad es.

public class IndexViewData : MasterViewData
{
    public string Name { get; set; }
    public float Price { get; set; }
    public SubViewData SubViewData { get; set; }
}

<% Html.RenderPartial("Sub", Model.SubViewData); %>

Questo è solo un esempio di codice e non deve essere compilato così com'è. Progettato per ASP.Net MVC 1.0.


4
Questo è il metodo consigliato da Scott Gutherie, quindi dovrei essere d'accordo.
Simon Fox,

@ Simon Fox - hai un link alla raccomandazione di scottgu? Impossibile trovarlo.
orip


Scusate. Avere un po 'di difficoltà a capire parte di questo. Al costruttore per il controller viene passata un'istanza di IViewDataFactory ma il sistema si aspetta un costruttore senza parametri. Inoltre, non ho familiarità con la sintassi di C # (in particolare "MasterViewData, new ()") per l'interfaccia. Qualcuno può spiegarlo o indicarmi una buona risorsa. Grazie.
Jason

5
Mi piace avere modelli fortemente tipizzati con cui lavorare, ma non sono un grande fan dell'accoppiamento dei dati master con tutti i miei altri modelli e azioni. Sono entrato in questo thread un po 'tardi, ma ho pubblicato il mio approccio ai dati master che mantengono le cose più sciolte.
Todd Menier

59

Preferisco suddividere le parti guidate dai dati della vista principale in parziali e renderle utilizzando Html.RenderAction . Ciò presenta diversi vantaggi distinti rispetto al popolare approccio di ereditarietà del modello di visualizzazione:

  1. I dati della vista master sono completamente disaccoppiati dai modelli di vista "normali". Questa è la composizione sull'ereditarietà e si traduce in un sistema più debolmente accoppiato che è più facile da modificare.
  2. I modelli di visualizzazione principale sono costituiti da un'azione del controller completamente separata. Le azioni "regolari" non devono preoccuparsi di questo e non c'è bisogno di una fabbrica di dati di visualizzazione, che sembra eccessivamente complicata per i miei gusti.
  3. Se ti capita di utilizzare uno strumento come AutoMapper per mappare il tuo dominio ai tuoi modelli di visualizzazione, ti sarà più facile configurarli perché i tuoi modelli di visualizzazione saranno più simili ai tuoi modelli di dominio quando non ereditano i dati della vista principale.
  4. Con metodi di azione separati per i dati master, è possibile applicare facilmente la memorizzazione nella cache dell'output a determinate aree della pagina. In genere le viste principali contengono dati che cambiano meno frequentemente rispetto al contenuto della pagina principale.

3
+1. Un altro vantaggio è che puoi fare in modo che la stessa vista utilizzi pagine master diverse a seconda dello stato di runtime corrente.
StriplingWarrior

1
Mi piace molto questa risposta: gli altri approcci delineati sembrano un po 'troppo complicati.
Paddy

2
Questa è la soluzione più elegante secondo me.
autonomatt

1
Anche questa soluzione mi sembra la migliore. Grazie mille!
JimDaniel

1
Questo è un ottimo modo, ma ricorda che devi ancora specificare percorsi per le tue "azioni parziali". Vedi questa risposta stackoverflow.com/a/3553617/56621
Alex

20

MODIFICARE

L'errore generico ha fornito una risposta migliore di seguito. Per favore leggilo!

Risposta originale

Microsoft ha effettivamente pubblicato una voce sul modo "ufficiale" di gestire questa situazione. Ciò fornisce una guida dettagliata con una spiegazione del loro ragionamento.

In breve, raccomandano di usare una classe controller astratta, ma guarda tu stesso.


GRAZIE! Questo esempio è ESATTAMENTE quello che sto facendo ... categoria su ogni pagina proveniente dal database.
Martin

Scott Gutherie, uno degli autori di MVC consiglia la soluzione fornita da @Generic Error di seguito
Simon Fox,

1
+1 per aver indirizzato alla migliore risposta anche quando la tua è ufficialmente corretta e accettata come risposta da OP.
IsmailS

+1 per aver indirizzato alla migliore risposta anche quando la tua è ufficialmente corretta e accettata come risposta da OP.
Dave Jellison

In realtà, Todd Menier è attualmente la migliore risposta per questo.
andreialecu

7

I controller astratti sono una buona idea e non ho trovato un modo migliore. Mi interessa anche vedere cosa hanno fatto altre persone.



2

Trovo che un genitore comune per tutti gli oggetti del modello che passi alla vista sia eccezionalmente utile.

In ogni caso, ci saranno sempre alcune proprietà di modello comuni tra le pagine.


0

L'oggetto Request.Params è modificabile. È abbastanza facile aggiungere valori scalari come parte del ciclo di elaborazione delle richieste. Dal punto di vista della visualizzazione, tali informazioni avrebbero potuto essere fornite in QueryString o FORM POST. hth


0

Penso che un altro buon modo potrebbe essere quello di creare l'interfaccia per la visualizzazione con alcune proprietà come ParentView di alcune interfacce, in modo da poterlo utilizzare sia per i controlli che richiedono un riferimento alla pagina (controllo padre) sia per le viste principali a cui si dovrebbe accedere da visualizzazioni.


0

Le altre soluzioni mancano di eleganza e richiedono troppo tempo. Mi scuso per aver fatto questa cosa molto triste e impoverita quasi un anno intero dopo:

<script runat="server" type="text/C#">
    protected override void OnLoad(EventArgs e)
    {
        base.OnLoad(e);
        MasterModel = SiteMasterViewData.Get(this.Context);
    }

    protected SiteMasterViewData MasterModel;
</script>

Quindi chiaramente ho questo metodo statico Get () su SiteMasterViewData che restituisce SiteMasterViewData.


per molti questo potrebbe sembrare un po 'hacky o' impuro 'ma porta a termine il lavoro velocemente
argh

Ugh. Il tuo codice sembra molto più difficile da mantenere che se avessi usato Html.RenderAction ().
Dan Esparza
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.