how to link separate css files to aspx files - asp.net

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.

Related

master and content pages

I have a master page and two content pages that uses the master page for layout and design. I have 2 css files for my master page. Now what I want to do is that when I run first content page master page uses the first css file and when I run the second content page it uses the other one. Any suggestions about how should I do this .
First off, this should not be your normal approach unless you are doing something unusual. The whole point of using a common master page is so that you can easily have a common look and feel across your website.
But you can do it a few ways. One way would be to put a placeholder in your master pages <head> section. Then create content for that placeholder in each content page that includes the appropriate css file.
You can use a ContentPlaceHolder in the master page, and inside the head to change the css differently on every next page, or just ignore it to keep some default.
Here is an example:
<head runat="server">
<asp:ContentPlaceHolder ID="styleHolder" runat="server" >
<link rel="stylesheet" type="text/css" href="default.css">
</asp:ContentPlaceHolder>
</head>
<body>
and inside on the page with the different css, just include the the PlaceHolder and change it.

How to have a default title for a web page?

It seems straightforward enough, and testing it, it actually works:
<title>Default text</title>
In the Masterpage. And:
<%# Page Title="Specific name"...
in the specific page. Or in its codebehind:
Title = "Specific name";
So why am I asking? Because searching for it I've found all sorts of more complicated methods for doing that. (Yes. In Asp.net.)
So is there any drawback to the way I wrote above?
Not sure what you've found but that's how it is normally done.
Master page has the default, with overrides from specific pages.
An alternative (and I'm not specifying it's better) is to use a Content Placeholder.
On Master Page
<title>
<asp:ContentPlaceHolder id="PageTitle" runat="server">Default Title</asp:ContentPlaceHolder>
</title>
On specific page
<asp:Content ContentPlaceHolderID="PageTitle" runat="server">Specific Title</asp:Content>
But the drawback is that it's not as easy to set the title from code-behind.
What you have to know here that the <title></title> can not change from the code behind, or from the page declaration if is NOT inside the header with runat="server" So only if you have like that :
<head runat="server">
<title>Default Title</title>
</head>
you can have it as default, and then change it on pages. If the head is not runat="server" then the code behind can not find it to change it and the default title is shown.
All the rest stands as they are, I also use the same way, a default title on the master page, that I change it from the page if I can, or if not the default title is shown.

Understanding the runat server attribute

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.

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