I have a Razor Pages layout page that includes a nav bar as a partial page
<html>
...
<body>
...
<partial name="_Nav" />
Inside my _Nav.cshtml
<div class="links">
link 1
link 2
<!-- custom links that are set by each page go here-->
</div>
This layout is used by every page in the website. I would like to be able include "extra" links that pertain to each page in the website.
I've tried doing it was #RenderSection, but it seems that sections are only allowed in the Layout page. Does this mean I need to do away with my _Nav partial and and lump all the code into one file? Or is there a way to keep an organized code structure and still pass some code around? With jinja2 code blocks this is no problem, so I'm hoping there is a nice way in Razor Pages as well!
Also, I really don't want to pass full html strings from the c# class out to the html, I'm already passing out any variables I need in the links.
Thanks for your help!
You don't have to store html in your ViewDataDictionary.
On every view that has extra links to add, store a List<string>, strings being urls, something like this:
View:
#{
ViewData["Links"] = new List<string>(){ "https://www.google.com", "https://www.facebook.com" };
}
Then in your Layout view:
<partial name="_Nav" view-data="#ViewData" />
Now in your partial view:
//Default Links
#if (ViewData["Links"] != null)
{
//We have extra links
List<string> links = (List<string>)ViewData["Links"];
foreach (string link in links)
{
link1
}
}
RenderSection can only be called from a layout page.
There is no such plugin to add the dynamic link to the partial view.
As a workaround,you could put a div outside the _Nav.cshtml like below and use RenderSection to dynamic add link to the div:
....
<div class="links">
<partial name="_Nav" />
#RenderSection("Html", required: false)
</div>
....
_Nav.cshtml:
link 1
link 2
Test View:
#page
#model IndexModel
//do your stuff...
#section Html
{
<a href='#link3'>link3</a>
}
Related
I try to understand how works sections in Razor views. I have 2 layout files: _Layout.cshtml and _LayoutChild.cshtml which use the first layout inside. I try to declare sections in _Layout.cshtml and render it in the same file. Markup not appears but when I declare section in _LayoutChild.cshtml everything works. See example below:
_Layout.cshtml:
<!DOCTYPE html>
<html>
<head>
#RenderSection("A", false)
</head>
<body>
#section A{
<script>
alert("I'm in Layout!");
</script>
}
</body>
</html>
_LayoutChild.cshtml
#{
Layout = "_Layout";
}
#section A{
<script>
alert("I'm in LayoutChild!");
</script>
}
I understand that declaring section in the same file looks strange but I would like to know why it don't work?
While developing web site or application. Every page have some common section like header, footer, sidebar etc. Write and maintain these on every page is a hard job. So, we need a way to put them in one single place. Luckily in MVC we have Layout concept for this. We put all the common code in it and changing content in Views which will render in layout where we call #RenderBody() method.
Why we need sections ?
Some time we wanted to show specific content on some specific pages like newletters only show on blogs and home page, top news or some advertising banners on specific pages. For these type of scenarios sections rescue us in MVC.
How we can use section ?
We need to follow these two steps to used sections in MVC.
Declare Section in Layout, give it a name and tell is it required on
every page or not.
Define it in view
When views render then section content also added where we declare the section.
Code Example
1. Most of the time we need some specific javascript code for view. So we can do it like this
_Layout.cshtml
#RenderSection("scripts", required: false)
view.cshtml
#section scripts{
<script>
alert("I'm in Layout!");
</script>
}
2. News Letter example
_Layout.cshtml
#RenderSection("newletter", required: false)
view.cshtml
#section newletter{
<h3> New Letter </h3>
... rest of the html ...
}
As per requirement, i need to retrieve html page layout from database (that system user can update through system) with some html helpers (Dropdown, TextBox etc).
<html>
<body>
<div>
#Html.DropDown(x=>x.SomeId,Model.ElementCollection)
</div>
<div>
#Html.TextBoxFor(x=>x.Property)
</div>
</body>
</html>
In the above example, i need to get html from database but before render the page i want added some html helper's.So it will work like formal page.
Tried Solution:
For this i have created Custom View Engine and i am replacing text into Render function of IView inherited class.but its not resolving html from helper.
Question:
Is there any to get html from htmlHelper.If yes, then i can simply replace string into action method and return Content from action method?
Suggest please.
I found some useful link, to implement same functionality with Custom View Engine and Virtual Views.
Link1 And Link2
Thanks :)
I am trying to implement what I think is a pretty standard "dashboard" layout. The trick is I know ASP.NET but not so familiar with MVC so this is a learning project.
I have read many an article and they have helped me progress right to the point where I am very stuck and confused.
Part of my confusion comes from an existing advanced MVC project that I am familiar with from a user perspective. This helps in that I am able to pick through the source code and match up what I am learning to what I have seen from the user perspective.
This is not the problem just an example...
For example I read here what I believe is a very good introduction to the concepts. (http://www.codeproject.com/Articles/383145/RenderBody-RenderPage-and-RenderSection-methods-in)
In the MVC project I get to pick through however I see in the _Layout
#if (IsSectionDefined("statusbar"))
{
#RenderSection("statusbar")
}
however #section statusbar is not defined in the _Layout. If I do a global search for #section I find this:
#{
Layout = "~/Views/Shared/_Layout.cshtml";
}
#section header
{
}
#section headermenu
{
}
#section statusbar
{
}
#RenderBody()
So am I correct in guessing that statusbar is defined but it is an empty shell?
If it is an empty shell how does it get populated...cause when the project is running the statusbar does indeed have information???
So again this isn't my problem it is just an example of how the information at hand is confusing me.
This IS the problem:I'm not sure when to use PartialView, RenderSection...etc
My layout renders goofy. What is goofy? The only thing I can think of is to show you a screenshot of what happens.
What I want...
Here is the code used to generate these pages. The tags etc. for bootstrap etc. are omitted for brevity.
_Layout.cshtml
<!DOCTYPE html>
<html lang="en">
<head>
<title>#PageTitle</title>
</head>
<body>
<div class="container-fluid">
<div class="row">
<div class="col-md-12">
Header Stuff
</div>
</div>
<div class="row">
<div class="col-md-4">
#RenderBody()
</div>
<div class="col-md-8">
Main Content
</div>
</div>
<div class="row">
<div class="col-md-12">
Footer Stuff
</div>
</div>
</div>
</body>
</html>
Index.cshtml
#model DashboardModel
#{
Layout = "~/Views/Shared/_Layout.cshtml";
}
<div class="col-md-1">
<nav id="Navbar" class="navbar navbar-left" role="navigation">
<div id="organizer">
#(Html.Kendo().PanelBar()....etc....)
</div>
</nav>
</div>
<div class="col-md-3">
This is a place holder for my subnav...????
</div>
Stuff1Link cshtml
#model StuffModel
<div style="height:400px; border:dashed; border-width:thick;">
#{ Html.Kendo().MobileLayout().Name("mlay_PropStatus"); }
#(Html.Kendo().MobileView().....
</div>
Seems like layout is not put in Stuff1Link.cshtml
Can you put it like,
#{
Layout = "~/Views/Shared/_Layout.cshtml";
}
1.If your view just has some Html code just use "PartialView" :
#Html.Partial("_theLastPost")
2.If your view has controller for passing data it's better use "RenderAction":
#{ Html.RenderAction("_theLastPost"); }
and its controller
public PartialViewResult _theLastPost()
{
var a = (from c in db.Posts
orderby c.ID_Post descending
select c);
return PartialView(a);
}
3.I do not use render section . For more information about RenderSection go asp.net mvc layouts and sections with razor
I've got a post on my blog that discusses some of this you might want to check out.
The layout code you're referencing doesn't make much sense. The only purpose to declaring an empty section, really, is to fulfill a requirement that it exists, when you don't want to actually pass anything there. Since the layout is what defines whether it must be present or not, it makes no sense for it to exist there, empty. More than that, if you implement a section in your base layout, you'll get a runtime error because there's no place higher in the view chain where it's defined.
Long and short, to provide a place holder in your layout for a section you use:
#RenderSection("SectionName", [true|false])
The boolean param indicates whether views that utilize this layout must implement the section; false means it's optional, while true means it's required.
To implement a section in a view, you use:
#section SectionName
{
...
}
If you have a layout that inherits from another layout, that layout must implement all required sections in the layout it inherits from. If you want the the section to be available to views that utilize the sub-layout, you must redefine the section in the section implementation:
_Layout.cshtml
#RenderSection("Foo", true)
_SubLayout.cshtml
#{ Layout = "Views\Shared\_Layout.cshtml"; }
#section Foo
{
#RenderSection("Foo", true)
}
Finally, as to partial views vs. sections, it all comes down to whether you want to insert something into the layout or the view. For example, sections are most commonly used for inserting link tags to CSS files in the head or script tags before the closing body tag, where the view itself would not be able to touch directly. However, it's almost an apples and oranges comparison. Partials can be utilized in the layout, in the view, or even in a section. Whereas, sections can only be utilized in the layout.
I'm new to ASP.NET MVC and am wondering what I should be doing if I my _Layout.cshtml has an element
<div class="navbar navbar-inverse navbar-fixed-top">
...
</div>
that I don't want generated for a particular page with controller SomePageController.cs and view SomePage.cshtml. Do I just wrap that piece of HTML in an if statement like
#if(not on SomePage) {
<div class="navbar navbar-inverse navbar-fixed-top">
...
</div>
}
or is there a more proper way?
I usually use a magic string in ViewBag for this. I set it in my controller (or you can do it in the top of the view, if you wish).
ViewBag.HideNavBar = true;
in the _Layout:
#if(ViewBag.HideNavBar == null) {
<div class="navbar navbar-inverse navbar-fixed-top">
...
</div>
}
I use this strategy to pass options into the layout (such as datepicker options) all the time.
Give the single page that doesn't need that <div> a different Layout:
#model Foo
#{
Layout = "~/Views/Shared/_LayoutWithoutNavigation.cshtml";
}
<!-- rest of HTML -->
you can do it multiple way
1: Simple trick.. just use If condition and get the route name from Query string and match it with your route .
2: use two different layouts. one with that HTML part and one without HTML part.
and when creating view just specify the layout without HTML.
3: Use ViewBag / tempData
Approaches:
First:
if(Request.QueryString["routeName"] != "MyRoute" )
{
//Render HTML Part
}
second:
#{
layout = "~/shared/LayoutWithoutHTML.cshtml";
}
Third
in your Controller where you want to hide HTML
viewBag.HTMLCheck = true;
In your View
if(viewBag.HTMLCheck != true)
{
// Html Part
}
Your solution seems like an appropriate way to go about it - ideally though, if it's not going to be on every page, the pages without that section should use a different Layout.
What is the best method to render some navigation hyperlinks depending on which page the user is on (I am using C# MVC 4).
I have a _layout.cshtml which looks like the following (shortened down for display purpose).
<body>
#{Html.RenderAction("MainNav", "Navigation");}
<div id="container">
#RenderBody();
</div>
</body>
If a user navigates to /Home/Index then I would want the MainNav to render hyperlinks of Home | Management
Then if a user clicks Management that will change to Home | Company | Teams | Roles and will change again if they click one of these links.
Using Html.RenderAction() or Html.Action() would involve passing a parameter identifying your current view and using multiple if/else blocks to define what the partial should render. Instead you can use Razor sections to act as placeholders for specific content that can be placed anywhere in the layout.
In the layout, add #RenderSection(), in this case named "menu" to act as a placeholder for your menu links
<div id="sidebar">
#RenderSection("menu", required: false)
</div>
<div id="container">
#RenderBody();
</div>
Then in each view, add #section menu { ... } containing the links to display
Index.cshtml
// content to be displayed
#section menu {
#Html.ActionLink("Home", .....)
#Html.ActionLink("Management", .....)
}
Management.cshtml
// content to be displayed
#section menu {
#Html.ActionLink("Home", .....)
#Html.ActionLink("Company", .....)
#Html.ActionLink("Teams", .....)
#Html.ActionLink("Roles", .....)
}
The more you think about it, the more complex the problem you're describing becomes. So I tend to use a library. Even though it might seem overkill at this point, but in my experience it pays off later:
<body>
#Html.MvcSiteMap().Menu()
<div id="container">
#RenderBody();
</div>
</body>
This is all you need to do when using https://github.com/maartenba/MvcSiteMapProvider
Install-Package MvcSiteMapProvider
Just annotate your actions like this:
[MvcSiteMapNode(Title = "Menu Title")]