Render section on Razor Page - asp.net-core

Using Razor Pages #RenderSection does not seem to be available on a Razor Page, I get "RenderSection does not exist in the current context"
I have a number of Razor pages where I am trying to use a partial page on the partial page the is some accompanying css and Javascript I would like injected into the css and script section
If I just define the sections on the partial page nothing gets rendered, so after some searching it seems that on the page using the partial you need to add RenderSection in the various sections.
Any help would be appreciated.

May be you have missed the point on usage of #RenderSection in ASP.NET Core. #RenderSection should be only in Layout page as follows:
<script src="~/lib/jquery/dist/jquery.js"></script>
#RenderSection("Scripts", required: false)
Then Razor page should be as follows:
#{
ViewData["Title"] = "My Razor Page";
Layout = "_Layout"; // If this specified in the `_ViewStart.cshtml` then you don't need it
}
<partial name="_YourPartial.cshtml"/>
#section scripts {
<script src="~/js/yourjs.js" asp-append-version="true"></script> // this is specific to this Razor page only and it will also be available on the partial view called inside this Razor Page
}
And during the generation of html, the scripts on your Razor Page will be rendered as follows:
<script src="~/lib/jquery/dist/jquery.js"></script>
<script src="~/js/yourjs.js" asp-append-version="true"></script>
Hope it will make you clear!

Related

dotnet core 2.1 error in rendering view after adding html code

I have a razorview which uses a layout with name ReportsLayout. I was pulling configuration strings by injecting IConfiguration into the Layout as well as page views as below.
_Layout View
#using Microsoft.Extensions.Configuration
#inject IConfiguration Configuration
Page View
#using Microsoft.Extensions.Configuration
#inject IConfiguration Configuration
#model DayFuelSalesView
#{ Layout = "~/Views/Shared/_ReportsLayout.cshtml"; }
It was working fine until I added some more code to the razorview page which is basically pure html code.
After adding the code, during the debugging, the debugger show error as below in the web browser while trying to open the page.
This is the first time I am seeing such kind of error and I am unable to get it to work.
Any help is appreciated.
Try to check if you have #Render xxx{} in your Page View.If so,you need to add #await RenderSectionAsync("xxx", required: false) to your _Layout View.Try to refer to the Sections in the official doc.For example,if you have the following code in your view:
#section Scripts
{
...
}
You need to make sure you have #await RenderSectionAsync("Scripts", required: false) in your _ReportsLayout.cshtml.

Full identity scaffolding fails because of Razor script tag

I scaffolded all the Razor views, because I want to edit them.
However some of them have this at the bottom:
#section Scripts {
<partial name="_ValidationScriptsPartial" />
}
This is the error that I get:
InvalidOperationException: The following sections have been defined but have not been rendered by the page at '/Areas/Identity/Pages/Account/Manage/_Layout.cshtml': 'Scripts'. To ignore an unrendered section call IgnoreSection("sectionName").
Note that I do want those scripts to be rendered. Why does it crash? How to best resolve it?
Refer to this thread.
It means that you have defined a section in your master Layout.cshtml, but you have not included anything for that section in your View.
In your /Areas/Identity/Pages/Account/Manage/_Layout.cshtml,it should include the code:
#section Scripts
{
#RenderSection("Scripts", required: false)
}

.NET Core Blazor Dynamically retreive html as string from Razor Page or Blazor Component

I have a Razor Page (.cshtml) which is a PDF Template. Now i am required to retreive html as string from the page itself to Save it as a PDF file. In MVC, i could use IRazonEngine interface for the same. But in Blazor what can used to obtain this.
Additionally, if i can use Blazor component instead of a Razor Page, how can i get the string of HTML?
Please help!
This is the sample Razor Page I have
#model UserModel
<div>
<strong>Full Name:</strong>
<div>#Html.DisplayFor(model => model.FullName)</div>
</div>
<div>
<strong>Address:</strong>
<div>#Html.DisplayFor(model => model.Address);</div>
</div>
<div>
<strong>DOB:</strong>
<div>#Html.DisplayFor(model => model.DateOfBirth);</div>
</div>
UPDATE :
I have now used RazorLight.NETCore3 and working smooth.
I think this is not about blazor or mvc pages, but you can use RazorEngine.NetCore library to convert the cshtml and fill in the dynamic data using a model and retrieve the completed html.
Here is a guide on how to do it: https://khalidabuhakmeh.com/generate-outputs-with-razor-engine-in-dotnet-core
Github project: https://github.com/fouadmess/RazorEngine
Here is a simple code which I have used in the past:
public string CompileContent(string content, object model)
{
var stringContent = Engine.Razor.RunCompile(content, Guid.NewGuid().ToString(), null, model);
return stringContent;
}

ASP.NET Core 3.0 - Identity UI Manage folder not receiving layout

I have Identity scaffolded out in accordance with the documentation, and everything works properly except for the layout of the /Manage folder.
The directory setup is exactly as it gets scaffolded.
Directory setup with all misc. files removed
For clarity's sake:
/Areas/Identity/Pages/Account/Manage is the problem folder.
/Pages Contains the _ViewStart file which sets the Layout from my Views/Shared folder.
/Pages/Account Receives the layout from _Viewstart and works properly.
/Pages/Account/Manage Everything in here only receives the _ViewStart layout. The _Layout file in here isn't automatically found by the pages inside of it.
Areas/Identity/Pages/Account/Manage/_Layout.cshtml
#{
Layout = "~/Views/Shared/_Layout.cshtml";
}
<h1>Manage your account</h1>
<div>
<h4>Change your account settings</h4>
<hr />
<div class="row">
<div class="col-md-3">
<partial name="_ManageNav" />
</div>
<div class="col-md-9">
#RenderBody()
</div>
</div>
</div>
#section Scripts {
#RenderSection("Scripts", required: false)
}
This is exactly as it gets scaffolded in and the layout only breaks when you change AddDefaultIdentity() to AddIdentity(). I work with a reference I scaffolded and it just leads me to believe I'm not accounting for something when removing the default UI. The only workaround I found was manually setting the layout of each .cshtml file within /Manage
#{
Layout = "_Layout";
}
This fixes everything and causes the layout to work properly for the pages inside of /Manage. I read the documentation and it states that each Razor Page controller should search its own folder for a _Layout file before searching elsewhere. Is there a reason it isn't detecting the file?
"The only workaround I found was manually setting the layout of each .cshtml file within /Manage":
You don't have to do that. Simply create a _ViewStart.cshtml under your Manage/ foler:
#* file: Manage/_ViewStart.cshtml *#
#{
Layout = "_Layout"; // Use a partial layout name instead of absolute name
}
Also be careful that the default Manage/Layout.cshtml uses a parent layout of /Areas/Identity/Pages/_Layout.cshtml which might not exist in your scaffolded files :
#* file: Manage/Layout.cshtml *#
#{
Layout = "/Areas/Identity/Pages/_Layout.cshtml"; // you might want to change this to `/Views/Shared/_Layout.cshtml`
}
"it states that each Razor Page controller should search its own folder for a _Layout file before searching elsewhere"
That's true only when you're using a partial _Layout name. However, if you're using an absolute name that starts with a slash, it will use that layout directly. See official docs :
When a partial name is provided, the Razor view engine searches for the layout file using its standard discovery process. The folder where the handler method (or controller) exists is searched first, followed by the Shared folder. This discovery process is identical to the process used to discover partial views.
In your case, the layout name /Areas/Identity/Pages/_Layout.cshtml, which starts with a /, is not a partial name. That's the reason why your pages cannot discover the layout. In order to fix this issue, using a partial name _Layout instead. (This can be done by a single _ViewStart.cshtml file as I do above, don't add it for every page)
Finally, you might wonder why it renders normally when using AddDefaultIdentity(). As you find out, the AddDefaultIdentity() will add the default UI, which eventually invokes the AddRelatedParts() method. This allows that it fallbacks to the default UI when there's no such a layout or page. e.g., when you scaffold Identity with Visual Studio, it offers a list which you can use to override the default pages. The above /Areas/Identity/Pages/_Layout.cshtml comes from the default UI.

Use section in partial view

In my shared layout I would like to have a "scripts" section to stuff it with all the scripts needed for page functionality.
Layout.cshtml
<html>
<head>
<title>Test</title>
<script src="#Url.Content("~/Scripts/jquery-2.0.3.js")" type="text/javascript"> </script>
#RenderSection("Scripts", required: false)
</head>
<body>
#RenderBody()
</body>
</html>
So, my view loads a specific javascript, and I want it to be in "scripts" section, and it's working.
Index.cshtml
#model PlatformaPu.Areas.Inventura.Models.Home.Index
#section Scripts {
<script src="#Url.Content("~/Areas/Inventura/Scripts/Home/Index.js")" type="text/javascript"></script>
}
{CONTENT REMOVED FOR BREVITY}
#section Footer {
#Html.Partial("~/Views/Shared/_AppSelector.cshtml", Model.AppSelector)
}
Finally, my view renders a partial and I have a javascript that this partial loads.
_AppSelector.cshtml
#model PlatformaPu.Models.Shared._AppSelector
#section Scripts {
<script src="#Url.Content("~/Scripts/Shared/_AppSelector.js")" type="text/javascript"></script>
}
{CONTENT REMOVED FOR BREVITY}
...and this is NOT working - javascript tag is NOT rendered in "scripts" section
How can I do this?
As discussed in this question, it is not possible to use sections in a partial view:
Sections don't work in partial views and that's by design. You may use some custom helpers to achieve similar behavior, but honestly it's the view's responsibility to include the necessary scripts, not the partial's responsibility. I would recommend you using the #scripts section of the main view to do that and not have the partials worry about scripts.
You should add the script reference to the main view that references the partial.
This is my first answer!
I've being working with webforms for years and now i'm dealing with MVC 5. Bit hard.
Perhaps is the wrong solution, but works :)
In Layout.cshtml. add second "ScriptsPartial" section
#RenderSection("ScriptsPartial", required: false)
In Index.cshtml, add ", new ViewDataDictionary(ViewData) { { "ViewPage", this } }"
#section Footer {
#Html.Partial("~/Views/Shared/_AppSelector.cshtml", Model.AppSelector, new ViewDataDictionary(ViewData) { { "ViewPage", this } })
}
In _AppSelector.cshtml, remove this
#section Scripts {
<script src="#Url.Content("~/Scripts/Shared/_AppSelector.js")" type="text/javascript"></script>
}
In _AppSelector.cshtml, add this in any place
#{
if (ViewData.ContainsKey("ViewPage"))
{
System.Web.Mvc.WebViewPage viewPage = (System.Web.Mvc.WebViewPage)ViewData["ViewPage"];
viewPage.DefineSection("ScriptsPartial", () =>
{
// viewPage.Write(Scripts.Render("~/AppSelector/Scripts")); // If you use a Bundle
viewPage.WriteLiteral("<script src=\"" + Url.Content("~/Scripts/Shared/_AppSelector.js") + "\" type=\"text/javascript\"></script>");
});
}
}
Just "send" the View to the PartialView (no Parent property like in WebForms?) and use it to add content to "ScriptsPartial" section.
"ScriptsPartial" is needed because DefineSection throws an error "section already defined: Scripts"
So, no more than one PartialView can use "ScriptsPartial" section... not so good solution.
Best regards,
Paco Ferre