Specify different _Layout.cshtml depending on controller - asp.net

I created an asp mvc3 project, I want to have a different _Layout.cshtml depending on which controller is selected. This is because with controller 1 it has 2 buttons with the controller2 there will be 3 and with the controller3 there will be 4. Each controller is for a specific type of user, so it depends on the login.
How can i link a controller and its views to another Layout.cshtml, right now there is one layout and it's under the Shared folder.
Thanks!

The View should determine the layout, not the controller.
The Controller should just determine what View is returned.
Then in the top of your view you can specify the layout.
You could add a If statement around it to change it based on your data
#{
if(ViewBag.someValue)
Layout = "~/Views/Shared/_Layout.cshtml";
else
Layout = "~/Views/Shared/_otherLayout.cshtml";
}

At this point since the other one is a bit dated and with mvc 5 , I know you will have some issues with not having brackets. If you wish to use the View to be doing logic then here is a more complete answer.
Controller
public ActionResult Index()
{
ViewBag.Admin = 1;
return View();
}
View
#{
if (ViewBag.Admin == 1)
{
Layout = "~/Views/Shared/_AdminLayout.cshtml";
}
else
{
Layout = "~/Views/Shared/_Layout.cshtml";
}
}

Related

how to remove _layout for admin dashboard

I want to exclude _layout for specific admin dashboard View. The only way I'm aware is with JS to hide those divs. Is there any other way?
In the razor page for which you don't want to use a layout, you can do:
#{
Layout = null;
}
If you want to exclude Layout from view temporarily, you can return view from a controller action using this code
if(...) return PartialView("name",model);
return View("name",model)
When you return a partial view, it will show only a view, no a layout
If your wont to exclude a layout permanenly for some views, you can use this code inside of the view
#{
Layout = null;
}
but don't forget that a Layout usually contains the most of Javascript and css libraries. So it is better to create a special layout for some views.
or you can use ViewStart page
#{
string CurrentName = Convert.ToString(HttpContext.Current.Request.RequestContext.RouteData.Values["Controller"]);
dynamic Layout;
switch (CurrentName)
{
case "User":
Layout = "~/Views/Shared/_Layout.cshtml";
break;
default:
//Admin layout
Layout = "~/Views/Shared/_AdminLayoutPage.cshtml";
break;
}
}

How to use views of View Component in different places in ASP.NET Core?

I use view components in my projects. Sometimes, I need to use the same view component as various styles. I researched a lot but I don't find a solution.
The code below works fine but when I do like this, I couldn't use it the way I wanted.
View component class:
public IViewComponentResult Invoke(BlogSidebarViewModel vm)
{
vm.BlogTags = _uow.BlogTag.GetAllByPriority(true,vm.LangId,vm.WebsiteId);
vm.BlogCategories = _uow.BlogCategory.GetAllByPriority(true,vm.LangId,vm.WebsiteId).Include(p=>p.BlogTag);
vm.RecentBlogs = _uow.Blog.GetAllByEnabledDate(true,vm.LangId,vm.WebsiteId);
//return View(vm); //For Default Blog Sidebar View Component
//return View("RedComponent", vm); //For Red Blog Sidebar View Component
//return View("GreenComponent",vm);//For Green Blog Sidebar View Component
}
But, when I write the following code, I get an error.
#await Component.InvokeAsync("BlogSidebar/RedComponent");
or
#await Component.InvokeAsync("~/Views/Shared/Components/BlogSidebar/GreenComponent.cshtml");
I want to use view components in various views. How can I do? Can I do it?
EDIT
Can I use the views of view component at the same time? For example, while I use the "GreenComponent" in the "Blogs/ABC.cshtml" view, I would like to use the "RedComponent" View in the "Blogs/XYZ.cshtml" view.
Please follow the steps below to use View Components:
1.Create GreenComponent.cshtml in folder:Views/Shared/Components/BlogSidebar.
2.Create View Component named BlogSidebar:
public class BlogSidebar : ViewComponent
{
public IViewComponentResult Invoke(BlogSidebarViewModel vm)
{
vm.Id = 1;
vm.Name = "aaa";
return View("GreenComponent",vm);
}
}
3.GreenComponent.cshtml:
#model BlogSidebarViewModel
Name: #Model.Name
4.Index.cshtml:
#model BlogSidebarViewModel
#await Component.InvokeAsync("BlogSidebar",new BlogSidebarViewModel())
Result:

Using ViewBag in Layout page

I have my _Layout.cshtml file that uses the ViewBag model to render some dynamic content.
I understand ViewBag can be populated in the controller and accessed in the view and/or layout page.
My question is, if my Layout page is using #ViewBag.SiteName, I want to avoid having to set this variable in each controller before I return the view. Is there a way to set this variable on a global level? Or how else should I pass this data to the layout page?
If you set anything in ViewBag - this happens after the Layout has been rendered -
You've missed the boat.
As others have mentioned, you can create a "helper" controller:
public class LayoutController : BaseController
{
[ChildActionOnly]
public ActionResult SiteName()
{
return new ContentResult {Content = "Site name goes here"};
}
}
Then, in your layout:
#{Html.Action("SiteName", "Layout")}

Having two master pages in mvc 3 application?

I have a MVC application that exist at the moment using a _MainLayoutPage for its Master Page.
I want to create another Master Page for a different purpose. I will be creating a new controller as well.
How can I do this?
The simplest way is in your Action Method, set a Viewbag property for your Layout
public ActionResult Index()
{
ViewBag.Layout= "~/Views/Shared/layout2.cshtml";
In your View, set the layout property
#{
Layout = #ViewBag.Layout;
}
In _ViewStart.cshtml, put this:
#{
try {
Layout = "~/Views/" + ViewContext.RouteData.Values["controller"] + "/_Layout.cshtml";
}
catch {
Layout = "~/Views/Shared/_Layout.cshtml";
}
}
And then you can put a controller specific _Layout.cshtml in your controller folders, like
~/Views/User/_Layout.cshtml for a controller named UserController
~/Views/Account/_Layout.cshtml for a controller named AccountController
And because of the try/catch, it will fall back to the '~/Views/Shared/_Layout.cshtml' layout if one is not defined for a specific controller.

Insert _ViewStart.cshtml

Is that possible to use viewstart only for a particular controller and view?
I was using only _Layou.cshtml file inside views folder.
Now i added _ViewStart.cshtml as common view inside views folder and moved _Layout to Shared folder.
This is program structure:
Homecontroller
public ActionResult Index()
{
return View();
}
Index.cshtml
#{
Layout = "~/Views/_Layout.cshtml";
}
_Layout.cshtml
{
//design code for Index.chtml
}
as per the above code, _Layout rendered for homecontroller .
When done the changes mentioned at the very first line, I'm getting the controls inside _Layout.cshtml in every controller I use.
I use nearly 6 controllers.
How to make this change without disturbing the entire code.
Please help.
PS: I need to introduce _ViewStart into the program since I'm integrating openid with my already developed project.
You can create another _ViewStart.cshtml (in Views/[controller] a sub-folder for example) that will override the root one, something like:
#{ Layout = null; }
You can simply use the ViewBag to determine whether to use Layout or not:
public ActionResult AnotherAction()
{
....
ViewBag.NoLayout = true;
return View();
}
and in your _ViewStart:
#{
if (ViewBag.NoLayout == null || !ViewBag.NoLayout)
Layout = "~/Views/_Layout.cshtml";
}
You can read more about MVC3 Razor layouts on Scott Guthrie's Blog

Resources