How can I include pages, style sheets, or links to them, automatically into my ASP VBscript pages? I read something about 'global' pages, but I am unsure what they mean and how it is that I can accomplish such a thing. I'm sure this is an easy question, but it's of great help to me as I've been writing VBscript for 2 days now! I'm not exactly an expert on HTML in general either, but I feel I have a reasonably good grasp of things. I would appreciate a good detailed example of how a 'global' page plays with my other ASP pages.
I'm setting up my first site...a management site for the main site I intend to build afterward. I want to get all my ducks in a row before moving forward with the public site. Can someone please give me some detailed information on how to include these pages/links automatically (page includes(header/footer), style sheets, etc) globally throughout my site without the need of using <!--#include file.... on each page I make, because that is kind of a pain and I'm sure there is an easier way. If there is, I know you can help! Thanks in advance, I look forward to hearing what options/possibilities are available.
If you insist on using ASP Classic you may find some method for handling masterpage like functionality but it is, to the best of my knowledge, not suppoerted as such by the framework.
[Edit] Given the edit of the original question the method first demonstrated is not so interesting, hence I suggest an alternative method too.
You could make a general ASP-page which serves all traffic to the site. A queryparameter then specifies which subpage should be displayed. Subpages are made as seperate ASP-pages which are executed by the general/master page or by another subpage. A very crude example of this could look like this:
<%
url = Request.QueryString("url") & ""
if url = "/" or url = "" then
subpage = "home.asp"
else
subpage = url & ".asp"
end if
%>
<!DOCTYPE html>
<html>
<head>
<title>Header for all pages</title>
<link rel="stylesheet" href="/css/site.css" />
</head>
<body>
<% Server.Execute(subpage) %>
</body>
</html>
The site should then be addressed in this fashion:
www.domain.com/default.asp?url=/contact
which would load the contact.asp subpage into the masterpage or:
www.domain.com/default.asp?url=/user/1234/profile
to load a user's profilepage (displayed by the profile.asp in the folder user/1234). This last example raises some issues because then every user has to have a folder containing all the asp-files (which is far from optimal) so you might want to employ some interpretation of the url queryparameter to redirect input in a more intelligent way.
Another issue is the fact that subpages are ASP-pages themselves which means someone could reference them directly. This calls for some action to protect those subpages from direct reference. It can be done but this would probably mean including some code => back to square one!
Another disadvantages of this approach is that subpages are rendered in their own context and hence can't access functionality and data from the calling page's context. This means that global data has to be shared in some other way (session, application, database or some other way). Data can't be passed to the subpage either (and no, Server.Execute doesn't allow query-parameters).
The include-way
Personally I think you get the most flexibility by using header/footer includes as demonstrated in my original post and shown below.
One way is to put your general stuff in includes and then includes those bits on each ASP-page. E.g.:
<!-- #include virtual="/includes/header.asp" -->
content goes here
<!-- #include virtual="/includes/footer.asp" -->
And your header.asp could look something like this:
<!DOCTYPE html>
<html>
<head>
<title>Header for all pages</title>
<link rel="stylesheet" href="/css/site.css" />
</head>
<body>
and footer.asp like so:
</body>
</html>
This strategy has some disadvantages. The header is fairly static which could present some problems with SEO; For one the title should fit the pagecontent which is hard to accomplish when the include contains the header-markup. This could be facilitated by some global variables that are set prior to the include-section i.e.:
<%
title = "Title for this page's content"
%>
<!-- #include virtual="/includes/header.asp" -->
content goes here
<!-- #include virtual="/includes/footer.asp" -->
and then in the header like so
<!DOCTYPE html>
<html>
<head>
<title><%=title%></title>
<link rel="stylesheet" href="/css/site.css" />
</head>
<body>
but that already begins to "smell" a little because you set up some expectations for the including page inside the include-file. At least you have to be very disciplined when constructing your pages.
The term you're looking for is Master Page, not Global Page, that may be why you're having a hard time finding what you're looking for on Google. Basically consider a master page a template. You create a master page, then load other pages into it. There are content place holders that you put in the master then populate on your other pages.
So a very basic example would look something like this.
<%# Master Language="VB" CodeFile="general.master.vb" Inherits="master1_general"%>
<!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 id="Head1" runat="server">
<link rel="stylesheet" type="text/css" href="/styles/main.css?v2"/>
<asp:ContentPlaceHolder id="head" runat="server">
</asp:ContentPlaceHolder>
</head>
<body>
<form id="form1" runat="server">
<asp:ContentPlaceHolder id="body" runat="server">
</asp:ContentPlaceHolder>
</form>
</body>
</html>
Then your individual pages would look like this:
<%# Page Language="VB" MasterPageFile="~/master/general.master" AutoEventWireup="false" CodeFile="base.aspx.vb" Inherits="_Default" title="Opportunities" %>
<asp:Content ID="Content1" ContentPlaceHolderID="head" Runat="Server">
//any additional head stuff specific to this page goes here.
</asp:Content>
<asp:Content ID="Content2" ContentPlaceHolderID="body" Runat="Server" >
//your body mark up goes here.
</asp:Content>
Notice how the Master page is actually a web page. Then it has place holders in certain spots. In this one there is a place holder in the head and one in the body. Then on individual pages I identify which master page to use and what data (if any) goes in the place holders. I always include a placeholder in the head so I can load js or resources that specific pages need on that page only.
Then the individual pages are just the content that goes in the placeholders.
Related
Every page in my ASP.NET application is based on Main masterpage, which in its turn is based on another Base masterpage (nested masterpages). I try to set different title for every page. I tried two approaches, but it does not work without any obvious reason.
1st attempt: <%# Page Title="ABC" ....... %>. I do not know why, but it does nothing. No <title> tag is generated in resulting HTML.
2nd attempt: <%# Page meta:resourcekey="PageTitle" ....... %> and PageTitle.Title to .resx. Same here. No <title> tag at all.
What did I miss?
I discovered the reason: looong time ago I removed runat="server" from my <head> tag. When I add it back - the Title directive starts to work, but it breaks other functionality, like <link rel="stylesheet" type="text/css" href="/css/<%= www.Utils.LanguageName %>/language14.css" />.
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.
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.
I'm attempting to precompile a few master pages (not update-able) to share them across multiple applications. The project I'm precompiling is a Web Site. The project that references precompiled assemblies is a Web Application. However, I'm getting a Could not load type 'ASP.xxx_master' every time i try to reference the master page from the client.
<%# Master Language="C#" Inherits="ASP.sitebase_master" %>
My precompiled master page looks like this.
<%# Master Language="C#" ClientIDMode="Static" %>
<!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 id="AspNetHead" runat="server">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<!--[if IE]><meta http-equiv="X-UA-Compatible" content="IE=7" /><![endif]-->
<asp:ContentPlaceHolder ID="MetaContent" runat="server" />
<title>Web Portal</title>
<link href="/media/css/style.css" rel="stylesheet" type="text/css" />
<link href="/media/js/plugins/colorbox/colorbox.css" rel="stylesheet" type="text/css" />
<asp:ContentPlaceHolder ID="StyleContent" runat="server" />
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.5.1/jquery.min.js" type="text/javascript" language="javascript"></script>
<script src="/media/js/plugins/colorbox/jquery.colorbox-min.js" type="text/javascript" language="javascript"></script>
<script src="/media/js/plugins/filestyle/jquery.filestyle.min.js" type="text/javascript" language="javascript"></script>
<script src="/media/js/portal.master.js" type="text/javascript" language="javascript"></script>
<script language="javascript" type="text/javascript">
PORTAL.debug.init();
PORTAL.init();
</script>
<asp:ContentPlaceHolder ID="ScriptContent" runat="server" />
</head>
<body>
<div id="hld">
<div class="wrapper">
<form id="AspNetForm" runat="server">
<asp:ContentPlaceHolder ID="BodyContent" runat="server" />
</form>
<asp:ContentPlaceHolder ID="FooterContent" runat="server" />
</div>
</div>
</body>
I'm stumped. No idea why the type isn't resolved. Anybody got suggestions? Both projects (precompiled web site and client web application) are built for ASP.NET 4.0.
EDIT: Here is the list of dependencies of the precompiled assembly. No 3rd party references.
mscorlib,
System,
System.Web
UDPATE 1
Well, the quick fix to this issue is to specify the full path to the master page.
<%# Master Language="C#" Inherits="ASP.sitebase_master, App_Web_sitebase.master.cdcab7d2" %>
After doing that, I'm receiving the following error:
An error occurred while try to load the string resources (FindResource failed with error -2147023083).
After doing some research, this appears to be related to the way HTML markup is parsed within the master page. Not entirely sure yet. I haven't dug much deeper into it. Overall, I can't believe this is the recommended way to share controls as it is absolutely, mindbogglingly idiotic.
UPDATE 2
I couldn't make anything of value out of this. It appears to be hating "script" tags in the head section, but I don't know why. The Master Page works great with a single script include. As soon as i start adding more I keep getting that error. After wasting a full day on this I ended up submitting a bug report to Microsoft. If anyone wants to bump it, please do.
UPDATE 3
I spent a few more days debugging this after no response from MS. Here is my findings. I initially thought that the code generated by CodeDOM provider is looking for a .NET resource that somehow did not get embedded in the assembly when it was published. I was wrong. After some investigation it appears that what's happening is after the Master Page reaches a certain size, a chunk of it is stored in the Resource Table in PE Data Directories section of the assembly. In fact, after looking at the generated assembly in PE resource viewer, i was able to confirm this by finding all my script includes in the Resource Table. Now, here is the actual problem. What's happening is that the CodeDOM provider generates a call to Win32 FindResource to pull that resource from the Resource Table. However, FindResource doesn't work on assemblies in memory, only on disk. So it fails with the above exception. I'm getting close, but still no workaround.
I finally have a workaround. It's not pretty, but it resolves the issue. Apparently using LoadControl to pre-load precompiled MasterPages loads all of the resources that FindResource cannot find otherwise. So, here is all i did to make this work.
In my client application I created a dummy master page (i.e. Dummy.Master) which references my precompiled master page like so:
<%# Master Language="C#" Inherits="ASP.sitebase_master, App_Web_sitebase.master.cdcab7d2" %>
Now, any .aspx page which references Dummy.Master needs to preload the precompiled MasterPage type like so:
protected override void OnPreInit(EventArgs e)
{
ASP.sitebase_master mp = (ASP.sitebase_master)Page.LoadControl(typeof(ASP.sitebase_master), null);
base.OnPreInit(e);
}
I don't know why this works, but it does. This code must run before the MasterPage is resolved, so PreInit worked great. After glancing at the .NET code for a few seconds in Reflector, it appears that LoadControl actually does some assembly compiling voodoo when it attempts to load a certain control type. So perhaps something in there loads that PE resource data section. The best place to put it would be in the base class I suppose which all pages could inherit from. Also, each loaded control (master page in this case) ought to be cached. Here is a good article explaining just that.
Hopefully this helps someone as much as it helped me. It was a pretty big show stopper for me.
I have inherited an ASP.net codebase and I have very limited ASP.net skills. I am struggling to understand why something works and also why it only works in IE.
The following code appears in a page :-
<%# Page Language="C#" AutoEventWireup="true" CodeFile="map.aspx.cs" Inherits="Romtrac.auth_map" Culture="auto" UICulture="auto" %>
<!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 id="Head1" runat="server">
<title>
<% = Resources.Resource.map %>
</title>
</head>
<body>
<form id="adminlw_map_form" action="<%=geturl()%>" method="post" >
<% = Resources.Resource.loading %>...
<textarea name="xml" id="xml" runat="server" style="display:none" cols="1" rows="1"></textarea>
</form>
<script language="javascript" type="text/javascript" >
//submit main form immediately
document.getElementById('adminlw_map_form').submit();
</script>
</body>
</html>
This code runs fine in ASP.net. The form is automatically submitted and the page returned is rendered correctly within an Iframe. My question is;
1) Does the javascript within the body just get executed when it is encountered? Is this good practice or should it be executed in response to an event?
2) Why does this not work in other browsers?
Yes
The javascript is being executed before the browser has fully rendered the page. In this case, the form has not been rendered and is not accessible via the DOM.
The execution needs to happen after the DOM is fully loaded by the browser and can be implemented by encapsulating the call within a function and calling that function via the onload event of the body or by using a javascript library like jquery to hook into the load event of the page.
1) Yes, No. jQuery does it best with it's $(document).ready() function, but you should wait for the page to finish loading before running Javascript.
2) Do #1 and you won't need to worry about this. However I'll leave the floor open to someone with a better answer.
Some browsers prevent the submission of a form without user interaction in the page's load 9it's a security risk). I've had this issue a number of times in the past. I would combine the page's load, with a window.setTimeout of say 100ms.
<body onload="window.setTimeout( document.getElementById('adminlw_map_form').submit, 100)">
....
Remember when using JavaScript to keep it unobtrusive. There are still people out there who have JS switched off and your page should not really on it. It should serve as an enhancement.
Same as Mike Robinson's answer but surely you can just use <body onload="myfunction();">?