2012-06-26 33 views
7

consideriamo due viste che utilizzano lo stesso layout compostaAsp.Net MVC layout e viste parziali

  • Una colonna di sinistra contiene un "corpo" (che è riempito in modo diverso da entrambe le visite)
  • A colonna destra che visualizza le informazioni generali (passate tramite il modello)

Invece di definire la parte destra due volte, mi chiedevo se potevo creare un PartialView da collegare direttamente dalla pagina di layout.

Il problema è che le viste parziali ereditano implicitamente i propri modelli dalla vista che viene renderizzata. E poiché ogni vista ha il suo modello, finisco con una mancata corrispondenza del tipo di modello nella vista parziale.

Da qui vedo due soluzioni:

  • ho potuto inserire la parte comune del modello vista nella ViewBag. Sfortunatamente questo significa che ogni vista che usa questo layout deve implementare questa "convenzione" ma nulla avverte lo sviluppatore al momento della compilazione ...
  • Potrei usare il polimorfismo per rendere ogni modello di vista ereditato dalla stessa classe base (modifica : o interfaccia) che utilizza le viste parziali. Ciò funzionerebbe fino a un certo punto, ma aumenterebbe potenzialmente in modo esponenziale della complessità non appena avrò una seconda vista parziale nello stesso layout.

Così qui sono le domande:

  • ho ragione con le ipotesi di cui sopra?
  • Vedi altre possibilità?
  • Qualche ritorno sull'esperienza su questo?

Grazie mille, TB.

+0

Circa 2017, è anche possibile rendere la parte comune una proprietà di ciascun modello e quindi passarla come modello a '@ Html.RenderPartial' – jpaugh

risposta

7

Utilizzare uno Interface e implementarlo sui due modelli, questo è esattamente il tipo di cosa per cui sono utilizzati.

Ecco un esempio di due diverse viste che utilizzano due modelli diversi che implementano entrambe un'interfaccia. Questo è subtyping anziché ad-hoc polymorphism.

public class ViewModelOne : IReusableView 
{ 
    public string Name { get; set; } 
    public string Something { get; set; } 
    public int ANumber { get; set; } 
} 

public class ViewModelTwo : IReusableView 
{ 
    public string Name { get; set; } 
    public string Thing { get; set; } 
    public string SomethingElse { get; set; } 
    public int ANumber2 { get; set; } 
} 

public interface IReusableView 
{ 
    string Name { get; } 
} 

Così abbiamo la molto semplice vista parziale qui che è 'InnerPartialView':

@model TestIntegration.Models.IReusableView 
<div> 
    @Model.Name 
</div> 

che viene utilizzato in casa e sulle pagine di questo esempio di controllo:

public class HomeController : Controller 
    { 
     public ActionResult Index() 
     { 
      ViewBag.Message = "Welcome to ASP.NET MVC!"; 

      return View(new ViewModelOne() { Name = "hello", Something="sdfsdfs", ANumber = 1 }); 
     } 

     public ActionResult About() 
     { 
      return View(new ViewModelTwo() { Name = "hello 2", SomethingElse = "aaaddd", ANumber2 = 10, Thing="rand" }); 
     } 
    } 

La vista iniziale:

@model TestIntegration.Models.ViewModelOne 
@{ 
    ViewBag.Title = "Home Page"; 
} 

<h2>@ViewBag.Message</h2> 
<p> 
    To learn more about ASP.NET MVC visit <a href="http://asp.net/mvc" title="ASP.NET MVC Website">http://asp.net/mvc</a>. 
    @Html.Partial("InnerPartialView") 
</p> 

Il merito a View:

@model TestIntegration.Models.ViewModelTwo 
@{ 
    ViewBag.Title = "About Us"; 
} 

<h2>About</h2> 
<p> 
    Put content here. 
     @Html.Partial("InnerPartialView") 
</p> 
+0

Questo è ciò che intendevo per" base ". Ho solo paura che una volta che ottengo più viste parziali, i miei modelli di visualizzazione crescono abbastanza rapidamente nella complessità, implementando questa o quell'interfaccia a seconda del contesto. Suppongo che sia meglio dell'alternativa che ho menzionato, ma sono sorpreso di non trovare alcuna procedura migliore qui ... –

+0

Una classe base e un'interfaccia sono molto diverse. Ho aggiornato con un esempio completo perché non c'è nulla di complesso in questo. Non esagerare con questo, se ad esempio aggiungi un menu, non lo inseriresti nel ViewModel, lo passeresti nel controller usando il viewbag e gestendolo nella pagina di layout. Questo metodo dovrebbe essere usato per funzionalità che si desidera riutilizzare sugli oggetti, non per cose come footer, menu o barre laterali. – mattmanser

+0

Poiché hai detto che il riquadro destro doveva visualizzare informazioni "generali", ciò implica che sta mostrando informazioni abbastanza generiche, quindi non dipenderebbe troppo dalla sottoclasse dettagliata. Non hai parlato molto del tuo dominio applicativo, quindi è difficile dirlo. Ad esempio, se si tratta di un sito per ricette alimentari, ci si aspetterebbe che ogni ricetta (indipendentemente dalla sottoclasse) abbia alcune proprietà comuni (titolo, resa, tempo di cottura) e queste potrebbero essere espresse in un'interfaccia. Se il tuo sito gestisce tipi molto diversi con niente in comune, non ci possono essere informazioni "generali" significative per mostrare –

3

durante il rendering della vista parziale, è possibile inviare un modello:

@Html.RenderPartial(MVC.Partials.Views.Sidebar, Model.SideBarModel); 

così si potrebbe far scendere i dati come parte del modello di genitore che è il modello di la barra laterale parziale.

+0

Che funzionerebbe se sapessi quale fosse il modello. Poiché eseguo questa RenderPartial nel layout, il mio modello può essere qualsiasi cosa. A meno che non abbia una base di riferimento o un'interfaccia comune per tutti i miei modelli, non posso assumere nulla a riguardo. –

0

Nelle viste parziali, i modelli sono di tipo dynamic quindi non è necessario sapere di che tipo si tratta. Tuttavia, devi solo assicurarti che il modello abbia la proprietà di cui hai bisogno. In altre parole, è possibile utilizzare Model.MyProperty o Model.MyProperty come MyPropertyType quando si utilizza Html.Partial.

Problemi correlati