Forum Moderators: open
A true "dynamic include" isn't possible because SSI is processed before the ASP. I.e., a statement like,
<!-- #include file="<%= GroupName %>.asp" -->
I've found that doing a Server.Execute will work, e.g.,
FileName = GroupName & ".asp"
Server.Execute(FileName)
This, however, errors out ungracefully if a file hasn't been set up for a particular group.
Is there a way to trap this kind of error, or is there a better way to do this?
<% if (typ == "B") { %>
<!-- #include file="fin/billStudent.asp" -->
<% } else if (typ=="E") { %>
<!-- #include file="fin/enterBill.asp" -->
<% } else if (typ == "M") { %>
<!-- #include file="fin/misctrans.asp" -->
<% } else if (typ == "R") { %>
<!-- #include file="fin/recMoney.asp" -->
<% } else if (typ == "P") { %>
<!-- #include file="fin/payBill.asp" -->
<% } else if (typ == "D") { %>
<!-- #include file="fin/deposit.asp" -->
<% } %>
<% // end make transaction %>
For these sorts of purposes I have a general purpose function I call that uses the FileSystemObject to open and display the contents of the include file I want. Not exactly a true include but it works. Plus with error handling you can check for the existence of the include file and not include it if it doesn't exist thus avoiding any error messages being sent to the client. :)
INCLUDE FILE (test.asp):
<%if group= "1" then %>
<p>1</p>
<%elseif group= "2" then %>
<p>2</p>
<%elseif group= "3" then %>
<p>3</p>
<%end if %>
PAGE:
<%
dim group
group="1"
'group can be set dynamically according to the DB call
%>
<html>
<head>
</head>
<body>
<!--#include file="test.asp" -->
</body>
</html>
Of course, "group" has to be set before the include file.
With this solution you only have one include file, and only the desired part of it will be included on the page.
defanjos, your solution seems very elegant. I'll play around with it later on after supper. The only drawback I can see is you could wind up with a huge test.asp file.
For the server.execute(filename) method, why not just check the file exists first using the scripting.filesystemobject, rather than waiting for an error to occur.
txbakers, I tried every variation on your code and could not get it to work. The double equal signs throw an error. So does the use of open and close curly brackets to take the place of "then" and "end if." On the bright side, I did learn you can use // for comments instead of the standard apostrophe.
I'm using JScript instead of VBScript for my coding.....
That's the syntax for that scripting language.
Checking the file first would be OK... I'll check out that possibility. A nonexistent file would be possible, as the site owner might add a new group but not the include file.
But, why dont you just stick with your original solution and provide a default error handling page:
if find( GroupName, Groups() )
FileName = GroupName & ".asp"
else
FileName = InvalidGroupErrorPage & ".asp?ID=" & GroupName
end if
Server.Execute(FileName)
Wouldn't the FileExists function in FSO be more efficient?
And then he could open the file as a TextStream and use the ReadAll function as the parameter for a Response.Write.
I do this all the time and my network admin tells me there are no serious security issues with this method and from his perspective it's a very efficient procedure.
He tells me the security issues with FSO exist mainly when you need to do something other than read files. In other words, something that would require Modify permissions on a file or folder so you can write to and/or delete the file.
I'd be happy to post the function I use if you want to see it.
It searches for the existence of the one file specified as a parameter to FileExists. :)
Here's the procedure I use. You'll probably want to encapsulate the paramFileName in a Server.MapPath function to get the full path to the file just once:
Public Sub DisplayIncludeFile(ByVal paramFileName)
Dim FSO 'As FileSystemObject
Dim IncFile 'As TextStream
Set FSO = Server.CreateObject("Scripting.FileSystemObject")
If FSO.FileExists(paramFileName) Then
Set IncFile = FSO.OpenTextFile(paramFileName, 1)
Response.Write IncFile.ReadAll
IncFile.Close
Set IncFile = Nothing
End If
Set FSO = Nothing
End Sub
The only issue with a SSI is ALL the include files must exist! So if I reference one, I make sure I have a blank page there or I leave it out of the statement. IF statements also work.
(VB Script and IIS)
Select Case Num
Case 1
<!-- Include file One -->
Case 2
<!-- Include file Two -->
Case Else
<!-- Include file Default -->
End Select
You don't need to use the Server.Execute
Also, the case solution takes the "dynamic" aspect out of the code as a new case must be coded manually. The FSO solution allows a new Group to be added to the database and the page will automatically load the correct file (or skip it if the file isn't there).
The case approach is simple & elegant, though, for small option sets.
The function is somewhat long because it filters out the <% and %>, and all possible sorts of comment tags (//, ' and the Rem function)
For me this works brilliantly, because the limitation of Server.Transfer and Server.Execute is that you cannot use objects and variables from the executed file in the parent file. With this function you can.
Here it is:
'--------------------------------------------------------------------------
'INCLUDE
'Dynamically includes and executes strFile. If strFile is not
'found, it will return and error and stop parsing the page.
'--------------------------------------------------------------------------
Sub Include(strFile)
Dim objRegExp
Dim objFSOSet objRegExp = new RegExp
With objRegExp
.Global = True
.MultiLine = True
.IgnoreCase = True
End With
Set objFSO = Server.CreateObject("Scripting.FileSystemObject")
If objFSO.FileExists(Server.MapPath(strFile)) Then
// Include file is found, start preparing the execution
// Open the file for reading, and read the contents
Set objFile = objFSO.OpenTextFile(Server.MapPath(strFile), 1)
strSource = objFile.ReadAll
// Filter out comment- and ASP tags cos they return errors
strSource = Replace(strSource, Chr(60)&Chr(37), "")
strSource = Replace(strSource, Chr(37)&Chr(62), "")
objRegExp.Pattern = "^[ \t]*(//¦\')[\s\S]*?$"
strSource = objRegExp.Replace(strSource, "")
// Execute the code
On Error Resume Next
Execute strSource
// If an error occurs, detect it here and stop parsing after displaying error.
If Err.Number>0 Then
Response.Write "---FATAL ERROR: while trying to execute <b>" & strFile & "</b>---<br>"
Response.Write "---Error description: " & Err.Description & "<br>"
Response.Write "---Error Source: " & Err.Source & "<hr>"
Response.Write "<b>Script Source</b><br>"
Response.Write Replace(Replace(Server.HTMLEncode(strSource), Chr(10), "<br>"), Chr(9), " ")
Response.End
End If
On Error GoTo 0
Else
// Include file is not found, abort.
Response.Write "--- <b>FATAL:</b> Include file <b>" & strFile & "</b> is not found ---<br>"
Response.End
End If
End Sub