2010-10-28 8 views
7

Chciałbym ustawić domyślny układ żyletek za pomocą kodu w kontrolerze bazowym lub atrybucie. W Dokumentach wspomniano, że jest to możliwe, ale nie wiem, jak to się robi.Jak ustawić układ żyletek w MVC przez filtr atrybutów?

Wiem, że istnieje parametr MasterPage dla metody View, ale chciałbym, aby wszystkie widoki zwrócone przez kontroler miały tę wartość ustawioną automatycznie.

I nie, nie mogę użyć _ViewStart do tego, ponieważ moje widoki będą znajdować się w różnych miejscach (nie jest to normalna konfiguracja witryny MVC).

Dzięki

Odpowiedz

15

Myślę, że można po prostu napisać ActionFilter jak ...

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"; 
      } 
     } 
} 

Właśnie napisałem ten kod przez siedzibie spodnie bez kompilatora więc prawdopodobnie nie będzie kompilować ale prawdopodobnie się pomysł . Myślę, że IResultFilter jest właściwym interfejsem, który chcesz, ma metody, które są wykonywane tuż przed renderowaniem widoku. Jeśli jest to poprawne, powinieneś być w stanie zmodyfikować MasterName dla widoku, który ma być renderowany w locie.

To byłoby użycie kodu kontrolera.

[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

Właściwie nie musisz dziedziczyć bezpośrednio z 'IResultFilter', ponieważ' ActionFilterAttribute' już to robi: 'public abstract class ActionFilterAttribute: FilterAttribute, IActionFilter, IResultFilter'. – Oliver

3

Najprostszym sposobem mogę myśleć w ten sposób jest poprzez kontrolerów wynika z niestandardowej klasy bazowej, która nadpisuje Zobacz metodę:

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 
    } 
} 

W kodzie powyżej można jawnie ustawić masterName do pewnej zakodowanej wartości. Lub Twoje kontrolery mogą przesłonić metodę, aby zapewnić układ specyficzny dla kontrolera. Albo można odczytać go z jakiegoś atrybutu na kontrolerze, coś podobnego do:

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

Oczywiście trzeba by utworzyć MyCustomAttribute.

+0

Podoba mi się tutaj idea kontrolera bazowego, wydaje się najbardziej prosta. Czy wiesz, czy istnieje jakiś sposób, aby atrybut przechwycił wywołanie View? –

+0

Nie jestem pewien, co masz na myśli, ale atrybuty nie mogą nic zrobić na własną rękę. Niosą informacje (lub może zachowanie), które musi wywoływać coś, co ma kontekst (jak ControllerActionInvoker). Co dokładnie masz na myśli przez "przechwytywanie"? – marcind

+0

Cóż, jeśli zbudowałem atrybut filtru akcji, który został wykonany przed wykonaniem widoku, mógłbym zmodyfikować widok i ustawić stronę układu. Po prostu nie jestem pewien, czy można zmodyfikować ActionResult, ale podejrzewam, że tak jest. –

Powiązane problemy