2013-07-29 65 views
4

在asp.net MVC 3有没有一种方法来覆盖从控制器或操作过滤器的视图中设置的布局声明?如何覆盖视图布局声明

@{ 
    Layout = "~/Views/Shared/_Layout.cshtml"; 
}

我试图覆盖在OnResultExecuted的MasterName财产或类似下面的代码片段的OnResultExecuting,但无济于事。

public override void OnResultExecuting(ResultExecutingContext filterContext) 
{ 
    var view = filterContext.Result as ViewResult; 
    view.MasterName = null; 
}

回答

3

您可以创建一个动作过滤器来覆盖布局文件,但如果你想删除它,你必须创建一个空的布局文件,而不是分配主属性设置为null的。就像这样:

public class OverrideLayoutFilter : ActionFilterAttribute 
{ 
    public override void OnResultExecuting(ResultExecutingContext filterContext) 
    { 
     var view = filterContext.Result as ViewResult; 
     view.MasterName = "_LayoutEmpty"; 
     base.OnResultExecuting(filterContext); 
    } 
} 

控制器:

public class HomeController : Controller 
{ 
    [OverrideLayoutFilter] 
    public ActionResult Index() 
    { 
     return View(); 
    } 
} 

现在这个新布局文件需要被放置在SharedFolder,你只把RenderBody函数内部

_LayoutEmpty.cshtml

@RenderBody() 

注意:如果您在视图中定义了要覆盖布局的部分,我们也必须定义那些空白内容的部分。

+0

你知道为什么设置MastName为空不起作用吗? – Victor

+0

我不确定,但我认为它与MVC不知道空值已被“由用户”设置的事实有关,因此它假定它需要加载默认布局文件。这只是一个猜测。 –

2

使用ViewBag 当你需要改变布局打电话的动作,并把新的布局(甚至零)的viewbag。

@{ 
    Layout = ViewBag.layout; 
} 

和行动

if(something) 
    ViewBag.layout = "~/Views/Shared/whatever.cshtml"; 
else 
    ViewBag.layout = null; 
+0

我m寻找一种方法来保持我的布局声明在视图中,并且只是有一个业务规则来决定何时从控制器切换它。 – Victor

2

另一个地方,你可以控制布局是在_ViewStart.cshtml内。

在这里,您可以执行所需的逻辑并以编程方式指定要使用的布局。这使您可以将逻辑放在一个地方,并将其保留在视图外。

@{ 
    if(myBusinessRule) 
    { 
     Layout = "~/Views/Shared/_Layout.cshtml"; 
    } 
    else 
    { 
     Layout = "~/Views/Shared/_SecondaryLayout.cshtml"; 
    } 
} 

Blog post where it was introduced by Scott Gu