Casual layout patern in mvc with razor - asp.net-mvc

I can't find the reel intentions behind MVC-Razor layouts through internet.
In shared folder, there is :
_Layout.cshtml
_LoginPartial.cshtml
Should i use the _Layout for pages that dosen't require to be logged in, and use _LoginPartial for pages that require to be logged in ? Or am i completely lost ?
To make it simple :
If i create a new view that can only be reached when logged in, should it be beginning with
Layout = "~/Views/Shared/_Layout.cshtml";
or
Layout = "~/Views/Shared/_LoginPartial.cshtml";
?
Edit :
Checking tutorials and explanation from everyone (thanks all)
_Layout.cshtml is exactly like a master page in WEB FORM,
So i should always use :
Layout = "~/Views/Shared/_Layout.cshtml";
at the begining of a page i want to have formated like others.
The Login partial can be applied after authentification to alter the layout (disconnect button instead of connect, ect.)

The file _Layout.cshtml represent the layout of each page in the application. While partial view is a custom, reusable component that you can use in each page you need it. For example, we can create a partial view for customer and call it many time in page
<table class="table table-condensed">
#foreach (var student in Model.Students)
{
#Html.Partial("_StudentForm ", student)
}
</table>
So _Layout is meant to be used for all pages and _LoginPartial.cshtml can be used inside the page you need to have a login form in. Check this article about partial view
Tips and Tricks about Razor Partial Views

Layout = "~/Views/Shared/_Layout.cshtml";
in your view start file (_ViewStart.cshtml), may times its the ONLY thing in that file.
#{
Layout = "~/Views/Shared/_Layout.cshtml";
}
the _Layout.cshtml and _Viewstart.cshtml combo is similar to a master page in web applications but these will not have controller actions associated with them. if you set the layout setting in the _ViewStart file you don't need to set it in your actual views, they will inherit it from the viewstart file.
If you look inside the layout file you will see this line somewhere
#RenderBody()
That is where your individual views HTML will end up when your specific view is called.
The Login partial is just a quick start to demonstrate a view that can change display based on if the user is logged in or not.

You can use the same _Layout.cshtml but your controller ActionMethod should change to Authenticate. Use the below link for more info.
Authenticate User in MVC

Its more of a naming convention for layouts.
views will inherit it from the viewstart file. If you look inside the layout file you will see the renderbody method.
#RenderBody()
This is where the HTML code is read and shown in the browser.
The same goes for the _loginPartial.cshtml its just there for looks and to show you what Mvc is capable of.
Visual Studio creates the layout _Layout.cshtml when all but
the Empty project template is used. This layout is applied to all views by default through the /Views/_ViewStart.cshtml file.
If you do not want the default layout applied to views, you can change the settings in _ViewStart.cshtml (or delete the file entirely) to specify another layout in the view, like this:
#{
Layout = "~/Views/Shared/MyLayout.cshtml";
}
Or you can disable any layout for a given view, like this:
#{
Layout = null;
}
Hope this helps.

Related

Does the layout or the view get loaded first in ASP.NET MVC?

I've read somewhere that in ASP.NET MVC, the view gets "loaded" before the layout (the view logic gets applied before the layout logic). So I was wondering what's the real answer here, and is there a way to check this?
If you mean what view get rendered in which order you can simply add debug statements to the views to find out. For example:
_Layout.cshtml
#{ System.Diagnostics.Debug.WriteLine("Pre-RenderBody()");}
#RenderBody()
#{ System.Diagnostics.Debug.WriteLine("Post-RenderBody()");}
index.cshtml
#{ System.Diagnostics.Debug.WriteLine("index.cshtml:start");}
<div>Home Page</div>
#{ System.Diagnostics.Debug.WriteLine("index.cshtml:end");}
Show ouput from: [Debug]:
index.cshtml:start
index.cshtml:end
Pre-RenderBody()
Post-RenderBody()
So the index.cshtml is executed first. Then the layout, and the content is inserted (not really the right term as it's actually appended to the stream/string/stringbuilder prior to everything after #RenderBody()).
The server returns whole HTML rendered from the view and layout.
I would say that the layout logic gets loaded "first." For example, I have logic in my _layout that states:
#if (User.isAdmin)
{
#Html.ActionLink("Settings", "Index","Admin")
}
Saying that if the users role is admin then allow them to view/click the settings button. So the layout logic would have to load "first."

adding attributes in HTML tag of specific views only?

I am working on a MVC application with razor view engine.
HTML, Head and Body tags are placed in shared view _Layout.cshtml and other views are using this as layout.
While supporting application I am in need to add a custom attribute in some of pages (not in all pages). If I add attribute in layout it will appear in all pages. Can you pleased guide me how adding an attribute can be managed only in desired pages.
Below is my html tag with attribute:
<html ng-app="business_rules">
You can create a Layout where you need all these attributes and just refer this layout for desired pages using
#{
Layout = "Path/To/Layout.cshtml";
}
on the top of those pages.
For rest of the pages, you will use the different layout without those attributes.
You can define the Layout form the controller too. It can be done as below:
public ActionResult Index()
{
MyMOdel model = new MyMOdel ();
//TO DO:
return View("Index", "_AdminLayout", model);
}
I would use jquery. Just add on pages where you need this attribute following code:
<script>
$(document).ready(function(){
$('html').attr("ng-app", "business_rules")
});
</script>
I came across the exact same problem right now and the best solution I came up with was this below (I don't really want to add an entirely separate layout just for an attribute on the body tag). You've got a couple of suggestions on the asp net forums as well
I added an item to the view bag, a (probably overly) generic one called BodyAttributes:
ViewBag.BodyAttributes = "ng-app=\"moduleName\"";
Then I render this in pure htlm on the body tag
<body #Html.Raw(ViewBag.BodyAttributes)>
This keeps your layout non page specific and the angular doesn't need to be bootstrapped on every view. Plus, whether or not the angular is bootstrapped is now controlled from within the view itself where it belongs.

Setting the layout of ServiceStack Razor views on per-customer basis

I am working on a ServiceStack-based web application that will be used by multiple clients. There is a default layout/design that will be used in the absence of a client-specific one. So I was hoping to take advantage of the support for cascading layout templates available now in ServiceStack Razor but am having no luck making it work.
Here is roughly how I have structured the views in my project:
\
_ViewStart.cshtml
DefaultLayout.cshtml
SomeSharedContentPage.cshtml
\Views
SomeSharedViewPage.cshtml
\ClientA
LayoutA.cshtml
StylesA.css
\ClientB
LayoutB.cshtml
StylesB.css
The logic in _ViewStart.cshtml checks the identity of the logged-in user and sets the appropriate layout kind of like this (in a simplified form):
if (user.Client.ID == CLIENT_A_ID)
Layout = "~/Views/ClientA/LayoutA.cshtml";
else
Layout = "~/Views/ClientB/LayoutB.cshtml";
In turn, client-specific LayoutA and LayoutB both use the shared basic design/layout defined in DefaultLayout.cshtml by including the following at the top:
#{
Layout = "~/DefaultLayout.cshtml";
}
I was hoping to achieve a cascading nested layout effect whereby both SomeSharedViewPage.cshtml and SomeSharedContentPage.cshtml are displayed with the final layout comprising both the default and custom elements.
Unfortunately it doesn't work even when I hard-code one of the layouts in the view, nor when I explicitly specify the path of the layout page (e.g. Layout="~/Views/ClientA/LayoutA.cshtml" instead of Layout="LayoutA").
What am I doing wrong?
UPDATE
I got the top-level shared layout to work by renaming DefaultLayout.cshtml to _Layout.cshtml but client-specific layouts LayoutA and LayoutB are still not not being applied, so obviously SS Razor now simply falls back to _Layout.cshtml by convention.
I know that support for cascading nested layouts was recently added to ServiceStack, so I must be doing something wrong.
Based on the testing I've done, I don't think ServiceStack Razor supports _ViewStart.cshtml. However, you should be able to dynamically change the Layout via code using other methods. For example, you could set it up like this:
Default.cshtml
<h2>Default</h2>
Views\_Layout.cshtml (the default for ServiceStack Razor)
#{
if (user.Client.ID == CLIENT_A_ID)
Layout = "_Layout2";
else
Layout = "_Layout3";
}
Views\_Layout2.cshtml
<h1>Layout2</h1>
#RenderBody()
Views\_Layout3.cshtml
<h1>Layout3</h1>
#RenderBody()
You should also be able to use \Views\ClientA\ALayout.cshtml but you will have to make sure all the layout files use a unique name like ALayout.cshtml and BLayout.cshtml.

How to use other Layout for page the _Layout.vbhtml in .net mvc 3 view

I want to use a different layout for all the Views in one folder. It's all my Panel views controlled by PanelController.vb
Function LogIn() As ActionResult
Return View()
End Function
Currently all the views in my project utilize _Layout.vbhtml for the layout etc.
How can I make these specific pages utilize e.g. _PanelLayout.vbhtml instead of the default?
See below of what files I am talking about:
I am using Visual Studio 2010, .NET MVC 3, Pages are Razor or something like that.
You can define the view's layout file at the top of the view -
#{
ViewBag.Title = "Index"
Layout = "~/Views/Shared/_PanelLayout.vbhtml"
}
The question specifically calls for vbhtml (or vb.net) page. The accepted answer is for cshtml (C#) razor page. The correct answer for vb.net is:
#CODE
Layout ="~/Views/Shared/_PanelLayout.vbhtml"
End Code

Can I use a Controller to give information to _Layout.cshtml?

Basically, my _Layout.cshtml file is my MasterPage type View.
In it I'm designing the common look that will be shared across all Views.
I'm trying to load a left sidebar with a listing of all Categories in my database. For this purpose I've created a ViewModel called SidebarNavigation.cs
In my _Layout.cshtml I'd like to do something like:
<div id="leftnavigationbar">
#Html.Partial("_SideBarMenu", model)
</div>
But it seems that _Layout.cshtml doesn't actually use a Model up top in the page.
Any suggestions?
Just like in the aspx view engine the layout page "receives" the same model as the content page. For additional view data like this you should add it to the ViewData dictionary

Resources