2010-10-28 7 views
7

Me gustaría establecer un diseño de Razor por defecto en un controlador base o un atributo. Se mencionó en los documentos que esto es posible, pero no puedo entender cómo se hace.¿Cómo establecer un diseño Razor en MVC a través de un filtro de atributos?

Sé que existe el parámetro masterPage para el método de vista disponible, pero me gustaría que todas las vistas devueltas por un controlador tengan este valor establecido automáticamente.

Y no, no puedo usar _ViewStart para esto ya que mis vistas van a estar en varios lugares (esta no es una configuración de sitio MVC normal).

Gracias

Respuesta

15

Creo que sólo podría escribir un ActionFilter como ...

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

acaba de escribir este código por el asiento de mis pantalones sin compilador por lo que probablemente no se compilará pero es probable que obtener la idea . Creo que IResultFilter es la interfaz correcta que desea, tiene métodos que se ejecutan justo antes de que se visualice la vista. Si esto es correcto, debería poder modificar el MasterName para la vista que está por renderizarse sobre la marcha.

Este sería el uso del código del controlador.

[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

En realidad, no necesita heredar de 'IResultFilter' directamente ya que' ActionFilterAttribute' ya lo hace: 'clase abstracta pública ActionFilterAttribute: FilterAttribute, IActionFilter, IResultFilter'. – Oliver

3

La forma más fácil se me ocurre hacer esto es por medio de los controladores se derivan de una clase base personalizada que reemplaza el método 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 
    } 
} 

En el código anterior podría configurar de forma explícita el nombre maestro a algún valor codificado. O bien, sus Controladores podrían anular el método para proporcionar un diseño específico del Controlador. O bien, podría leerlo de algún atributo en el controlador, algo similar a:

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

Por supuesto que tendría que crear su MyCustomAttribute.

+0

Me gusta la idea del controlador base aquí, parece ser la más sencilla. ¿Sabes si hay alguna forma de que un atributo intercepte la llamada a View? –

+0

No estoy seguro de lo que quiere decir, pero los atributos no pueden hacer nada por sí mismos. Llevan información (o tal vez comportamiento) que debe ser invocada por algo que tenga contexto (como ControllerActionInvoker). ¿Qué quieres decir con "interceptar"? – marcind

+0

Bueno, si construí un atributo de filtro de acción que se ejecutó antes de que se ejecutara la vista, podría modificar la vista y establecer la página de diseño. Simplemente no estoy seguro de si es posible modificar ActionResult de esa manera, aunque sospecho que sí. –

Cuestiones relacionadas