Writing to head, but not via _Layout.cshtml - c#

I would like to write to the HTML head element independently via the page view, not through the _Layout.cshtml as each page will require different scripts, meta data, titles etc. Can this be done in ASP.NET MVC 3, with C# / Razor?
#using Test.Models;
#model IEnumerable<Player>
<!--
Put JavaScript, CSS etc... Into the page <head> here.
-->
<h2>Index</h2>
<table id="scores">
<tr>
<th>Name</th>
<th>Age</th>
<th>Gender</th>
</tr>
#foreach(Player p in Model)
{
<tr>
<td>#p.name</td>
<td>#p.age</td>
<td>#p.gender</td>
</tr>
}
</table>
<canvas id="game" width="800" height="600">
<p>Download a modern browser.</p>
</canvas>

You can do this by using sections. Go to your _Layout.cshtml and add a new section called head like this:
<head>
<meta charset="utf-8" />
<title>#ViewBag.Title</title>
<link href="#Url.Content("~/Content/Site.css")" rel="stylesheet" type="text/css" />
#RenderSection("head", false)
</head>
The new section is added with the #RenderSection. Now in your individual views you can add content to the head like this:
#section head
{
<script type="text/javascript">
//Your java script here
</script>
}
When the complete view is rendered the javascript would be rendered in the head section just below the link tag. You could put anything in there. For example, meta tags.

var newHeadElement = createSomeElementOrString;
document.getElementsByTag("head")[0].appendChild(newHeadElement);

Have you tried using razor sections?

Related

Unable to load css for views in ASP.NET MVC

I'm learning asp.net and using mvc as a starting point. I've got the app running however when trying to add CSS to a particular view it doesn't do anything. I've seen many solutions but not seem to work for me. Plugging css selector directly in _Layout works only for the main page but doesnt for independent views
Refresh cache
#Styles.Render("~/Content/styles.css") add to view
link css in head of _Layout
I am obviously missing something; can someone figure out what I am doing wrong and explain why it works?
Folder structure:
_Layout.cshtml head
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>#ViewData["Title"] - bugtracker</title>
<link rel="stylesheet" href="~/lib/bootstrap/dist/css/bootstrap.min.css" />
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons#1.5.0/font/bootstrap-icons.css">
<link rel="stylesheet" href="~/bugtracker.styles.css" asp-append-version="true" />
<link href="~/Content/css/styles.css" rel="stylesheet" type="text/css"/>
</head>
Index.cshtml
#model IEnumerable<bugtracker.Models.Issue>
#{
ViewData["Title"] = "Index";
}
#foreach (var item in Model) {
<span class="cardborder">
<p> ID: #Html.DisplayFor(modelItem => item.Id) </p>
<p> #Html.DisplayFor(modelItem => item.Name) </p>
<p> #Html.DisplayFor(modelItem => item.Description) </p>
<p> #Html.DisplayFor(modelItem => item.Type) </p>
<p> #Html.DisplayFor(modelItem => item.Priority) </p>
</span>
}
Content/css/styles.css
.cardborder{
border: 1px solid red;
}
Yes, I'd also try to load the script at the bottom of the _Layout.cshtml to see if that changes behavior, also make sure to have caching turned off in your browser.

Can a view selectively populate sections that appear outside the view in ASP.NET mvc?

I'm making a simple site with bootstrap and .net core mvc (v3.0). Because most of the pages reuse the bootstrap container, I decided to put that in the layout file, so that I wouldn't be repeating the same setup everywhere.
This has the downside that if a view needs fixed elements, those end up getting fixed to the container, not the viewport.
I'm wondering if it's possible to call some sort of syntax inside the view.cshtml file that could cause a section to be rendered in the _Layout.cshtml file (sorry if this has been answered, but I wasn't sure what to search for).
For instance
_Layout.cshtml
#using Microsoft.Extensions.Hosting
#inject Microsoft.AspNetCore.Hosting.IWebHostEnvironment _environment
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>#ViewData["Title"]</title>
</head>
<body>
#* this div only gets rendered based on logic inside the view*#
<div id="conditionalViewDiv">
</div>
<div class="content container-fluid pl-0 pr-0 moveable" id="containerMain">
<main role="main">
#RenderBody()
</main>
</div>
#RenderSection("Scripts", required: false)
</body>
</html>
and then in SomeView.cshtml
#{
ViewData["Title"] = "title";
Layout = "~/Views/Shared/_Layout.cshtml";
}
#MadeUpRenderCommand("conditionalViewDiv")
#*other view stuff*#
Thank you for any help.
According to the docs, View components are intended anywhere you have reusable rendering logic, similar to partial views, but they're much more powerful. The main difference is when you use partial view you still have dependency on controller while in View Component you don't need a controller. So there is a separation of concern.
A view component is a C# class that provides a partial view
with the data that it needs, independently from the parent view and the action that renders it.
Good enlightening examples can be found, particularly:
https://www.c-sharpcorner.com/article/working-with-view-components-in-asp-net-core-mvc/
https://jakeydocs.readthedocs.io/en/latest/mvc/views/view-components.html
Hope this helped.

Placement of style tag in view

Looking at some Razor views, I see a lot of times where a <style> tag is added directly in a view (CSHTML) file.
This seems to work fine, but in fact it adds the <style> tag inside the <body> tag, while it should generally be inside the <head> tag.
How would you some inline CSS to a single razor page so that it appears within the <head> tag? Is there a preferred way?
Like this:
Shared/_Layout.cshtml
<!DOCTYPE html>
<html>
<head>
...
#RenderSection("HeadStyles", required: false)
</head>
<body>
...
</body>
</html>
Home/Index.cshtml or whatever other view you need to do this in
#section HeadStyles {
<style>
.custom-style { color: red; }
</style>
}
The reason why inclusion of <style> tags is not recommended inside <body> is because of causing FOUC.
But if your <style> tag applies to content that's after it in DOM, that risk is null.
No browser currently in use has any trouble parsing <style> tags placed in <body>.
Technically, when the browser meets a <style> tag in DOM it:
pauses rendering
reconstructs CSSOM to include the new declarations
rebuilds the already rendered DOM (this is where FOUC happens, if)
carries on with rendering
best variant is -
<html>
<head>
<link rel="stylesheet" href="styles.css">
</head>
<body>
<!-- here is page content -->
<script src="scripts.js" type="text/javascript"></script>
</body>
</html>
in this case browser will load in this sequence
styles
content (which will be already styled)
scripts (which will not slow down page rendering in case if scipts are not so little)

How to make asp:buttons same width with bootstrap and css

I am making an asp website with bootstrap. I am wondering how do I make all asp button widths the same instead of padding the text with spaces. I created an alternate css file and used the css class tag. am i missing something?
<%# Page Language="C#" AutoEventWireup="true" CodeBehind="admin.aspx.cs" Inherits="SCBA.admin" %>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title>Admin</title>
<link href="../Content/bootstrap.min.css" rel="stylesheet" />
<link rel="stylesheet" type="text/css" href="stylesheet3.css"/>
<style>
.box {
border:1px solid grey;
background-color:#d3d3d3;
}
</style>
</head>
<body>
<form id="form1" runat="server">
<script src="../Scripts/jquery.min.js"></script>
<script src="../Scripts/boostrap.min.js"></script>
<div class="navbar navbar-default">
<div class="container">
<div class="navbar-header">
<asp:Button ID="Button2" runat="server" onclick="Button2_Click" Text="Administration" /> <br />
<asp:Button ID="Button3" runat="server" cssClass="button1" onclick="Button3_Click" Text="Resource" />
</div>
</div>
</div>
</form>
</body>
</html>
Here is my CSS
.button1
{
width: 200px;
}
Depending on which browser you are using, learn to use the browser tools so you can inspect the HTML and CSS elements yourself.
Here are some steps to get you in the right direction:
Look at the Bootstrap documentation for the button classes then override the relevant Bootstrap CSS class in your custom style sheet to change its appearance. Also, do NOT use fixed widths in responsive sites, use percentages. It looks like you are not leveraging the Bootstrap classes at all for this
.NameOfBootstrapButtonClass
{
width: 25%;
}
Move your script links to just before the closing body tag
Remove all inline CSS and CSS links - then from Solution Explorer drag the CSS files you need into the head section of your ASP page. This guarantees your links are correct but only applies if you are using VS
Do not use minified CSS files in development - when deploying you will have all your min versions bundled up for performance. Personally, I comment out much of the bundling in the RegisterBundles method of the BundleConfig class when working locally
If you're building a site you are going to have a lot of redundancy without the judicious use of master pages and user controls
You have no viewport tag in the head so your site will not be responsive in any mobile browser
<meta name="viewport" content="width=device-width, initial-scale=1.0">
If you are supporting IE9 and IE8, you need to reference the Modernizr library. You need to give some thought to which browsers you need to support
Remove the xmlns namespace attribute from the html tag

Why isn't this script running from the masterpage?

I have a Page that is associated with a master page. In the master page, I put the css links in the head section and I put the jquery script tag and the script that contains the function to toggle the grid, but when it is not working. Looks like it is not even calling showhide when I click on an item.
Here is a snippet of the master page:
<head runat="server">
<title></title>
<link href="MainLayout.css" rel="stylesheet" type="text/css" />
<link href="ajaxtab.css" rel="stylesheet" type="text/css" />
<link href="dialog.css" rel="stylesheet" type="text/css" />
<link href="grid.css" rel="stylesheet" type="text/css" />
<link href="pager.css" rel="stylesheet" type="text/css" />
<link href="subgrid.css" rel="stylesheet" type="text/css" />
<script src="jquery-1.3.2.min.js" type="text/javascript"></script>
<script type="text/javascript">
//master: id of div element that contains the information about master data
//details: id of div element wrapping the details grid
function showhide(master, detail) {
//First child of master div is the image
var src = $(master).children()[0].src;
//Switch image from (+) to (-) or vice versa.
if (src.endsWith("plus.png"))
src = src.replace('plus.png', 'minus.png');
else
src = src.replace('minus.png', 'plus.png');
//Set new image
$(master).children()[0].src = src;
//Toggle expand/collapse
$(detail).slideToggle("normal");
}
</script>
<asp:ContentPlaceHolder ID="head" runat="server">
</asp:ContentPlaceHolder>
</head>
Here is the div that contains the showhide function in the onclick event in the aspx page:
<div class="searchgroup"
id='<%#String.Format("master{0}",Container.DataItemIndex)%>'
onclick='showhide(<%#String.Format("\"#master{0}\"",Container.DataItemIndex)%>
,
<%#String.Format("\"#detail{0}\"",Container.DataItemIndex) %>)'>
<asp:Image ID="imgCollapsible"
CssClass="first"
ImageUrl="plus.png"
Style="margin-right: 5px;"
runat="server" />
<span class="searchheader"><%#Eval("Business")%></span>
</div>
Here is html it generates for the master and detail div:
//master div
<div class="searchgroup"
id='master0'
onclick='showhide("#master0","#detail0")'>
<img id="ctl00_ContentPanel_gvMaster_ctl02_imgCollapsible"
class="first" src="plus.png"
style="border-width:0px;margin-right: 5px;" />
<span class="searchheader">ABC</span>
</div>
//details div
<div id='detail0' class="searchdetail">
<div>
<table class="searchgrid"
id="ctl00_ContentPanel_gvMaster_ctl02_gvDtails">
<tr>
<th>Status</th>
<tr class="searchrow">
<td>2</td>
</tr>
</table>
</div>
</div>
I could not get the JQuery working and I was running out of time, so for now I decided to use the collapsible panel externder from the ajax control toolkit. When I get time, I will investigate the JQuery Issue, Thanks for all your suggestions so far. If anyone has any more, please let me know.
Your javascript is throwing an error at src.endsWith("plus.png") because there is no built in endsWith function in js. replace that with src.substr(-8) == "plus.png" instead and it works:
<script type="text/javascript">
//master: id of div element that contains the information about master data
//details: id of div element wrapping the details grid
function showhide(master, detail) {
//First child of master div is the image
var src = $(master).children()[0].src;
//Switch image from (+) to (-) or vice versa.
if (src.substr(-8) == "plus.png")
src = src.replace('plus.png', 'minus.png');
else
src = src.replace('minus.png', 'plus.png');
//Set new image
$(master).children()[0].src = src;
//Toggle expand/collapse
$(detail).slideToggle("normal");
}
</script>
EDIT - Working example:
MasterPage.master
<%# Master Language="C#" AutoEventWireup="true" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title>Untitled Page</title>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js"></script>
<script type="text/javascript">
//master: id of div element that contains the information about master data
//details: id of div element wrapping the details grid
function showhide(master, detail) {
//First child of master div is the image
var src = $(master).children()[0].src;
//Switch image from (+) to (-) or vice versa.
if (src.substr(-8) == "plus.png")
src = src.replace('plus.png', 'minus.png');
else
src = src.replace('minus.png', 'plus.png');
//Set new image
$(master).children()[0].src = src;
//Toggle expand/collapse
$(detail).slideToggle("normal");
}
</script>
<asp:ContentPlaceHolder id="head" runat="server">
</asp:ContentPlaceHolder>
</head>
<body>
<form id="form1" runat="server">
<div>
<asp:ContentPlaceHolder id="ContentPlaceHolder1" runat="server">
</asp:ContentPlaceHolder>
</div>
</form>
</body>
</html>
Default2.aspx
<%# Page Language="C#" MasterPageFile="~/MasterPage.master" AutoEventWireup="true" Title="Untitled Page" %>
<asp:Content ID="Content1" ContentPlaceHolderID="head" Runat="Server">
</asp:Content>
<asp:Content ID="Content2" ContentPlaceHolderID="ContentPlaceHolder1" Runat="Server">
<div class="searchgroup" id='master0' onclick='showhide("#master0","#detail0")'>
<img id="ctl00_ContentPanel_gvMaster_ctl02_imgCollapsible" class="first" src="plus.png" style="border-width:0px;margin-right: 5px;" />
<span class="searchheader">ABC</span>
</div>
<div id='detail0' class="searchdetail">
<div>
<table class="searchgrid"
id="ctl00_ContentPanel_gvMaster_ctl02_gvDtails">
<tr>
<th>Status</th>
</tr>
<tr class="searchrow">
<td>2</td>
</tr>
</table>
</div>
</div>
</asp:Content>
" Looks like it is not even calling showhide when I click on an item." If you simplify the function with just an alert() function, does it work.
The code looks fine to me. Maybe there is some id mismatch.
You may check if jquery's path is correct in your page (that which uses this master page).
To be sure if its calling showhide() you can use Firebug in Firefox with a breakpoint in the function.
Also, it will give you more clues to debug and guess what is going wrong.
The code seems to be ok to me, too.
just a thought, if you right click view source on the browser, do you see the jquery path correctly? my experience tells me you need to resolve javascript urls on master pages (it works fine for css, but not js files)
<script src="<%= ResolveUrl("~") %>jquery-1.3.2.min.js" type="text/javascript"></script>

Categories