我该如何在ASP.NET MVC 3 Razor的ViewStart文件中指定不同的布局?

333

我想在我的应用程序中有2个不同的布局。我们假设其中一个是网站公共部分的布局,另一个是会员侧的布局。

为简单起见,我们假设每个站点的所有逻辑都被整齐地包装到2个不同的控制器中:

  • PublicController
  • StaffController

并且它们各自拥有一组相应的布局文件,供其下属的所有视图使用:

  • _PublicLayout.cshtml
  • _StaffLayout.cshtml

如何使用 _ViewStart.cshtml 文件指定所有在“Public”下的视图/操作都使用 PublicLayout,并且所有在“Staff”下的都使用 StaffLayout?


5
注意:如果你想为特定的Razor视图删除布局,只需设置Layout = null; - Leniel Maccaferri
4
关于你的示例,我想提供一些评论。你可能不应该将控制器命名为Public和Staff。通常情况下,控制器是对特定业务实体执行CRUD类操作的入口点,例如EventController、UserController等等。如果你的应用程序足够大,Public/Staff控制器的职责将会非常广泛。考虑使用区域(Areas)代替。http://msdn.microsoft.com/en-us/library/ee671793%28VS.100%29.aspx 如果你已经知道这点,那很好,但是其他人可能会对此产生错误的想法,所以仅供参考。 - Alex
3个回答

582

你可以在/Views/Public文件夹中放置一个_ViewStart.cshtml文件,它将覆盖/Views文件夹中默认的文件,并指定所需的布局:

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

类比一下,您可以在 /Views/Staff 文件夹中放置另一个 _ViewStart.cshtml 文件,并包含以下内容:

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

你还可以指定在控制器操作中返回视图时应使用哪种布局,但这是针对每个操作的:

return View("Index", "~/Views/Shared/_StaffLayout.cshtml", someViewModel);

另一个可能性是使用自定义操作筛选器覆盖布局。正如您所看到的,有许多实现此目的的可能性。由您选择最适合您场景的方法。


更新:

根据评论部分的请求,这里提供一个选择主页面的操作筛选器示例:

public class LayoutInjecterAttribute : ActionFilterAttribute
{
    private readonly string _masterName;
    public LayoutInjecterAttribute(string masterName)
    {
        _masterName = masterName;
    }

    public override void OnActionExecuted(ActionExecutedContext filterContext)
    {
        base.OnActionExecuted(filterContext);
        var result = filterContext.Result as ViewResult;
        if (result != null)
        {
            result.MasterName = _masterName;
        }
    }
}

然后使用自定义属性装饰控制器或操作,指定你想要的布局:

[LayoutInjecter("_PublicLayout")]
public ActionResult Index()
{
    return View();
}

1
@DarinDimitrov 我应该在什么地方创建 LayoutInjecterAttribute?是否有特定的位置? - kbvishnu
2
@VeeKeyBee,你可以将它放在“ActionFilters”子文件夹中。 - Darin Dimitrov
LayoutInjecterAttribute 的一个潜在问题是:它在控制器的 OnException 方法之前被调用。因此,如果控制器在异常处理过程中提供了视图结果,则布局不会被设置。 - Jeff Sharp

40

还有一种方法是在视图内定义布局:

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

在这里可以找到更多的操作方式,点击这里,希望对某人有所帮助。


1
这样做是行不通的 - 没有单独的_ViewStart.cshtml,你的视图仍然会在其他布局的@RenderBody()方法中呈现。 - Tillman32
1
这个!为什么每个人都提出这些极其复杂的过程,当你所需要做的就是这个! - George Harnwell

19

这种方法是初学者控制ASP.NET MVC应用程序中布局渲染的最简单方法。我们可以通过识别控制器并将布局呈现为控制器,来完成此操作,我们可以在视图文件夹的根目录中的_ViewStart文件中编写代码。以下是一个示例,显示如何完成此操作。

@{
    var controller = HttpContext.Current.Request.RequestContext.RouteData.Values["Controller"].ToString();
    string cLayout = "";

    if (controller == "Webmaster")
        cLayout = "~/Views/Shared/_WebmasterLayout.cshtml";
    else
        cLayout = "~/Views/Shared/_Layout.cshtml";
    
    Layout = cLayout;
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接