如何在ASP.NET Core MVC中指定不同的布局

时间:2016-10-05 09:30:41

标签: asp.net-core-mvc

我想在我的应用程序中有2个单独的布局。假设一个是网站的公共部分,另一个是空的,原因我们需要。

在核心之前我可以这样做来定义过滤器:

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

}

现在,ViewResult没有MasterName属性。是否可以立即执行,而不是在查看布局定义中使用。

6 个答案:

答案 0 :(得分:22)

你仍然可以做一些与原始方法非常相似的事情,使用ViewData来传递布局名称(尽管我会将其创建为Result Filter):

public class ViewLayoutAttribute : ResultFilterAttribute
{
    private string layout;
    public ViewLayoutAttribute(string layout)
    {
        this.layout = layout;
    }

    public override void OnResultExecuting(ResultExecutingContext context)
    {
        var viewResult = context.Result as ViewResult;
        if (viewResult != null)
        {
            viewResult.ViewData["Layout"] = this.layout;
        }
    }        
}

然后在_ViewStart.cshtml文件中:

@{
    Layout = (string)ViewData["Layout"] ?? "_Layout";
}

最后,假设您创建了一个像Views/Shared/_CleanLayout.cshtml这样的新布局,您可以在任何控制器或操作上使用该属性:

[ViewLayout("_CleanLayout")]
public IActionResult About()
{
    //...
}

答案 1 :(得分:19)

这就是我在ASP.NET核心MVC应用程序中使用多个布局的方式。

你可以这样试试 -

_ViewStart.cshtml中指定默认_Layout,如下所示 -

@{
    Layout = "_Layout";
}

如果要在page.cshtml中设置特定于页面的布局,可以指定其他视图 -

@{
    Layout = "~/Views/Shared/_Layout_2.cshtml";
    ViewData["Title"] = "Page Title";
}

看看这是否有帮助。

答案 2 :(得分:3)

如果您想根据某些条件使用不同的布局,可以在@{ if (some condition) { Layout = "_Layout1"; } else if (some other condition) { Layout = "_Layout2"; } etc. } 文件中使用此代码:

User.IsInRole("admin")

我在我的一个项目中使用它。在我的情况下,条件为_ViewStart.cshtml,我的@{ if (User.IsInRole("admin")) { Layout = "_AdminLayout"; } else { Layout = "_Layout"; } } 文件如下:

{{1}}

由于我的项目中只有两个角色,这导致只有一个条件,这种解决方法在我的情况下并不算太糟糕。我希望有类似情况的人会觉得这很有用:)

答案 3 :(得分:1)

在ASP.NET Core 2.0中,我受到了@Daniel J.G的回答的启发。

我做了ViewLayoutAttribute

[AttributeUsage(AttributeTargets.Class)]
public class ViewLayoutAttribute : Attribute
{
    public ViewLayoutAttribute(string layoutName)
    {
        this.LayoutName = layoutName;
    }

    public string LayoutName { get; }
}

控制器类的例子:

[ViewLayout("_Layout2")]
public class MyController : Controller 
{
// Code
}

我创建了一个扩展来从ViewContext

获取此属性
public static class RazorExtensions
{
    /// <summary>
    /// Gets the <see cref="ViewLayoutAttribute"/> from the current calling controller of the <see cref="ViewContext"/>.
    /// </summary>
    public static ViewLayoutAttribute GetLayoutAttribute(this ViewContext viewContext)
    {
        ViewLayoutAttribute layoutAttributeFound = null;

        // Property ControllerTypeInfo can be seen on runtime.
        Type controllerType = (Type)viewContext.ActionDescriptor
            .GetType()
            .GetProperty("ControllerTypeInfo")
            .GetValue(viewContext.ActionDescriptor);

        if (controllerType.IsSubclassOf(typeof(Controller)))
        {
            layoutAttributeFound = Attribute.GetCustomAttribute(controllerType, typeof(ViewLayoutAttribute)) as ViewLayoutAttribute;
        }

        return layoutAttributeFound;
    }
}

_ViewStart.cshtml

@using MyApp.Extensions

@{
    Layout = ViewContext.GetLayoutAttribute()?.LayoutName ?? "_Layout";
}

答案 4 :(得分:0)

您可以使用IViewLocationExpander界面根据需要呈现视图。 有关详细信息,请参阅此链接Working with IViewLocationExpander in mvc

此致

罗希特夏尔

答案 5 :(得分:0)

要在 asp.net core 中实现多布局非常简单,请按照以下步骤操作:

第 1 步:在“位于视图下的共享文件夹”中创建布局,并为其命名并带有前缀“_”,即 _myLoginLayout.cshtml

第 2 步:在要应用的页面开头指定布局,例如 @{ Layout = "~/Views/Shared/_myLoginLayout.cshtml"; ViewData["Title"] = "TestMe";//您也可以添加标题... } 因此,当 _ViewStart.cshtml 为您的页面加载布局时..它会读取您指定的布局。