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 ...
}
Related
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>
}
This question already has answers here:
how to add script src inside a View when using Layout
(4 answers)
Closed 4 years ago.
Suppose I have a view called Login.cshtml, which I need to load these:
<link href="~/css/particle.css" rel="stylesheet" />
<script src="~/js/particle-js/particles.min.js"></script>
<script src="~/js/particle-js/app.js"></script>
In my application I have also _Layout.cshtml which contains the basic script to load for each, page. How can I load the script and css above in the when the user access to Login.cshtml view, as happen in _Layout.cshtml?
What I learned is the existence of #section, but I don't if is the best practive to do this, someone could suggest me how to do it properly?
Thanks in advance.
Section seems to be the appropriate solution for this use case.
So you will use the RenderSection method in your layout cshtml file. For example, if you want to include some static resources inside the head section of the document, you will create a new section in the head element of your layout
<head>
#RenderSection("PageCss",required:false)
</head>
<body>
<div>
#RenderBody()
#RenderSection("scripts", required: false)
</div>
</body>
and in your view(Login.cshtml), you will add the static resources through this specific section.
#section PageCss
{
<link href="~/css/particle.css" rel="stylesheet" />
<script src="~/js/particle-js/particles.min.js"></script>
<script src="~/js/particle-js/app.js"></script>
}
#section PageCss
{
<script src="~/js/anotherSciptWhichDoesNotBlockRendering.js"></script>
}
When razor executes the code, it will render the correct html.
You may create more than one section and use it as needed.
Consider using the async and defer attributes on script tag as appropriate to prevent render blocking script download/execution behavior.
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 :)
In a .NET MVC partial view, I'd like to do something like this:
<% ScriptCollection.RequireScript("path/to/script.js"); %>
That would require a method in the ScriptCollection object that looks like this:
public void RequireScript(string src)
{
if (!_List.Contains(src))
_List.Add(src);
}
Then, in my Master page, I would have something like this:
<html>
<head></head>
<body>
<!-- Content would go here -->
<% foreach (var script in ScriptCollection) { %>
<script type="text/javascript" src="<%= script %>"></script>
<% } %>
</body>
</html>
My question is this:
How can I make the ScriptCollection object available to be updated by a partial view and also available to be used by a Master page?
Edit:
I do not want to add the required scripts in a controller, nor do I want to use a strongly typed Master page. Though suggestions on doing so are welcome if those methods are considered a best practice.
Edit #2:
This would be easy with extension properties. I could just give the HtmlHelper class the ScriptCollection property. Am I missing something like this that already exists?
I checked out the Telerik assemblies. They're a little overkill for what I need. Also, the open-source license (GPL v2) isn't the type I'm looking for.
I started a project licensed under the MIT open-source license and am hosting it on Google Code. It's a lightweight solution to my problem.
code.google.com/p/script-keeper
You could take a look at Telerik's ScriptRegisterBuilder class implementation which does exactly what you want. Or you can just use it as well. In addition it also has support for:
Combining multiple JS files into one which result in less requests by the browser.
Compressing JS files.
HTTP Caching.
Content Delivery Networks.
release/debug versions of your JS resources depending on your build mode.
Now even when you don't use any of the other stuff Telerik provides you can use the ScriptRegisterBuilder class but then it's advised to disable the automatic jquery & jquery validation script registration. See also the link provided.
Also take a look the StyleSheetRegistrarBuilder class. This is the nephew of the ScriptRegisterBuilder class and handles the CSS assets.
I did noticed the MVC2 tag in your question but my simple example uses razor and is just for making the point. It shouldn't be hard to make it work for MVC2/ASPX as well. Otherwise let me know.
Master
#using Telerik.Web.Mvc.UI
<!DOCTYPE html>
<html>
<head>
<title>#ViewBag.Title</title>
#Html.Telerik().StyleSheetRegistrar().DefaultGroup(group => group.Add("~/Content/Site.css"))
</head>
<body>
#RenderBody()
#Html.Telerik().ScriptRegistrar().jQuery(false).jQueryValidation(false)
</body>
</html>
Partial View
#using Telerik.Web.Mvc.UI
#{
ViewBag.Title = "Home Page";
Html.Telerik().StyleSheetRegistrar().DefaultGroup(group => group.Add("~/Content/Site2.css"));
Html.Telerik().ScriptRegistrar().DefaultGroup(group => group.Add("~/Scripts/Test.js"));
}
<h2>#ViewBag.Title</h2>
<p>
Bla bla bla
</p>
I have a page that generates a printable table. I need to show this page without my surrounding _Layout page, for printer-friendliness.
How would I go about doing this?
Assuming you use razor view engine (you mentioned layout, not master page)
#{
Layout = null;
}
Well actually you should use razor view engine but anyways, idea is simple. Do not specify (remove) master page file reference in your aspx view and remove all ContentPlaceHolders, write all content directly in page. Or there's another way if you don't wish to remove them for some reason. Make PrintMaster.master master page which will contain nothing but ContentPlaceHolders.
While creating a new view, you can uncheck the use layout checkbox.
This will create you a view with layout as null.
#{
Layout = null;
}
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width" />
<title>Test</title>
</head>
<body>
<div>
</div>
</body>
</html>
When you create the view it allows you to change the Master Page. If you unmark the checkbox, the view comes with no Master Page and you can modify the whole page.
If you need to support displaying results on a page as well as having a printable view, you could create a second view (named PrintView for example) that does not use a page layout and call return View("PrintView"); from your controller.
A standard print style action can be done in several ways.
1. use a different view with a print button that sets the layout to null assuming you can map to razor.
To do this with CSS - you will want a separate css file that will be loaded on print and will hide your masterpage items. See the various articles on keywords
css media print
for example:
http://webdesign.about.com/cs/css/a/aa042103a.htm
This uses
<link rel="stylesheet" type="text/css" href="print.css" media="print" />
with the key here being media="print" which will use that css during print only.