Use single view with two different layouts in Razor - asp.net-mvc

This might be a weird question, but I have two layout files in my project and I have a single view I'd like to render separately in each layout file (depending on URL).
So the issue I have is when I define the sections in the view. Both layout pages have similarly functioning sections, but they are named different. For example, if I wanted to use layout1 it would be #section main1 and for layout2 it would be #section main2.
The view will render the same content within these sections, so can I dynamically set the section name rather than making two copies of the same content with just the section name changed?

You can easily change the layout page by setting the layout you want to use, but you can't dynamically set the name to my knowledge. If you really can't change the section names of one of them, what you could do is create a nested layout of the one, and in that nested layout define section names that match in the nested one.
Basically you define:
#section a
{
#RenderSection("namethatmatchesotherlayout")
}
And through this you can get something that matches.

Related

Shared content between templates

I would like to share content (essentially blocks of html) between templates.
For example, suppose I have a common footer section with a graphic or two, text and links to 'about us', 'contact us' and so on.
I have different templates for different page layouts, but they all require this footer.
So far I can think of three ways :
Nesting templates : ie have a master one which has the footer content, then a child one for each layout, then the actual page template, but this could get tricky if some pages need a different footer
Using a Partial View to hold the footer content and using #Html.Partial() to pull in the partial view on the various templates
Create a settings document with the footer content and use Umbraco.Content() to fetch the footer property
Is any of these the recommended process (and are there any pitfalls?) or is there a better way?
I would normally do one of the following:
Have properties on the homepage for the footer links etc (in a separate tab) and pull in the values into the footer partial, this way you only have to set it once, rather than having it on every page
Have a Site Settings node at the same level as the home page and pull the values from there into the footer partial
That seems to be fairly standard from most of the Umbraco sites that I've worked on. I wouldn't have all of the properties on each page, unless you need a unique footer each page for some reason.
For example, lets say you add a tab called "Footer Settings" to the Home Page DocType with a single string property with the alias "copyRightNotice" and then you want to display that in a partial, your partial might look something like:
#inherits Umbraco.Web.Mvc.UmbracoTemplatePage
#{
var rootPage = Model.Content.AncestorOrSelf(1);
<h3>#rootPage.GetPropertyValue("copyRightNotice")</h3>
}

When should a page use a layout in MVC?

When should a page use layout or render layout? I'm a little confused when I should create a page which the page using layout.
different between
#{
Layout = null;
}
And
#{
ViewBag.Title = "Edit";
Layout = "~/Views/Shared/_Layout.cshtml";
}
_Layout is like a masterpage in ASP.NET webforms. If you want to apply a common theme (menu, styles ..) across many pages then _Layout file is the best place to put into.
You can have one single _Layout file for the entire application or one each for each specific module of the application.
_ViewStart file has the reference to the _Layout page used in the application.
If you use the below code then the respective page resets the layout to null and does not render the layout defined in _ViewStart. Code in _ViewStart file gets executed at the start of each View.
#{
Layout = null;
}
If you want any specific layout in a page overriding the default layout defined int _ViewStart then you can do as below
#{
ViewBag.Title = "Edit";
Layout = "~/Views/Shared/_OtherLayout.cshtml";
}
You don't need to explicitly set the Layout in any of the individual view files unless if you want to override the default layout defined in _ViewStart.
Or if you want the _ViewStart to decide which layout page to render based on the controller then you can write something like below in _ViewStart page. The view will have the respective layout themes applied when rendered.
#{
var controller = HttpContext.Current.Request.RequestContext.RouteData.Values["Controller"].ToString();
string layout = "";
if (controller == "ReportController")
{
layout = "~/Views/Shared/_ReportsLayout.cshtml";
}
else
{
layout = "~/Views/Shared/_Layout.cshtml";
}
Layout = layout;
}
Ade,
I answered a similar question a while back:
*From scottgu's blog (ref: http://weblogs.asp.net/scottgu/archive/2010/10/22/asp-net-mvc-3-layouts.aspx):
Starting with the ASP.NET MVC 3 Beta release, you can now add a file called _ViewStart.cshtml (or _ViewStart.vbhtml for VB) underneath the \Views folder of your project:
The _ViewStart file can be used to define common view code that you want to execute at the start of each View’s rendering. For example, we could write code within our _ViewStart.cshtml file to programmatically set the Layout property for each View to be the SiteLayout.cshtml file by default:
Because this code executes at the start of each View, we no longer need to explicitly set the Layout in any of our individual view files (except if we wanted to override the default value above).
Important: Because the _ViewStart.cshtml allows us to write code, we can optionally make our Layout selection logic richer than just a basic property set. For example: we could vary the Layout template that we use depending on what type of device is accessing the site – and have a phone or tablet optimized layout for those devices, and a desktop optimized layout for PCs/Laptops. Or if we were building a CMS system or common shared app that is used across multiple customers we could select different layouts to use depending on the customer (or their role) when accessing the site.
This enables a lot of UI flexibility. It also allows you to more easily write view logic once, and avoid repeating it in multiple places.*
see Where and how is the _ViewStart.cshtml layout file linked? for details
The _Layout is a template/framework/masterpage for all your views. It saves you from adding things like menus, sidebars, the html head or javascript/css includes on each and every new view you create. Use a layout page to take have "wrapping" html that is rendered around your views.

MVC - Have View affect sections of main layout

I've created a layout with all the styling etc. I have a menu and sub menu here, also a 3 column layout for content.
The left column will be used as a filter for reports most of the time, center for main content and the right column for help tips depending on the view you're at.
Can I define what the links in the sub menu are?
What is populated in the Left and Right columns, depending on the current view?
If you're looking to add new content in those areas, you want to be looking at sections.
You can see an example of this in the default project, just do a file-new-project to check out the layout page. You'll want something like this in your layout:
#RenderSection("SideBar", false)
The false here lets you opt-out of putting sidebar content on a view.
Your view would then have something like this:
#section SideBar {
// your sidebar stuff
}
As always, the Gu knows best: http://weblogs.asp.net/scottgu/archive/2010/12/30/asp-net-mvc-3-layouts-and-sections-with-razor.aspx
Cheers.

The following sections have been defined but have not been rendered for the layout page "~/Views/Shared/_Layout.cshtml"

I know there are a few questions that have been answered but I didn't find something specific to my case.
I'm using the mobile capabilities of MVC4. So I created a _layout.mobile.cshtml and the corresponding views.
The error above happens when I go in with a mobile device. As you can see, it is trying to display the regular _layout.cshtml instead of the _layout.mobile.cshtml. So I'm assuming it is also trying to display the view (say Index.mobile.cshtm) which doesn't have the section in question. Basically it is mixing the regular layout with the mobile views.
This doesn't happen all the time. If I recycle the pool it works again for a while and then all of the sudden it goes back to having the error and it will continue until I recycle the pool again.
Has anyone seen this problem before that can shed some light?
Thanks
John
In the _ViewStart.cshtml available under the Views folder, change the Layout value to your custom layout. I think this may help.. (Make sure that you are returning View instead of partial view)
for example
#{
Layout = "~/Views/Shared/_layout.mobile.cshtml";
}
In case if you want to change the layout for a specific page you can explicitly define it at the top of the page as a page directive.
in the index.cshtml there is a section being called defined in the original layout file "_LayoutHome.cshtml" that is not defined in the new bootstrap layout.
specifically: #RenderSection("featured", required: false)
So the solution is to either add this section to the new layout (look for it in the original layout and paste it) or simply delete it from the index.cshtml.
I had also face the same problem I removed
#section featured {
From View
Another way to do this is to use a conditional block in your _ViewStart.cshtml page. For example, you may have two layouts depending on the device regular user. Using pseudo-code for the reading of the device/browser type bit, it would look something like this:
#{
if(userIsMobile)
{
Layout = "~/Views/Shared/_MobileLayout.cshtml";
}
else
{
Layout = "~/Views/Shared/_Layout.cshtml";
}
}
I have used this to display or hide sections or menu items as needed for different classes of user; it should work as well for device-specific layouts.
Joey Morgan

How does a view know which layout to use? Where is the default?

In default mvc app. There are Layout and content pages, You know (_Layout, Home, Contact, etc.)
And content pages do not contain layout refrence as this:
Layout = "~/Views/Shared/_Layout.cshtml";
In content pages this code is missing.
But they works. How does it do this without layout refrence?
Because your _ViewStart.cshtml contains a reference to the default layout that will be used when a specific one is not stated on the view.
When you want to change the layout for a single view, you would include a Layout = "..."; to that view.
If you want folder specific layouts i.e. (Home, Account, Product etc), you can put _ViewStart.cshtml in that folder & point out whichever layout tobe used in that file & it will override the root level layout.
Find ScottGu's blogs for more details on layouts & sections here & here

Resources