Understanding the runat server attribute - asp.net

I'm really new to ASP.NET. I was just checking out a default ASP.NET web application. It comes by default with a few pages (Default.aspx, About.aspx etc).
I noticed that the Site.master file is the file where i create the main layout for my pages.
But i also noticed that the head tag has a runat="server" attribute.
I know this tag is used in <asp:XXX> tags, but why in a <head> tag???
Also, when i remove that attribute, then all of the styles are gone from the webpage. So appearently it's doing something. I just don't understand what its exactly doing...
So why is it there, on an HTML tag...??? I don't see any code in there that should be run on the server...
<head runat="server">
<title>Hallo</title>
<link href="~/Styles/Site.css" rel="stylesheet" type="text/css" />
<!-- This part is run on the server. So why does the head tag
also need a runat=server ?? -->
<asp:ContentPlaceHolder ID="HeadContent" runat="server">
</asp:ContentPlaceHolder>
</head>

You asked why the styles are not applied anymore when removing the runat="server" from the<head> element.
It is simple: by running on the server side, the parser will replace the ~/ from the stylesheet declaration <link href="~/Styles/Site.css" rel="stylesheet" type="text/css" /> with the root path of the application.
The ~ is illegal in a URL. Thus, if this is not replaced by the parser, the file will not be found thus the stylesheet will not be applied.
Oh, btw, setting the runat="server" attribute on the <head> element will force all its sub-elements to be run on the server, thus why the <link> element is run on the server.

The head element contains a runat="server" attribute, which indicates that it is a server control (rather than static HTML). All ASP.NET pages derive from the Page class, which is located in the System.Web.UI namespace. This class contains a Header property that provides access to the page's region. Using the Header property we can set an ASP.NET page's title or add additional markup to the rendered section. It is possible, then, to customize a content page's element by writing a bit of code in the page's Page_Load event handler.
' Programmatically add a <meta> element to the Header
Dim keywords As New HtmlMeta()
keywords.Name = "keywords"
keywords.Content = "master page,asp.net,tutorial"
Page.Header.Controls.Add(keywords)
For more info see Specifying Meta Tags in ASP.NET with VB.NET.

The runat="server" tag in ASP.NET allows the ability to convert/treat most any HTML element as a server-side control that you can manipulate via code at generation time. Some controls have explicit implementations, others simply revert to a generic control implementation.

The runat attribute basically tells ASP.Net that it needs to parse the element, its attributes and it's contents as a server control. Enabling code, on the server, to be executed to configure the response.
Without it, any child controls contained within the <head> section will not get parsed. So, any dynamic header includes, title manipulations or any other server-controls will not be interpreted.

Related

how to link separate css files to aspx files

I've inherited an .net 4 aspx solution and I need to make a number of changes. All the styles in the main seem to be set in-line. So to make it a bit more maintainable I'm trying to create seperate css files for each aspx file. This may seem overkill, but it's a first stage of gradually moving over to .net core.
Ordinarily I'd simply do something like:
<asp:Content......
<link href="myStyleSheet"....
</asp:Content>
but the link statement causes an error stating that it cannot be nested within a td element. Placing it outside the content block also errors stating that Content is not supported outside the content block.
How should I reference my stylesheets on an individual basis without placing a reference to them all in the <head> section of the master page?
the link statement causes an error stating that it cannot be nested within a td element
Well, that's true. You don't put <link> elements inside a table. According to MDN they can go in "Any element that accepts metadata elements." <td> definitely is not such an element. <head> certainly is, and is probably the safest place to put these.
In your master page you can add a ContentPlaceHolder in the <head>:
<head runat="server">
<title>Your page title</title>
<!-- etc. -->
<asp:contentplaceholder id="HeaderPlaceholder" runat="server" />
</head>
Then in the individual pages put the <link> elements in a Content control for that placeholder:
<asp:Content ID="ContentHeader" ContentPlaceHolderID="HeaderPlaceholder" runat="server">
<link href="myStyleSheet" etc... />
</asp:Content>
This may seem overkill
Ya, it kinda does. Why a separate stylesheet for each page? Seems like it would make more sense to have one stylesheet for the site. For any styling that needs to target only a specific page and nothing else, some wrapper element around that page's content (such as a <div>) with a specific id will make that easy.

Referencing favicon from inside folder using ASP.Net master page and themes

I have the following situation on my new ASP.Net page:
I am using a master page
I am using themes
I have pages in separate folders
I need to reference a favicon from my master page based on the current theme.
Unfortunately the ~App_Themes/Basic/Images/favicon.ico path resolves to http://example.com/folder/App_Themes/Basic/Images/favicon.ico.
How can I uniformly refer to my favicon.ico located in the App_Themes/Basic/Images/favicon.ico path from master page used by the following differently located pages:
~/Home.aspx
~/Secure/Dashboard.aspx
~/Accounts/Login.aspx
Usually ASP.NET themes are limited to skin files and CSS files with all images referenced from the CSS file. In that scenario, the paths to images are relative from the CSS file.
If you need a path to a file inside the current theme's folder relative from a page, you can use the Page.Theme property combined with the Page.ResolveUrl() method:
<%= Page.ResolveUrl(String.Format("~/App_Themes/{0}/Images/favicon.ico", Page.Theme)) %>
If you want to use that in a <link rel="shortcut icon"> element you can just put the code above inside the href attribute. Unless you have a <head runat="server">, in which case ASP.NET may throw an HttpException:
The Controls collection cannot be modified because the control
contains code blocks (i.e. <% ... %>).
This can be fixed by putting the <link> element inside an <asp:PlaceHolder> control:
<head runat="server">
<asp:PlaceHolder runat="server">
<link rel="shortcut icon" href="<%= ... %>" />
</asp:PlaceHolder>
</head>

Implementing CSS as a variable in the site.master page in ASP.NET MVC3

I am implementing a web application using ASP.NET MVC3. In the application I want to add the option of switching between CSS files (for themes) based on clicking some links. I did some research and I came up with the following:
To pass data to site.master, the good solution is to create an abstract controller and inherit that into the other controllers that have site.master as their template, according to this article: Passing Data to View Master Pages
I can pass a viewbag message to the link which controls the css file URL to set the current css file to use, based on the code that I am seeing being passed to scripts at the top of the site.master page:
script src="<%: Url.Content("~/Scripts/jquery-1.5.1.min.js") %>" type="text/javascript"
So I created an abstract controller, ApplicationController, with the following method:
public ApplicationController()
{ViewBag.NewMessage = "../../Content/Site2.css";}
And in the site.master, I included this link:
<link href="<%: (string) ViewBag.NewMessage %>" rel="stylesheet" type="text/css" />
However, that doesn't seem to be working, as it is being interpreted as:
<link href="<%: (string) ViewBag.NewMessage %>" rel="stylesheet" type="text/css" />
And only when I remove the quotation marks:
<link href=<%: (string) ViewBag.NewMessage %> rel="stylesheet" type="text/css" />
is it being interpreted correctly (and the webpage gets rendered with the correct css), except that it violates html standards:
<link href=../../Content/Site2.css rel="stylesheet" type="text/css" />
Any suggestion about how to go tackling this problem or is there a more elegant solution I'm missing? I was going to proceed and implement variables in the ApplicationController that get selected based on links the user clicks at the top of the page, to switch between css styles.
Thank you!
Check to make sure your <head> tag does not have runat="server".
After making this change, be sure to check your script and css tags. This change can break the paths if you use the ~/ to ref app root. To help with this, use the Url.Content(...) helper.

asp.net derived master pages, page titles and dynamic css links

Not sure if the derived page is actually relevant to the problem here, but ran into an interesting gotcha on some code I'm working through at the moment.
I have a custom masterpage class, which derives from System.Web.UI.MasterPage so that it can be extended with additional useful properties.
The page that that uses this masterpage has a declaration at the top (note the Page Title being set).
<%# Page Language="C#" MasterPageFile="~/MasterPages/Landing.master" AutoEventWireup="true" CodeFile="Index.aspx.cs" Inherits="Index" Title="Welcome to the site" %>
In addition, the master page has stylesheet references in the head which are pulled from a CDN that is defined in a config file.
<head id="Head1" runat="server">
<link rel="stylesheet" type="text/css" href="<%= CDN %>/css/main.css" />
</head>
Now the example above obviously doesn't work, because the runat attribute in the head container means that the codeblock in the the link is static text, and renders as is, in the resulting html.
If I remove the runat attribute from head, the CDN works, but now I notice that the Title is no longer being set. If I debug, and try to access Page.Title in the Immediate Window, I get an exception:
// Using the Title property of Page requires a header control on the page. (e.g. <head runat="server" />).
So, is there a way to get the Page Title from the declaration, put my own title placeholder in the head and set it from the master page code-behind, or, is there a better way to dynamically set the CDN domain for the stylesheets? The only way I think I can do that is to build the entire html link tag(s) and append it to the header control, but I thought there might be a more elegant solution, so I'm asking here first.
Insofar as the CDN goes, we build a special Url.ResolveContentUrl() method that spoke with our configuration and pointed at the correct stylesheets (and any other static asset) depending on running mode, etc. So your dev and QA work locally then your production goes to the CDN with zero code changes.
Also, you should put a content placeholder into the part of the masterpage. It is the only way to fly.
In your masterpage, you can create a routine like this:
Public Sub AddStyleSheetLink(ByVal fileName As String, Optional ByVal media As String = "all")
Dim stylesheetLink As New HtmlLink
With stylesheetLink
.Attributes("href") = fileName
.Attributes("type") = "text/css"
.Attributes("rel") = "stylesheet"
.Attributes("media") = media
End With
MasterHeader.Controls.Add(stylesheetLink)
End Sub
And in your Page_Init (the page that inherits your masterpage), so something like this
CType(Master, MasterPage).AddStyleSheetLink(CND & "/css/main.css")
You can dynamically add what you need without messing with your <head> tags and page title.

Usercontrol access Javascript from a Content's Page's Master Page

Hello all I have a problem. I have a masterpage that all of my Content pages inherit from. Within this masterpage I have a script tag pointing to the Javascript file folder ~/Scripts/validation.js
On my content pages I use different usercontrols that require the use of many of the functions within the validation.js file however if I dont put the <script> tag and the Javascript functions within a contentholder on the contentpage the usercontrols do not see these functions and I get errors like OnNameValidation is not defined.
Of course I can copy the Javascript code into all of the pages but that's 30+ pages and a maintenance nightmare if I find a bug in one of the Javascript functions.
So the question (if you haven't already figured out from my long dissertation) is how can I declare the script tag with the path to the validation.js file so that contentpages and their usercontrols etc. can access the functions/code.
What you are trying to do should work, so I suspect that the path to your javascript file is wrong (without seeing your html code I can only assume). Keep in mind that you can only reference the javascript file like this: "~/Scripts/validation.js" if you have the link in a HEAD runat="server" tag. Without the runat="server" it won't find the file. You would have to do something like "../scripts/validation.js"
As a test I would try to call your javascript function in the masterpage, so you can rule out a bad file reference.
I picked up this tip from ScottGu here.
Add this to you user control which enables Intellisense in user controls but always evaluates false:
<% if (false) { %>
<script src="/Scripts/validation.js" type="text/javascript"></script>
<% } %>
I am currently doing this in my site by going to the Source code on the master page and putting the following in the head and outside of the ContentPlaceHolder.
<head>
<asp:ContentPlaceHolder ID="HeadContent" runat="server">
</asp:ContentPlaceHolder>
<script src="CP.js" type="text/javascript"></script>
</head>
The path you are assigning for your js file is probably not matching in all the pages.
script src="../JavaScript/Scriptaculous/scriptaculous.js"
It should have something like above this if you have separate folder for Scripts, MasterPages, Pages & Controls.

Resources