2010-10-28 54 views
7

我想通过代码在基础控制器或属性中设置默认的Razor布局。文档中提到这是可能的,但我无法弄清楚它是如何完成的。如何通过属性过滤器在MVC中设置Razor布局?

我知道有可用的View方法的masterPage参数,但我希望控制器返回的所有视图自动设置该值。

不,我不能使用_ViewStart这个,因为我的意见将在不同的地方(这不是一个正常的MVC网站配置)。

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

在上面的代码,你可以明确地设置:

感谢

回答

15

我想你可以只写一个ActionFilter像...

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

我只是我凭感觉写了这个代码,没有编译器,它可能不会编译,但你可能得到的想法。我认为IResultFilter是你想要的正确接口,它有在渲染视图之前执行的方法。如果这是正确的,那么您应该能够修改将要即时呈现的视图的MasterName。

这将是控制器代码的使用情况。

[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

因为ActionFilterAttribute已经这样做了:''public abstract class ActionFilterAttribute:FilterAttribute,IActionFilter,IResultFilter'',所以你实际上不需要直接从'IResultFilter'继承。 – Oliver 2012-10-05 15:34:24

3

我能想到这样做的最简单的方法是通过你的控制器从覆盖查看方法的定制基类派生masterName指定一些硬编码值。或者您的控制器可以覆盖该方法来提供控制器特定的布局。或者你可以从控制器上的一些属性,阅读类似的东西来:

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

当然你必须创建MyCustomAttribute

+0

我喜欢这里的基本控制器的想法,它似乎是最直接的。你知道是否有任何方法让属性拦截对View的调用? – 2010-10-29 02:43:20

+0

我不确定你的意思,但属性不能单独做任何事情。它们携带必须由具有上下文的内容调用的信息(或者可能是行为)(如ControllerActionInvoker)。 “拦截”是什么意思? – marcind 2010-10-29 03:35:08

+0

那么,如果我构建了在视图执行之前执行的动作过滤器属性,我可以修改视图并设置布局页面。我只是不确定是否可以像这样修改ActionResult,尽管我怀疑它是如此。 – 2010-10-29 19:18:25