|
|
by Remas Wojciechowski
|
The question how to include files dynamically is probably top 10 of the most frequently asked questions. There is no straight-forward answer to that question. This article briefly discusses how server-side includes work in IIS and why straigt-forward answers fail. It also shows different approaches that can be employed to simulate dynamic includes.
Scenario
Say we have a page that has 3 different states (views): a public, a private and a print view. Each view employs a different bit of HTML code, different pages in the same view share the same HTML code.
Since on our sample site there are many pages, each having these 3 states, we want to encapsulate the HTML bits into include files. Depending on the value of Request.QueryString("view") ("pc", "pe", "pt") a corresponding file should be included ("pc.asp", "pe.asp", "pt.asp").
The Anatomy of Server-Side Includes
The most important thing to know about server-side includes is that included files are inserted into the host file before the host file, or rather the host file plus the included files, is processed by the Web server.
|
|
Example
We have two files: include_1.asp and include_2.asp.
- include_1.asp
<% Dim a a = 1 %> <!-- #include file="include_2.asp" --> <% Response.Write(a) %>
- include_2.asp
<% a = a + 1 %>
Before the Web server starts interpreting the code in include_1.asp, it inserts include_2.asp into include_1.asp. In that sense, the #include directive is merely a placeholder for the source of the file it points to.
- include_1.asp when the Web server starts interpreting
<% Dim a a = 1 %> <% a = a + 1 %> <% Response.Write(a) %>
|
|
|
|
- straightforward.asp
<% Dim reqView reqView = Request.QueryString("view") If reqView = "" Then reqView = "pc" %> <!-- #include file="<%= reqView %>.asp" -->
|
|
|
|
The intention of this code was to dynamically generate the name of the include file (pc.asp for view=pc, pe.asp for view=pe, etc.). Unfortunaltely, since the Web server first inserts the include files, it will attempt to include a file of the name <%= reqView %>.asp and you'll will end up in the error message: Active Server Pages, ASP 0126 (0x80004005): The include file '<%= reqView %>.asp' was not found.
Apparently we need a different solution.
Include-Them-All Approach
One viable way to achieve dynamic includes to include all files but intersperse them with some conditional statement to make sure that only one will actually be executed. For our scenario, the following code would result:
|
|
- includethemall.asp
<% Dim reqView reqView = Request.QueryString("view") Select Case reqView Case "pc" %> <!-- #include file="pc.asp" --> <% Case "pe" %> <!-- #include file="pe.asp" --> <% Case "pt" %> <!-- #include file="pt.asp" --> <% Case Else %> <!-- #include file="pc.asp" --> <% End Select %>
|
|
|
|
The above code will include all three files but depending on the value of reqView only one file will defacto be executed.
Server.Execute Approach
With ASP 3.0 some new features have been added, among others the Server object was extended by the Execute method. That method calls an .asp file and processes it as if it were part of the calling ASP script.
More information about Server.Execute @ http://msdn.microsoft.com/library/psdk/iisref/vbob9pid.htm
|
|
- serverexecute.asp
<% Dim reqView Dim strFileName reqView = Request.QueryString("view") If reqView = "" Then reqView = "pc" strFileName = reqView & ".asp" Server.Execute(strFileName) %>
|
|
|
|
What was impossible in the straight-forward approach with #include, is possible with Server.Execute. Still, Server.Execute does not exactly behave like #include (I plan to write a short article about that and post a link here) and you need IIS5 / ASP 3.0!
Write-A-Function Approach
Both the Include-Them-All and the Server.Execute approach have one thing in common--the love-it-or-leave-it include files. They contain plain code that is executed once encoutnered.
An approach that appeals to me much more is to combine the optional include files into a procedure (Function or Sub).
In our scenario we would want a function that takes the view mode as argument displays the corresponding HTML. Here's our code:
|
|
- procedure.asp
<% Sub SetView(ByVal strView) Select Case strView Case "pc" ' The code from pc.asp
Case "pe" ' The code from pe.asp
Case "pt" ' The code from pt.asp
End Select End Sub %>
- includeprocedure.asp
<!-- #include="procedure.asp" --> <% Dim reqView reqView = Request.QueryString("view") If reqView = "" Then reqView = "pc" Call SetView(reqView) %>
|
|
|
|
As you can see, all three include files have been combined into one procedure. When the procedure.asp file is included, in fact no output is generated. Only when the procedure SetView is explicitly called, does some action take place. So, apart from providing a solution for the dynamic-includes problem, it also gives you better control over what happens in your code. Not to mention the fact that when using procedures, you don't need to worry about duplicate variable names.
|
|