Asp.net core mvc 如何在ASP.NET核心MVC中指定不同的布局

Asp.net core mvc 如何在ASP.NET核心MVC中指定不同的布局,asp.net-core-mvc,Asp.net Core Mvc,我想在我的应用程序中有2个单独的布局。假设一个是网站的公共部分,另一个是空的,因为我们需要的一些原因 在Core之前,我可以这样定义一个过滤器: public class LayoutInjecterAttribute : ActionFilterAttribute { private readonly string _masterName; public LayoutInjecterAttribute(string masterName) { _mast

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

在Core之前,我可以这样定义一个过滤器:

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属性。是否可以立即执行此操作,而不在视图中使用布局定义。

您可以使用
IViewLocationExpander
界面根据需要渲染视图。 有关更多详细信息,请参阅此链接

问候,


Rohit

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

你可以这样试试-

@{
    Layout = "_Layout";
}
@{
    Layout = "~/Views/Shared/_Layout_2.cshtml";
    ViewData["Title"] = "Page Title";
}
\u ViewStart.cshtml
中指定如下默认布局-

@{
    Layout = "_Layout";
}
@{
    Layout = "~/Views/Shared/_Layout_2.cshtml";
    ViewData["Title"] = "Page Title";
}
如果要设置特定于页面的布局,则可以在该
page.cshtml
中指定其他类似的视图-

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

看看这是否有帮助。

您仍然可以执行与原始方法非常类似的操作,使用
ViewData
传递布局名称(尽管我会将其创建为:

然后在
\u ViewStart.cshtml
文件中:

@{
    Layout = (string)ViewData["Layout"] ?? "_Layout";
}
@{
    if (some condition)
    {
        Layout = "_Layout1";
    }
    else if (some other condition)
    {
        Layout = "_Layout2";
    }
    etc.
}
最后,假设您创建了一个新的布局,如
Views/Shared/_CleanLayout.cshtml
,您可以在任何控制器或操作上使用该属性:

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

如果您想根据某些条件使用不同的布局,可以在
\u ViewStart.cshtml
文件中使用以下代码:

@{
    Layout = (string)ViewData["Layout"] ?? "_Layout";
}
@{
    if (some condition)
    {
        Layout = "_Layout1";
    }
    else if (some other condition)
    {
        Layout = "_Layout2";
    }
    etc.
}
我在我的一个项目中使用它。在我的情况下,条件是User.IsInRole(“admin”),我的
\u ViewStart.cshtml
文件如下所示:

@{
    if (User.IsInRole("admin"))
    {
        Layout = "_AdminLayout";
    }
    else
    {
        Layout = "_Layout";
    }
}

因为在我的项目中只有两个角色,这只会导致一种情况,所以在我的情况下,这种变通方法并不太糟糕。我希望有类似情况的人会发现这一点很有用:)

在ASP.NET Core 2.0中,@Daniel J.G.的答案启发了我

我制作了一个
ViewLayoutAttribute

[AttributeUsage(AttributeTargets.Class)]
公共类ViewLayoutAttribute:属性
{
公共视图布局属性(字符串布局名称)
{
this.LayoutName=LayoutName;
}
公共字符串LayoutName{get;}
}
控制器类的示例:

[ViewLayout(“\u Layout2”)]
公共类MyController:Controller
{
//代码
}
我创建了一个扩展来从
ViewContext
获取这个属性:

公共静态类RazorExtensions
{
/// 
///从的当前调用控制器获取
/// .
/// 
公共静态ViewLayoutAttribute GetLayoutAttribute(此ViewContext ViewContext)
{
//看看页面是否。。。
如果(viewContext.ActionDescriptor为CompiledPageActionDescriptor ActionDescriptor)
{
//无论发生什么,我们都需要属性。
返回Attribute.GetCustomAttribute(actionDescriptor.ModelTypeInfo,typeof(ViewLayoutAttribute))作为ViewLayoutAttribute;
}
//查看MVC控制器是否。。。
//在运行时可以看到Property ControllerTypeInfo。
变量controllerType=(类型)viewContext.ActionDescriptor
.GetType()
.GetProperty(“ControllerTypeInfo”)?
.GetValue(viewContext.ActionDescriptor);
if(controllerType!=null&&controllerType.IsSubclassOf(typeof(Microsoft.AspNetCore.Mvc.Controller)))
{
返回Attribute.GetCustomAttribute(controllerType,typeof(ViewLayoutAttribute))作为ViewLayoutAttribute;
}
//什么也没找到。
返回null;
}
}
\u ViewStart.cshtml
中:

@using MyApp.Extensions

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

要在asp.net core中具有多个布局非常简单,请执行以下步骤:

步骤1:在“位于视图下的共享文件夹”中创建布局,并给它一个前缀为“u”的名称,即
\u myLoginLayout.cshtml

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

Thx,但这不是我想要的。但这个想法很有趣。我是这样做的,但我不喜欢这种方式。它并不优雅。对我来说是可行的,另一种方法似乎很麻烦。如何在应用程序开始时在viewStart中获取用户对象?如果您使用的是Razor,它在默认情况下应该是可用的。intellisense甚至应该提出这个建议(我知道这是在Visual Studio 2015+中)。如果您在访问时遇到问题,请告诉我,以便我可以帮助您这正是我想要做的,只是我想为用户会话缓存User.IsInRole(“admin”)的结果,这样它就不会为每个请求触发(让它在会话中为每个后续请求检索它)。我已经实现了我自己的“SessionCacheService”,其中我有一些预定义的会话变量,该服务在ViewStart.cshtml文件中是否可用?将此服务的依赖项注入放在ViewStart.cshtml中?您可以使用“@”从视图中引用项目中的任何类。假设您的项目“MyProject”在名为“Cache”的文件夹中有“SessionCacheService”;您可以使用“@MyProject.Cache.SessionCacheService”在任何视图(包括ViewStart.cshtml)中引用它。这有帮助吗?谢谢-这是对asp.net核心mvc过滤器/mvc生命周期的一个非常好的介绍-并且一次性解决了我的问题。这对我帮助很大!