如何在ASP.NET MVC 3剃须刀ViewStart文件中指定不同的布局?


313

我想在我的应用程序中有2个单独的布局。可以说一个是网站的“公共”部分,另一个是会员侧的。

为了简单起见,可以说所有这些站点的所有逻辑都巧妙地包装在2个不同的控制器中。

  • PublicController
  • StaffController

并且它们每个都有一个对应的布局,用于每个视图下的所有视图。

  • _PublicLayout.cshtml
  • _StaffLayout.cshtml

如何使用_ViewStart.cshtml文件指定“公共”下的所有“视图” /“操作”都使用PublicLayout,“工作人员”下的所有内容都使用StaffLayout?

谢谢!


4
以防万一:如果您要删除给定Razor视图的布局,请设置Layout = null;
Leniel Maccaferri 2014年

3
就像对示例的评论一样,您可能不应该具有名为Public和Staff的控制器。控制器通常被实现为对某些关键业务实体(如EventController,UserController等)的CRUD类操作的入口。如果您的应用程序相当大,则公共/工作人员控制器的职责将变得广泛。请考虑区域。msdn.microsoft.com/zh-cn/library/ee671793%28VS.100%29.aspx您可能已经知道了这一点,但是其他人读到的可能会得出错误的主意,因此仅供参考。
Alex

Answers:


558

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

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

以此类推,您可以使用以下命令将另一个_ViewStart.cshtml文件放入/Views/Staff文件夹中:

@{
    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 2012年

2
@VeeKeyBee,您可以将其放在ActionFilters子文件夹中。
达林·迪米特洛夫

一个潜在的问题LayoutInjecterAttribute:在控制器方法之前调用它OnException。因此,如果控制器在异常处理期间提供了查看结果,则不会设置布局。
杰夫·夏普

作为MVC的新手,我想感谢您教我很多有关此答案的信息。但是我不知道里面发生了什么OnActionExecuted。你能为我更新答案吗?
Imad 2014年

29

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

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

您可以在此处找到更多方法,希望对您有所帮助。


1
这将不起作用-如果没有单独的_ViewStart.cshtml,您的视图仍将在其他布局的@RenderBody()方法内呈现。
Tillman32 '16

这个!当您只需要这样做时,为什么每个人都会提出这些极其复杂的流程!
乔治·哈恩威尔,

15

对于初学者来说,此方法是控制ASP.NET MVC应用程序中的Layouts呈现的最简单方法。我们可以识别控制器并将布局呈现为par控制器,为此,我们可以在Views文件夹的根目录下的_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;
}

在此处阅读完整文章“如何在ASP.NET MVC中呈现不同的布局”

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.