How do I specify different Layouts in the ASP.NET Core MVC

冷暖自知 提交于 2019-12-03 01:51:18

You can still do something very similar to your original approach, using ViewData to pass around the layout name (Although I would create it as a 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;
        }
    }        
}

Then in the _ViewStart.cshtml file:

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

Finally, assuming you create a new layout like Views/Shared/_CleanLayout.cshtml, you can use that attribute on any controller or action:

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

This is how I am using multiple layouts in my ASP.NET core MVC application.

You can try like this-

In _ViewStart.cshtml specify default _Layout like this-

@{
    Layout = "_Layout";
}

If you want to set page specific layout then in that page.cshtml, you can assign other view like this-

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

See if this helps.

If you want to have a different layout based on some condition, you could use this code in the _ViewStart.cshtml file:

@{
    if (some condition)
    {
        Layout = "_Layout1";
    }
    else if (some other condition)
    {
        Layout = "_Layout2";
    }
    etc.
}

I use this in one of my projects. In my case the condition is User.IsInRole("admin") and my _ViewStart.cshtml file is as follows:

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

Since there are only two roles in my project, which result in only one condition, this workaround is not too bad in my case. I hope someone with in a similar situation will find this useful :)

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

You can use IViewLocationExpander interface to render view as you want. Please refer this link Working with IViewLocationExpander in mvc for more details

Regards,

Rohit

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!