Im using ASP.NET Core 2.2. The problem that I have is I don't know where to use
#RenderBody() in my _Layout page. This is representation of what I want to do:
The green parts should come from _Layout and white parts coming from HomePage.cshtml. My HomePage consists of two parts a slider and a list of content below it.This is what I tried, but it doesn't meet my need because i can't put slider in it.
this is _Layout
<html>
<body>
<main>
<header></header>
<div class="left-col">
<div class="content">#RenderBody()</div>
<div class="right-col">
<footer></footer>
</main>
</body>
</html>
You can define a section in the layout to render the desired content
HomePage.cshtml
#{
ViewBag.Title = "Home Page";
}
#section Slider {
<div>My HomePage slider</div>
}
<p>My HomePage content</p>
The layout would check to see if the section exists and render it if it does
_Layout.cshtml
<html>
<body>
<main>
<header></header>
#if (IsSectionDefined("Slider")) {
<div class="homepage-slider">
#RenderSection("Slider", required: false)
</div>
}
<div class="left-col">
<div class="content">#RenderBody()</div>
<div class="right-col">
<footer></footer>
</main>
</body>
</html>
You would obviously have to specify what ever styling needed to position the section where desired.
Reference Layout in ASP.NET Core: Sections
Related
I'm facing an issue when I'm trying to link my .cshtml file and my JavaScript reference in an ASP.NET Core 6 MVC.
As of right now, I have made a webpack setup such that it generates my JavaScript tags in a separate file called home.sources.cshtml:
#section Scripts
{
<script src="/js/npm.popperjs.bundle.js"></script>
<script src="/js/npm.jquery.bundle.js"></script>
<script src="/js/npm.bootstrap.bundle.js"></script>
<script src="/js/home.bundle.js"></script>
}
As you can see, my tags are encapsulated in the Scripts section. All these dependencies are for my View/Home/Index.cshtml page:
#{
ViewData["Title"] = "Home Page";
}
<div class="text-center">
<h1 class="display-4">Welcome</h1>
<p class="test">Learn about building Web apps with ASP.NET Core.</p>
</div>
// Insert Script Section here
I want to make it so that the contents of home.sources.cshtml gets appended to this page at runtime. I don't want to manually add the script section myself, nor do I want to modify the page later on should I add more JavaScript dependencies. Any extra JavaScript dependencies that I add or remove will have their changes reflected only in home.sources.cshtml.
How do I go about doing that?
I was looking into #Html.Partial() in the attempt to add the Script section into the page as a partial view, but that doesn't seem to work.
That's a very odd way to add script references if I understand what you're doing here.
Normally in MVC You see a couple lines in the layout page that look like this:
#Styles.Render("~/Content/css")
#Scripts.Render("~/bundles/modernizr")
Those refer to a set of bundles in App_Start -> BundleConfig.cs
That's the standard way of adding .js files to your runtime pages.
Thank you Jonespopolis for giving me this approach.
Essentially, what I need to do is to make a Layout template file, specifying that I am using my preexisting Layout file that I was already using, and declaring where all the JS tags would go. For instance, here's my template file:
#{
Layout = "_Layout";
}
#RenderBody()
#section Scripts
{
<% for (index in htmlWebpackPlugin.files.js) { %>
<script src="<%= htmlWebpackPlugin.files.js[index] %>"></script>
<% } %>
}
This template file refers back to my original _Layout.cshtml file:
<!DOCTYPE html>
<html lang="en">
<head>
<!-- Head content here -->
</head>
<body>
<!-- Header content here -->
<div class="container">
<main role="main" class="pb-3">
#RenderBody()
</main>
</div>
<!-- Footer content here -->
</footer>
#await RenderSectionAsync("Scripts", required: false)
</body>
</html>
The #await RenderSectionAsync("Scripts", required: false) line will render the Script section that I created in my template file.
From there, I used Webpack's Htmlwebpackplugin with the following config:
plugins: [
new HtmlWebpackPlugin({
inject: false,
template: 'Views/Shared/PageTemplate.cshtml',
filename: '../../Views/Shared/home.sources.cshtml',
minify: false
}),
],
Running the webpack command will net us a home.source.cshtml file containing everything in the template file, but it shows my actual JS references needed for home.cshtml. All that's left is to make this file be the Layout for the page, by inserting this at the beginning:
#{
Layout = "home.sources";
}
Running the application gives me the home page with all the correct JS tags downloaded! Now if I ever change my JS dependencies, I don't need to ever worry about generating the tags nor inserting them into the page, since all of that has been automated now, which is exactly what I wanted!
I literally would do a partial, because it makes it look cleaner. So I have a partial called _ScriptsPartial and I have all js I need in it.
<script src="~/lib/jquery/dist/jquery.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap#5.0.2/dist/js/bootstrap.bundle.min.js"
integrity="sha384-MrcW6ZMFYlzcLA8Nl+NtUVF0sA7MsXsP1UyJoMp4YLEuNSfAP+JcXn/tWtIaxVXM"
crossorigin="anonymous"></script>
<script src="~/js/site.js" asp-append-version="true"></script>
<script src="//cdn.jsdelivr.net/npm/sweetalert2#11"></script>
<script src="//cdn.datatables.net/1.12.1/js/jquery.dataTables.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/toastr.js/latest/toastr.min.js"></script>
<script src="https://cdn.tiny.cloud/1/srxbhbztd7jetvbg65d7si3gxatiku0ym7l8if3mda35vxxe/tinymce/6/tinymce.min.js" referrerpolicy="origin"></script>
Then I use it as such in my layout like this I make many partials
<!DOCTYPE html>
<html lang="en">
<head>
<partial name="_HeadPartial" />
</head>
<body>
<header>
<partial name="_NavPartial" />
</header>
<div class="container">
<main role="main" class="pb-3">
<partial name="_Notification" />
#RenderBody()
</main>
</div>
<footer >
<partial name="_FooterPartial" />
</footer>
<partial name="_ScriptsPartial" />
#await RenderSectionAsync("Styles", required: false)
#await RenderSectionAsync("Scripts", required: false)
</body>
</html>
this seems to work okay :)
Please, I need a way to master Blazor multi-layered layouts, but for now, I desperately need to know how to null layouts so that I can add everything from `
<html>
to
</html>
`
myself on the #page directly.
Why do I want to do this?
in MVC I can make the ViewModel inherit from the _layout ViewModel so that I can dynamically add user images, name, properties... in the navigation and side-nav, even hide some nav options. like in the picture below.
Looks like you want to custom your MainLayout?
You can just clear it, open MainLayout.razor (where the _Layout lies) and only add #Body in it:
#inherits LayoutComponentBase
#Body
From your example, seems you just want to custom your NavMenu?
It's the same,open NavMenu.razor and just modify the navs.
And for extension, if you want to different types of Layout, you can use NavigationManager to
check the parameter in your url and it will use the related Layout, like:
#inherits LayoutComponentBase
#inject NavigationManager _navManager
#if (_navManager.Uri.Contains("CustomLayout1"))
{
#Body
}
else
{
<div class="page">
<div class="sidebar">
<NavMenu />
</div>
<div class="main">
<div class="top-row px-4">
About
</div>
<div class="content px-4">
#Body
</div>
</div>
</div>
}
So if the page is #page "/CustomLayout1/counter" Then it will use your null MainLayout in this demo.
I think you want multiple layouts.
The base file (_Host.cshtml for blazor server side or index.html for WASM), needs to be as empty as possible to only have and
For _Host.cshtml, you probably need to do something like:
#page "/"
#namespace YOURNAMESPACE.Pages
#addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
#{
Layout = null;
}
<html>
<component type="typeof(App)" render-mode="ServerPrerendered" />
</html>
For index.html, something like:
You can read more here: https://learn.microsoft.com/en-us/aspnet/core/blazor/layouts?view=aspnetcore-5.0
I am getting an error ("Server Error in '/' Application") when I nest partial views in my MVC app. The views work fine individually, but not when nested. It's my understanding that it's okay to do this, so what am I doing wrong?
Essentially, I am trying to use partials as sub-layouts within my _Layout.cshtml.
Here's my main layout - _Layout.cshtml
<!DOCTYPE html>
<html>
<head>...</head>
<body style="padding-top: 80px;">
<div class="container-fluid">
<div class="row">
<div id="myTab" class="col-lg-12 col-md-12 col-sm-12">
...
<div class="tab-content">
<div class="tab-pane fade" id="search">
#Html.Partial("~/Areas/Search/Views/Shared/_SearchLayout.cshtml")
</div>
</div>
</div>
</div>
</div>
#RenderBody()
#RenderSection("scripts", required: false)
</body>
</html>
This is the first partial view (_SearchLayout). If I remove the partials AND #RenderBody, no error.
<div class="container-fluid">
#Html.Partial("_PolicySearch")
#Html.Partial("_ClaimSearch")
</div>
#RenderBody()
This partial view is nested in the first partial view (_SearchLayout):
<div class="row top-buffer search-outline form-horizontal">
<div class="col-md-1 search-icon-size text-primary">
<i class="glyphicon glyphicon-heart"></i>
</div>
<div class="col-md-1 search-icon-size text-primary">
<h4>Claim Search</h4>
</div>
</div>
In your first partial view:
Remove RenderBody
Replace Html.Partial to Html.RenderPartial
I also would recommend to rename your partial view to something not containing the word "Layout" to avoid the mismatch between the view types.
Use Html.RenderPartial instead
The problem is #RenderBody(). This can only be called in a layout, which when used in this way _SearchLayout.cshtml is not, despite its name.
The important thing to remember about layouts, partials and views in ASP.NET MVC is that they're all views. The only thing that differentiates them is how they're used. In this instance, you're using the _SearchLayout.cshtml view as a partial, and partials can't use #RenderBody().
Is it possible to wrap a view with a partial file? Sort of like a layout, but with a partial?
For example:
Layout
<html>
...
<body>
<div>#RenderBody</div>
</body>
</html>
View
#{
Layout = "~/Views/Shared/_PartialWrapper.cshtml";
}
<!--content I want to wrap with partial-->
<div class='alert alert-info'>HELLO WORLD</div>
Partial
#{
Layout = "~/Views/Shared/_Layout.cshtml";
}
<div style='border:1px solid #cccccc;'>
<div style='background-color:black;color:white;'>
StackOverflow Rocks
</div>
<div>
#RenderBody
</div>
</div>
When I tried the above scenario, I get an error on the partial file on the "#RenderBody" line. The error:
The best overloaded method match for 'System.Web.WebPages.WebPageExecutingBase.Write(System.Web.WebPages.HelperResult)' has some invalid arguments
Is there a better way to do this -- or make the above work?
As #Overmachine mentioned, RenderBody is a Method so you need to write #RenderBody() like so:
#{
Layout = "~/Views/Shared/_Layout.cshtml";
}
<div style='border:1px solid #cccccc;'>
<div style='background-color:black;color:white;'>
StackOverflow Rocks
</div>
<div>
#RenderBody()
</div>
</div>
I've seen a few posts on this topic:
Razor Nested Layouts with Cascading Sections
MVC 3 - Nested layouts - sections don't render in Areas
And it always seems to be problematic. However they are both pretty old so wondering if things have changed.
Basically I have a master layout, and 3 different body templates based on what kind of page it is. For examples sake:
_Layout.cshtml
<html lang="en">
<head>
</head>
<body style="padding: 50px 0;">
<header class="navbar navbar-default navbar-fixed-top" role="banner">
#Html.Partial("_MenuPartial")
</header>
<ol class="breadcrumbs">
#RenderSection("breadcrumbs", true);
</ol>
<section>
#RenderBody();
</section>
<footer class="navbar navbar-default navbar-fixed-bottom">
#Html.Partial("_FooterPartial")
</footer>
#Html.Partial("_ScriptInitPartial")
</body>
</html>
_LayoutForEdit.cshtml
<div class="panel panel-primary">
<div class="panel-body">
<div class="col-lg-2">
<ul class="nav nav-pills nav-stacked">
#RenderSection("tabs", true)
</ul>
</div>
<div class="col-lg-10">
<div class="tab-content">
#RenderBody()
</div>
</div>
</div>
<div class="panel-footer">
<button class="btn btn-primary" data-bind="enable: Entity.isValid, click: save">Save</button>
</div>
</div>
Now this renders fine when called. Almost.
The rendering of sections must be in the child layout it seems. If I try to put the breadcrumbs in the _Layout.cshtml, it will fail because _LayoutForEdit.cshtml never rendered it. How can I fix this?
The following sections have been defined but have not been rendered for the layout page "~/Views/Shared/_LayoutForEdit.cshtml": "breadcrumbs".
I know it's an old question. I thought I'd share this anyway in case anyone else runs into this (like I did).
At the bottom of your child layout, you define a section with the same name as the section in the parent layout. Inside of this section you simply put a #RenderSection, again specifying the same name as before. Once this is in place, you essentially have the child layout "bypass" content from pages, up to its parent layout:
#section breadcrumbs {
#RenderSection("breadcrumbs", true)
}
Not sure if you still need help, but I'll answer anyways.
There RenderSection method takes the following parameters according to the
MSDN Documentation:
public HelperResult RenderSection(
string name,
bool required
)
Parameters
name
Type: System.String
The section to render.
required
Type: System.Boolean
true to specify that the section is required; otherwise, false.
Change the call to:
#RenderSection("breadcrumbs", false);
If the section "required" parameter is false, it will not give an error if that section is not included by a view.