2010-10-28 4 views
7

Mi piacerebbe impostare un layout Rasoio predefinito tramite codice in un controller di base o in un attributo. È stato menzionato nel documento che è possibile, ma non riesco a capire come è fatto.Come impostare un layout Razor in MVC tramite un filtro di attributo?

so che c'è il parametro masterpage al metodo View disponibile, ma vorrei tutte le viste restituiti da un controller di avere questo valore impostato automaticamente.

E no, non posso usare _ViewStart per questo poiché i miei punti di vista si troveranno in vari punti (questa non è una normale configurazione del sito MVC).

Grazie

risposta

15

Penso che si può solo scrivere un ActionFilter come ...

public class YourCustomLayoutAttribute : ActionFilterAttribute, IResultFilter 
{ 
     public override void OnResultExecuting(ResultExecutingContext filterContext) 
     { 
      var viewResult = filterContext.Result as ViewResult; 
      if(viewResult != null) 
      { 
       // switch the layout 
       // I assume Razor will follow convention and take the "MasterName" property and change the layout based on that. 
       viewResult.MasterName = "CustomLayout"; 
      } 
     } 
} 

Ho appena scritto questo codice per la sede dei miei pantaloni senza compilatore in modo che probabilmente non si compila, ma probabilmente l'idea . Penso che IResultFilter sia l'interfaccia corretta che desideri, ha metodi che vengono eseguiti immediatamente prima della visualizzazione della vista. Se questo è corretto, dovresti essere in grado di modificare il MasterName per la vista che sta per essere resa al volo.

Questo è l'utilizzo del codice del controller.

[YourCustomLayout] // this should trigger your custom action result for all actions 
public class MyController : Controller 
{ 
    public ActionResult Index() 
    { 
     return View("Index", "MainLayout"); // even if you were to use the overload to set a master, the action result should override it as it executes later in the pipeline. 
    } 
} 
+0

In realtà non è necessario ereditare direttamente da 'IResultFilter' poiché' ActionFilterAttribute' lo fa già: 'classe pubblica astratta ActionFilterAttribute: FilterAttribute, IActionFilter, IResultFilter'. – Oliver

3

Il modo più semplice che posso pensare di fare questo è di avere i controller derivano da una classe base personalizzata che l'override del metodo Vista:

public class MyControllerBase : Controller { 
    public override ViewResult View(string viewName, string masterName, object model) { 
     if(String.IsNullOrEmpty(masterName)) { 
      masterName = GetDefaultLayout(); 
     } 
     base.View(viewName, masterName, model); 
    } 

    public virtual string GetDefaultLayout() { 
     return // your default layout here 
    } 
} 

Nel codice di cui sopra è possibile impostare esplicitamente il nome principale con un valore codificato. In alternativa, i controller potrebbero ignorare il metodo per fornire un layout specifico del controller. Oppure si potrebbe leggere da qualche attributo Controller, qualcosa di simile a:

masterName = GetType().GetCustomAttributes(). 
      OfType<MyCustomAttribute>().FirstOrDefault().DefaultLayoutPage; 

Naturalmente dovreste creare il MyCustomAttribute.

+0

Mi piace l'idea del controller di base qui, sembra la più semplice. Sai se esiste un modo per un attributo di intercettare la chiamata a View? –

+0

Non sono sicuro di cosa intendi, ma gli attributi non possono fare nulla da soli. Portano informazioni (o forse comportamenti) che devono essere invocati da qualcosa che ha un contesto (come il ControllerActionInvoker). Cosa intendi esattamente per "intercettare"? – marcind

+0

Bene, se ho creato un attributo filtro azione eseguito prima dell'esecuzione della vista, potrei modificare la vista e impostare la pagina di layout. Non sono sicuro se sia possibile modificare ActionResult in questo modo, anche se sospetto che lo sia. –

Problemi correlati