I just started working with, NET and I'm not very familiar with razor code.
I want to remove redundancy in my razor (.Net) code, without a big mess. I have about a dozen, PDF generating .cshtml files with razor code in it and the number is growing. Each file is nearly the same. The whole structure is always the same, only the content is always different. Because the files are pretty big, I will make an abstract example (ignore the real meaning of the elements, the list could be a different div for example):
File 1:
<div>
<p>
#content
</p>
</div>
<ul>
<li>
<a>
#comment
</a>
</li>
</ul>
File 2:
<div>
<p>
#picture
</p>
</div>
<ul>
<li>
<a>
<div>
#link
#metadata
</div>
</a>
</li>
</ul>
I thought it's not very clean to use #helper or #function for the different sections that are the same. The code would be not very clear to read with 10+ functions in it, that is only for the structure there.
I cant either just make a function to insert the value because sometimes there is, for example, a link or an additional div element inside the main structure.
At the end I want to have one place where I can change the basic structure, to change all structures, without going through 10+ files and change them one by one.
Is it possible to make such a "template"?
You can use Layout pages that define the overall structure. "Content", "Comment", etc are defined as sections in the layout, these sections get their content from the cshtml file that uses the layout. Creating a Consistent Layout in ASP.NET Web Pages (Razor) Sites.
_Layout.cshtml
<div>
<p>
#if (IsSectionDefined("content")) {
#RenderSection("content", false)
}
</p>
</div>
<ul>
<li>
<a>
#if (IsSectionDefined("comment")) {
#RenderSection("comment", false)
}
</a>
</li>
</ul>
.cshtml that uses this layout
#{ Layout = "~/Views/Shared/_Layout.cshtml"; }
#section content {
<div>My content</div>
}
#section comment {
bla bla bla ...
}
Related
I would like to visualize data from my model in my layout page - specifically when user adds an item to the shopping cart I would like to count number of items in the shopping cart and display it in the navbar next to the image of shopping cart.
User can add the product from more then 1 page (e.g. from Index page, or Product/index page etc.).
Anyone dealt with something similar?
I would like my navbar to look like this :
Navbar
<div class="navbar-collapse collapse show" id="navbarColor01" style="">
<ul class="navbar-nav mr-auto">
<li class="nav-item active">
<a asp-page="/Index" class="nav-link" >Home <span class="sr-only">(current)</span></a>
</li>
<li>
<a asp-page="/ShoppingCart/Index"> <i class="fas fa-shopping-cart fa-1x fa-cog "></i></a>
<div class="badge badge-danger badge-pill">5</div> //here is the number to be displayed
</li>
</ul>
</div>
There are different ways to achieve this, evaluate your options then decide what to do.
You can achieve this by:
Using view bags. This would cause code reputation throughout your project. Because you are going to set the view bag for each page visit.
Using partial views. By calling Ajax request to the action, and then return partial view. Partial views usually intended to be part of the Controller/Page, which wouldn't make sense to have GetCart from different controller/page. Also it is best for avoiding view reputation.
View Component. This is usually the ideal way to do it, since you need to do work behind the scene then return the value. View Components can live in their own, which is good for SoC.
My personal recommendation would be View Component, it is a new feature in asp.net core (replacing ChildAction).
I'm trying to make an FAQ page. The content structure is like this:
FAQ
-- Question 1
-- Question 2
-- Question 3
I can't seem to work out how to get the child templates to render though (I'm new to this).
FAQ Entries (Parent page)
#inherits Umbraco.Web.Mvc.UmbracoTemplatePage
#{
Layout = null;
var faqContentId = (int)CurrentPage.faqContent;
}
<html>
#Html.Partial("head")
<body>
#Html.Partial("header")
<div class="content">
#{
foreach (var child in Umbraco.Content(1168).Children) {
// render children here
}
}
</div>
#Html.Partial("footer")
</body>
</html>
FAQ Entry (Child pages)
#inherits Umbraco.Web.Mvc.UmbracoTemplatePage
<div class="accordion" id="accordionExample">
<div class="card">
<div class="card-header" id="headingOne">
<h5 class="mb-0">
<button class="btn btn-link" type="button" data-toggle="collapse" data-target="#collapseOne" aria-expanded="true" aria-controls="collapseOne">
#Umbraco.Field("title")
</button>
</h5>
</div>
<div id="collapseOne" class="collapse show" aria-labelledby="headingOne" data-parent="#accordionExample">
<div class="card-body">
#Umbraco.Field("answer")
</div>
</div>
</div>
Welcome my dear Umbraco Dev. Let me point you to a few directions:
If you only want the solution, skip to number 3.
1) Refrain from using #inherits Umbraco.Web.Mvc.UmbracoTemplatePage as it will soon be deprecated. Use #inherits Umbraco.Web.Mvc.UmbracoViewPage instead which will get you strongly typed stuff in your view and your code will look like #Model.GetPropertyValue("myValue")
Even better, create a custom model or try using Umbraco ModelsBuilder
which will get you cleaner code and stronger bindings with strongly typed models. But that's for another day.
2) I would recommend not grabbing nodes by id Umbraco.Content('id').Children like this. The reason is that if you for some reason delete the node and then create it again later on with the same name, the id will be different and your code will break the website.
Look at this page where people pointed me to the correct way of traversing umbraco Umbraco traversing
It talks about speed but it basically shows you also the correct way to traverse. you could also find the rest you need within Umbraco's documentation.
3)To the actual question: I'm assuming that the page you're on is the parent and you just want to grab the children. Then it's as easy as :
var collection = Model.Content.Children();
#foreach (var child in collection ) {
child.GetPropertyValue("yourValueAliasHere")
}
if you were using #inherits Umbraco.Web.Mvc.UmbracoViewPage you would have:
var collection = Model.Children();
#foreach (var child in Model.Children()) {
child.GetPropertyValue("yourValueAliasHere")
}
It should be something like #Html.Partial("FAQ Entry", child), where the 2nd parameter is the model (child object) that you want to pass into the partial view.
I need to add html tags dynamically in asp.net code behind , here is the scenario :
List<Product> products = ProductManager.GetProductList();//read data from database
Product is a class containing information I need to show in website such as product name, image,… .
For adding html code I tried this to show 5 products per page :
String finalHtmlCodeContainer="";
for(int i=0;i<=5;i++)
{
String myBox= "<div class=\"box\"> </div>";
finalHtmlCodeContainer+=mybox;
}
boxWrapper.InnerHtml=finalHtmlCodeContainer;
boxWrapper is a div that would contain our 5 product info.up to now everything is ok but problem appears when insted of "<div class=\"box\"> </div>",myBoxcontains long characters of html code , the original myBox should include this:
<div class="boxWrapper">
<div class="box">
<div class="rightHeader">rightHeader</div>
<div class="leftHeader">leftHeader</div>
<div class="article">
<img src="../Image/cinemaHeader.jpg" />
<p>
some text here <!--product.content-->
</p>
</div><!--end of article-->
<div class="rightFooter"><span>rightFooter</span>
<div class="info">
<ul>
<li>item1</li>
<li>item2</li>
<li>item3</li>
</ul>
</div>
</div><!--end of rightFooter-->
<div class="leftFooter"><span>leftFooter</span>
</div><!--end of leftFooter-->
</div><!--end of box-->
</div><!--end of boxWrapper-->
you see if i add producet.atrributes to code snippet above, it would be more messy,hard to debug , has less scalability and... . what is your solution?
It depends on the underlying product. If you are using web forms, I'd suggest using a data bound control that supports templating like the ListView or Repeater. It gives you full control over the UI, and also supports reloading the UI in ViewState. In your scenario, you'd have to build the UI on every postback. The ListView or Repeater track it in ViewState.
If you are using MVC, well using a helper method can make this easier as you can stick the item template within and then use a foreach and render out the helper.
If you are talking doing it in JavaScript, then there are templating components for doing the same thing.
I suggest you to Add repeater in your <p> tag ,
<p>
<asp:Repeater runat="server" ID="rpDetail">
<ItemTemplate>
<div class="box">
<%# Eval("YourDataField") %>
</div>
</ItemTemplate>
</asp:Repeater>
</p>
And make your products list as Repeater's datasourse in code behind .
rpDetail.DataSource = products ;
rpDetail.DataBind();
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.
I've created a section for a footer in my asp.net MVC 3 Web Application:
<footer>
#RenderSection("Footer", true)
</footer>
This footer will be the same on every page, so it doesn't make sense for me to define it for each and every view. So, is there any way I can globally declare this footer section for all views? The footer will contain code so as far as I know it's bad practice, if not impossible, to directly define it in the .cshtml file.
Thank you in advance.
I have handled the same scenario by creating a partial view "_Footer" and place it on the "_Layout".
#ViewBag.Title
#Html.Partial("_Header")
<div id="content">
<div id="nav-bar">
#Html.Partial("_Menu")
</div>
<div class="container">
#RenderBody()
</div>
</div>
<div id="footer">
#Html.Partial("_Footer")
</div>
#Html.Partial("_Scripts")
Sure:
<footer>
#if (IsSectionDefined("footer"))
{
#RenderSection("footer")
}
else
{
... put your default footer here
}
</footer>
And in views that you want to override the footer simply define the section.
You can place the footer in your SiteLayout.cshtml. See this article for more information on using layouts with MVC 3.