8

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

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

不,我不能为此使用 _ViewStart,因为我的视图将在不同的地方(这不是正常的 MVC 站点配置)。

谢谢

4

2 回答 2

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.
   }
}
于 2010-10-30T05:45:37.727 回答
3

我能想到的最简单的方法是让你的控制器派生自一个覆盖 View 方法的自定义基类:

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

在上面的代码中,您可以将 masterName 显式设置为某个硬编码值。或者您的控制器可以覆盖该方法以提供特定于控制器的布局。或者您可以从控制器上的某些属性中读取它,类似于:

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

当然,你必须创建你的MyCustomAttribute.

于 2010-10-29T01:34:45.417 回答