Can I use a Controller to give information to _Layout.cshtml? - asp.net-mvc

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

Related

Casual layout patern in mvc with razor

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.

ASP.Net MVC Partial View Model Binding

I'm very new to MVC and I am looking to put a list of links on the main layout(master page) based on database table. I'm sure I read before that you shouldn't try to load models on the master page but use Partial Views instead (correct me if I'm wrong).
I've looked on Google and on other questions here but they only seem to talk about passing data from a main view to a partial view via ViewBag but I think I just want to add a partial view that I can add to the master page.
Can someone please tell me how to create a partial view I can add to master page so its used on every page and be able to load the list of links required i.e. by binding IEnumerable model to Partial View?
Try using ChildActionExtensions.Action
In your layout:
#Html.Action("MyAction", "MyController")
Controller:
public ActionResult MyAction()
{
var list = // get your list values
return PartialView("MyViewName", list);
}
Then just create your partial view:
#model IEnumerable<WhateverType>
#* View goodness *#
You can use this to bind whatever model you need to your partial view and if you use the Action helper in your Layout.cshtml it'll be rendered on every page.

Changing some of static content of shared partial view depending on main view

I have several shared razor partial views in my application to show some details of products on different pages. Now i need to change some of links inside partial views depending on what main view rendered that partial.
For example:
If partial view is rendered inside "index.cshtml", one of the links in partial view should be:
site1 called from index.cshtml
and if it's inside "insert.cshtml" then link need to be
other site that's not 1 and it's called from insert.cshtml
something like:
#if (something.parentview = "index.cshtml")
{ site1 called from index.cshtml}
else {
other site that's not 1 and it's called from insert.cshtml
}
Is there a way to do this?
When you call the Shared PartialView you know where are you.
Is far more easy to pass a parameter to your partial at the time of rendering that rely in "detect" inside of which view is rendered. Imagine... you have 3 levels of nesting... things get more complicated. Imagine if you change routing or view names?
You can use the ViewBag to pass the parameter: in your view you can set something to check inside the Partial. Not controller code is needed.
A more robust approach is pass a ViewModel to your Partial, but if the only data you need to pass is just a parameter, the ViewBag is simpler.

loading partial view differently

i am new in mvc and i know only two way one can render partial view like
#Html.Partial("PartialView1")
another one is to load partial view using jquery. i like to know is there any other ways around to load partial view.
when i render partialview like this way from my action method
[HttpPost]
public ActionResult Save(string name, string salary, string btnSubmit)
{
return PartialView("TestPView");
}
then PartialView content was render in page but shared look & feel goes out from the page when PartialView shown.
what i need to include in partial view as a result common look & feel show when partial view render. please guide me and show me all the various way to load partial view. thanks
Have a look at below link. It will help u to better understand the possible ways of rendering the partial views in MVC:
http://www.dotnet-tricks.com/Tutorial/mvc/Q8V2130113-RenderPartial-vs-RenderAction-vs-Partial-vs-Action-in-MVC-Razor.html
If I understand you correctly, what you are looking for is a layout and not a PartialView.
The PartialView provides you with the option to reuse a part of the view across several views.
The layout gives you the general look and feel of the website.
Here is the default example, that the VS generates for you :
#{ Layout = "~/Views/Shared/_Layout.cshtml"; }

Can a controller influence the _layout.cshtml file?

I'm stuck! I'm under the impression that the _layout.cshtml file is used for MasterPage-like content. Everything there is rendered on every page. Naturally, I want to write the code for rendering my sidebar menu in that file.
I want to dynamically display a list of Categories from my DB, but I'm having a problem with passing the actual model of categories to Layout.cshtml since it seems no controller actually touches it.
Any suggestions?
Otherwise please tell me how to approach this problem. I've been wracking my brain for the past three days and still no elegant solution.
I need to:
Dynamically fetch a list of Categories from the DB.
Display this list of Categories on every single view. (Hence the use of _layout.cshtml)
Elegantly handle each different categories click.
I'm at my wits end. :P How would you solve this?
_layout.cshtml
#if(isSectionDefined("Categories"))
{
<div id="sidebar">
#RenderSection("Categories", required: false )
</div>
}
index.cshtml
#section Categories {
<ul>
<li>Category One</li>
<li>Category Two</li>
<li>Category Three</li>
</ul>
}
see this : http://weblogs.asp.net/scottgu/archive/2010/12/30/asp-net-mvc-3-layouts-and-sections-with-razor.aspx
Any viewmodel that you pass to your view is automatically available within your master page. If you do not use RenderAction/Action which is the best approach, then you must create the necessary master page data in every action and add it to viewdata - either by having a common base class for your strongly typed viewmodel that contains all master page data or by using the viewdata dictionary.
I would strongly recommend that you go down the html.action approach though. In this way, you have a totally separate controller action for dealing with your list of categories. This action can retrieve the neccesary category data and return the categorylist usercontrol as a partialview and you will not have to worry about polluting all your other actions with this data.
As I see it, ViewData (and its relatives like ViewBag, Model, etc.) is meant for the specific current view. Your _Layout.cshtml is not specific to the current view; and it would be awkward if EVERY controller would have to pass the categories data in addition to whatever else data it needs to pass for the view.
Instead, what I do, is provide a static method in one of my helper classes that retrieves the categories from the DB. I also do some caching there, so that I do not have to hit the DB on every single request. The _Layout.cshtml then simply calls this static method. Simple and elegant.
If you wish, you can bring this out to a partial view, make it a helper method, whatever.
One note of caution though - my custom error view also uses the same _Layout.cshtml, and if the DB goes down, you get an exception trying to display the exception. ASP.NET MVC is smart enough to detect this and abort processing, but you're left with a nondescript default error page. What I did was to place try...catch statements around these dangerous calls, which quietly ignore the exception if the current page is the error view.
I've achieved something similar by having my ViewModels implement an Interface which has members that contain the menu data. In my action method I set that data. Then in my view I check to see if my view-model implements that inteface, pull the menu data out and render the menu (in a partial view actually)

Resources