In ASP.NET Core 2.0, I was inspired by the answer of @Daniel J.G.
I made a ViewLayoutAttribute:
[AttributeUsage(AttributeTargets.Class)] public class ViewLayoutAttribute : Attribute { public ViewLayoutAttribute(string layoutName) { this.LayoutName = layoutName; } public string LayoutName { get; } }
Exemple of a controller class:
[ViewLayout("_Layout2")] public class MyController : Controller { // Code }
And I created an extension to get this very attribute from the 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) { // See if Razor Page... if (viewContext.ActionDescriptor is CompiledPageActionDescriptor actionDescriptor) { // We want the attribute no matter what. return Attribute.GetCustomAttribute(actionDescriptor.ModelTypeInfo, typeof(ViewLayoutAttribute)) as ViewLayoutAttribute; } // See if MVC Controller... // Property ControllerTypeInfo can be seen on runtime. var controllerType = (Type)viewContext.ActionDescriptor .GetType() .GetProperty("ControllerTypeInfo")? .GetValue(viewContext.ActionDescriptor); if (controllerType != null && controllerType.IsSubclassOf(typeof(Microsoft.AspNetCore.Mvc.Controller))) { return Attribute.GetCustomAttribute(controllerType, typeof(ViewLayoutAttribute)) as ViewLayoutAttribute; } // Nothing found. return null; } }
And in _ViewStart.cshtml:
@using MyApp.Extensions @{ Layout = ViewContext.GetLayoutAttribute()?.LayoutName ?? "_Layout"; }