| |||||||||
![]() |
|
|
«
Previous Thread
|
Next Thread
»
|
Thread Tools | Search this Thread | Rate Thread | Display Modes |
|
#1
|
|||||
|
|||||
|
Executing Dynamically Included ASP
We've all hit a point sometime where we've wanted #include a file with a dynamic name, or with querystrings attached, or maybe even include different files based on an If..Then or Select Case block. Perhaps you've even wanted to create a plug-in architecture for your website that would load plugins automatically.
And as we've all found, this is next to impossible with ASP. But here's the code to make it work: asp Code:
So what does this code do? Essentially, it simply reads the file passed in the "sFile" variable, stripping the ASP tags from the beginning and end, and then executes the remaining code. This will allow you to write dynamically included files that contain functions, subs, classes - whatever you like. To use this function, just call it from your code with a complete physical path - like Code:
include "c:\inetpub\wwwroot\mysite\filename.asp" Obviously, since the filename parameter can be a variable, you can also simply loop through all the files in a "/plugins" folder (for example) and include them all dynamically at runtime. The only drawback to this approach that I've noticed is that any errors that occur in the included files will be displayed as a file error on the "ExecuteGlobal" line of the subroutine. So far, I haven't found a way around that, so make sure your code works before including it this way. Use a regular #include during the development process, then switch to dynamic when the code is working. For those concerned about speed, I haven't noticed any serious drop in performance on the site I used this technique on. Any given page will be dynamically including a minimum of 5 ASP files (mostly just Class blocks in these files, though one contains a number of functions), and the page still generates in about 0.005 seconds (yes, 0.005 seconds) after removing the database code. Last edited by Rust Indy : April 9th, 2006 at 06:05 PM. Reason: Title change |
|
#2
|
||||
|
||||
|
since IIS 5.0 there is the Server.Execute method that does pretty much the same.
![]() |
|
#3
|
|||
|
|||
|
The Server.Execute method is ideal for transferring out of your currently executing script and into a new one, taking the Request collections with you (Querystring and Form). No variables can be transferred oustide of those means (except, obviously, session and application vars). And it does have it's uses (as in my URL rewriting code).
An example where Server.Execute would not be useful might be if you were writing a blog that needed to be able to use multiple databases. As a developer, you might put database specific code into a class for each DB, with identical methods and properties (for example, you might have "sql2k.asp" and "mysql5.asp" and "postgres.asp", each containing a "Class Database" block). In your blog-engine code, you simply create a new Database class and use it - the engine doesn't care what type of DB it is, so you can *only* include the class file for the database you want to use. You can't use #include, you'll get an error about redefining a class name, even if you wrap an If..Else or Select Case block around your #include statements. You can't use Server.Transfer, your application will simply stop executing (unless you Server.Transfer back to the calling ASP page, which will create an infinite transfer loop). The Server.Execute function will likewise fail here since the class will be destroyed as soon as control is passed back to the calling script. You *could* use different class names in those files. Or you *could* just include() the one you wanted, based on the user's preference. The same goes for a web app that has plugin capability. Instead of requiring the site maintainer (who is generally not the site coder) to modify a file with a new #include line, you can just have them place the plugin in a "/plugins" folder. Any ASP file in the plugins folder can then be dynamically included into the web application without any extra typing or additional points of failure. Another case where Server.Transfer is useless. So yes, Server.Transfer does have it's uses, but dynamic includes is not really one of them. In my opinion, natch. Server.Transfer is simply a server-side redirection, not much unlike a browser-side redirection via Response.Redirect. |
|
#4
|
||||
|
||||
|
I was refering to Server.Execute, not Server.Transfer that indeed has nothing
to do with including. however you're correct about "class will be destroyed as soon as control is passed back to the calling script" - in this, Server.Execute is different from SSI and your code indeed solve this. cheers yet again, keep it coming! ![]() |
|
#5
|
|||
|
|||
|
LOL, sorry about that, I got confused while I was typing
![]() Server.Execute is also scope-specific, so my example of losing a class would never occur since a class cannot be defined from within a function, sub, or property of any kind. Theoretically, the class would remain as long as Server.Execute was called from root script (i.e. not within a function or sub or property). But it didn't work for me ExecuteGlobal forces the equivalent of page-scope, as opposed to function or class scope ![]() |
|
#6
|
||||
|
||||
|
I made simple test: page1.asp had Server.Execute("page2.asp") and in page2.asp
I had class MyClass - when I tried to create instance of MyClass in page1.asp I got "undefined variable" which means you are correct. ![]() |
|
#7
|
|||
|
|||
|
Wow, I'd like to rewrite my previous two posts here, since I had totally confused myself
![]() Server.Transfer: Redirects a user from one ASP script to another at the server, which doesn't require the browser to make a new page request like Response.Redirect does. Also doesn't affect the URL that the user types in, making it ideal for URL rewriting. Also preserves the Request.Form and Request.Querystring collections, but not variables or functions or classes defined in the first ASP file. Server.Execute: executes and ASP page from within another ASP page. However, script variables and functions are not passed between the two pages, including the Request collections. You have to use querystrings or session or application vars to do that. Variables and functions/subs/classes created in one ASP file are not accessible to the other one. Execute: executes any valid VBScript code within the scope of the page, function, sub or property that made the call. ExecuteGlobal: executes any valid VBScript code in the global context, no matter what scope the call was made from. So my dynamic include example could, theoretically, use the Execute command instead of ExecuteGlobal, but if the file you are dynamically including contains anything other than in-line script and variable/constant definitions, it must be called from outside of any other function, sub or property, limiting it's usefullness (since you cannot define a new function from within another function). Code that is executed via Execute is done in-place, just as if you typed it in right where the Execute call is being made. I hope everyone (including myself) is clear on the different functionality now ![]() |
|
#8
|
||||
|
||||
|
yes that's about as clear as it can be, thanks!
![]() |
|
#9
|
|||
|
|||
|
NOTE: This code is not the equivalent of #include and does not provide the same functionality. It's a good technique, but more appropriately this topic would be called "dynamic code execution".
__________________
====== Doug G ====== I didn't attend the funeral, but I sent a nice letter saying I approved of it. --Mark Twain |
|
#10
|
||||||
|
||||||
|
If this topic was about ExecuteGlobal, then yes, this would be about dynamic code execution. But this thread is about a function that loads an arbitrary file and then executes the code within that file, which is, if I'm not completely mistaken, functionally equivalent to a dynamically included file. That this function makes use of ExecuteGlobal is incidental. I'll even provide a nice example here to show that the functionality is there. Your two existing files are "File1.asp" asp Code:
And "File2.asp" asp Code:
Now when you open "File1.asp" in your browser, you should see Code:
This is File1.asp This is File2.asp This is a function in File1.asp This is a function in File2.asp Looks right, yes? That does exactly what it looks like it does, right? Now change line 3 of "File1.asp" to read |