Is there an easier way to do Classic ASP "relative path"? - asp-classic

Right now, I'm having trouble.
First of all I have a page, let's call it "http://blah.com/login".
That obviously goes strait to "index.asp"
A line of Main.asp:
<!--#include file="resource/menu.asp"-->
Page top includes all of what I need for my menu... so:
Part of resource/menu.htm:
<div id="colortab" class="ddcolortabs">
<ul>
<li><span>Main</span></li>
...
</ul>
</div>
<!--Main drop down menu -->
<div id="dropmain" class="dropmenudiv_a">
Announcements
Contact Information
Meeting Plan
Photo Gallery
Upcoming Events
</div>
Let's say I click on the "announcements" (http://blah.com/login/main/announcements.asp) link... Now I'm at the announcements page!
But wait, I include the same menu file. Guess what happens:
I get sent to "http://blah.com/login/main/main/announcements.asp
Which doesn't exist...
My solution:
Make a menu_sub.asp include for any subpages.
But wait a second... this WORKS, but it gets REALLY REALLY messy... What can I do to use just one main "menu.asp" instead of "menu_sub.asp"? using "/main/announcements.asp" WON'T be an option because this is a web application that will be on different directories per server.

There is no magic bullet fix. Here is how I would do this.
Create a separate include file that DIM's and Initializes global variables called info.asp
Inside info.asp DIM a variable called strRelativePath and initialize it to ""
Include info.asp at the top of each asp page above the menu.asp include
Modify menu.asp and include <%=strRelativePath%> in all the urls
Inside each asp page set strRelativePath as necessary:
<!--#include file="includes/info.asp"-->
strRelativePath = "Login/"
<!--#include file="resource/menu.asp"-->

Add this function to your menu.asp:
Function GetApplicationPath()
GetApplicationPath = Mid(Request.ServerVariables("APPL_MD_PATH"), Len(Request.ServerVariables("INSTANCE_META_PATH")) + 6) & "/"
End Function
Dim prefix: prefix = GetApplicationPath()
Now structure your references in the menu.asp using:
Announcements
This will make these references absolute but they will vary appropriately with whatever virtual folder path the website has your ASP application installed under.

There is a similar question here where the highest rated answer states that you can find the root with the following function:
Function ToRootedVirtual(relativePath)
Dim applicationMetaPath : applicationMetaPath = Request.ServerVariables("APPL_MD_PATH")
Dim instanceMetaPath : instanceMetaPath = Request.ServerVariables("INSTANCE_META_PATH")
Dim rootPath : rootPath = Mid(applicationMetaPath, Len(instanceMetaPath) + Len("/ROOT/"))
ToRootedVirtual = rootPath + relativePath
End Function
You can then call it:
ToRootedVirtual("/")
or
ToRootedVirtual("/index.asp")
etc. to return the root from the server.

You can use Virtual instead of File because Virtual accepts an absolute path from the root directory, not relative like File.
Like this:
<!--#INCLUDE VIRTUAL="/resource/menu.asp"-->
Also, make sure your IIS settings allow Includes, See this link for details:
http://tech.mikeal.com/blog1.php/server-side-includes-for-html-in-iis7

This can be fixed with the HTML base tag:
Add this tag in the beginning of each page:
<base href="http://blah.com/login">

Related

Kentico NodeName as a body class?

I'm trying to identify the home page, and then sub-pages on nodes. Ideally as a class on the Body so i can make style changes based on which section the user is in.
I have two .master pages, Global and Site. The body tag is in Global, and Site is a child master.
As this is an English/French site, I'm hoping using the Node Name would be the easiest approach for me.
If your home page and internal pages are of different Page Type then you can benefit from the macro below. We use something like this to give Page type specific id on the body tag and is usually helpful
<body class="{% CurrentDocument.NodeClass.ClassName.ToString() #%}">
However, it can be tweaked to suit your needs.
I'd recommend you to implement one generic stylesheet, shared across all the pages, and a couple of section specific stylesheets.
I'm not 100% clear about what you are describing, but you could use NodeLevel direct as / is NodeLevel = 0, and everything else will be Level 1+
Here's what i've come up in the .cs of my global .Master. So far it seem to be giving me enough to work with. From here i can use js and css to target what i need.
string aliasPath = CMS.DocumentEngine.DocumentContext.OriginalAliasPath.ToLower().TrimStart('/');
if (aliasPath == "")
{
this.BodyClass += " home";
}
else
{
this.BodyClass += " " + aliasPath.Replace("/","_");
}
The simplest approach, if you are willing to add either a data attribute or an id attribute to the body tag, is to add something like this to the master page, in the text box of the body tag:
id="{%nodealias%}"
Since the node alias will typically be unique unless you have multiple pages, at different paths, with the same name, ID should work fine. I prefer to use "nodealias" as opposed to the friendly name because it ensures there will not be any special characters, and will replace white space etc with a dash "-". The above macro will add the node alias as an id attribute to the body tag. Here's a screenshot:
Alternative approach explained here: https://devnet.kentico.com/forums/f49/t43559/body-class which involves setting the body class using a combination of macros and code behind, or via a custom web part. Basically you can modify it using CMS.CMSHelper.CMSContext.CurrentBodyClass (this was written in 2014 so the syntax will be slightly different)
-Edit:
Adding to some of the other answers, if you'd rather add a stylesheet on a template or page level, you can do so. To add a stylesheet reference on every instance of a template, edit the template header properties:
If you want to include the stylesheet on any particular page, this can be accomplished by editing the General tab on the page level, but this will remove the main stylesheet you are using (depending on how you are including it in the page):
In the body section in the Master page you can start with
<script runat="server">
protected void Page_Load(object sender, EventArgs e)
{
if(CurrentDocument.DocumentName== "Site")
CMS.DocumentEngine.DocumentContext.CurrentBodyClass += "body-site";
else
CMS.DocumentEngine.DocumentContext.CurrentBodyClass += "body-global";
}
</script>

Setting file location of PIE.htc

I created another folder for my pie.htc..but when I load my html file in IE8 it does not work..i already tried setting different location to its behavior but still it wont work..
here's my code..
behavior: url(/pie/PIE.htc);
As others have noted elsewhere, and as documented here http://css3pie.com/documentation/known-issues/, the PIE.htc file location must be relative to the page where it's used, not relative to the css file. If you'll need to use PIE from within several different pages, consider adding a reference to it dynamically.
Here's how we handled it in a C# .Net application with a master page:
In the master page's markup between the head tags, place the following line:
<style id="InlinePageStyles" runat="server" type="text/css"></style>
In the Page_Load method of the master page's code behind, place the following line:
//get path to PIE.htc and add it to the page as a style (creates a class called Pie)
InlinePageStyles.InnerHtml += string.Format(".Pie {{ behavior: url({0}PIE.htc); }}", ConvertRelativeUrlToAbsoluteUrl(this.Request, ResolveUrl("~/")));
Also in the code behind, add this method:
private string ConvertRelativeUrlToAbsoluteUrl(HttpRequest request, string relativeUrl)
{
return string.Format("http{2}://{0}{1}", request.Url.Host, System.Web.VirtualPathUtility.ToAbsolute(relativeUrl), request.IsSecureConnection ? "s" : string.Empty);
}
Next, remove the behavior from your CSS.
Finally, add the "Pie" class to any page elements that need it.
Hope this helps.
behavior: url(../pie/PIE.htc);
".." for folder selection and pie is the folder
...............................
HI now put your pie.htc in root location and
write to css as like this
behavior: url(PIE.htc);
more info

Use Respnse.WriteFile instead of user control

I have a large html file that I want to split apart. I have managed to split it apart and place each part in a htm file. As a result my structure now looks like:
note all the files in the folder are just specific to the Default.aspx page. I like to have my code spitted into several parts; I find it easier to program that way.
Anyways why when I do:
<%
Response.WriteFile("_Menu.htm");
%>
that creates a different output that if I where to go to _Menu.htm copying the entire content and pasting it in there? I know I can create a user control for each file. but if I do so I will have to create a page directive at the root of the page for each file and plus I just need to place static content I don't need to call an aspx page. Why does Response.WriteFile include stuff that I don't have in the file. For example it places '"' marks whenever I have a paragraph.
EDIT
I use user controls when I plan to reuse html. In this case I am just spliting apart a page into several ones. I will like to have the content of each chunk in a separate file.
EDIT 2
Doing:
<%
//Response.WriteFile("_Menu.htm");
Response.Write(System.IO.File.ReadAllText(#"A:\Users\Antonio\Dropbox\VisualStudio Projects\Websites\Boat\Boat\MasterPages\User\_Menu.htm"));
%>
works great. why is Response.WriteFile including " (paragraph) " at the the beginning!?
create your Response.Write method:
Create the following extension method globaly so all your pages can access it:
using System.Web.UI;
public static class StaticExtensionMethods
{
public static void Include(this System.Web.UI.Page Page, string path)
{
Page.Response.Write(System.IO.File.ReadAllText(Page.Server.MapPath(path)));
}
}
then do:
<%
this.Include("_Menu.htm");
%>

ASP.NET Theming Programmatically: Image Paths

We have a multilingual site, or culture-sensitive, and some of the static content now needs to be targeted; for this I'm using themes as it seems the easiest way to achieve what I want, but I can't for the life of me get the images to pick up.
I'm setting the theme in code-behind, and thought at first that maybe this was the issue, but on checking up it looks like I'm doing the right thing (setting on Pre-Init).
I expect to be able to reference images using relative paths where App_Themes/ThemeName/ is automatically resolved, such as:
<asp:Image runat="server" ImageUrl="images\image.jpg"/>
For whatever reason, however, the image isn't being pulled through at all.
This is the code we have in place for setting the theme (the only really relevant part, I'm sure, being the Theme = CurrentSite.CultureName, which is applied successfully):
Private Sub SetTheme()
Dim themesPath = Server.MapPath("~/App_Themes")
If Directory.Exists(themesPath) Then
Dim themePaths = Directory.GetDirectories(themesPath)
Dim themePathInfo As DirectoryInfo
For Each _path In themePaths
themePathInfo = New DirectoryInfo(_path)
If Not themePathInfo Is Nothing Then
If themePathInfo.Name = CurrentSite.CultureName Then
Theme = CurrentSite.CultureName
Exit For
End If
End If
Next
End If
End Sub
In the above code, CurrentSite.CultureName would be a language culture name (for example, en-gb, or nn-no) that does have an existing corresponding theme folder containing all required resources.
Pages do have EnableTheming set to True. Also, I have tried removing the theme-setting code and applying the theme in the page using Theme="en-gb" to no avail.
Is there anything immediately evident as to why the URLs aren't resolved?
Use a Skin file to do this. Change your Image tag to:
<asp:Image runat="server" SkinID="SomeImage/>
And in your App_Themes\MyTheme\ folder, add a new Skin file (MyTheme.skin) and add this:
<asp:Image runat="server" SkinID="SomeImage" ImageUrl="images\image.jpg"/>
This image skin now points to image.jpg within the App_Themes\MyTheme\ folder.
For dynamic images you can do this in your BasePage (assuming you have one):
public string ThemePath { get { return "~/App_Themes/" + this.Theme + "/"; } }
public string MapThemePath(string relativePath)
{
return string.Format("{0}{1}", this.ThemePath, relativePath);
}
But, since I can't see what you're actually doing, I can't say this is the recommended solution. In general your theme contains only things needed or layout and display. You're talking about dynamic images which, to me, doesn't sound like it belongs in a theme? Not sure, just a thought.

Can I export generated html pages from ASP.NET website through Visual Studio?

My friend uses Visual Studio to develop websites in ASP.NET. She only uses the Master Page facility, other than that it's 100% normal HTML and CSS.
Is there a way to export the website to HTML pages based upon their master pages?
If not, it's either loading each page manually and saving the HTML, or I write a little app that does it.
Alternatively, does anyone know of a tool to achieve something similar?
Visual Studio doesn't have this ability out of the box. However, it should be possible to write a tool that walks through a site map, captures the rendered html from the response object, and then write it to a file.
I do not really know how to export an entire site to a local copy.
There are however tool - website downloaders. I know of one - TeleportPro, there should be others. Check them out if it sound as an option to you.
You could give Macromedia Dreamweaver a shot if you feel like experimenting. It caters for Client-side and Server-side page development.
When using MasterPages, the content of the MasterPage is merged with the content page on the server-side (either at pre-compile or the page's first request). So you need to have the content pages and MasterPage compile via aspnet_compile at some point. See the "Runtime Behavior" section of this MSDN article.
Your friend may want to use old fashioned server side includes (which is essentially what a MasterPage is doing for you anyway):
<!--#include virtual="/includes/header.html" -->
<!--#include virtual="/includes/nav.html" -->
<p> content </p>
<!--#include virtual="includes/footer.html" -->
If this is blocked by your web server/host of choice (some disable it for security reasons) then I would create a main index page and use an Ajax call to fill a content DIV. Of course, if Javascript is disabled, your visitors will not see any content.
I think your going to need to roll your own for this one. This function visits a url and gets the contents:
Public Shared Function GetHTTPContent(ByVal url As String) As String
Dim req As WebRequest = System.Net.HttpWebRequest.Create(url)
Dim encode As System.Text.Encoding = System.Text.Encoding.GetEncoding("utf-8")
Dim sr As New StreamReader(req.GetResponse().GetResponseStream(), encode)
Dim HTTPContent As String = sr.ReadToEnd
sr.Close()
sr.Dispose()
Return HTTPContent
End Function
Lots of these exist, here is one:
HTTrack Website Copier
This is also called spidering because it's the same thing search engines do.
Here is my quick solution that crawls your local website for .aspx files and generates .html files next to html.
protected void ButtonGenerate_Click(object sender, EventArgs e)
{
RecursivelyGenerateHtmlFiles(Server.MapPath("~/"), new DirectoryInfo(Server.MapPath("~/")));
}
private void RecursivelyGenerateHtmlFiles(string root, DirectoryInfo folder)
{
foreach (var aspxPage in folder.GetFiles("*.aspx"))
{
var destination = aspxPage.FullName.Substring(0, aspxPage.FullName.Length - 4) + "html";
if (File.Exists(destination))
File.Delete(destination);
var url = "http://" + Request.Url.Authority + "/" + aspxPage.FullName.Replace(root, "");
var request = HttpWebRequest.Create(url);
File.WriteAllText(destination, new StreamReader(request.GetResponse().GetResponseStream()).ReadToEnd());
}
foreach (var subDirectory in folder.GetDirectories())
{
RecursivelyGenerateHtmlFiles(root, subDirectory);
}
}
Worked for me.
Also, you can edit a .bat file to generate a folder with all the .html files from your site. This is useful when giving creative a flat copy.
set folder="Generated"
cd /d %folder%
for /F "delims=" %%i in ('dir /b') do (rmdir "%%i" /s/q || del "%%i" /s/q)
cd /d ..
xcopy /r /d /i /s /y /exclude:exclude.txt PAHtml Generated
Here is the exclude.txt file to use
.dll
.cs\
.aspx
.pdb
.csproj
.user
.vspscc
.config

Resources