我想在我的应用程序中有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属性。是否可以立即执行,而不是在查看布局定义中使用。
答案 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
为您的页面加载布局时..它会读取您指定的布局。