ASP Quick Lessons written by Charles M. Carroll
http://www.learnasp.com/learn/index.asp Page 1


Table of Contents

/learn Table of Contents

ASP Quick Lessons - Table of Contents (/learn/index.asp) - Page 1
Credits (/learn/credits.asp) - Page 2
Core Ideas (/learn/core.asp) - Page 3
        What is ASP? Obtaining The Software (/learn/whatis.asp) - Page 4
        AspInstall listserver (/learn/aspinstall.asp) - Page 5
        Simple ASP Page, Server Scripting (/learn/whatisexample.asp) - Page 6
        MS Online Documentation (/learn/docs.asp) - Page 7
        Response: Basics (/learn/res.asp) - Page 8
        Response: Buffers, Redirect (/learn/res2.asp) - Page 9
        Response: Redirection (/learn/res3.asp) - Page 10
        Response: Quotes & Special Characters (/learn/res4.asp) - Page 11
        Response: Encoding URLs, HTML (/learn/res5.asp) - Page 12
        Include: Basics (/learn/inc.asp) - Page 13
        Include: Dynamic FileName (/learn/includedynamic.asp) - Page 14
        Includes: Other Sites, Dynamic FileNames (/learn/includeasphttp.asp) - Page 15
        Include/Redirects: New Win2k Commands (/learn/incwin2k.asp) - Page 16
        Include: Books Sample Exercise (/learn/booksample.asp) - Page 17
        More Book Sample Exercises (/learn/booksample2.asp) - Page 18
        Format: Numbers #1 (/learn/formatnumbers.asp) - Page 19
        Format: Numbers #2 (/learn/formatnumbers2.asp) - Page 20
        Format: Dates #1 (/learn/formatdates.asp) - Page 21
        Date/Time on ASP Pages by Tony Arguelles (/learn/datetime.asp) - Page 22
        Loops: DO WHILE/UNTIL #1 (/learn/DoLoop.asp) - Page 23
        Loops: Timeouts #2 (/learn/DoLoop2.asp) - Page 24
        Loops: Intercepting Timeouts #3 (/learn/DoLoop3.asp) - Page 25
        Server Variables: Popular Ones (/learn/server.asp) - Page 26
        Server Variables: Domain/Host Name (/learn/server2.asp) - Page 27
        Server Variables: Displaying All (/learn/serverall.asp) - Page 28
        Random Content/Rotating Info (/learn/randomadvice.asp) - Page 29
        Browscap: Basics (/learn/bc.asp) - Page 30
        Browscap: Intricate Details (/learn/bcdetails.asp) - Page 31
        Listserver for Browser Problems (/learn/aspbrowserheck.asp) - Page 32
State Management (/learn/statemanagement.asp) - Page 33
        State Management Introduction (/learn/stateintro.asp) - Page 34
        What are ASP Sessions? (/learn/sessionswhat.asp) - Page 35
        Application Data (/learn/sessionsapps.asp) - Page 36
        Application Data: Worlds Fastest ListBox (/learn/speedappdata.asp) - Page 37
        XML, Database Caches - Fast Retrieval (/learn/xmlfastlist.asp) - Page 38
        Say No To Databases w/Sessions or Application scope (/learn/nodbsession.asp) - Page 39
        Session Overview & Myths (/learn/sessionoverview.asp) - Page 40
        Sessions: Global.asa and Scalability (/learn/globalproblems.asp) - Page 41
        Sessions: Global.asa Events (/learn/global.asp) - Page 42
        Global.asa, Sessions, Custom Stats Resources (/learn/statemore.asp) - Page 43
        State Methods: Pros and Cons (/learn/stateproscons.asp) - Page 44
        Pass Data w/Hidden Fields (/learn/hidden.asp) - Page 45
        Pass Data w/Cookies (/learn/cookies.asp) - Page 46
        Pass Data w/Session Vars (/learn/statesessions.asp) - Page 47
        Pass Data w/ID tied to database (/learn/statedb.asp) - Page 48
        [aspStateManagement] Listserver (/learn/aspstatemanagement.asp) - Page 49
Forms/Decisions (/learn/Form.asp) - Page 50
        Forms: Introduction (/learn/formintro.asp) - Page 51
        Forms: Text Box (/learn/formtextbox.asp) - Page 52
        Forms: Text Area (/learn/formtextarea.asp) - Page 53
        Forms: Check Box (/learn/formcheckbox.asp) - Page 54
        Forms: Radio Buttons (/learn/formradio.asp) - Page 55
        Forms: List Box (/learn/formlistbox.asp) - Page 56
        Forms: CASE syntax #1 (/learn/case.asp) - Page 57
        Forms: CASE syntax #2 (/learn/case2.asp) - Page 58
        Forms: IF syntax #1 (/learn/if.asp) - Page 59
        Forms: IF syntax #2 (/learn/if2.asp) - Page 60
        Forms: IF syntax #3 (/learn/if3.asp) - Page 61
        Forms: IF syntax #4 (/learn/if4.asp) - Page 62
        Forms: For Each Iteration (/learn/formforeach.asp) - Page 63
        Form - Submit To Self' (/learn/formsubmitself.asp) - Page 64
        Form - Change Action on Fly (/learn/formactionchange.asp) - Page 65
Databases (/learn/database.asp) - Page 66
        Displaying Table w/Simple Code (/learn/dbsimple.asp) - Page 67
        List Box Displayed Generically (/learn/dblist.asp) - Page 68
        Database to ListBox Online Resources (/learn/dblistmore.asp) - Page 69
        DSNLess Connections (/learn/dbopen.asp) - Page 70
        DSN Setup #1 by Rob Martinson (/learn/dsn1.asp) - Page 71
        DSN Setup #2 by Rob Martinson (/learn/dsn2.asp) - Page 72
        DSN Setup #3 by Rob Martinson (/learn/dsn3.asp) - Page 73
        DSN Setup #4 by Rob Martinson (/learn/dsn4.asp) - Page 74
        DSN Setup #5 by Rob Martinson (/learn/dsn5.asp) - Page 75
        DSN Setup #6 by Rob Martinson (/learn/dsn6.asp) - Page 76
        Full Cycle #1 Show/Edit/Update (/learn/dbfull1.asp) - Page 77
        Full Cycle #2 Show/Edit/Update (/learn/dbfull2.asp) - Page 78
        Full Cycle #3 Show/Edit/Update (/learn/dbfull3.asp) - Page 79
        SQL Mistakes Everyone Makes (/learn/dbtroubleshoot2.asp) - Page 80
        DB: Table Displayed Generically (/learn/dbtable.asp) - Page 81
        Getstring to display database table (/learn/dbtablegetstring.asp) - Page 82
        Getrows to display database table (/learn/dbtablegetrows.asp) - Page 83
        GetRows w/no Numbers (/learn/dbtablegetrowsnonum.asp) - Page 84
        Disconnected Recordsets, Display Table (/learn/dbtabledisconnected.asp) - Page 85
        DB: More ways To Display Tables (/learn/dbtablemore.asp) - Page 86
        DB: Generic DB by Eli Robillard (/learn/genericdb.asp) - Page 87
        Generic DB Listserver (/learn/aspgenericdb.asp) - Page 88
        DB: Converting a DB to a Comma-Delimited file (/learn/dbconvert.asp) - Page 89
        DB: Deleting a Record w/SQL (/learn/dbSQLdelete.asp) - Page 90
        DB: Access Scalability (/learn/accesstest.asp) - Page 91
        ADO: Paging Records (/learn/dbtablepaged.asp) - Page 92
        ADO: Limiting Number of Records (/learn/dbmaxrecs.asp) - Page 93
        ADO: Count Records in Query (/learn/dbcount.asp) - Page 94
        ADO: Cursor Types by Phil Paxton (/learn/adocursortypes.asp) - Page 95
        ADO: Input Form (/learn/dbnewrec.asp) - Page 96
        ADO: Input Form, added w/SQL (/learn/dbnewSQL.asp) - Page 97
        ADO: Input Form, Added w/ADO .addnew (/learn/dbnewADO.asp) - Page 98
        ADO: Tables within Databases (/learn/dbtablelists.asp) - Page 99
        ADO: Schemas to access table lists (/learn/dbschemas.asp) - Page 100
        ADO: Schemas to access All Data (/learn/dbschemasall.asp) - Page 101
        ADO: Show Table,1 param (/learn/db1parm.asp) - Page 102
        ADO: Update/edit Record (/learn/dbupdate.asp) - Page 103
        DB: Troubleshooting Part 1 (/learn/dbtroubles.asp) - Page 104
        DB: Troubleshooting Part 2 (/learn/dbtroubles2.asp) - Page 105
SQL Basics, Searching Databases (/learn/SQL.asp) - Page 106
        SQL Troubles (/learn/SQLtroubles.asp) - Page 107
        SQL: Example Tables (/learn/SQLexamples.asp) - Page 108
        SQL: Where Clause Basics (/learn/SQLwhere.asp) - Page 109
        SQL: Where Clause Examples (/learn/SQLwhere2.asp) - Page 110
        SQL: Search Forms #1 (/learn/SQLwhereform1.asp) - Page 111
        SQL: Search Forms #2 (/learn/SQLwhereform2.asp) - Page 112
        SQL: Search Forms #3 (/learn/SQLwhereform3.asp) - Page 113
        SQL: Search AND/OR Operators (/learn/SQLandor.asp) - Page 114
        SQL: Search AND/OR Examples (/learn/SQLandor2.asp) - Page 115
        SQL: COUNT, GROUPBY (/learn/SQLcount.asp) - Page 116
        SQL: SUM, MIN, AVE, MAX (/learn/SQLaggregate.asp) - Page 117
        SQL Joins by Aaron Alexander (/learn/dbjoin.asp) - Page 118
RSFAST: Lightning Fast Database Library (/learn/rsfast.asp) - Page 119
        RSFast Library Introduction (/learn/rsfast-intro.asp) - Page 120
        Table Display Fast (/learn/rsfast-table.asp) - Page 121
        Table Display Fast + Caching (/learn/rsfast-table-cached.asp) - Page 122
        Listbox Display Fast (/learn/rsfast-lists.asp) - Page 123
        Listbox Display Fast + Caching (/learn/rsfast-lists-cached.asp) - Page 124
        Templates for any look Fast (/learn/rsfast-templates.asp) - Page 125
        Debug Info helps troubleshoot (/learn/rsfast-lists-debug.asp) - Page 126
        Library Source Code (/learn/rsfast-lib.asp) - Page 127
        caching Method Explained (/learn/rsfast-cache.asp) - Page 128
        New Features for Future Versions (/learn/rsfast-newfeatures.asp) - Page 129
Editors Used With ASP (/learn/editors.asp) - Page 130
        ASPExpress: HOT ASP Editor (/learn/aspexpress.asp) - Page 131
        Visual Interdev + Admunsen Resources (/learn/admunsen.asp) - Page 132
        Visual Interdev Listserver (/learn/aspvisualinterdev.asp) - Page 133
        Homesite: HTML editor (/learn/homesite.asp) - Page 134
        DreamWeaver: HTML and Script Editor (/learn/dreamweaver.asp) - Page 135
Essential Commercial Components (/learn/components.asp) - Page 136
        ASPDB: Displaying Data (/learn/aspdb1.asp) - Page 137
        ASPDB: Editing, Adding Data (/learn/aspdb2.asp) - Page 138
        BrowserHawk: Determing Browser Type (/learn/bhbrowtype.asp) - Page 139
        AOL detection w/BrowserHawk (/learn/bhaol.asp) - Page 140
        MS-Wallet w/BrowserHawk (/learn/bhwallet.asp) - Page 141
        Reverse DNS lookups w/BrowserHawk (/learn/bhresolveip.asp) - Page 142
        BrowserHawk - Frame support (/learn/bhframes.asp) - Page 143
        Flash Detection w/BrowserHawk (/learn/bhflash.asp) - Page 144
        ServerObject Mail: Simple Example (/learn/serverobjectsmail.asp) - Page 145
        ServerObject: Mailing Form w/ASPMail (/learn/formsendmail.asp) - Page 146
        3rd Party Mail, CDO/CDONTS Listserver (/learn/aspmail.asp) - Page 147
        SA: File Upload, Simple Example (/learn/uploadsimple.asp) - Page 148
        SA: File Upload, Multi-part form (/learn/uploadmultipart.asp) - Page 149
        SA: File Upload, Limit Size (/learn/uploadlimitsize.asp) - Page 150
        SA: File Upload, Many Files (/learn/uploadmanyfiles.asp) - Page 151
        Upload/Soft-Artisans Listserver (/learn/aspsoftartisans.asp) - Page 152
        Perf Counters on ASP page (/learn/perfcounters.asp) - Page 153
Authentication & Security (/learn/authenticate.asp) - Page 154
        Authenticate: Overview by Kevin Flick (/learn/authenticateoverview.asp) - Page 155
        Authenticate: Comparison by Kevin Flick (/learn/authenticatecomparisons.asp) - Page 156
        Authenticate: NT Challenge/Response by Kevin Flick (/learn/authenticatentcr.asp) - Page 157
        Authenticate: Basic Authentication by Kevin Flick (/learn/authenticatebasic.asp) - Page 158
        Authenticate: Cookies by Kevin Flick (/learn/authenticatecookies.asp) - Page 159
        Authenticate: Certificates by Kevin Flick (/learn/authenticatecertificate.asp) - Page 160
        Authenticate: Build Your Own by Kevin Flick (/learn/authenticatebuild.asp) - Page 161
        Authenticate: Protect Pages via Login #1 (/learn/security.asp) - Page 162
        Authenticate: Protect Pages via Login #2 (/learn/security2.asp) - Page 163
        Authenticate: 3rd Party by Kevin Flick (/learn/authenticate3rdparty.asp) - Page 164
        Authentix Flicks Support Listserver (/learn/aspflicks.asp) - Page 165
Troubleshooting, Error Trapping (/learn/troubles.asp) - Page 166
        Errors: Basics (/learn/errors1.asp) - Page 167
        Errors: More Ways To Trap (/learn/errors2.asp) - Page 168
        Errors: Resources Online (/learn/errormore.asp) - Page 169
        Errors: Trapping EVERY Error (/learn/dbtablewitherrortrap.asp) - Page 170
        Debug variables Easy Way (/learn/debug1.asp) - Page 171
        Errors: DB Error Information Trapping (/learn/dbtroubleshoot.asp) - Page 172
        DBFAQ: Operation must use Updatable Query (/learn/FAQdbUpdate.asp) - Page 173
        DBFAQ: User Entered ' in field (/learn/FAQdbSinglequote.asp) - Page 174
        DBFAQ: LIKE operator * not working (/learn/FAQdbLIKE.asp) - Page 175
        DBFAQ: retrieving MEMO/BLOBs generates error (/learn/FAQdbMEMO.asp) - Page 176
        DBFAQ: Syntax Error in SQL Statement (/learn/FAQdbSQLSyntax.asp) - Page 177
        SQL Debugging Made Easy (/learn/debug2.asp) - Page 178
        Errors: Trapping Open Connections (/learn/dbtroubleshootopen.asp) - Page 179
        Troubleshoot: Getting Help from Lists! (/learn/asptroubles.asp) - Page 180
        Troubleshoot: Worldwide (/learn/asptroubles2.asp) - Page 181
        Troubleshoot: Specialized (/learn/asptroubles3.asp) - Page 182
        Troubleshoot: Version of ASP Sofware (/learn/versioncheck.asp) - Page 183
        Troubleshoot: Registered Components (/learn/componentchecker.asp) - Page 184
        Troubleshoot: DB Drivers by Christophe Wille (/learn/connectioninfo.asp) - Page 185
        PWS: Personal Web Server Introduction (/learn/PWS.asp) - Page 186
Code w/all ASP Features. Quality, Re-usable Code (/learn/qualitycode.asp) - Page 187
        Strings: Core Functions (/learn/strings.asp) - Page 188
        Strings: SPLIT Function (/learn/stringsplit.asp) - Page 189
        Strings: REPLACE Function (/learn/stringreplace.asp) - Page 190
        Strings: JOIN Function (/learn/stringjoin.asp) - Page 191
        Arrays: Basics (/learn/arrays.asp) - Page 192
        Arrays: Variable Size (/learn/arrays2.asp) - Page 193
        Arrays: Best Way To Load (/learn/arrays3.asp) - Page 194
        Arrays: Resources Online (/learn/arraysmore.asp) - Page 195
        Dictionary Objects (/learn/dictionary.asp) - Page 196
        Getrows Ultimate! (/learn/getrowsultimate.asp) - Page 197
        Subroutine: Working with Dates #1 (/learn/subdates.asp) - Page 198
        Subroutine: Working with Dates #2 (/learn/subdates2.asp) - Page 199
        Subroutine: Query2Table (/learn/subdbtable.asp) - Page 200
        Subroutine: Query2List (/learn/subdblist.asp) - Page 201
        Subroutine: Highly Reusable (/learn/subreusable.asp) - Page 202
        Subroutines w/Dictionary Objects (/learn/subdictionary.asp) - Page 203
        Getrows Ultimate! (/learn/getrowsultimate.asp) - Page 204
        Subroutine: List Box w/optional params (/learn/subDBlistbest.asp) - Page 205
        Subroutine: Abstract HTML by Phil Paxton (/learn/libhtml.asp) - Page 206
        Function: Working Days (/learn/functionworkingdays.asp) - Page 207
        New Features in VBScript version5 (/learn/vbs5.asp) - Page 208
        Text Files: Reading Them off Server (/learn/txtread.asp) - Page 209
        Text Files: Writing Them on Server (/learn/txtwrite.asp) - Page 210
        Text Files: Meyers-Briggs parsing #1 (/learn/mb1.asp) - Page 211
        Text Files: Meyers-Briggs parsing #2 (/learn/mb2.asp) - Page 212
        Text Files: Meyers-Briggs parsing #3 (/learn/mb3.asp) - Page 213
        XML/XLST Myers-Briggs example (/learn/xmlmb.asp) - Page 214
        Content Linker: Prev/Next Page (/learn/cl.asp) - Page 215
        Content Linker: Table of Contents (/learn/cl2.asp) - Page 216
        Content Linker: Listbox of contents (/learn/cl3.asp) - Page 217
        Content Linker Library (/learn/contentlinker.asp) - Page 218
        File Objects: Read Directory (/learn/fileobjects.asp) - Page 219
        File Objects: Display Directory as Links/Graphics (/learn/fileobjects2.asp) - Page 220
        File Objects: Read Disk Drive by Steven Harper (/learn/fileobjects3.asp) - Page 221
        File Objects: Show Dir List by Tim Foster (/learn/fileobjects4.asp) - Page 222
        Graphic Size Detector (/learn/graphicdetect.asp) - Page 223
High Speed Code, Scalable Code... (/learn/speedscale.asp) - Page 224
        Time Tasks with Millisecond Accuracy (/learn/speedtimer.asp) - Page 225
        Speed: Coding Tips (/learn/speedtips.asp) - Page 226
        Why Buffer? (/learn/whybuffer.asp) - Page 227
        Why GetRows or Getstring to get Data (/learn/whygetrows.asp) - Page 228
        Speed: Server Optimization (/learn/speedserver.asp) - Page 229
        Speed/Optimize Resources (/learn/speedmore.asp) - Page 230
        Speed: [aspfastcode] listserver (/learn/speedresearch.asp) - Page 231
        Speed: Database Percieved Speed (/learn/speedtables.asp) - Page 232
        Database Retrieval Speed (/learn/speedtablesall.asp) - Page 233
        OLEDB & ODBC Drivers differences (/learn/speedtablesdrivers.asp) - Page 234
        IsClientConnected & Stray Tasks (/learn/isclientconnected.asp) - Page 235
        Scale: Virtues of Nothing (/learn/nothing.asp) - Page 236
        Scale: Connection Pooling (/learn/dbpooling.asp) - Page 237
        Thread Basics: What is a Thread? (/learn/threads.asp) - Page 238
        Thread Safety Issues (/learn/threadsafe.asp) - Page 239
        Round-Robin Code Execution (/learn/roundrobin.asp) - Page 240
        ASP Scalability Listserver (/learn/aspscalability.asp) - Page 241
ASP Components Building (/learn/buildcomponents.asp) - Page 242
        C++/ATL: Component Building (/learn/buildc.asp) - Page 243
        Java ASP Components Building (/learn/buildjava.asp) - Page 244
        VB: Simple Component (/learn/buildvbsimple.asp) - Page 245
        VB: Registering Component (/learn/buildregister.asp) - Page 246
        VB: DLL overwrite problems (/learn/FAQvbDLLoverwrite.asp) - Page 247
        VB: ADO, Run It! (/learn/buildvbado.asp) - Page 248
        VB: ADO, Build It! (/learn/buildvbado2.asp) - Page 249
        VB: Warnings/Guidelines (/learn/buildvbguidelines.asp) - Page 250
        VB: General Building Guidelines (/learn/buildvb.asp) - Page 251
        VB: Installation Requirements (/learn/buildvb2.asp) - Page 252
        VB: Threading Models (/learn/buildvbthreads.asp) - Page 253
MTS - Microsoft Transaction Server (/learn/buildmtx.asp) - Page 254
        MTS: Overview (/learn/buildmtxoverview.asp) - Page 255
        MTS: Essentials (/learn/buildmtx2.asp) - Page 256
        MTS: Transactional ASP pages (/learn/buildmtxasp.asp) - Page 257
        MTS: Book (/learn/booksmtx.asp) - Page 258
        MTS: Book (/learn/booksmtx2.asp) - Page 259
        MTS: Registering Components (/learn/buildmtxregister.asp) - Page 260
Advice For Better Coding! (/learn/advice.asp) - Page 261
        Database in Session or App. Say NO! (/learn/dbsessionapp.asp) - Page 262
        advice: Cache No More by Phil Paxton (/learn/cachenomore.asp) - Page 263
        advice:Option Explicit (/learn/explicit.asp) - Page 264
        advice: Encode with Redirects (/learn/encode.asp) - Page 265
        advice: Write Your SQL (/learn/sqlwrite.asp) - Page 266
        advice: Named constants for ADO are better (/learn/namedconstants.asp) - Page 267
        advice: Clean Up Your Room, I mean Objects (/learn/cleanup.asp) - Page 268
        advice: Server.MapPath is Good (/learn/pathmap.asp) - Page 269
        advice: Just Say No to Session COM objects (/learn/nosessionobjects.asp) - Page 270
        advice: Don't Read COM Properties Twice (/learn/propertyexpense.asp) - Page 271
        advice: Secure Code and Data (/learn/securecode.asp) - Page 272
        advice: Encaspulate Code! (/learn/encapsulate.asp) - Page 273
        advice: CASE reads better than IF (/learn/caseisbetter.asp) - Page 274
        advice: Error Trapping Strategies (/learn/errorstrategies.asp) - Page 275
        advice: Error Trapping Secrets (/learn/errorsecrets.asp) - Page 276
        advice: You Should... (/learn/shoulds.asp) - Page 277
Appendix A: Overview of ASP Objects (/learn/overview.asp) - Page 278
        ASP Objects: Built In (/learn/aspobjects.asp) - Page 279
        ASP Objects: Created when Needed (/learn/aspobjects2.asp) - Page 280
Appendix B: Related Web/Com Technologies (/learn/webcom.asp) - Page 281
        Index Server via ADO (/learn/indexserver.asp) - Page 282
        Commerce and ASP (/learn/commerce.asp) - Page 283
        Server JavaScript: Resources (/learn/javascript.asp) - Page 284
        Validation Resources (/learn/validationmore.asp) - Page 285
        Listboxes: Linked Dynamically w/JavaScript (/learn/listdynamic.asp) - Page 286
        Dynamic ListBox Online Examples (/learn/listdynamicmore.asp) - Page 287
        Listboxes: Linked Dynamically from Database w/JavaScript (/learn/listdynamicdb.asp) - Page 288
        Listboxes: Easy Choices by Bill Wilkinson (/learn/listdual.asp) - Page 289
        Server Perlscript: Resources (/learn/perlscript.asp) - Page 290
        Remote Scripting Simple Example (/learn/remotescripting.asp) - Page 291
        Remote Scripting Listbox (/learn/remotescriptinglist.asp) - Page 292
        Remote Scripting Microsoft Example (/learn/remotescriptingms.asp) - Page 293
        [aspRemoteScript] list (/learn/aspremotescripting.asp) - Page 294
        RDS: Remote Data Services Intro (/learn/rds.asp) - Page 295
        RDS Resources by Carl Prothman (/learn/prothman.asp) - Page 296
        ADSI: Active Directory Services Interface Intro (/learn/ADSI.asp) - Page 297
        MSMQ: Overview (/learn/MSMQ.asp) - Page 298
        Usability: Resources (/learn/usability.asp) - Page 299
        Usability: Safe Color Pallete (/learn/safecolors.asp) - Page 300
Appendix C: Oracle and ASP (/learn/oracle.asp) - Page 301
        Oracle: I can't connect (/learn/FAQOracleconnect.asp) - Page 302
        Oracle: Getting Help from Listserver (/learn/asporacle.asp) - Page 303
        Oracle: Calling Stored Procs (/learn/FAQOraclestoredproc.asp) - Page 304
        Oracle: OLEDB Resource(Session) Pooling (/learn/oracleoledbpooling.asp) - Page 305
        Oracle: Recordsets from Stored Procedures using REF CURSORs (/learn/oraclerecordsetsfromsp.asp) - Page 306
        Oracle: Returning Recordsets via ADO (/learn/oraclerecordsetsado.asp) - Page 307
        Oracle: Know any good books? (/learn/FAQOraclebooks.asp) - Page 308
Appendix D: ASP Books & Online Resources (/learn/research.asp) - Page 309
        Must Buy Component Building Book (/learn/bookcomponents.asp) - Page 310
        ASP101.com Scripts for your site (/learn/asp101.asp) - Page 311
        4GuysFromRolla.com Tons of ASP Material (/learn/4guysfromrolla.asp) - Page 312
        ASPToday.com from WROX (/learn/asptoday.asp) - Page 313
Appendix E: Frequently Asked Questions (/learn/faqs.asp) - Page 314
        Commerce: certificates, https:// (/learn/FAQCommerceCertif.asp) - Page 315
        Commerce: online charging (/learn/FAQCommerceCharge.asp) - Page 316
        Commerce: components, shopping carts (/learn/FAQCommerceCarts.asp) - Page 317
        Jscript: closing DB Connections (/learn/FAQJscriptCleanUp.asp) - Page 318
        Jscript: online references (/learn/FAQJscriptRefs.asp) - Page 319
        Jscript: display databases (/learn/FAQJscriptDB.asp) - Page 320
        VB: Recommended books (/learn/FAQvbBooks.asp) - Page 321
Alphabetical Index (/learn/alphaindex.asp) - Page 322
Coming Soon/Very Rough Drafts! (/learn/comingsoon.asp) - Page 323
        Data Types: VBScript (/learn/types.asp) - Page 324
        Data Types: Conversion (/learn/convert.asp) - Page 325
        Loops: FOR NEXT #1 (/learn/ForNext.asp) - Page 326
        Loops: FOR NEXT #2 (/learn/ForNext2.asp) - Page 327
        Ad Rotator (/learn/ad.asp) - Page 328
        Content Rotator (/learn/cr.asp) - Page 329
        DB: Command Object (/learn/command.asp) - Page 330
        DB: Command Object/Queries (/learn/commandquery.asp) - Page 331
        DB: Command Object/Create Tables (/learn/commandcreate.asp) - Page 332
        Reporting: Simple Example (/learn/reportsimple.asp) - Page 333
        Reporting: Powerful Example (/learn/reportpowerful.asp) - Page 334
        Dictionaries: Different Approach #1 By Paul Rigor (/learn/dictionaryadvanced.asp) - Page 335
        Dictionaries: Different Approach #2 by Paul Rigor (/learn/dictionaryadvanced2.asp) - Page 336
        Validate data (/learn/validate.asp) - Page 337
        3rd Party: WebJam (/learn/webjam.asp) - Page 338
        Time Tasks: VB Component by Sunny Yu #1 (/learn/asptime.asp) - Page 339
        Time Tasks: VB Component by Sunny Yu #2 (/learn/asptimer.asp) - Page 340
        Cookies: Reading Them (/learn/cookiesform.asp) - Page 341
        Cookies: Writing Them (/learn/cookiesformrespond.asp) - Page 342
        Cookies: Deleting Them (/learn/cookiesforget.asp) - Page 343
        Cookies: Simplified by Paul Rigor (/learn/cookiesub.asp) - Page 344


ASP Quick Lessons written by Charles M. Carroll
http://www.learnasp.com/learn/credits.asp Page 2


Credits for Tutorial at LearnASP.com

All material is ©1998-2000 by Charles Carroll. All rights reserved. May be used and printed for any single individual with no restriction. Cannot be reprinted, resold, or commercially made available without the written consent of Charles Carroll.

  Primary Writer/Site Programming:
     Charles M. Carroll

  Business Manager:
     Naoko Yoshitsugu

  Inspiration, Assistance, Motivation:
     Hitoshi & Michiko Carroll

     Contact Info

Additional Writers/Contributors:
    Aaron Alexander, Kevin Flick, Steve Genusa, Steven Harper, John Kauffman. Andrew Laken, Juan Llibre,  Rob Martinson, Phil Paxton,  George Reilly, Paul Rigor, Christophe Wille, David Wihl, and Sunny Yu.

thanks for feedback, support:
    Joao Oliveira contato123@zipmail.com.br
    Scott Mitchell www.4guysfromrolla.com

ASP Quick Lessons is a on-line book published @
http://www.learnasp.com

Recent family photos


ASP Quick Lessons written by Charles M. Carroll
http://www.learnasp.com/learn/core.asp Page 3


Section Contents

Core Ideas
        What is ASP? Obtaining The Software (whatis.asp) - Page 4
        AspInstall listserver (aspinstall.asp) - Page 5
        Simple ASP Page, Server Scripting (whatisexample.asp) - Page 6
        MS Online Documentation (docs.asp) - Page 7
        Response: Basics (res.asp) - Page 8
        Response: Buffers, Redirect (res2.asp) - Page 9
        Response: Redirection (res3.asp) - Page 10
        Response: Quotes & Special Characters (res4.asp) - Page 11
        Response: Encoding URLs, HTML (res5.asp) - Page 12
        Include: Basics (inc.asp) - Page 13
        Include: Dynamic FileName (includedynamic.asp) - Page 14
        Includes: Other Sites, Dynamic FileNames (includeasphttp.asp) - Page 15
        Include/Redirects: New Win2k Commands (incwin2k.asp) - Page 16
        Include: Books Sample Exercise (booksample.asp) - Page 17
        More Book Sample Exercises (booksample2.asp) - Page 18
        Format: Numbers #1 (formatnumbers.asp) - Page 19
        Format: Numbers #2 (formatnumbers2.asp) - Page 20
        Format: Dates #1 (formatdates.asp) - Page 21
        Date/Time on ASP Pages by Tony Arguelles (datetime.asp) - Page 22
        Loops: DO WHILE/UNTIL #1 (DoLoop.asp) - Page 23
        Loops: Timeouts #2 (DoLoop2.asp) - Page 24
        Loops: Intercepting Timeouts #3 (DoLoop3.asp) - Page 25
        Server Variables: Popular Ones (server.asp) - Page 26
        Server Variables: Domain/Host Name (server2.asp) - Page 27
        Server Variables: Displaying All (serverall.asp) - Page 28
        Random Content/Rotating Info (randomadvice.asp) - Page 29
        Browscap: Basics (bc.asp) - Page 30
        Browscap: Intricate Details (bcdetails.asp) - Page 31
        Listserver for Browser Problems (aspbrowserheck.asp) - Page 32


ASP Quick Lessons written by Charles M. Carroll
http://www.learnasp.com/learn/whatis.asp Page 4


subdates from ASP Quick Lessons

(surprisingly even though ASP was shipped in Feb 1996, most explanations are still HUGE in books and use quite scary technical terms) We will try to present this all in clear, concise terms and be complete as well. Hang on. Here we go.

ASP is:

  1. an abbreviation for Active Server Pages
  2. FREE and already built into Win2000. It is part of IIS and must be added with add/remove programs menu there.
  3. FREE for NT4 or Win 95/98 if one installs the NT4 Option Pack. Can be downloaded from http://www.microsoft.com/ntserver/nts/downloads/recommended/NT4OptPk/default.asp
    since ASP can be installed on Win 95/98 computers to test ASP scripts; thus we can  conclude the NT Option Pack4 has a very misleading name since it installs on Win 9x as well.
  4. The code inside ASP is mixed in with standard HTML and is NEVER seen by the browser. ASP pages run in ALL browsers UNLESS the person making the page uses HTML or browser commands outside of the ASP portions.

Tip: Trouble/Errors installing PWS? Here is the answer(s):

http://www.acceleratedcomputers.com/pws4.htm
has the answer to several annoying error messages!

http://rwebs.net/webdesign/pwsmore.htm
also has some excellent info about how and whether to install PWS.

Tip: Trouble/Errors installing IIS5?

When IIS5 does not start:
http://www.iisfaq.com/Articles/134/
 

More ASP facts:

  1. See www.learnasp.com/hosts for links to FREE hosts if you want to develop a site on the WWW web without spending money; Commercial hosts are also listed to serve busy corporate sites you build.
  2. It is part of IIS (Internet Information Server) which takes care of all the non-asp chores (FTP, serving plain HTML, serving video). IIS  is also FREE with NT4 or Win2000.
  3. It can be purchased for Unix, Notes/Domino, Novell servers and other platforms.  Two vendors currently offer this: Chilisoft and Halcyonsoft (see www.learnasp.com/hosts for links to them)

Are you one of those unlucky folks who gets cryptic errors or has trouble Installing Asp? Just join http://www.asplists.com/asplists/aspinstall.asp and submit your problem by email. Others will help you!


ASP Quick Lessons written by Charles M. Carroll
http://www.learnasp.com/learn/aspinstall.asp Page 5


Listserrver Join aspinstallListserver for more info @

http://www.asplists.com/asplists/aspinstall.asp

Related Links:

 
Excellent info about how and whether to install PWS @
   http://rwebs.net/webdesign/pwsmore.htm
The answer to several annoying error messages @
   http://www.acceleratedcomputers.com/pws4.htm
PWS NT Otion Pack4 WILL Install on Win9x @
   http://www.microsoft.com/ntserver/nts/downloads/recommended/NT4OptPk/default.asp

Recommended Books:

     

Related Lists:

Mobile lists by Asplists @
   http://www.asplists.com/asplists/mobile.asp
Mobile lists by WROX @
   http://p2p.wrox.com/mobile/

Rules:

Mailing List Manners (suggested by Bob Filipiak) @
   http://db.tidbits.com/getbits.acgi?tbser=1141
Ken Shaffer's Advice on Asking For Help... @
   http://www.adopenstatic.com/personal/help.asp


ASP Quick Lessons written by Charles M. Carroll
http://www.learnasp.com/learn/whatisexample.asp Page 6


subdates from ASP Quick Lessons

Now let us go over the essential mechanisms that are ASP:

  1. A user asks for a page say:
    http://www.coyoteindustries.com/hi.asp

  2. The Web Server find the file and then processes all the ASP code between <% ... %> before handing back the page. Code between  <% ... %> never arrives at the browser.
<html><head>
<TITLE>hi.asp</TITLE>
</head>
<body bgcolor="#FFFFFF">
Today is <%=now%> and all is well<br>
<%if hour(now())>12 THEN%>
Good Evening
<%ELSE%>
Good Morning!
<%END IF%>
</body></html>
The webserver file

<<<<<<<


ASP compiler grabs page
Interprets all the <% %> markers
before
browser sees page!
<html><head>
<TITLE>hi.asp</TITLE>
</head>
<body bgcolor="#FFFFFF">
Today is Tue 10:30am and all is well<br>
Good Morning
</body></html>
Before 12pm the user at the browser receives

<<<<<<<


<html><head>
<TITLE>hi.asp</TITLE>
</head>
<body bgcolor="#FFFFFF">
Today is Tue 02:00pm and all is well<br>
Good Day!
</body></html>
After 12pm the user at the browser receives

<<<<<<<


ASP Quick Lessons written by Charles M. Carroll
http://www.learnasp.com/learn/docs.asp Page 7


ASP/IIS Docs for Active Server Pages from MS

Microsoft Documentation

There is quite a bit of online documentation that comes with Microsoft Active Server Pages. Our tutorial was written with the express purpose of being a friendlier, easier to understand set of lessons than the free documentation Microsoft gives you below:

IIS4 Docs  
NT4 Option Pak /iishelp
ASP objects reference /iishelp/iis/htm/asp/intr1orp.htm
Ex Air /IISSamples/ExAir/default.asp
Installable Components for ASP /iishelp/iis/htm/asp/comp275c.htm
JScript Language Reference  /iishelp/JScript/htm/JStoc.htm
VBScript Language Reference /iishelp/VBScript/htm/VBStoc.htm
Server Side Include Reference  /iishelp/iis/htm/asp/iissiref.htm
ASP Quick reference card /iishelp/iis/htm/asp/iiwaref.htm
ASP Tutorial* click here
IIS3 Docs  
Roadmap / Official IIS3 Docs /iasdocs/aspdocs/roadmap.asp
IIS3 Code Samples /aspsamp/samples/samples.htm
AdventureWorks /AdvWorks/default.asp

* ASP Tutorial resides at this ridiculously long URL:
/iishelp/iis/htm/asp/iiselect.asp?LessonFile=%2Fiishelp%2Fiis%2Fhtm%2Fasp%2Fiiatmd1%


ASP Quick Lessons written by Charles M. Carroll
http://www.learnasp.com/learn/res.asp Page 8


Response Object ASP Quick Lessons

Response Object

The response object is useful, feature rich, and subtle. We are going to focus on it's most fundamental capabilities -- the 20% you will use 80% of the time. The capabilities we think are vital include:

Here is a script utilizing response.write to send some information to the browser. It also uses dateadd, a built-in function documented at http://help.activeserverpages.com/iishelp/VBScript/htm/vbs90.htm.

   <html><head>
   <title>response.asp</title>&
   <body color="#FFFFFF">
   <%
   when=now()
   tommorow=dateadd("d",1,when)
   twoweekslater=dateadd("ww",2,when)
   fourteenweekdayslater=dateadd("w",14,when)
   monthlater=dateadd("m",1,when)
10   
11   sixminuteslater=dateadd("n",6,when)
12   sixhourslater=dateadd("h",6,when)
13   fortysecslater=dateadd("s",40,when)
14   
15   response.write "Now <b>" & when & "</b><br>"
16   response.write "tommorow <b>" & tommorow & "</b><br>"
17   response.write "2 weeks from Now <b>" & twoweekslater & "</b><br>"
18   response.write "fourteen working days from Now <b>" & fourteenweekdayslater & "</b><br>"
19   response.write "1 month from Now <b>" & monthlater & "</b><br>"
20   %>

21   six minutes from now <b> <%=sixminuteslater%> </b><br>
22   six hours from now <b> <%=sixhourslater%> </b><br>
23   fourty seconds later <b> <%=fortysecslater%> </b><br>
24   </body></html>

Here is a script utilizing response.end to prematurely end a page:

   <html><head>
   <title>end.asp</title>&
   <body color="#FFFFFF">
   <%
   when=now()
   tommorow=dateadd("d",1,when)
   twoweekslater=dateadd("w",2,when)
   monthlater=dateadd("m",1,when)
   sixminuteslater=dateadd("n",6,when)
10   sixhourslater=dateadd("h",6,when)
11   
12   response.write "Now <b>" & when & "</b><br>"
13   response.write "1 month from Now <b>" & monthlater & "</b><br>"
14   response.end
15   response.write "2 weeks from Now <b>" & twoweekslater & "</b><br>"
16   %>

17   six minutes from now <b> <%=sixminuteslater%> </b><br>
18   six hours from now <b> <%=sixhourslater%> </b><br>
19   </body></html>


ASP Quick Lessons written by Charles M. Carroll
http://www.learnasp.com/learn/res2.asp Page 9


Buffering from ASP Quick Lessons

Response Object Part2 - Buffer Explanation

Does this error message plague you?

Response object error 'ASP 0156 : 80004005'
Header Error
whatever.asp, line
#
The HTTP headers are already written to the client browser. Any HTTP header modifications must be made before writing page content.

The Simple Fix....
<%response.buffer=true%>
needs to be added as the very first line to any pages made by any HTML document that mixes redirects/headers and content.  And buffering is a great idea anyway from overall server speed viewpoint see http://www.learnasp.com/advice/whybuffer.asp).

One drawback to <%response.buffer=true%> is if a page takes a while to compose (i.e. a couple thousand records from a database) people see nothing until the page is completely rendered. If a page takes 20 seconds to render, the browser user sees nothing until the 20th second! In that situation to avoid appearing as the page is dead, a well-placed
<%response.flush%> tell server to send HEADER + whatever text so far so lets readers see the portions of the page being built. Increasing percieved speed of database displays is explained at http://www.learnasp.com/learn/speedtables.asp by judicous use of flushing buffer.

NT4 and Win 2000 differences

NT4 <%buffer=false%> by default which hurts overall server speed (http://www.learnasp.com/advice/whybuffer.asp). Win 2000 <%buffer=true%> by default. A clever administrator can change NT4 registry so buffer=true for all scripts and will see major server performance improvements (see http://www.learnasp.com/learn/speedserver.asp for other ones).

Here is a non-working page that will display the error:

   <%response.buffer=false%>
   <html><head>
   <title>dailystuff.asp</title>
   </head>
   <body>
   <%
   whatweekday=Weekday(now())
   select case whatweekday
   case vbSunday
10      response.redirect "http://www.cnn.com"
11   case vbMonday
12      response.redirect "http://www.activeserverpages.com"
13   case vbTuesday
14      response.redirect "http://www.aspalliance.com"
15   case vbWednesday
16      response.redirect "http://www.aspconvention.com"
17   case vbThursday
18      response.redirect "http://www.aspmagazine.com"
19   case vbFriday
20      response.redirect "http://www.dilbert.com"
21   case vbSaturday
22      response.redirect "http://www.movielink.com"
23   end select
24   %>

25   </body>
26   </html>

Here is the fixed page that will NOT display the error:

   <%response.buffer=true%>
   <html><head>
   <title>dailystuff.asp</title>
   </head>
   <body>
   <%
   whatweekday=Weekday(now())
   select case whatweekday
   case vbSunday
10      response.redirect "http://www.cnn.com"
11   case vbMonday
12      response.redirect "http://www.activeserverpages.com"
13   case vbTuesday
14      response.redirect "http://www.aspalliance.com"
15   case vbWednesday
16      response.redirect "http://www.aspconvention.com"
17   case vbThursday
18      response.redirect "http://www.aspmagazine.com"
19   case vbFriday
20      response.redirect "http://www.dilbert.com"
21   case vbSaturday
22      response.redirect "http://www.movielink.com"
23   end select
24   %>

25   </body>
26   </html>

Why? (The Tough Answer with Gory Details)

...first of all thanks to Ken Schaefer of Adopenstatic.com for pointing out huge flaws and misleading information in this page as it was written before 1/10/2001. Its revision on 1/10 was prompted by Ken. He wrote an article on this too at http://www.adopenstatic.com/faq/headererror.asp...

That line will do away with all "headers are already sent" messages. It essentially tells the server don't write anything at all to browser until
a) response.end executes thus stopping the page dead in tracks and sending to browser
b) response.flush executes
c) 100% of the page is executed and it finishes all the ASP and HTML.
d) response.redirect is sent (provided no content or text has been sent with response.flush)

An ASP page must be sent to browser in a specific strict order: first the header, and then the content. The header could contain cookies (see http://www.learnasp.com/learn/cookies.asp), redirects, other headers inserted by the response.addheader command and other header information. If your page mixes content (any text) and mixes in header info this is not following the strict rules. If the browser writes any data that is page content, and then headers cannot be sent -- it is "too late" -- it can't change "horses in midstream" -- that is header info cannot come inside or after data. Buffering does not send the page content and headers in exact order they appear in script. Even if headers and content is mixed the header and content are sent in correct order when buffer is flushed (either by explicit response.flush or script completes).


ASP Quick Lessons written by Charles M. Carroll
http://www.learnasp.com/learn/res3.asp Page 10


Res3 ASP Quick Lessons

Response Object - Redirects

The response object can be used to decide what page to send a user to next. Specifically the response.redirect method will work in that capacity. We have made a script formjump.asp that takes advantage of this.

   <html><head>
   <TITLE>FormJump.asp</TITLE>
   </head><body bgcolor="#FFFFFF">
   <form action="FormJumpRespond.asp" method="get">
   <SELECT NAME="wheretogo">
   <OPTION SELECTED VALUE="fun">Fun</OPTION>
   <OPTION value="news">Daily News</OPTION>
   <OPTION value="docs">ASP IIS3 Roadmap/Docs</OPTION>
   <OPTION value="main">MainPage of ActiveServerPages.com</OPTION>
10   <OPTION value="sample">IIS 3 Sample ASP scripts</OPTION>
11   </SELECT>
12   <input type=submit value="Choose Destination">
13   </form>
14   </body></html>

The responder that reacts to this form is:

   <%response.buffer=true%>
   <html><head>
   <title>formjumprespond.asp</title>&
   <body bgcolor="#FFFFFF">
   <%
   ' My ASP program that redirects to URL
   thisURL="http://www.activeserverpages.com"
   where=Request.QueryString("Wheretogo")
   Select Case where
10   case "main"
11         response.redirect thisURL & "/"
12   case "samples"
13         response.redirect thisURL & "/aspsamp/samples/samples.htm"
14   case "docs"
15         response.redirect thisURL & "/iasdocs/aspdocs/roadmap.asp"
16   case "news"
17         response.redirect "http://www.cnn.com"
18   case "fun"
19         response.redirect "http://www.dilbert.com"
20   End Select
21   response.write "All dressed up and I don't know where to go<br>"
22   response.write "I recommend --> " & "<br>"
23   response.write server.htmlencode(thisURL & "/learn/test/res2.asp?where=fun") & "<br>"
24   response.write "for a good laugh!" & "<P>"
25   %>

26   </body></html>


ASP Quick Lessons written by Charles M. Carroll
http://www.learnasp.com/learn/res4.asp Page 11


Res4 ASP Quick Lessons

Response Object and Quotes

The response object is often used with a variety of syntax variations which we will detail here.

   <html><head>
   <title>res4.asp</title>
   </head><body bgcolor="#FFFFFF">
   <%
   ' The response object can be used to write text a variety of ways
   ' depending on what style you personally prefer
   
   ' Various permutations of writing to the browser
   response.write "<form>"
10   response.write "Hello, Joe<br>"
11   
12   who="Joe"
13   response.write "Hello, " & who & "<br>"
14   %>

15   
16   Hello, <%=who%><br>
17   
18   Which Book? <input type="TEXT" name="book" value="The Stand"><br>
19   
20   <%
21   response.write "Which Book? <input type=""TEXT"" name=""book"" value=""The Stand""><br>"
22   %>

23   
24   <%
25   response.write "Which Book? <input type='TEXT' name='book' value='The Stand'><br>"
26   %>

27   
28   <%
29   quote=chr(34)
30   response.write "Which Book? <input type=" & quote & "TEXT" & quote & " name=" & quote & "book" & quote & " value=" & quote & "The Stand" & quote & "><br>"
31   %>

32   
33   
34   <%bookname="The Stand"%>
35   Which Book? <input type="TEXT" name="book" value="<%=bookname%>"><br>
36   
37   <%
38   response.write "Which Book? <input type=""TEXT"" name=""book"" value=""" & bookname & """><br>"
39   %>

40   </form>
41   </body></html>


ASP Quick Lessons written by Charles M. Carroll
http://www.learnasp.com/learn/res5.asp Page 12


Res5 ASP Quick Lessons

Response Object and HTML Encoding

The response object is often used in conjunction with various kinds of coding schemes. No discussion of response would be complete without a discussion of how to "handle" or "escape" special characters. This sample script demonstrates common conversion and transformation commands that make sense to use with the response.write command:

   <html><head>
   <title>res5.asp</title>
   </head><body bgcolor="#FFFFFF">
   <%
   ' The response object can be used to write text
   ' but sometimes some functions must be used to transform
   ' the text instead of sending as is to the browser
   
   response.write "<B>Hyperion</b> by <I>Dan Simmons</i> is a great novel"
10   response.write "<p>"
11   response.write server.htmlencode("<B>Hyperion</b> by <I>Dan Simmons</i> is a great novel")
12   response.write "<p>"
13   
14   
15   response.write "Joe Smith & Hilda = a team"
16   response.write "<p>"
17   response.write server.URLencode("Joe Smith & Hilda = a team")
18   %>

19   
20   </body></html>


ASP Quick Lessons written by Charles M. Carroll
http://www.learnasp.com/learn/inc.asp Page 13


Include Files ASP Quick Lessons Databases

Include Files

The include option is the heart of making efficient ASP files and re-usable chunks. It basically has two forms and now we will present the forms and their differences:

<!--#include virtual="/whatever.asp"-->
would include any file on your site (in this example, whatever.asp is in the web server's root directory) but you must fully qualify the filename with a path.

<!--#include file="whatever.asp"-->
can include the whatever.asp file in  the directory of the script that contains the statement. It ASSUMES the current directory!

Example #1
<!--#include virtual="/sally/filename.asp"-->
could include a file from sally's directory, even if the page with this statement is (for example) in the /fred/finance folder.

Example #2:
<!--#include file="/sally/filename.asp"-->
will fail from fred's directory.

Example #3:
<!--#include file="../sally/filename.asp"-->
will succed from fred's directory but if the script that contains it is moved to a different level in the tree structure it will fail to locate the file. INCLUDE VIRTUAL is better if a script may be moved and is immune to relative path issues.

IMPORTANT: Include files are always processed and inserted before ASP scripts on the page are calculated. Thus a page with many IFs and SELECT CASEs that selectively include files in fact always include the file before the script begins executing.


ASP Quick Lessons written by Charles M. Carroll
http://www.learnasp.com/learn/includedynamic.asp Page 14


Include Files Dynamically from ASP Quick Lessons

Includes Files Dynamically

The include files are gathered and processed BEFORE any ASP code. Soif your code looks like this:

<%SELECT CASE
     CASE 1 %>
    <!--#include virtual="whatever1.asp"-->
     CASE 2 %>

    <!--#include virtual="whatever2.asp"-->
     CASE 3 %>
    <!--#include virtual="whatever3.asp"-->
<%END SELECT%>

Three includes are performed before any ASP code is executed.

YOU CANNOT DO:

<%
     whichfile="1"%>
  <!--#include virtual="whatever<%=whichfil%>.asp"-->

Though this is a reasonable idea.

<!--#include virtual="whatever.asp"-->

We however have coded a workaround that is FREE you may find useful. The workaround is:

   <html><head>
   <TITLE>includedynamic.asp</TITLE>
   </head><body bgcolor="#FFFFFF">
   <%
   whichfile="bookscifi.asp"
   Call ReadDisplayFile(whichfile)
   response.write "<hr>"
   
   whichfile="bookhorror.asp"
10   Call ReadDisplayFile(whichfile)
11   response.write "<hr>"
12   
13   
14   whichfile="/learn/test/bookmarketing.asp"
15   Call ReadDisplayFile(whichfile)
16   response.write "<hr>"
17   %>

18   
19   </body></html>
20   <%
21   SUB ReadDisplayFile(FileToRead)
22      whichfile=server.mappath(FileToRead)
23      Set fs = CreateObject("Scripting.FileSystemObject")
24      Set thisfile = fs.OpenTextFile(whichfile, 1, False)
25      tempSTR=thisfile.readall
26      response.write tempSTR
27      thisfile.Close
28      set thisfile=nothing
29      set fs=nothing
30   END SUB
31   %>

The only downside to this method is no ASP Code ( i.e. anything in <% %> ) will be parsed or executed in the included file. If you must execute ASP code the Win2k server.execute @
/learn/incwin2k.asp
or the 3rd party components like ASPHTTP must be employed @
/learn/include/asphttp.asp


ASP Quick Lessons written by Charles M. Carroll
http://www.learnasp.com/learn/includeasphttp.asp Page 15


Includes - Other Sites, Dynamic Code

Includes - Other Sites/Dynamic FileNames

3rd party components like ASPHTTP can grab the HTML contents of a specific URL into an ASP string. Supports GET/POST/HEAD documents via the HTTP protocol, examining response headers, transfering requests to a file (including binary transfers) and password authentication support. They can also be used on YOUR OWN SITE to make dynamic includes possible.

available at http://www.serverobjects.com/products.htm

Microsoft includes WinInet which seems to be ideally suited for this EXCEPT is currently not thread safe, see:
http://www.learnasp.com/advice/threadsafe.asp
so Tools like ASPHTTP are a necessity.

Here is a sample where ASPHTTP is used to grab contents from another site.

   <html><head>
   <title>asphttpother.asp</title>
   </head>
   <body>
   <%
         Set HttpObj = Server.CreateObject("AspHTTP.Conn")
   
         HttpObj.Url = "http://www.funinspace.com"
         strResult = HttpObj.GetURL
10         
11         STRresult=server.htmlencode(STRresult)
12         response.write STRresult
13   
14         SET HTTPobj = nothing
15   %>

16   </body>
17   </html>
18   
19   

Here is a sample where ASPHTTP is used to allow a string to decide  which page on our site is executed.

   <html><head>
   <title>asphttpdynamic.asp</title>
   </head>
   <body bgcolor="#FFFFFF">
   <%
      mystring="/learn/test/response.asp"
   
         Set HttpObj = Server.CreateObject("AspHTTP.Conn")
         HttpObj.Url = "http://www.learnasp.com" & mystring
10         strResult = HttpObj.GetURL
11         response.write STRresult
12   
13         SET HTTPobj = nothing
14   %>

15   </body>
16   </html>
17   
18   


ASP Quick Lessons written by Charles M. Carroll
http://www.learnasp.com/learn/incwin2k.asp Page 16


Include Files ASP Quick Lessons Databases

Include/redirect Goodies from Win2000

Win 2000 introduces two new ways to deal with redirects and includes:

server.transfer
which unlike redirect, does not interact with the browser. The server switches to a different page/site without any browser interaction or headers.

server.execute
which can take a dynamically generated string and execute the code in the asp script named by the string.


ASP Quick Lessons written by Charles M. Carroll
http://www.learnasp.com/learn/booksample.asp Page 17


Book Sample from ASP Quick Lessons

Book Sample by Charles Carroll

The Recommend Book Sample Files provides you with several files that when created, prepare you for applying several powerful content management tools and session examples in the following pages. The features detailed will include:

all come together in this example.

Here is the code for bookheader.asp:

   Recommended Books for <%=session("fname")%> &nbsp; <%=session("lname")%><br><hr>

Here is the code for bookfooter.asp:

   <hr><br>
   Recommended Books has <%=application("howmany")%> people reading it now!

Here is the code for bookfuture.asp:

   <html><head>
   <title>bookfuture.asp</title>&
   <!--#include file="bookheader.asp"-->
   <body>
   <h1>Future Books</h1>
   <ul>
       <li><b><i>Visions</b></i><br>Michio Kaku</li>
       <li><b><i>Future Magic</b></i><br>Robert Forward</li>
   </ul>
10   <!--#include file="bookfooter.asp"-->
11   </body></html>

Here is the code for bookhorror.asp:

   <html><head>
   <title>bookhorror.asp</title>&
   <!--#include file="bookheader.asp"-->
   <body>
   <h1>Horror Books</h1>
   <ul>
       <li><b><i>Carrion Comfort</b></i><br>Dan Simmons</li>
       <li><b><i>The Stand</b></i><br>Steven King</li>
       <li><b><i>Children of Darkness</b></i><br>Dan Simmons</li>
10       <li><b><i>Thinner</b></i><br>Steven King</li>
11       <li><b>Fires of Eden<i></b></i><br>Dan Simmons</li>
12   </ul>
13   <!--#include file="bookfooter.asp"-->
14   </body></html>

Here is the code for bookmarketing.asp:

   <html><head>
   <title>bookMarketing.asp</title>&
   <!--#include file="bookheader.asp"-->
   <body>
   <h1>Marketing Books</h1>
   <ul>
       <li><b><i>22 Immutable Laws of Branding</b></i><br>Reiss and Reiss</li>
       <li><b><i>22 Immutable Laws of Marketing</b></i><br>Reiss and Trout</li>
       <li><b><i>Marketing Warfare</b></i><br>Reiss and Trout</li>
10       <li><b><i>Horse Sense</b></i><br>Reiss and Trout</li>
11       <li><b><i>Words That Sell</b></i><br>by ??</li>
12   </ul>
13   <!--#include file="bookfooter.asp"-->
14   </body></html>

Here is the code for booknovels.asp:

   <html><head>
   <title>booknovels.asp</title>&
   <!--#include file="bookheader.asp"-->
   <body>
   <h1>Recommended Novels</h1>
   <ul>
       <li><b><i>A Prayer for Owen Meaney</b></i><br>John Irving</li>
       <li><b><i>Cider House Rules</b></i><br>John Irving</li>
       <li><b><i>Heart of the Country</b></i><br>Greg Mathhews</li>
10       <li><b><i>All That Remains</b></i><br>Patricia Cornwell</li>
11       <li><b><i>Presumed Innocent</b></i><br>Scott Turrow</li>
12       <li><b><i>Time to Kill</b></i><br>John Grisham</li>
13       <li><b><i>Disclosure</b></i><br>Michael Chrichton</li>
14       <li><b><i>Mount Dragon</b></i><br>Lincoln and Childs</li>
15   </ul>
16   <!--#include file="bookfooter.asp"-->
17   </body></html>

Here is the code for bookscifi.asp:

   <html><head>
   <title>bookscifi.asp</title>&
   <!--#include file="bookheader.asp"-->
   <body>
   <h1>Science Fiction Recommended Books</h1>
   <ul>
       <li><b><i>Ender's Game</b></i><br>Orson Scott Card</li>
       <li><b><i>Hyperion</b></i><br>Dan Simmons</li>
       <li><b><i>Childhood's End</b></i><br>Arthur Clarke</li>
10       <li><b><i>TommyKnockers</b></i><br>Steven King</li>
11   </ul>
12   <!--#include file="bookfooter.asp"-->
13   </body></html>

Here is the code for bookselfhelp.asp:

   <html><head>
   <title>bookselfhelp.asp</title>&
   <!--#include file="bookheader.asp"-->
   <body>
   <h1>Self Help Books</h1>
   <ul>
       <li><b><i>Road Less Travelled</b></i><br>Scott Peck</li>
       <li><b><i>The Seven Habits of Highly Effective People</b></i><br>Steven Covey</li>
       <li><b><i>First Things First</b></i><br>Steven Covey</li>
10   </ul>
11   <!--#include file="bookfooter.asp"-->
12   </body></html>


ASP Quick Lessons written by Charles M. Carroll
http://www.learnasp.com/learn/booksample2.asp Page 18


Book Sample from ASP Quick Lessons

Book Sample Exercises

Not Ready Yet.

Will tie into the content linker and session login/abandon examples.


ASP Quick Lessons written by Charles M. Carroll
http://www.learnasp.com/learn/formatnumbers.asp Page 19


Format Numbers

Format Numbers - Reference

Frequently you want a number to appear in a certain format. The most commands requests are for a set total number of digits and a set number of digits to the right of the decimal place. Less frequently there is a call for negative amounts displayed in parenthesis or that there should be leading zeros.

The FormatNumber function takes the contents of a number type variable and returns the contents in the specified format.

Syntax: FormatNumber(expression, iDigits, bleadingDigit, bParen, bGroupDigits)

argument meaning
expression the variable holding the raw number
iDigits number of digits to right of decimal point
bleadingDigit 1 for leading zeros
0 for no leading zeros
bParen 1 for parenthesis around negative numbers
0 for no parenthesis around negative numbers
bGroupDigits 1 to display numbers as per regional settings in the Control Panel
0 to over-ride settings in the Control Panel


ASP Quick Lessons written by Charles M. Carroll
http://www.learnasp.com/learn/formatnumbers2.asp Page 20


Format Numbers Sample Code

Format Numbers Part2 (by Charles Carroll)

The easiest way to demonstrate format numbers is just have some sample code that tries evry permutation of the command.

   <html><head>
   <TITLE>formatnumbers2.asp</TITLE>
   </head><body bgcolor="#FFFFFF">
   <%
   ' My ASP formatting number sample
   mynumber=123.4567
   response.write "<hr>" & mynumber & "<br>"
   response.write "formatnumber(mynumber,0)" & "<br>"
   response.write formatnumber(mynumber,0) & "<hr>"
10   response.write "formatnumber(mynumber,2)" & "<br>"
11   response.write formatnumber(mynumber,2) & "<hr>"
12   response.write "formatnumber(mynumber,6)" & "<br>"
13   response.write formatnumber(mynumber,6) & "<hr>"
14   
15   mynumber=.4567
16   response.write mynumber & "<br>"
17   '0 means means no leading zeroes
18   response.write "formatnumber(mynumber,2,0)" & "<br>"
19   response.write formatnumber(mynumber,2,0) & "<hr>"
20   '1 means means pad with leading zeroes
21   'response.write "formatnumber(mynumber,2,1)" & "<br>"
22   'response.write formatnumber(mynumber,2,1) & "<hr>"
23   
24   'mynumber=-123.4567
25   'response.write mynumber & "<br>"
26   '0 means means no parentheses for negative numbers
27   'response.write "formatnumber(mynumber,2,0,0)" & "<br>"
28   'response.write formatnumber(mynumber,2,0,0) & "<hr>"
29   '1 means means yes parentheses for negative numbers
30   'response.write "formatnumber(mynumber,2,0,1)" & "<br>"
31   'response.write formatnumber(mynumber,2,0,1) & "<hr>"
32   %>

33   </body></html>


ASP Quick Lessons written by Charles M. Carroll
http://www.learnasp.com/learn/formatdates.asp Page 21


FormatDates ASP Quick Lesson

Format Dates by Charles Carroll

The built-in date functions (described in next paragraph) are pretty lame. The holy grail of data formatting is at:
http://www.4guysfromrolla.com/webtech/112098-2.shtml

http://www.learnasp.com/iishelp/VBScript/htm/vbs109.htm are the official online docs for the FormatDateTime function. The easiest way to demonstrate formatting dates is just have some sample code that tries every permutation of the command.

   <html><head>
   <title>formatdates.asp</title>
   </head><body bgcolor="#FFFFFF"><html>
   <%'My ASP program that formats dates
   response.write "<hr>"
   for counter=0 to 4
      currentdate=now()
      response.write "today is..." & "<br>"
      response.write currentdate & "<P>"
10      select case counter
11      case 0
12         whichformat="vbgeneraldate"
13      case 1
14         whichformat="vblongdate"
15      case 2
16         whichformat="vbshortdate"
17      case 3
18         whichformat="vblongtime"
19      case 4
20         whichformat="vbshorttime"
21      end select
22      response.write "FormatDate(now()," & whichformat & ")="
23      response.write Formatdatetime(currentdate,counter) & "<P><HR>"
24   next%>

25   </body></html>


ASP Quick Lessons written by Charles M. Carroll
http://www.learnasp.com/learn/datetime.asp Page 22


Adding the date and time to your ASP pages

Date and Time By Tony Arguelles tony@southbaywebdesigns.com

Summary

Including the date and/or time on a web page can be a subtle yet valuable addition when designing a web site. The addition of the date to the home page can create the impression that a site is constantly being updated with new content since each time a visitor loads the page, the current date will be displayed.

In this tutorial I'll teach you how to add the date and time to your ASP pages using the VBScript FormatDateTime() function. I'll explain how the function works, teach you how to integrate it into your ASP pages and illustrate the output you'll get depending on the arguments you pass. I'll round out the tutorial of the FormatDateTime() function by covering a few limitations that it has, which might or might not be a big deal depending on your specific needs.

Just FYI, this article assumes you know basic HTML and how to add ASP scripts to your web pages.

The FormatDateTime() Function

Microsoft provides a ton of predefined VBScript functions designed to reduce coding time. The FormatDateTime() function is one of those powerful functions and is really easy to use, too. This function uses the following format:

FormatDateTime(date, format)

There are two arguments the function accepts: date and format. Table 1-1 below describes these arguments in greater detail:

   Table 1-1: The FormatDateTime() function and its arguments
Argument Argument Description
date This argument is required and can be any valid date expression such as Date or Now

format

This format constant or format value specifies how the date and/or time will be displayed on your ASP page.

When specifying the format argument, you can either type the Visual Basic constant name (name in left column), or the constant's corresponding value (0 - 4, from the middle column). They do the same thing, it's just less typing if you use the value.

Constant
Format Value
Format Description
vbGeneralDate
0
This is the default. Not specifying a value or specifying 0 will produce a date in the format of mm/dd/yy.

If the date expression is Now, it will also return the time, after the date, in hh:mm:ss PM/AM format.

vbLongDate
1

This is my personal favorite :-) Passing this value will produce a date in the format of
weekday, month day, year*

* The year is Y2K compliant :-).

vbShortDate
2

Passing this value returns a date formatted just like the default of 0 (mm/dd/yy).

vbLongTime
3
Passing this value returns the time in hh:mm:ss PM/AM format.

vbShortTime
4
Passing this value returns military time in this format hh:mm

Table 1-1 is a good reference once you've got a feel for how the FormatDateTime() function works or if you're an experienced programmer. For those of you that aren't clear on how all the information in table 1-1 relates to "real world" implementations, let's take a look at some examples:

Returning the Current Date

If you would like to display the current date, here are a few different ways to do it along with the results they produce:

<%= FormatDateTime(Date) %> returns: 3/11/2001
(You would get the same result by coding this: <%= FormatDateTime(Date, 0) %>)

<%= FormatDateTime(Date, 1) %> returns: Sunday, March 11, 2001

<%= FormatDateTime(Date, 2)%> returns: 3/11/2001

Returning the Current Time

If you would like to return the current time, here are a couple of ways to do that:

<%= FormatDateTime(Now, 3)%> returns: 10:39:25 AM

<%= FormatDateTime(Now, 4)%> returns: 10:39

Returning the Current Date and Time

If you would like to return the current date and time together, here's how to do just that:

<%= FormatDateTime(Now) %> returns: 3/11/2001 10:39:25 AM

If you're like me, you probably don't like the way the date and time displays above; it's not very cool looking, is it? In cases like this, you can actually include two FormatDateTime() functions next to each other, in order to get the date and time in a more desriptive format, like this:

<%= FormatDateTime(Date, 1) %>&nbsp;&nbsp;<%= FormatDateTime(Now, 3)%> returns:
Sunday, March 11, 2001   10:39:25 AM

Adding the code to your page

Integrating the code into your ASP pages is really easy; here is how the code would look on a page with basic HTML to display the date:

<html>
<head>
<title>Here's the date</title>
</head>

<body>

Thank you for coming to this page. The current date is: <%= FormatDateTime(Date, 1) %>

</body>

</html>

Limitations of the FormatDateTime() function

The FormatDateTime() function is an extremely handy bit of code that can help you add a touch of flair almost instantly. I would like to mention four limitations that stick out in my mind, which may be an issue to you (or your clients) depending on the project at hand:

Limitation 1: The unneeded zero

On the first through ninth days of a month the day shows up in the format of "Month 01, Year". I know it seems like a small thing but trust me, it's can be a big deal to some.

Limitation 2: Only basic formatting allowed

You are limited to basic formatting of the string that's returned by the FormatDateTime() function. Since the date and/or time function returns is a single string, you can bold, italicize and change the whole date/time by adding HTML or style sheet tags around it, but you can't change the display properties for a single part (e.g., the month).

With the FormatDateTime() function, you can do this:

<b><%= FormatDateTime(Date, 1) %></b> which would return this: Sunday, March 11, 2001

But you can't do this:

Wednesday, January 1, 1999

If limitations 1 or 2 are a major hang up for you, you'll need to use different ASP/VBScript techniques to add the date to your page. I'll cover those in my next article!

Limitation 3: The time isn't necessarily "their" time.

Limitation 3 is more of a by-product than a limitation, but I figured I would keep the naming conventions the same for this section. If you use the the FormatDateTime() function (or any other date related function) on the server side, the date/time returned will be whatever the server's date and time is, not your client's time from their system.

If you want to ensure that the date and/or time a visitor sees on your page is the date in their part of the coutry or world, then consider using client side VBScript as an Internet Explorer only solution, or switch to client side JavaScript for a universal browser solution.

Limitation 4: It's static.

Think of the displayed date or time as a "snap shot" of when the page was requested by the visitor. You cant use this function to display a "clock" that updates every second, or automatically update the date on the page when one day turns to the next.

If you wanted to display a dynamic clock on your page, you would need to use client side JavaScript, or VBScript (IE only) to handle that task.

I hope you've enjoyed this article on the FormatDateTime() function. I'll be back soon with more date and time related ASP fun! If you have any questions or comments, send me an Email at: tony@southbaywebdesigns.com


ASP Quick Lessons written by Charles M. Carroll
http://www.learnasp.com/learn/DoLoop.asp Page 23


DoLoop ASP Quick Lessons

Do Loop Part #1  by Charles Carroll

To execute a code sequence more than once ASP provides:

Either of these statements can be followed by UNTIL or WHILE.

DO UNTIL
     .....code to be repeated...
LOOP

DO
     .....code to be repeated...
LOOP UNTIL


ASP Quick Lessons written by Charles M. Carroll
http://www.learnasp.com/learn/DoLoop2.asp Page 24


DoLoop2 ASP Quick Lessons

Do Loop and Timeouts by Charles Carroll

A loop that is infinite will not run forever. IIS will timeout the script (default is 90 seconds).

Here is an infinite loop that IIS will timeout:
   <%response.buffer=true%>
   <TITLE>doloop1.asp</TITLE>
   <body bgcolor="#FFFFFF">
   <HTML>
   <%
   DO
      counter=counter+1
      response.write counter & "<br>"
      response.flush
10   LOOP
11   %>

12   </BODY>
13   </HTML>
14   

Here is an infinite loop that we explicitly set a timeout for:
   <%
   response.buffer=true
   server.scripttimeout=20
   %>

   <TITLE>loop2.asp</TITLE>
   <body bgcolor="#FFFFFF">
   <HTML>
   <%
   DO
10      counter=counter+1
11      response.write counter & "<br>"
12      response.flush
13   LOOP
14   %>

15   </BODY>
16   </HTML>
17   
18   

It has been assumed that a timed out script was impossible to intercept, but the next lesson shows how to use the transactional aspect of an ASP script to capture this elusive condition.


ASP Quick Lessons written by Charles M. Carroll
http://www.learnasp.com/learn/DoLoop3.asp Page 25


DoLoop3 ASP Quick Lessons

Do Loop Intercept Timeouts by Charles Carroll

The transactional nature of ASP pages can be used to intercept a script timeout.

loop3.asp traps a timeout:
   <%@ TRANSACTION=Required%>
   <%
   response.buffer=true
   server.scripttimeout=20
   %>

   <HTML>
   <TITLE>loop3.asp</TITLE>
   <body bgcolor="#FFFFFF">
   </BODY>
10   <%
11   DO
12      counter=counter+1
13      response.write counter & "<br>"
14   LOOP
15   response.flush
16   response.write "Script executed without incident"
17   %>

18   </HTML>
19   <%
20   Sub OnTransactionAbort()
21          response.clear
22       Response.Write "The Script Timed Out"
23   end sub
24   %>

loop4.asp succeeds and does not trigger the trap:
   <%@ TRANSACTION=Required%>
   <%
   response.buffer=true
   server.scripttimeout=40
   %>

   <HTML>
   <TITLE>loop4.asp</TITLE>
   <body bgcolor="#FFFFFF">
   </BODY>
10   <%
11   DO  UNTIL counter=400
12      counter=counter+1
13      response.write counter & "<br>"
14   LOOP
15   response.flush
16   response.write "Script Exexuted without incident!"
17   %>

18   </HTML>
19   <%
20   Sub OnTransactionAbort()
21          response.clear
22       Response.Write "The Script Timed Out"
23   end sub
24   %>


ASP Quick Lessons written by Charles M. Carroll
http://www.learnasp.com/learn/server.asp Page 26


Server Variables from ASP Quick Lessons

Server Variables by Charles Carroll

Available Server Variables are the result of a combination of the browser software and the server software. They are not always exactly the same on your server and with specific browsers as we document here. Server Variables are retrieved with request.servervariables("variablename"), for example:

sn=request.servervariables("script_name") name of script, i.e./learn/server.asp in this case
ref=request.servervariables("http_referer") name of site page (unless they just typed the URL) they clicked on to get here.
br=request.servervariables("http_user_agent") Identification string emitted by browser.
lan=request.servervariables("http_accept_language") en for english. Basically indicates language the browser is targetted to.
user=request.servervariables("logon_user") IE passes back NT logon in this variable!

This script below demonstrates accessing a couple of these variables:
   <html><head>
   <title>server.asp</title>&
   <body>
   <%
   sn=request.servervariables("script_name")
   response.write "Script Name=" & sn & "<br>"
   
   ref=request.servervariables("http_referer")
   response.write "Page thats links to this=" & ref & "<br>"
10   
11   ua=request.servervariables("http_user_agent")
12   response.write "Browser String=" & ua & "<br>"
13   
14   lan=request.servervariables("http_accept_language")
15   response.write "Browser Language=" & lan & "<br>"
16   
17   user=request.servervariables("logon_user")
18   response.write "NT Logon Name=" & user & "<br>"
19   %>

20   </body></html>


ASP Quick Lessons written by Charles M. Carroll
http://www.learnasp.com/learn/server2.asp Page 27


Server Variables #2 from ASP Quick Lessons

Server Variables To Determine Domain

Server Variables have many uses. We will show you a popular one here. Web sites are typically attached to an IP address, but sometimes several domain names may point to the same IP. A clever ASP script could display the same page different ways depending on which domain name was typed utilizing the HTTP_HOST. Our site, for example has three domain names tied to the same IP ( activeserverpages.com, asptraining.com, learnasp.com, help.activeserverpages.com ) and the following script will provide different results depending on what domain name it is called from:

   <html><head>
   <title>server2.asp</title>&
   <body>
   <%
   host=lcase(request.servervariables("HTTP_HOST"))
   SELECT CASE host
      CASE "www.asptraining.com"
         response.write "Welcome Training Customer!"
      CASE "www.activeserverpages.com"
10         response.write "Welcome To Our Reference Site!"
11      CASE "www.learnasp.com"
12         response.write "Welcome To Our Tutorial!"
13      CASE "www.aspeuro.com"
14         response.write "Welcome To Our European Site!"
15      CASE "www.asplists.com","www.asplist.com"
16         response.write "Welcome To Our ASP listservers!"
17      CASE "www.aspconventions.com","www.aspconvention.com"
18         response.write "Welcome To Our ASP convention site!"
19      CASE ELSE
20         response.write "Welcome!"
21   END SELECT
22   %>

23   </body></html>


ASP Quick Lessons written by Charles M. Carroll
http://www.learnasp.com/learn/serverall.asp Page 28


All Server Variables from ASP Quick Lessons

Listing All Server Variables by Charles Carroll

The available Server Variables vary based on the result of a combination of the browser software and the server software. They are not always exactly the same on your server and with specific browsers as we document here. There is an easy way to obtain a list. If the script is executed on a  given browser, the Server Variables displayed will reflect that browser plus your server.

   <%
   for each thing in request.servervariables
      tempvalue=request.servervariables(thing)
      response.write thing & "=" & tempvalue & "<br>"
   next
   %>

Since the above script appears in dozens of books and websites, we wanted to provide you with a better version. This script may prove useful as it will

   <html><head>
   <TITLE>serverall.asp</TITLE>&
   <body bgcolor="#FFFFFF">
   <%
   Response.Write("<P><B>Server Variables</b><br>")
   BlankVars="<P><B>Blank Server Variables</b><br>" & vbcrlf
   quote=chr(34)
   For Each Key in Request.ServerVariables
      If instr(Key,"_ALL")+instr(key,"ALL_")=0 then
10         tempvalue=trim(request.servervariables(Key))
11         If len(tempvalue)=0 then
12            BlankVars=BlankVars & Key & ", "
13         Else
14            response.write "request.servervariables(" & quote
15            response.write Key & quote & ") "
16            response.write " =<br><B>" & tempvalue & "</b><p>" & vbcrlf
17         End If
18      end if
19   Next
20   response.write mid(BlankVars,1,len(BlankVars)-2)
21   %>

22   </body></html>

If the server has been secured with https:// then the following script will display some additional variables:
https://secure.activeserverpages.com/learn/test/serverall.asp


ASP Quick Lessons written by Charles M. Carroll
http://www.learnasp.com/learn/randomadvice.asp Page 29


dbtable

Random Advice / Rotating Information by Charles Carroll

This page demonstrates how to use several commands together to serve varying content based on a random number:

The script randomadvice.asp shows different advice every time the pge is refreshed:

   <html><head>
   <TITLE>randomadvice.asp</TITLE>
   </head>
   <body bgcolor="#FFFFFF">
   <%
   ' generate a random number 1-6
   randomize
   randomnum=int(rnd*6)+1
   SELECT CASE randomnum
10   CASE 1,2,3%>

11      Plant your crops early this year<br>
12      No frost expected<br>
13   <%CASE 4%>
14      Never play cards<br>with a man named after a city<br>
15   <%CASE 5%>
16      You can never be too rich, too thin or backup too often<br>
17   <%CASE 6%>
18      A swallow keeps away the stork<br>
19   <%END SELECT%>
20   </body></html>


ASP Quick Lessons written by Charles M. Carroll
http://www.learnasp.com/learn/bc.asp Page 30


bc from ASP Quick Lessons

Browser Capabilites

The script below demonstrates the most commonly used property of the Browser Capabilites component.

   <html><head>
   <TITLE>bc.asp</TITLE>
   </head><body bgcolor="#FFFFFF">
   <% Set bc = Server.CreateObject("MSWC.BrowserType") %>
   Browser Name: <%=bc.browser %><p>
   Browser Version: <%=bc.version%><p>
   <% if (bc.frames = TRUE) then %>
   I  noticed you do frames<p>
   <% else %>
10   I  noticed you are frame challenged<p>
11   <% end if %>
12   <% if (bc.tables = TRUE) then %>
13   I  noticed you do tables<p>
14   <% else %>
15   I  noticed you can't do tables<p>
16   <% end if %>
17   <% if (bc.BackgroundSounds = TRUE)then %>
18   I  noticed you allow me to play music<p>
19   <% else %>
20   I  noticed you aren't a music listener<p>
21   <% end if %>
22   
23   <% if (bc.vbscript = TRUE) then %>
24   I  noticed you are VBscript capable<p>
25   <% else %>
26   I  noticed you can't understand VB Script<p>
27   <% end if %>
28   
29   <% if (bc.javascript = TRUE) then %>
30   I  noticed you understand JScript<p>
31   <% else %>
32   I  noticed you don't understand JScript<p>
33   <%
34   end if
35   set bc=nothing
36   %>

37   </body></html>


ASP Quick Lessons written by Charles M. Carroll
http://www.learnasp.com/learn/bcdetails.asp Page 31


Browser Capabilities Details

Browser Capability Details  (by Charles Carroll)

Any ASP script attempting to detect a browser needs to realize the following:

Browscap

Cyscape offer a downloadable latest, greatest BROWSCAP.INI and even offers e-mail subscriptions so you get the latest one sent to you. Visit http://www.cyscape.com/browscap to pick it up and/or subscribe. You can test in advance whether your browser is recognized by this file at http://www.cyscape.com/browtest.asp.

The latest, greatest BROWSCAP.ZIP  from Juan Llibre is available at http://www.asptracker.com.
Juan Libre's Detect Your Screen Res articles is another sample making use of BROWSCAP.INI.

These two sources give you the means to correctly identify the latest browser.

BROWSERAWARE1.gif (2779 bytes) The BrowserHawk Component at http://www.cyscape.com/browserhawk offers accuracy far better than what any browscap file can provide. It also provides information on more than twice as many properties, including FileUpload, MouseOver, SSL, DHTML, StyleSheets, Authenticode, OSDetails, Language, and many more! It will even download and install updated browser definition files for you automatically! Evaluation download available at:
http://www.cyscape.com/browserhawk/download.asp


ASP Quick Lessons written by Charles M. Carroll
http://www.learnasp.com/learn/aspbrowserheck.asp Page 32


Listserrver Join aspbrowserheckListserver for more info @

http://www.asplists.com/asplists/aspbrowserheck.asp

Related Links:

 
Validate HTML @
   http://validator.w3.org
Obtaining Your Users Browser Information @
   http://www.4guysfromrolla.com/webtech/121400-1.shtml
Detect Browser @
   http://www.learnasp.com/learn/bc.asp
Fix HTML browser problems @
   http://www.w3.org/People/Raggett/tidy/
HTML Validator @
   http://www.htmlvalidator.com/
AOL Coding @
   http://webmaster.info.aol.com/
the BEST browser detection component @
   http://www.browserhawk.com
AOL Coding @
   http://www.aolserver.com/
Update Browscap.ini @
   http://www.learnasp.com/learn/bcdetails.asp
Dynamic Duo Cross-Browser DHTML/Jscript @
   http://www.dansteinman.com/dynduo/

Recommended Books:

BrowserHawk detects:
 - disabled cookies
 - disabled JavaScript
 - Flash / plugins
 - screen size, more!
  FREE download
        

Related Lists:

Evolt.org lists @
   http://lists.evolt.org/
Good Javascript List @
   http://www.mountaindragon.com/javascript/
[aspClient] - DHTML, frames, active-x, etc. @
   http://www.asplists.com/asplists/aspclient.asp
Flash + ASP @
   http://www.asplists.com/asplists/aspflash.asp

Rules:

Mailing List Manners (suggested by Bob Filipiak) @
   http://db.tidbits.com/getbits.acgi?tbser=1141
Ken Shaffer's Advice on Asking For Help... @
   http://www.adopenstatic.com/personal/help.asp


ASP Quick Lessons written by Charles M. Carroll
http://www.learnasp.com/learn/statemanagement.asp Page 33


Section Contents

State Management
        State Management Introduction (stateintro.asp) - Page 34
        What are ASP Sessions? (sessionswhat.asp) - Page 35
        Application Data (sessionsapps.asp) - Page 36
        Application Data: Worlds Fastest ListBox (speedappdata.asp) - Page 37
        XML, Database Caches - Fast Retrieval (xmlfastlist.asp) - Page 38
        Say No To Databases w/Sessions or Application scope (nodbsession.asp) - Page 39
        Session Overview & Myths (sessionoverview.asp) - Page 40
        Sessions: Global.asa and Scalability (globalproblems.asp) - Page 41
        Sessions: Global.asa Events (global.asp) - Page 42
        Global.asa, Sessions, Custom Stats Resources (statemore.asp) - Page 43
        State Methods: Pros and Cons (stateproscons.asp) - Page 44
        Pass Data w/Hidden Fields (hidden.asp) - Page 45
        Pass Data w/Cookies (cookies.asp) - Page 46
        Pass Data w/Session Vars (statesessions.asp) - Page 47
        Pass Data w/ID tied to database (statedb.asp) - Page 48
        [aspStateManagement] Listserver (aspstatemanagement.asp) - Page 49


ASP Quick Lessons written by Charles M. Carroll
http://www.learnasp.com/learn/stateintro.asp Page 34


subdates from ASP Quick Lessons

State Management Intro by Charles Carroll

Anyone using a browser is accessing the web via HTTP. HTTP is a stateless protocol. What that means is every page fetched from the website has NO MEMORY of the last page fetched.

Whenever we devise some "tricks" so that a web page seems to remember some previous information we call that maintaining state with the user.

Keep in mind no matter how we do this there are limits. Each method may not work in some narrow situation.

A listserver exists where this is the ONLY topic discussed, see:
http://www.asplists.com/asplists/aspstatemanagement.asp


ASP Quick Lessons written by Charles M. Carroll
http://www.learnasp.com/learn/sessionswhat.asp Page 35


What are Sessions ASP Quick Lessons

What are Sessions?

Sessions are a very convenient ASP feature. When someone visits a web page on your site, ASP calls that a "session" and immediately can differentiate that user from all other users at a site. Anything stored in that user's session can be retrieved and manipulated from that page and the next pages they visit, and the data will be tied to that user. 

Session data is generally attached to one user. When a user visits their first page of your site, that page and every page they visit is collectively called a session. Any data attached stored in that session object is private to the pages that user is visiting.

The code to store data in a session variable is simple.  Here we will allow a user to flip a coin, i.e. flipcoin.asp and count their successes:

   <%
   response.write "Coin Tossed!<br>"
   randomize
   randomnum=int(rnd*2)+1
   IF  randomnum=1 THEN
      session("heads")=session("heads")+1
   ELSE
      session("tails")=session("tails")+1
   END IF
10   response.write "Heads= " & session("heads") & "<br>"
11   response.write "Tails= " & session("tails") & "<br>"
12   %>

Even though there are many people at the site they all have different scores for their "heads" and "tails" count. They each has a session and it co-ordinates and differentiates their values.

A much more practical example could protect access to a page based on a session variable that indicated their security level determined once upon login, see:
http://www.learnasp.com/learn/security.asp

Some basic things should be noted:


ASP Quick Lessons written by Charles M. Carroll
http://www.learnasp.com/learn/sessionsapps.asp Page 36


Applications vs. Sessions ASP Quick Lessons

Application Variables by Charles Carroll

There are two kinds of data that your program can manipulate that can be used to "remember" data:

Session data
which is "attached" to a person browsing your site. If the same page is accessed by 12 different users each user may have totally different session values.

Application data
which is attached to the webserver and is the same no matter which user is accessing the site.

Application values are visible to every user. But since, unlike session data, any web page could change the application's data there is a potential concurrency issue. The lock and unlock method of the application object eliminate concurrency issues. Once an application is locked, no other updates to the application object can occur until the unlock is executed.

One use for an application variable would be to store variables most scripts on a site needed to access or even HTML cached from databases like in
The Worlds Fastest Listbox Example @
http://www.learnasp.com/learn/speedappdata.asp

One example I use to illustrate the conceptual use for each type of data would be a website that simulated a casino. Player's individual winnings make perfect sense to maintain in session variables. However, the total number of players at each "virtual table" (blackjack, roulette, etc.) would be application data as the would be the same regardless of an individual player's status.

Here is a file called appblackjacklook.asp that displays how many people are at the table.

   <%
   response.write "Over at the BlackJack Table<br>"
   response.write "There are " & application("bjplayers") & " players there!<br>"
   %>

Here is a file called appblackjackarrive.asp that could be included in any script where someone arrived at the blackjack table!

   <%
   response.write "Welcome to the BlackJack Table<br>"
   application.lock
   application("bjplayers")=application("bjplayers")+1
   application.unlock
   response.write "There are " & application("bjplayers") & " players here!<br>"
   %>

Here is a file called appblackjackleave.asp that could be included in any script where someone left the blackjack table!

   <%
   response.write "Thanks for playing BlackJack!<br>"
   application.lock
   application("bjplayers")=application("bjplayers")-1
   IF  application("bjplayers")<0 THEN
      application("bjplayers")=0
   END IF
   application.unlock
   response.write "There are " & application("bjplayers") & " players still at the table!<br>"
10   %>


ASP Quick Lessons written by Charles M. Carroll
http://www.learnasp.com/learn/speedappdata.asp Page 37


dbtable

Worlds Fastest Listbox w/Application Data
by Charles Carroll

Sometimes data (like a HTML list box) is displayed on many pages of a website. In fact, the database generated list box is displayed thousands of times a day, and the database is queried every time, but it is unnecessary. The database it is drawn from is not changing thousands of times a day.

In the following example any page that displays the list boxes needs to only access the application variables, not hit the database. Very speedy. If the data changes or gains new records, a trigger mechanism could be added to sense data changes and only rebuild the list box if records were added or changed. Here is a demo script that displays the listboxes without re-querying the database.

ListMakedemo.asp is the main script. Simple enough.

   <HTML>
   <TITLE>listmakedemo.asp</TITLE>
   <body bgcolor="#FFFFFF">
   <br>
   City: <!--#include virtual="/learn/test/listcity.asp"-->
   <br>
   State: <!--#include virtual="/learn/test/liststate.asp"-->
   <br>
   Zip: <!--#include virtual="/learn/test/listzip.asp"-->
10   </BODY></html>
11   
12   
13   
14   

ListCity.asp displays listbox of cities.

   <!--#include virtual="/learn/test/lib_listmake.asp"-->
   <%
   IF  application("list_city")="" THEN
      myDSN="DSN=student;uid=student;pwd=magic"
      mySQL="select distinct city from publishers"
      application("list_city")=query2htmlist(mySQL,"cities",myDSN)
   END IF
   response.write application("list_city")   
   %>

ListState.asp displays listbox of states

   <!--#include virtual="/learn/test/lib_listmake.asp"-->
   <%
   IF  application("list_states")="" THEN
      myDSN="DSN=student;uid=student;pwd=magic"
      mySQL="select distinct state from publishers"
      application("list_states")=query2htmlist(mySQL,"state",myDSN)
   END IF
   response.write application("list_states")   
   %>

ListZip.asp displays listbox ofzips.

   <!--#include virtual="/learn/test/lib_listmake.asp"-->
   <%
   IF  application("list_zips")="" THEN
      myDSN="DSN=student;uid=student;pwd=magic"
      mySQL="select distinct zip from publishers"
      application("list_zips")=query2htmlist(mySQL,"zip",myDSN)
   END IF
   response.write application("list_zips")   
   %>

10   

Lib_Listmake.asp is a library that makes it easier to make listboxes.

   <%
   function query2htmList(myquery,myname,myDSN)
      dim conntemp, rstemp
      set conntemp=server.createobject("adodb.connection")
      conntemp.open myDSN
      set rstemp=conntemp.execute(myquery)
      query2HTMlist="<Select name='" & myname & "'>"
      do until rstemp.eof
         thisfield=trim(RStemp(0))
10         if isnull(thisfield) or thisfield="" then
11            ' ignore
12         else
13            query2HTMlist=query2HTMlist & "<option>" & thisfield & "</option>"
14         end if
15         rstemp.movenext
16      loop
17            query2HTMlist=query2HTMlist & "</select>"
18      rstemp.close
19      set rstemp=nothing
20      conntemp.close
21      set conntemp=nothing
22   end function
23   %>

ListMakeClear.asp is a crude mechanism to force all the listboxes to refresh. It could be invoked on a timed basis (every 15 minutes for example) or triggered by data-changes.

   <%
   application("list_city")=""
   application("list_states")=""
   application("list_zips")=""
   %>


ASP Quick Lessons written by Charles M. Carroll
http://www.learnasp.com/learn/xmlfastlist.asp Page 38


dbtable

Worlds Fastest Listbox with XML, Application Variables
by Jamiel Humayun Jhumayun@liveperson.com
and Ian Payne  ivpayne@wagga.fsnet.co.uk

Sometimes data (like a HTML list box or table) is displayed on many pages of a website. In fact, the database generated list box is displayed thousands of times a day, and the database is queried every time, but it is unnecessary. The database it is drawn from is not changing thousands of times a day.

In the following example any page that displays the database needs to only transform the XML application variables, not hit the database. Very speedy. If the data changes or gains new records, a trigger mechanism could be added to sense data changes and only rebuild the list box if records were added or changed. Here is a demo script that displays the listboxes without re-querying the database.

DisplayCity.asp is the main script. Simple enough.

   <!--#include file="XMLLibrary.asp"-->
   <html>
   <head>
      <title>Display XMLized Listbox</title>
   </head>
   <body bgcolor="#FFFFFF">
   <b>City Table:</b> <br>
   <% DisplayCityTable() %><br><br>
   <b>City List:</b> <br>
10   <% DisplayCityList() %><br><br>
11   </body>
12   </html>

ListBox.xsl is the style sheet to give it a list box look

   <?xml version="1.0"?>
   <xsl:stylesheet xmlns:xsl="http://www.w3.org/TR/WD-xsl">
   <xsl:template match="/">
   <select>
   <xsl:for-each select="xml/rs:data/z:row">
          <option><xsl:value-of select="@city"/></option>
   </xsl:for-each>
   </select>
   </xsl:template>
10   </xsl:stylesheet>

Table.xsl is the style sheet to give it a list box look

   <?xml version="1.0"?>
   <xsl:stylesheet xmlns:xsl="http://www.w3.org/TR/WD-xsl">
   <xsl:template match="/">
   <table cellpadding="2" cellspacing="0" border="1" width="100%">
   <xsl:for-each select="xml/rs:data/z:row">
   <tr><td><xsl:value-of select="@city"/></td></tr>
   </xsl:for-each>
   </table>
   </xsl:template>
10   </xsl:stylesheet>

XMLlibrary.asp is the library that does most of the work.

   <%
   adPersistXML=1
     
   Function GenXML (objRs)
         set stmXML = CreateObject("ADODB.Stream")
         
         If Not objRs.EOF Then
          objRs.Save stmXML, adPersistXML ' needs ADO 2.5
         End If
10         GenXML = stmXML.ReadText
11         Set stmXML = Nothing
12     
13   End Function
14     
15   Function GetCityXML ()
16          ' Database connection - Usually kept in an include file, but presented for display purposes
17          strConnection = "DSN=student;UID=student;PWD=magic;"
18          Set objConn = Server.CreateObject ("ADODB.Connection")
19          objConn.Open strConnection
20          strSQL = "SELECT DISTINCT city FROM publishers"
21          Set objRs = objConn.Execute (strSQL)
22          GetCityXML = GenXML(objRs)
23          Set objConn = Nothing
24          Set objRs = Nothing
25   End Function
26     
27   Function RenderXML (strXML,strStyleSheet)
28         Set objXML = CreateObject("MSXML.DOMDocument")
29         Set objXSL = CreateObject("MSXML.DOMDocument")
30         objXML.loadXML(strXML)
31         objXSL.load(Server.MapPath(strStyleSheet))
32         Response.Write objXML.transformNode (objXSL)
33         Set objXML = Nothing
34         Set objXSL = Nothing
35   End Function
36     
37   Sub DisplayCityTable()
38     if Application("City") = "" then Application("City") = GetCityXML()
39         strStyleSheet = "table.xsl"
40         Call RenderXML (Application("City"),strStyleSheet)
41   End Sub
42     
43   Sub DisplayCityList()
44         if Application("City") = "" then Application("City") = GetCityXML()
45         strStyleSheet = "listbox.xsl"
46         Call RenderXML (Application("City"),strStyleSheet)
47   End Sub
48     
49   %>

XMLcacheclear.asp is called to force a fresh database display.

   <%
   Application("City") = ""
   %>


ASP Quick Lessons written by Charles M. Carroll
http://www.learnasp.com/learn/nodbsession.asp Page 39


VB Component Building Guidelines from ASP Quick Lessons

Databases and Sessions.... Just Say No!
by Charles Carroll

Many new ASP programmers and some who even call themselves experienced aspire or accomplish placing recordsets and/or applications in session and/or application variables. They do it to speed things up but actually ensure that the site will perform slower as it gets busier. 

Putting a recordset or application into application or session scope leads to:

What works for few users will not for many

Imagine how fast and convenient a Porsche is when driving to Las Vegas with your significant other. Must be the best way to get there... Right? Now imagine a bunch of seniors want to go. 200 seniors x 100 trips in the porsche. Ouch! The tour bus or an airplane scales. The porsche does not. Developers should always design for scaling not minimal users.

Application Level Connections

Mechanically, creating one Application level variables with a database connection is simple.

SUB application_onstart
   set application("theCONN")=server.createobject("adodb.connection")
END SUB

Then any code that wants to use that connection might look like this:
<%
mySQL="select * from publishers where state='NY'
set rstemp=application("theconn").execute(mySQL)
%>

However this code will not scale well. The code is mechanically easy, but the scripts using this code will suffer from Thread-Affinity and Serialization.

An application variable lives until a web server shuts down. It also lives on a specific thread; we would say the object has thread affinity. Any script utilizing that object must live on same thread, as that object or make an expensive marshalled call to talk to that object.

Thread Affinity

Thread affinity is bad. If a request comes in it would be fast if any thread could perform the task. Thread affinity guarantees only 1 thread can service the request and if that thread is busy the task waits in line for that thread, despite other threads who may be able to service the request.

http://www.learnasp.com/advice/threads.asp
explains threading fundamentals.

Serialization is an enemy of Scalability

If multiple tasks all have affinity to the same thread they become serialized, that is to say they all run in sequence. As a real-world analogy for serialization imagine you wanted to buy a meal at a fast-food cashier and the person in front of you ordered 150 sandwiches for their swim-team. You don't get your 1 sandwich until they finish their order. 6 request for 150 records from a database means the fourth request for 1 record comes after those 900 are retrieved. Without thread affinity the requests could be divided among available threads.

Conclusion: All recordsets and database access would have some level of thread affinity if one connection only is made in global.asa. The side-effect would be recordsets that were forced to specific threads and serialized requests effectively slowing a site's overall performance and for specific scripts.

Recordsets stored at Sessions Level...

Mechanically, this is easy to accomplish:

SUB session_onstart
   set session("rstemp")=server.createobject("adodb.recordset")
END SUB

Then any code that wants to use that connection might look like this:
<%
    ...
    mySQL="select * from publishers where state='NY'
    set session("rstemp")=conntemp.execute(mySQL)
%>

However this code will not scale well. The code is mechanically easy, but the scripts using this code will suffer from Thread-Affinity, Serialization, and there will always be more recordsets than users accessing a site. In fact a more aggregious version of Thread Affinity occurs which I will nickname Thread-Locking.

Thread Affinity Part #2

In IIS3 and IIS4 once a user is assigned a session object (recordset or VB5/VB6 component) with thread affinity every script run in that session is forced onto the thread the first script is assigned. It effectively handcuffs every user's script to the thread their first script was assigned. This occurs because recordsets and VB5 and VB6 need to store their data on a specific thread and until destroyed (unlike C++ components which specifically aggregate the Free Thread marshaller) the objects may never be moved to a different thread which hurts performance.

More Recordsets than Users??? Please explain...

If for example a mere 20 users who access 1 page each and no others at tour site, their session objects (in this case recordsets) persist for the default session timeout (20 minutes unless the registry is modified or a page explicitly sets it using the session.timeout command. If then 50 users access several scripts and 20 of them go lunch or go home for the day, the recordsets will waste memory until their session times out. In this example there would be 90 recordsets and 30 active users within minutes. How can any scenario where significantly more resources are allocated than are being used be efficient?

http://www.learnasp.com/learn/globalproblems.asp
explains a typical scenario.

Create and Destroy on Every Page

Even though every page creates and destroys connections, the newly created ones can execute on any thread. Also because of round-robin execution resources are used sparingly and connections are never open too long.

Make Sure Connection Pooling is in Effect

Connection Pooling can speed up sites. ADO invisibly can co-ordinate that any destroyed connections are not instantly destroyed, instead they are left ready to be grabbed by the next page who requests creating a connection. That page's code has a create request that gets intercepted at a low-level and given an already created connection ready to do database access. The programmers code then is not being executed literally; their create requests often get serviced by already created connections.

http://www.learnasp.com/learn/dbpooling.asp
has more information and details.

What is the fastest way then (if I want fast, scalable database displays)?

"The Worlds Fastest Listbox"
http://www.learnasp.com/learn/speedappdata.asp
shows a lightning fast way to display databases.

GetString to speed up Data Transfer
http://www.learnasp.com/learn/dbtablegetstring.asp

GetRows to speed up Data Transfer
http://www.learnasp.com/learn/dbtablegetrows.asp

All we discuss is fast code over at:
http://www.asplists.com/asplists/aspfastcode.asp

What If I am willing to pay the price?

Make sure you test the load using tools like the Web Stress Tool @
http://homer.rte.microsoft.com

Much more information on scalability can be found on
http://www.asplists.com/asplists/aspscalability.asp
which has links  and a signup for an excellent 2 way listserver.


ASP Quick Lessons written by Charles M. Carroll
http://www.learnasp.com/learn/sessionoverview.asp Page 40


Applications vs. Sessions ASP Quick Lessons

Session Overview & Myths by Charles Carroll

Session data is greatly misunderstood. Sessions themselves were a subtle and complex issue, but the subject was confused considerably by bad information people gathered from code others made that misused sessions. It is also confused by anecdotal performance evidence when a site is small, or the testing is only done within simple stress tests that don't reveal all the speed issues. We will clarify it all now.

A couple analogies may help. A Porsche seems really fast to get anywhere (of course we assume you have 2 passengers) until you have 3-10 passengers. Then a mini-van will beat it because you have less trips to make. In client-server terms the Porsche doesn't SCALE WELL for more than 2 passengers. On the other hand, when a group of 100 wants to go to Atlantic city for the weekend we recommend a Tour Bus. However, someone taking a Tour Bus to the grocery store has anecdotal evidence it is not as fast as a Porsche.

Fact #1: When a browser window closes, the session DOES NOT end.

Fact #2: <%session.abandon%> command can end a session.

Fact #3: Another way a session ends is when a user has not visited any page within that site/application with  ___ minutes. The default is 20 minutes of inactivity. The following script can show what the settings are on your server:
   <html><head>
   <TITLE>sessionsettings.asp</TITLE>
   </head>
   <body bgcolor="#FFFFFF">
   <%
   response.write "Session Timeout=" & session.timeout & "minutes <br>"
   %>

   </body></html>

Fact #4: Session ids are not guaranteed to be different anytime a new session is generated. If there are 1,000 sessions there will be 1,000 unique session ids. But if 200 people loose session (due to timeout or explicit .abandon) and 150 new sessions are begun ASP may and will certainly use the same session IDs it was using earlier. 

Myth #1: Storing large objects (recordsets, database data, objects) users access in sessions saves memory*.

No. No. No. Since sessions start when users access one page and don't end until 20 minute after they access the last page. Think about it. If 200 news persons a minute hit your site for 5 minutes that is 1,000 sessions and appropriately 1000 x the memory consumed for session variables. If 500 people go away, you still have 1000 sessions and 500 users (twice as much memory is consumed as needed) until the server detects 20 minutes of inactivity for those 500 users who are not on the site.

Application variables (not session variables) can be used this way without wasting memory. They could be to store variables most scripts on a site needed to access or even HTML cached from databases like in The Worlds Fastest Listbox Example @
http://www.learnasp.com/learn/speedappdata.asp

Myth #2: Storing large objects (recordsets, database data, objects) users access in sessions speeds up access.

No. No. No. Objects in sessions have several potential speed barriers depending on their memory model.

Serialization explained: If 100 users hit the site their use of that code is in sequence. If all the users retrieves 10-20 records from a database you might notice no effect. But if person 3 retrieves 2,000 records, person 4 retrieving 2 records will occur after the person 3 retrieves 2,000 records. OUCH!!!!! Person 4 will think the webserver is very slow only retrieving 2 records.

Free-Threading explained: Users execution is more round-robin like where the webserver does not have to finish each users request before moving to another user. The code may be able to move to User 4 and grab their records and then person 5 and later finish person 3's large request.

Threads explained: Your web server spawns threads (4 per CPU is the default in IIS4; it should be adjusted to 20 see http://www.learnasp.com/learn/speedserver.asp. If your webserver had for example 4 threads, then 1000 users might be 250 per thread or 700 on one thread and 100 each on the other threads. The latter is a severe imbalance as one thread is overworked (thus slower) while other threads are underworked.


ASP Quick Lessons written by Charles M. Carroll
http://www.learnasp.com/learn/globalproblems.asp Page 41


GlobalProblems from ASP Quick Lessons

Global.asa Overkill by Charles Carroll

A global.asa file is a used extraneously and quite wastefully, but can be a very useful tool. First let us bring out what is good and bad about it.

Application variables are good. Since there is only one application variable in memory, no matter how many users are on your site, they can be a convenient place to store central information and retrieve it fast. Since there is only one application variable in memory regardless of the number of users at your site, remember the following characteristics:

Session variables (particularly COM objects put in a session variable) can:

Session Variable Constraints

Session variables containing simple variables (texts, numbers, dates, NOT COM objects) are not so wasteful as to be prohibitive. BUT remember, if you write any script that depends on session variables you are working under the following assumptions (and if these restrictions are fine, then use sessions as much as you need to):

If the task could be accomplished with hidden fields instead of session variables, then those limitations are not in effect -- and most tasks can.

Good uses of global.asa and session data include:

Examples of Wasteful Code and Alternatives...

Code that is particularly wasteful is code that places database connection info in the global.asa, i.e.

session_onstart
   session("dbname")="DSN=employees;"
   session("dbuser")="whoever"
   session("dbpass")="majic"
end sub

and the script that goes with it looks like this:

... code ....
set conntemp=server.createobject("adodb.connection")
conntemp.open session("dbname") & "uid=" & session("dbuser") & ";pwd=" & session("dbpass")
... code ....

Why? Do 700 users hitting that site hit 700 different databases with 700 different userids and passwords at the database level. Just 700 wasted session variables...Session variables are the worst way to keep such data; application variables the best or other mechanisms. Unfortunately Visual Interdev grossly misuses sessions and creates this bizzare concept in people's brains.

If for example, 700 users connect to a page using session variables to store DSN info, etc. You have 700 DSN variables in memory all with the same value. The purpose of sessions is to have separate data for users not the same data replicated for every session. Plus it means the site is unusable to a user not accepting cookies unnecessarily. It is really necessary to require cookies to display a database page where the DSN to the database does NOT change over a multi-month/year period?

The better alternatives would be:

Include Files (cheap and easy)

lib_connection.asp

<%
dbname="DSN=employees;"
dbuser="whoever"
dbpass="majic"
%>

and the script that goes with it looks like this:

<!--#include virtual="/lib_connection.asp"-->
... code ....
set conntemp=server.createobject("adodb.connection")
conntemp.open dbname & "uid=" & dbuser & ";pwd=" & dbpass
... code ....

Application Data (involves a COM object, but is memory cheap)

application_onstart
   application("dbname")="DSN=employees;"
   application("dbuser")="whoever"
   application("dbpass")="majic"
end sub

and the script that goes with it looks like this:

... code ....
set conntemp=server.createobject("adodb.connection")
conntemp.open application("dbname") & "uid=" & application("dbuser") & ";pwd=" & application("dbpass")
... code ....

In both approaches, if 700 users hit the site, no user specific variables are created. The same three variables are available to all users with no wasted memory.


ASP Quick Lessons written by Charles M. Carroll
http://www.learnasp.com/learn/global.asp Page 42


global from ASP Quick Lessons

Global.asa Events by Charles Carroll

This page demonstrates what a blank global.asa should look like:

   <script language=vbscript runat=server>
   SUB Application_OnStart
   END SUB
   
   SUB Application_OnEnd
   END SUB
   
   SUB Session_OnStart
   END SUB
10   
11   SUB Session_OnEnd
12   END SUB
13   </script>

A global.asa code is divided into four events, or segments:


ASP Quick Lessons written by Charles M. Carroll
http://www.learnasp.com/learn/statemore.asp Page 43


Text File Reading ASP Quick Lessons

Global.asa, Sessions, Custom Stats Resources

The global.asa, application and sesion variables are certainly a more complex and controversial subject than most ASP topics. Other sites and my site has a lot to say on this:

Everything you wanted to know about global.asa but were afraid to ask @
http://www.4guysfromrolla.com/webtech/113098-1.shtml

The lowdown on Global.asa, session vars and app. vars
http://www.asp101.com/resources/apps_sessions_gasa.asp

An example of home-brewed stats:
http://www.asp101.com/resources/active_users.asp

Steve Smith's Stats examples:

http://www.aspalliance.com/stevesmith/samples/whosoncode.asp

http://www.aspalliance.com/stevesmith/samples/sitestats.asp


ASP Quick Lessons written by Charles M. Carroll
http://www.learnasp.com/learn/stateproscons.asp Page 44


subdates from ASP Quick Lessons

State Management Methods, Pros and Cons by Charles Carroll

Several methods exist to maintain state. We will present a high-level summary here with advantages and drawbacks.

Method #1 Cookies

Pros: can be set for long periods of time. Wastes no server memory.

Cons: set on a machine. If user visits another machine their info is not there. If someone sits down at users machine, sites they visit may read cookie and it is NOT same person. Users may disable cookies.

Method #2 ASP Sessions

Pros: requires less lines of code than cookies. Easy to program.

Cons: wastes server memory. Evaporates and must be placed in durable storage if user changed session values. User who disable cookies can't have sessions.

Method #3 Hidden Fields

Pros: Works if user has disabled cookies.

Cons: adds Lots of code to each page. If someone invents a page that is not in your website and studies the HTML (where hidden fields are visible) they could feed incorrect hidden data to your form submits (negative numbers into shopping carts, $0 prices into shopping carts, etc.)

Method #4 Hidden Fields + Database

Pros: Works if user has disabled cookies.

Cons: adds Lots of code to each page. Since the hidden field is used to do a database retrieve, each page must hit a database.

Method #5 Homebrewed Sessions

Pros: Solves the problems of traditional ASP sessions.

Cons: Must build component or buy 3rd Party solutions (SASession from www.AspStudio.com for example).

Every site uses one or more of these methods to maintain state.


ASP Quick Lessons written by Charles M. Carroll
http://www.learnasp.com/learn/hidden.asp Page 45


Hidden Fields to Pass Form Data

Passing Data with Hidden Fields by Charles Carroll

This page demonstrates how to have several pages that are forms yet after all pages are filled out the final form has access to all inputs without session variables.

surveypage1.asp asks the user the first questions:

   <html><head>
   <TITLE>surveypage1.asp</TITLE>
   </head>
   <body bgcolor="#FFFFFF">
   <form action="surveypage2.asp" method="post">
   First Name<br>
   &nbsp;&nbsp;&nbsp;
   <input type="text" name="first" size="20"><br>
   Last Name<br>
10   &nbsp;&nbsp;&nbsp;
11   <input type="text" name="last" size="20">
12   <p>&nbsp;&nbsp;&nbsp;
13   <input type="submit" value="Next Question ->"></p>
14   </form>
15   </body></html>

surveypage2.asp asks the user the next questions:

   <html><head>
   <TITLE>surveypage2.asp</TITLE>
   </head>
   <body bgcolor="#FFFFFF">
   <form action="surveypage3.asp" method="post">
   <%
   first=request.form("first")
   last=request.form("last")
   %>

10   Hair Color<br>
11   &nbsp;&nbsp;&nbsp;
12   <input type="text" name="haircolor" size="20"><br>
13   Favorite Color<br>
14   &nbsp;&nbsp;&nbsp;
15   <input type="text" name="favoritecolor" size="20">
16   <p>&nbsp;&nbsp;&nbsp;
17   <input type="hidden" name="first" value="<%=first%>">
18   <input type="hidden" name="last" value="<%=last%>">
19   <input type="submit" value="Next Question ->"></p>
20   </form>
21   </body></html>

surveypage3.asp asks the user yet some more questions:

   <html><head>
   <TITLE>surveypage3.asp</TITLE>
   </head>
   <body bgcolor="#FFFFFF">
   <%
   first=request.form("first")
   last=request.form("last")
   haircolor=request.form("haircolor")
   favoritecolor=request.form("favoritecolor")
10   %>

11   <form action="surveypage3respond.asp" method="post">
12   Street Address<br>
13   &nbsp;&nbsp;&nbsp;
14   <input type="text" name="street" size="20">
15   <br>
16   City<br>
17   &nbsp;&nbsp;&nbsp;
18   <input type="text" name="city" size="20"><br>
19   State<br>
20   &nbsp;&nbsp;&nbsp;
21   <input type="text" name="state" size="20">
22   <br>
23   Zip<br>
24   &nbsp;&nbsp;&nbsp;
25   <input type="text" name="zip" size="20">
26   <br>
27   &nbsp;&nbsp;&nbsp;
28   
29   <input type="hidden" name="first" value="<%=first%>">
30   <input type="hidden" name="last" value="<%=last%>">
31   <input type="hidden" name="haircolor" value="<%=haircolor%>">
32   <input type="hidden" name="favoritecolor" value="<%=favoritecolor%>">
33   
34   <input type="submit" value="Final Step ->">
35   </form>
36   </body></html>

surveypage3respond.asp gathers all the answers and responds:

   <html><head>
   <TITLE>surveypage3respond.asp</TITLE>
   </head>
   <body bgcolor="#FFFFFF">
   <%
   first=request.form("first")
   last=request.form("last")
   haircolor=request.form("haircolor")
   favoritecolor=request.form("favoritecolor")
10   street=request.form("street")
11   city=request.form("city")
12   state=request.form("state")
13   zip=request.form("zip")
14   %>

15   Thanks for all your information<br>
16   We  are happy to meet you <%=first%>&nbsp;<%=last%><br>
17   We  know your hair color is <%=haircolor%><br>
18   and your favorite color is <%=favoritecolor%><br>
19   and we will ship all items to<br>
20   <%=first%>&nbsp;<%=last%><br>
21   <%=street%><br>
22   <%=city%>&nbsp;<%=state%>&nbsp;<%=zip%>
23   </body></html>


ASP Quick Lessons written by Charles M. Carroll
http://www.learnasp.com/learn/cookies.asp Page 46


Hidden Fields to Pass Form Data

Passing Data with Cookies by Charles Carroll

This page demonstrates how to have several pages that are forms yet after all pages are filled out the final form has access to all inputs even after the browser is opened and closed. The browser must accept cookies.

surveypage1c.asp asks the user the first questions:

   <html><head>
   <TITLE>surveypage1.asp</TITLE>
   </head>
   <body bgcolor="#FFFFFF">
   <%
   first=request.cookies("prefs")("first")
   last=request.cookies("prefs")("last")
   %>

   <form action="surveypage2c.asp" method="post">
10   First Name<br>
11   &nbsp;&nbsp;&nbsp;
12   <input type="text" name="first" size="20" value="<%=first%>"><br>
13   Last Name<br>
14   &nbsp;&nbsp;&nbsp;
15   <input type="text" name="last" size="20" value="<%=last%>">
16   <p>&nbsp;&nbsp;&nbsp;
17   <input type="submit" value="Next Question ->"></p>
18   </form>
19   <%
20      For Each cookie in Response.Cookies
21       Response.Cookies(cookie).Expires = now()+365
22      Next
23   %>

24   </body></html>

surveypage2c.asp asks the user the next questions:

   <%response.buffer=true%>
   <html><head>
   <TITLE>surveypage2c.asp</TITLE>
   </head>
   <body bgcolor="#FFFFFF">
   <%
   first=request("first")
   last=request("last")
   haircolor=request.cookies("prefs")("haircolor")
10   favoritecolor=request.cookies("prefs")("favoritecolor")
11   %>

12   <form action="surveypage3c.asp" method="post">
13   Hair Color<br>
14   &nbsp;&nbsp;&nbsp;
15   <input type="text" name="haircolor" size="20" value="<%=haircolor%>"><br>
16   Favorite Color<br>
17   &nbsp;&nbsp;&nbsp;
18   <input type="text" name="favoritecolor" size="20" value="<%=favoritecolor%>">
19   <p>
20   <%
21   response.cookies("prefs")("first")=first
22   response.cookies("prefs")("last")=last
23   For Each cookie in Response.Cookies
24       Response.Cookies(cookie).Expires = now()+365
25   Next
26   %>

27   <input type="submit" value="Next Question ->"></p>
28   </form>
29   </body></html>

surveypage3c.asp asks the user yet some more questions:

   <%response.buffer=true%>
   <html><head>
   <TITLE>surveypage3c.asp</TITLE>
   </head>
   <body bgcolor="#FFFFFF">
   <%
   haircolor=request("haircolor")
   favoritecolor=request("favoritecolor")
   street=request.cookies("prefs")("street")
10   city=request.cookies("prefs")("city")
11   state=request.cookies("prefs")("state")
12   zip=request.cookies("prefs")("zip")
13   %>

14   <form action="surveypage3crespond.asp" method="post">
15   Street Address<br>
16   &nbsp;&nbsp;&nbsp;
17   <input type="text" name="street" size="20" value="<%=street%>">
18   <br>
19   City<br>
20   &nbsp;&nbsp;&nbsp;
21   <input type="text" name="city" size="20" value="<%=city%>"><br>
22   State<br>
23   &nbsp;&nbsp;&nbsp;
24   <input type="text" name="state" size="20" value="<%=state%>">
25   <br>
26   Zip<br>
27   &nbsp;&nbsp;&nbsp;
28   <input type="text" name="zip" size="20" value="<%=zip%>">
29   <br>
30   <%
31   response.cookies("prefs")("haircolor")=haircolor
32   response.cookies("prefs")("favoritecolor")=favoritecolor
33   For Each cookie in Response.Cookies
34       Response.Cookies(cookie).Expires = now()+365
35   Next
36   %>

37   <input type="submit" value="Final Step ->">
38   </form>
39   </body></html>

surveypage3crespond.asp gathers all the answers and responds:

   <%response.buffer=true%>
   <html><head>
   <TITLE>surveypage3respond.asp</TITLE>
   </head>
   <body bgcolor="#FFFFFF">
   <%
   first=request.cookies("prefs")("first")
   last=request.cookies("prefs")("last")
   haircolor=request.cookies("prefs")("haircolor")
10   favoritecolor=request.cookies("prefs")("favoritecolor")
11   street=request("street")
12   city=request("city")
13   state=request("state")
14   zip=request("zip")
15   %>

16   Thanks for all your information<br>
17   We  are happy to meet you <%=first%>&nbsp;<%=last%><br>
18   We  know your hair color is <%=haircolor%><br>
19   and your favorite color is <%=favoritecolor%><br>
20   and we will ship all items to<br>
21   <%=first%>&nbsp;<%=last%><br>
22   <%=street%><br>
23   <%=city%>&nbsp;<%=state%>&nbsp;<%=zip%>
24   <%
25   response.cookies("prefs")("street")=street
26   response.cookies("prefs")("city")=city
27   response.cookies("prefs")("state")=state
28   response.cookies("prefs")("zip")=zip
29   For Each cookie in Response.Cookies
30       Response.Cookies(cookie).Expires = now()+365
31   Next
32   %>

33   </body></html>


ASP Quick Lessons written by Charles M. Carroll
http://www.learnasp.com/learn/statesessions.asp Page 47


subdates from ASP Quick Lessons

Passing Data with Sessions by Charles Carroll

These demos are not written yet but show the survey implemented with ASP sessions.


ASP Quick Lessons written by Charles M. Carroll
http://www.learnasp.com/learn/statedb.asp Page 48


subdates from ASP Quick Lessons

Passing Data with Databases by Charles Carroll

These demos are not written yet but show the survey implemented with a GUID and a request to a database to read and write state values for a user.


ASP Quick Lessons written by Charles M. Carroll
http://www.learnasp.com/learn/aspstatemanagement.asp Page 49


Listserrver Join aspstatemanagementListserver for more info @

http://www.asplists.com/asplists/aspstatemanagement.asp

Related Links:

 
Hidden Fields to Pass Data between pages @
   http://www.learnasp.com/learn/hidden.asp
Sessions: what are they? @
   http://www.learnasp.com/learn/sessionswhat.asp
Cache application level Recordset @
   http://msdn.microsoft.com/workshop/server/feature/cache.asp
Disconnected Recordsets in Session Variables by Don Hayward @
   http://www.insightgraphics.com/reference/ASPStateMgmt.htm
Global.asa Sclability problems @
   http://www.learnasp.com/learn/globalproblems.asp
Session Management without cookies @
   http://domaindlx.com/asms/
FREE Dictionary Component that is session/app safe @
   http://www.caprockconsulting.com/comsoftware.asp
Databases and Session/App Vars? Say no! @
   http://www.learnasp.com/advice/dbsessionapp.asp
4 Ways to Pass data from page to page @
   http://www.4guysfromrolla.com/webtech/041399-1.shtml
Cookie Munger - Sessions with no cookies @
   http://msdn.microsoft.com/workshop/server/toolbox/cookie.asp
Global.asa Basics @
   http://www.learnasp.com/learn/global.asp

Recommended Books:

Related Lists:

Mobile lists by Asplists @
   http://www.asplists.com/asplists/mobile.asp
Mobile lists by WROX @
   http://p2p.wrox.com/mobile/

Rules:

Mailing List Manners (suggested by Bob Filipiak) @
   http://db.tidbits.com/getbits.acgi?tbser=1141
Ken Shaffer's Advice on Asking For Help... @
   http://www.adopenstatic.com/personal/help.asp


ASP Quick Lessons written by Charles M. Carroll
http://www.learnasp.com/learn/Form.asp Page 50


Section Contents

Forms/Decisions
        Forms: Introduction (formintro.asp) - Page 51
        Forms: Text Box (formtextbox.asp) - Page 52
        Forms: Text Area (formtextarea.asp) - Page 53
        Forms: Check Box (formcheckbox.asp) - Page 54
        Forms: Radio Buttons (formradio.asp) - Page 55
        Forms: List Box (formlistbox.asp) - Page 56
        Forms: CASE syntax #1 (case.asp) - Page 57
        Forms: CASE syntax #2 (case2.asp) - Page 58
        Forms: IF syntax #1 (if.asp) - Page 59
        Forms: IF syntax #2 (if2.asp) - Page 60
        Forms: IF syntax #3 (if3.asp) - Page 61
        Forms: IF syntax #4 (if4.asp) - Page 62
        Forms: For Each Iteration (formforeach.asp) - Page 63
        Form - Submit To Self' (formsubmitself.asp) - Page 64
        Form - Change Action on Fly (formactionchange.asp) - Page 65


ASP Quick Lessons written by Charles M. Carroll
http://www.learnasp.com/learn/formintro.asp Page 51


FormIntro ASP Quick Lessons

Forms Introduction by Charles Carroll

Forms are the primary way that a user feeds information into ASP. A form is a web page that contains tags that cause the browser to show fields that the user can fill in.

Form with GET

<form action="x.asp" name="whatever" method=get>
   ....

   <input type=submit>
   <input type=reset>
</form>

Form with POST

<form action="x.asp" name="whatever" method="post">
   ....

   <input type=submit>
   <input type=reset>
</form>

Tips:

Tip #1: If using response.redirect to simulate a GET don't forget to encode:
/learn/encode.asp

Tip #2: A  text link can be used intead of a button to post above form would look like this:
<a href="javascript:document.yourformname.submit();">
send data</a>


ASP Quick Lessons written by Charles M. Carroll
http://www.learnasp.com/learn/formtextbox.asp Page 52


FormTextBox

Forms - Text Box   (by John Kauffman & Charles Carroll)

<INPUT NAME="NameLast"> This will create an input box of a default size and the browser will pass the user input to ASP with the label (identifier) of NameLast.
<INPUT NAME="ZipCode" SIZE="10"> This is not a limit to the number of characters that can be entered. Do not use size as a validation technique to limit verbose users.
<INPUT NAME="State" MaxLength="2"> This controls the maximum number of characters that can be entered.
<INPUT NAME="NameLast" VALUE="Bertrand"> The name of Bertrand will appear when the page is opened and will re-appear if the form is reset.

   <html><head>
   <title>FormTextBox.asp</title>
   </head><body bgcolor="#FFFFFF">
   <Form action = "FormTextBoxRespond.asp" method="get">
   Fill Out This Form For Us:<p>
   Last Name -> <Input NAME="NameLast" size ="10"><br>
   Country -> <Input NAME="Country" value="USA" size="10"><br>
   State -> <Input NAME="State" MaxLength="2" size="2"><br>
   <Input type="submit" value="Give me your data!">
10   <hr></form>
11   </body></html>

   <html><head>
   <title>FormTextBoxRespond.asp</title>
   </head><body bgcolor="#FFFFFF">
   <%
   lname=request.querystring("namelast")
   cty=request.querystring("country")
   st=request.querystring("state")
   
   response.write lname & "<br>"
10   response.write cty & "<br>"
11   response.write st & "<br>"%>

12   </body></html>


ASP Quick Lessons written by Charles M. Carroll
http://www.learnasp.com/learn/formtextarea.asp Page 53


FormTextArea ASP Quick Lessons

Forms - Text Area by John Kauffman & Charles Carroll

Multi-line text boxes are created using the TEXTAREA command as follows:

<TEXTAREA NAME="UserComments" ROWS=5 COLS=50>
... default text is typed here
</TEXTAREA>

Notes: Windows browsers typically provide scroll bars automatically.
Although the TEXT tag does not need to be closed, the TEXTAREA must have a </TEXTAREA>
The TEXTAREA tag (like all of the user-input objects) must be within the form tags discussed earlier.

   <html><head>
   <TITLE>formTextArea.asp</TITLE>
   </head><body bgcolor="#FFFFFF">
   <form action="FormTextAreaRespond.asp" method="post">
   <p>TextArea Example</p>
   <p>Please type your special shipping comments:</p>   
   <TEXTAREA NAME="shippingComments" ROWS="5" COLS="50">
   shipping comments go here
   </textarea>
10   <p><input type=submit value="send in comments!">
11   </form>
12   </body></html>

The responder to the form will look like this:

   <html><head>
   <TITLE>formTextArearespond.asp</TITLE>
   </head><body bgcolor="#FFFFFF">
   <%
   comm=request.form("shippingcomments")
   response.write comm
   %>

   <hr>
   </body></html>

Tip: Want to retain Hard-Returns the User Types?

Then change the form responder:

comm=request.form("shippingcomments")
becomes
comm=request.form("shippingcomments")
comm=replace(comm,vbcrlf,"<br>")


ASP Quick Lessons written by Charles M. Carroll
http://www.learnasp.com/learn/formcheckbox.asp Page 54


FormCheckBox ASP Quick Lessons

Forms - Check Boxes (by John Kauffman & Charles Carroll)

The checkbox object is coded along the same lines as radio buttons, however each checkbox must get its own unique name since the state of "checked" or "not checked" will be passed to ASP for each box. Remember that you can set more than one option to be checked.

   <html><head>
   <TITLE>FormCheckBox.asp</TITLE>
   </head><body bgcolor="#FFFFFF">
   <form action="FormCheckBoxRespond.asp" method="post">
   <p>CheckBox Form Example</p>
   <p>How do you want your order confirmed?</p>   
   <input TYPE="checkbox" NAME="USMail">confirmation sent by first class US Postal Service<br>
   <input TYPE="checkbox" NAME="UPS">confirmation sent by UPS overnight letter service<br>
   <input TYPE="checkbox" NAME="EMail" CHECKED>confirmation sent by EMail<br>
10   <input TYPE="checkbox" NAME="Fax">confirmation sent by Fax<br>
11   <input TYPE="checkbox" NAME="Tel" CHECKED>confirmation made by telephone call<br><br>
12   <input type="submit"><input type="reset">
13   </form><hr></body></html>

The responder looks like this:

   <html><head>
   <TITLE>formCheckBoxRespond.asp</TITLE>
   </head><body bgcolor="#FFFFFF">
   <%
   If   request.form("USMail")="on" then
         response.write "<br>We will confirm by US Mail"
   end if
   If   request.form("UPS")="on" then
         response.write "<br>We will confirm by UPS"
10   end if
11   If   request.form("EMail")="on" then
12         response.write "<br>We will confirm by EMail"
13   end if
14   If   request.form("fax")="on" then
15         response.write "<br>We will confirm by fax"
16   end if
17   If   request.form("tel")="on" then
18         response.write "<br>We will confirm by tel"
19   end if%>

20   </body>
21   </html>


ASP Quick Lessons written by Charles M. Carroll
http://www.learnasp.com/learn/formradio.asp Page 55


Forms - Radio Buttons

Forms - Radio Buttons  (by John Kauffman)

All of your user input objects in a form must have their own unique name which will be the label that the browser will assign to them when passing the data to ASP. The exceptions are radio buttons. Since only one piece of information will be passed to ASP from a set of radio buttons, they all get the same name. HTML requires that one of the buttons is selected by default, the one indicated by the CHECKED command. It is important to understand that the browser will send back to ASP the name and the value of the one button which is selected by the user. The browser will NOT send back the text which is associated with the button. For the example above, if the user checked on the button with the text New York City, then ASP would receive City=NY.

   <html><head>
   <TITLE>formRadio.asp</TITLE>
   </head><body bgcolor="#FFFFFF">
   <form action="FormRadiorespond.asp" method="post">
   <p><b>Radio Buttons </b> example</p>
   <p>Which Regional Office will you be visiting?</p>   
   <input TYPE="radio" NAME="City" VALUE="NY">New York City
   <input TYPE="radio" NAME="City" VALUE="LA">Los Angeles
   <input TYPE="radio" NAME="City" VALUE="SV" CHECKED>Savannah
10   <br><input type="submit" value="choose a city">
11   </form>
12   </body></html>

The responder looks like:

   <html><head>
   <TITLE>formradiorespond.asp</TITLE>
   </head><body bgcolor="#FFFFFF">
   <%myCity = request.form("City")
   Select Case ucase(MyCity)
   case "NY"
      response.write "New York meeting is on Jan 3"
   case "LA"
      response.write "LA meeting meeting is on Jan 15"
10   case "SV"
11      response.write "Savannah meeting is on Jan 20"
12   End Select%>

13   </body>
14   </html>


ASP Quick Lessons written by Charles M. Carroll
http://www.learnasp.com/learn/formlistbox.asp Page 56


FormListBox ASP Quick Lessons

Forms - List Boxes (by John Kauffman & Charles Carroll)

The listbox object is very popular since it makes data entry easy. They just pull down a list.

   <html><head>
   <TITLE>FormListBox.asp</TITLE>
   </head><body bgcolor="#FFFFFF">
   <form action="FormListBoxRespond.asp" method="post">
   <SELECT NAME="state">
      <OPTION SELECTED VALUE="md">Maryland</OPTION>
      <OPTION value="dc">District of Columbia</OPTION>
      <OPTION value="va">Virginia</OPTION>
      <OPTION value="whoknows">Somewhere Else!</OPTION>
10   </SELECT>
11   <input type=submit value="Choose State">
12   </form>
13   </body></html>

The responder looks like this:

   <html><head>
   <TITLE>formlistboxrespond.asp</TITLE>
   </head><body bgcolor="#FFFFFF">
   <%mystate = request.form("state")
   Select Case ucase(mystate)
   case "DC"
      response.write "DC meeting on 15th"
   case "MD"
      response.write "MD meeting on 20th"
10   case else
11      response.write "No meetings for you to attend!"
12   End Select%>

13   </body>
14   </html>


ASP Quick Lessons written by Charles M. Carroll
http://www.learnasp.com/learn/case.asp Page 57


Select2 ASP Quick Lessons

Select Case (by John Kauffman & Charles Carroll)

Using IF-THEN can be cumbersome, prone to programmer errors and slower to execute. A more efficient construct is SELECT CASE. It is optimized for testing one variable against many conditions.

   <html><head>
   <TITLE>case.asp</TITLE>
   </head><body bgcolor="#FFFFFF">
   <form action="caserespond.asp" method="get">
   Your First Name<INPUT NAME="FirstName" MaxLength=20><p>
   Your Last Name<INPUT NAME="LastName" MaxLength=20><p>
   <INPUT TYPE=submit><p><INPUT TYPE=reset>
   </form>
   </body></html>

Here is the select case that will determine what the form input means.

   <html><head>
   <TITLE>caserespond.asp</TITLE>
   </head><body bgcolor="#FFFFFF">
   <%
   fname=request.querystring("Firstname")
   lname=request.querystring("Lastname")
   %>

   Nice to Meet You <%=fname%> <%=lname%><p>
   <%If fname="" then%>
10   Sorry we are not on a first name basis...<p>
11   <%end if
12   select case lcase(lname)
13   case "washington","adams"
14      response.write "The first president has same last name<p>"
15   case "jefferson"
16      response.write "The third president has same last name<p>"
17   case "lincoln"
18      response.write "The sixteenth president has same last name<p>"
19   end select%>

20   </body></html>


ASP Quick Lessons written by Charles M. Carroll
http://www.learnasp.com/learn/case2.asp Page 58


SELECT CASE Part2 ASP Quick Lessons

Select Case Part2 (by John Kauffman & Charles Carroll)

Using IF-THEN can be cumbersome, prone to programmer errors and slower to execute. A more efficient construct is SELECT CASE. It is optimized for testing one variable against many conditions.

   <html><head>
   <TITLE>case2.asp</TITLE>
   </head><body bgcolor="#FFFFFF">
   <form action="case2respond.asp" method="get">
   Your First Name<INPUT NAME="FirstName" MaxLength=20><p>
   Your Last Name<INPUT NAME="LastName" MaxLength=20><p>
   Your Title
   <INPUT TYPE="Radio" name="Title" VALUE="employee">Entry Level
   <INPUT TYPE="Radio" name="Title" VALUE="temp" CHECKED>Temporary Employee
10   <INPUT TYPE="Radio" name="Title" VALUE="manager">Management Candidate
11   <INPUT TYPE="Radio" name="Title" VALUE="executive">Executive
12   <INPUT TYPE="Radio" name="Title" VALUE="vice-prez">The Vice President of...
13   <INPUT TYPE="Radio" name="Title" VALUE="CEO">The Boss<p>
14   <INPUT TYPE=submit><p>
15   </form>
16   </body></html>

Here is the select case that will determine what the form input means.

   <html><head>
   <TITLE>case2respond.asp</TITLE>
   </head><body bgcolor="#FFFFFF">
   <%
   fname=request.querystring("Firstname")
   lname=request.querystring("Lastname")
   title=request.querystring("title")
   response.write "Nice to Hire You " & fname & " " & lname & "<p>"
   Select Case lcase(Title)
10      case "employee","temp"
11         response.write("The washroom is in the hall")
12      case "manager","executive"
13         response.write("Here is your key to the Executive washroom")
14      case "ceo", "vice-prez"
15         response.write("The maid will attend to your private washroom")
16   End Select%>

17   </body></html>


ASP Quick Lessons written by Charles M. Carroll
http://www.learnasp.com/learn/if.asp Page 59


ASP Quick Lessons IF statement

IF statement (by John Kauffman & Charles Carroll)

Very often you must determine what to do next based on user input. This is one of the roles of the IF statement. First we make a form that will ask a user for their first name and last name.

   <html><head>
   <TITLE>if.asp</TITLE>
   </head><body bgcolor="#FFFFFF">
   <form action="ifrespond.asp" method=get>
   Your First Name<INPUT NAME="FirstName" MaxLength=20><p>
   Your Last Name<INPUT NAME="LastName" MaxLength=20><p>
   <INPUT TYPE=submit><p><INPUT TYPE=reset>
   </form></body></html>

Now we make a asp file that examines their first name and last name after the form is submitted.

   <html><head>
   <TITLE>ifrespond.asp</TITLE>
   </head><body bgcolor="#FFFFFF">
   <%fname=request.querystring("Firstname")
   lname=request.querystring("Lastname")
   If  fname="George" and lname="Washington" then%>

      Hi.<p>You must be the first president!
   <%else%>
      Hi!<p>Nice to Meet You
10   <%end if%>
11   </body></html>


ASP Quick Lessons written by Charles M. Carroll
http://www.learnasp.com/learn/if2.asp Page 60


IF2 ASP Quick Lessons

IF statement Part2 (by John Kauffman & Charles Carroll)

Very often you must determine what to do next based on user input. This is one of the roles of the IF statement. First we make a form that will ask a user for their first name and last name.

   <html><head>
   <TITLE>if2.asp</TITLE>
   </head><body bgcolor="#FFFFFF">
   <form action="if2respond.asp" method=get>
   Your First Name<INPUT NAME="FirstName" MaxLength=20><p>
   Your Last Name<INPUT NAME="LastName" MaxLength=20><p>
   <INPUT TYPE=submit><p><INPUT TYPE=reset>
   </form></body></html>

Now we make a asp file that examines their first name and last name after the form is submitted. As contrasted to the previous example this time we are checking multiple conditions utilizing elseif and we are dealing with entries no matter whether they were typed in upper or lower case.

   <html><head>
   <TITLE>if2respond.asp</TITLE>
   </head><body bgcolor="#FFFFFF">
   <%
   fname=lcase(request.querystring("Firstname"))
   lname=lcase(request.querystring("Lastname"))
   If  fname="george" and lname="washington" then%>

      Hi.<p>You must be the first president!
   <%elseIf fname="ronald" and lname="reagan" then%>
10      Hi.<p>You must be the actor president!
11   <%elseIf fname="jimmy" and lname="carter" then%>
12      Hi.<p>You must be the peanut farmer president!
13   <%elseIf fname="naoko" or fname="charles" then%>
14      Hi.<p>Your name reminds me of someone<p>
15          but I am not sure who!
16   <%else%>
17      Hi!<p>Nice to Meet You
18   <%end if%>
19   </body></html>


ASP Quick Lessons written by Charles M. Carroll
http://www.learnasp.com/learn/if3.asp Page 61


IF3 ASP Quick Lessons

IF statement Part3 (by John Kauffman & Charles Carroll)

Very often you must determine what to do next based on user input. This is one of the roles of the IF statement. First we make a form that will ask a user for their first name, last name and salary.

   <html><head>
   <TITLE>if3.asp</TITLE>
   </head><body bgcolor="#FFFFFF">
   <form action="if3respond.asp" method=get>
   Your First Name<INPUT NAME="FirstName" MaxLength=20><p>
   Your Last Name<INPUT NAME="LastName" MaxLength=20><p>
   Your Salary <INPUT NAME="Salary" MaxLength=7><p>
   <INPUT TYPE=submit><p><INPUT TYPE=reset>
   </form></body></html>

This example shows how IF can deal with ranges and use various other boolean operators.

   <html><head>
   <TITLE>if3respond.asp</TITLE>
   </head><body bgcolor="#FFFFFF">
   <%
   fname=request.querystring("Firstname")
   lname=request.querystring("Lastname")
   salary=request.querystring("Salary")
   response.write "Nice to Meet You " & fname & " " & lname & "<p>"
   if  salary>100000 then%>

10      Would you like to loan me some money?<p>
11      <%   
12      sstaxMarginal=15
13   else
14      SSTaxMarginal=15
15   end if
16   If  salary>6700 and salary<30000 then
17      SSTaxMarginal=0%>

18      Would you like me to loan you some money?<p>
19   <%end if
20   If  salary<6700 then
21      SSTaxMarginal=0
22   end if
23   %>

24   By  the way your marginal tax rate is <%=sstaxmarginal%>
25   </body></html>


ASP Quick Lessons written by Charles M. Carroll
http://www.learnasp.com/learn/if4.asp Page 62


IF4 ASP Quick Lessons

If Then Part4 (by John Kauffman & Charles Carroll)

Very often you must determine what to do next based on user input. This is one of the roles of the IF statement. First we make a form that will ask a user for their first name, last name and salary.

   <html><head>
   <TITLE>if4.asp</TITLE>
   </head><body bgcolor="#FFFFFF">
   <form action="if4respond.asp" method=get>
   Your First Name<INPUT NAME="FirstName" MaxLength="20"><p>
   Your Last Name<INPUT NAME="LastName" MaxLength="20"><p>
   Your Salary <INPUT NAME="Salary" MaxLength="7"><p>
   <INPUT TYPE=submit><p>
   </form></body></html>

This example shows how IF can deal with ranges but this example illustrates the critical factor of ordering. If you were to re-arrange these IFs they would not accurately report your salary grade.

   <html><head>
   <TITLE>if4respond.asp</TITLE>
   </head><body bgcolor="#FFFFFF">
   <%fname=request.querystring("Firstname")
   lname=request.querystring("Lastname")
   salary=request.querystring("Salary")
   response.write "Nice to Meet You " & fname & " " & lname & "<p>"
   if  salary>80000 then
      salarygrade=4
10   end if
11   if  salary <=80000 then
12      salarygrade=3
13   end if
14   If  salary <=60000 then
15      salarygrade=2
16   end if
17   if  salary <=40000 then
18      salarygrade=1
19   end if
20   response.write ("Your Salary is $" & salary)
21   response.write (", your Grade is " & salarygrade & ".<p>")
22   %>

23   </body></html>


ASP Quick Lessons written by Charles M. Carroll
http://www.learnasp.com/learn/formforeach.asp Page 63


Forms For Each from ASP Quick Lessons

Forms - For Each/Iteration by Charles Carroll

Forms with many elements may be easier to process if a FOR EACH construct is used to loop through every value submitted from the source form. In this example, there are many checkboxes and  instead of many IF statements we replace them with one FOR EACH loop.

   <html><head>
   <TITLE>monthlyForm.asp</TITLE>
   </head><body bgcolor="#FFFFFF">
   <form action="monthlyFormRespond.asp" method="post">
      <p>CheckBox Form Example</p>
      <p><b>Check Off The Days You Worked</b></p>   
      <%
          my_month=request.querystring("whichmonth")
      '   response.write my_month & "<br>"
10          if my_month="" then
11            my_date=now()
12      else
13         my_month=month(request.querystring("whichmonth") & "/1/2000")
14         my_date=dateserial(year(now()),my_month,1)
15      end if
16      'response.write my_date & "<br>"
17   
18      If my_month=12 then
19          my_day=1
20         my_month=1
21          my_year=my_year+1
22      else
23         my_day=1
24         my_month=month(my_date)+1
25          my_year=year(my_date)
26      end if
27      
28      lastdayofmonth=day(DateSerial(Year(my_Date), my_Month,0))
29      'response.write lastdayofmonth & "<br>"
30   
31      for counter=1 to lastdayofmonth%>

32         <input TYPE="checkbox" NAME="workingday<%=counter%>">day <%=counter%> Worked?<br>
33          <%next%>
34          <input type="submit" value="Submit Days Worked">
35   </form>
36   </body></html>

   <html><head>
   <TITLE>monthlyFormRespond.asp</TITLE>
   </head><body bgcolor="#FFFFFF">
   <%
   daysworked=0
   for each whatever in request.form
          thisvalue=request.form(whatever)
      If thisvalue="on" then
         daysworked=daysworked+1
10      end if
11   next
12   response.write "Thanks for working <b>" & daysworked & "</b> days"
13   %>

14   </body></html>


ASP Quick Lessons written by Charles M. Carroll
http://www.learnasp.com/learn/formsubmitself.asp Page 64


Forms - Submit To Self from LearnASP.com

Form Tricks #2: Self-Submitting Forms

There are some clever tactics programmers can apply when dealing with forms. They have their drawbacks and should be used sparingly.

Some people prefer to combine their forms and actions in one file. I don't because of usability issues -- a user who refreshes a combined form will be presented with a confusing choice "repost form data (y/n)"  which they are not presented with if the forms are separate. Such a form could be submitted twice accidentally when they just meant to redisplay the form.

   <html><head>
   <title>FormSubmitSelf.asp</title>
   </head><body bgcolor="#FFFFFF">
   <%
   SELECT CASE lcase(request.form("join"))
   CASE "join"
      response.write "Thanks for joining "
      response.write request.form("namefirst") & "&nbsp;"
      response.write request.form("namelast") & "&nbsp;"
10   CASE ELSE
11   %>

12   <Form method="post">
13      Fill Out This Form For Us:<p>
14      First Name <Input NAME="NameLast" size ="10"><br>
15      Last Name <Input NAME="NameLast" size ="10"><br>
16      <input type="submit" name="Join" value="Join">
17   </form>
18   <%END SELECT%>
19   </body></html>
20   


ASP Quick Lessons written by Charles M. Carroll
http://www.learnasp.com/learn/formactionchange.asp Page 65


Forms - Radio Buttons

Form Tricks #3:  Forms that Dynamically Change Action

There are some clever tactics programmers can apply when dealing with forms. They have their drawbacks and should be used sparingly.

Some forms need to vary their action.

   <html><head>
   <title>FormTextBox.asp</title>
   </head><body bgcolor="#FFFFFF">
   <Form name="profile" action = "profilerespond.asp" method="post">
      Fill Out This Form For Us:<p>
      First Name <Input NAME="NameLast" size ="10"><br>
      Last Name <Input NAME="NameLast" size ="10"><br>
      <a href="Javascript:army()">Join Army</a>
      <a href="Javascript:navy()">Join Navy</a>
10      <a href="Javascript:marines()">Join Marines</a>
11   </form>
12   </body></html>
13   
14   <form name=myform>
15   </form>
16   
17   <script language =javascript>
18   function army(form)
19   {  
20   document.myform.action="joinarmy.asp"
21   document.myform.submit()
22   }  
23   function navy(form)
24   {  
25   document.myform.action="joinnavy.asp"
26   document.myform.submit()
27   }  
28   function marines(form)
29   {  
30   document.myform.action="joinmarines.asp"
31   document.myform.submit()
32   }  
33   </script>


ASP Quick Lessons written by Charles M. Carroll
http://www.learnasp.com/learn/database.asp Page 66


Section Contents

Databases
        Displaying Table w/Simple Code (dbsimple.asp) - Page 67
        List Box Displayed Generically (dblist.asp) - Page 68
        Database to ListBox Online Resources (dblistmore.asp) - Page 69
        DSNLess Connections (dbopen.asp) - Page 70
        DSN Setup #1 by Rob Martinson (dsn1.asp) - Page 71
        DSN Setup #2 by Rob Martinson (dsn2.asp) - Page 72
        DSN Setup #3 by Rob Martinson (dsn3.asp) - Page 73
        DSN Setup #4 by Rob Martinson (dsn4.asp) - Page 74
        DSN Setup #5 by Rob Martinson (dsn5.asp) - Page 75
        DSN Setup #6 by Rob Martinson (dsn6.asp) - Page 76
        Full Cycle #1 Show/Edit/Update (dbfull1.asp) - Page 77
        Full Cycle #2 Show/Edit/Update (dbfull2.asp) - Page 78
        Full Cycle #3 Show/Edit/Update (dbfull3.asp) - Page 79
        SQL Mistakes Everyone Makes (dbtroubleshoot2.asp) - Page 80
        DB: Table Displayed Generically (dbtable.asp) - Page 81
        Getstring to display database table (dbtablegetstring.asp) - Page 82
        Getrows to display database table (dbtablegetrows.asp) - Page 83
        GetRows w/no Numbers (dbtablegetrowsnonum.asp) - Page 84
        Disconnected Recordsets, Display Table (dbtabledisconnected.asp) - Page 85
        DB: More ways To Display Tables (dbtablemore.asp) - Page 86
        DB: Generic DB by Eli Robillard (genericdb.asp) - Page 87
        Generic DB Listserver (aspgenericdb.asp) - Page 88
        DB: Converting a DB to a Comma-Delimited file (dbconvert.asp) - Page 89
        DB: Deleting a Record w/SQL (dbSQLdelete.asp) - Page 90
        DB: Access Scalability (accesstest.asp) - Page 91
        ADO: Paging Records (dbtablepaged.asp) - Page 92
        ADO: Limiting Number of Records (dbmaxrecs.asp) - Page 93
        ADO: Count Records in Query (dbcount.asp) - Page 94
        ADO: Cursor Types by Phil Paxton (adocursortypes.asp) - Page 95
        ADO: Input Form (dbnewrec.asp) - Page 96
        ADO: Input Form, added w/SQL (dbnewSQL.asp) - Page 97
        ADO: Input Form, Added w/ADO .addnew (dbnewADO.asp) - Page 98
        ADO: Tables within Databases (dbtablelists.asp) - Page 99
        ADO: Schemas to access table lists (dbschemas.asp) - Page 100
        ADO: Schemas to access All Data (dbschemasall.asp) - Page 101
        ADO: Show Table,1 param (db1parm.asp) - Page 102
        ADO: Update/edit Record (dbupdate.asp) - Page 103
        DB: Troubleshooting Part 1 (dbtroubles.asp) - Page 104
        DB: Troubleshooting Part 2 (dbtroubles2.asp) - Page 105


ASP Quick Lessons written by Charles M. Carroll
http://www.learnasp.com/learn/dbsimple.asp Page 67


dbtablesimple from ASP Quick Lessons

Database -- Simple Table Display by Charles Carroll

This page demonstrates the capabilities how to display a table from a SQL statement.

   <html><head>
   <TITLE>dbsimple.asp</TITLE>
   </head>
   <body bgcolor="#FFFFFF">
   <%
   ' this code opens the database
   myDSN="DSN=Student;uid=student;pwd=magic"
   set conntemp=server.createobject("adodb.connection")
   conntemp.open myDSN
10   
11   ' this code retrieves the data
12   mySQL="select * from publishers where state='NY'"
13   set rstemp=conntemp.execute(mySQL)
14   
15   ' this code detects if data is empty
16   If  rstemp.eof then
17      response.write "No records matched<br>"
18      response.write mySQL & "<br>So cannot make table..."
19      connection.close
20      set connection=nothing
21      response.end
22   end if
23   %>

24   <table border=1>
25   <%
26   ' This code puts fieldnames into column headings
27   response.write "<tr>"
28   for each whatever in rstemp.fields
29          response.write "<td><B>" & whatever.name & "</B></TD>"
30   next
31   response.write "</tr>"
32   
33   ' Now lets grab all the records
34   DO  UNTIL rstemp.eof
35      ' put fields into variables
36      pubid=rstemp("pubid")
37      name=rstemp("name")
38      company_name=rstemp("company name")
39      address=rstemp("address")
40      city=rstemp("city")
41      state=rstemp("state")
42        zip=rstemp("zip")
43      telephone=rstemp("telephone")
44      fax=rstemp("fax")
45      comments=rstemp("comments")
46   
47      ' write the fields to browser
48      cellstart="<td align=""top"">"
49      response.write "<tr>"
50      response.write cellstart & pubid & "</td>"
51      response.write cellstart & name & "</td>"
52      response.write cellstart & company_name & "</td>"   
53      response.write cellstart & address & "</td>"
54      response.write cellstart & city & "</td>"
55      response.write cellstart & state & "</td>"
56      response.write cellstart & zip & "</td>"
57      response.write cellstart & telephone & "</td>"
58      response.write cellstart & fax & "</td>"
59      response.write cellstart & comments & "</td>"
60   
61      response.write "</tr>"
62      rstemp.movenext
63   LOOP
64   %>

65   </table>
66   
67   <%
68   ' Now close and dispose of resources
69   rstemp.close
70   set rstemp=nothing
71   conntemp.close
72   set conntemp=nothing
73   %>

74   </body></html>


ASP Quick Lessons written by Charles M. Carroll
http://www.learnasp.com/learn/dblist.asp Page 68


Databases List Box ASP Quick Lessons

HTML List Box from Column

This page demonstrates the capabilities how to display a list box from a SQL statement. This is the simplest possible example. The script to display a list from a database is:

   <html><head>
   <TITLE>dblist.asp</TITLE>
   </head><body bgcolor="#FFFFFF">
   <%
   myDSN="DSN=Student;uid=student;pwd=magic"
   mySQL="select author from authors where AU_ID<100"
   
   ' displays a database field as a listbox
   set conntemp=server.createobject("adodb.connection")
10   conntemp.open myDSN
11   set rstemp=conntemp.execute(mySQL)
12   if  rstemp.eof then
13      response.write "no data for<br>"
14      response.write mySQL
15      conntemp.close
16      set conntemp=nothing
17      response.end      
18   end if
19   
20   %>

21   <form action="dblistrespond.asp" method="post">
22   <Select name="authorname">
23   <%
24   ' Now lets grab all the data
25   do  until rstemp.eof %>

26      <option> <%=RStemp(0)%> </option>
27      <%
28      rstemp.movenext
29   loop
30   
31   rstemp.close
32   set rstemp=nothing
33   conntemp.close
34   set conntemp=nothing
35   %>

36   <input type="submit" value="Choose Author">
37   </Select></form>
38   </body></html>

The form responder dblistrespond.asp is:
   <html><head>
   <TITLE>dblistrespond.asp</TITLE>
   </head><body bgcolor="#FFFFFF">
   <%
   my_author=request.form("authorname")
   %>

   You choose <%=my_author%><br>Thanks!<br>
   </body></html>


ASP Quick Lessons written by Charles M. Carroll
http://www.learnasp.com/learn/dblistmore.asp Page 69


Text File Reading ASP Quick Lessons

Database Listbox Resources

There are actually many approaches to creating listboxes from databases demonstrated on this site and other sites:

http://www.learnasp.com/learn/subdblist.asp

http://www.learnasp.com/learn/subdblistbest.asp

http://www.siteexperts.com/tips/elements/ts25/page1.asp

http://www.niblack.com/kbase/listbox_create_x.asp

http://www.niblack.com/kbase/listboxmgmt_x.asp

http://www.niblack.com/kbase/listbox_x.asp

And many people like dynamic list boxes where one listbox choice affects the values available in the other listbox:

http://www.learnasp.com/learn/listdynamic.asp

http://www.learnasp.com/learn/listdynamicdb.asp

http://www.learnasp.com/learn/listdynamicmore.asp

There are also some alternative approaches to building alternative, gimicky listboxes that are helpful:

http://www.learnasp.com/learn/listdual.asp

http://www.siteexperts.com/tips/elements/ts22/page1.asp

http://n2.neoshop.com/


ASP Quick Lessons written by Charles M. Carroll
http://www.learnasp.com/learn/dbopen.asp Page 70


DSNless connections from ASP Quick lessons

DSN, DSNless  connections by Charles Carroll

OLEDB Good Connection String (recommended)
strconn="PROVIDER=Microsoft.Jet.OLEDB.4.0;DATA SOURCE="
strconn=strconn & server.mappath(accessDB) & ";"
'strconn=strconn & "Password=whatever;"

ODBC Connection String (not recommended)
strconn="DRIVER={Microsoft Access Driver (*.mdb)};"
strconn=sourceDSN & "DBQ=" & server.mappath(accessdb)
strconn=sourceDSN & "Password=whatever;"

NOTE: An ODBC connection string to Access often results in the dreaded: Unable to open registry key or 'Unspecified Error' usually occurs with an ODBC connection string to Access, i.e.

Any ASP script that needs to connect to a database must open it on the server first. There are several ways:

SYSTEM DSN
which must be setup on the server, see:
/learn/dsn1.asp for detailed instructions or
http://www.aspalliance.com/components/database.asp for components that automate this task.
This is NOT the fastest way* since all the information resides on the server and need only be validated when the DSN is setup.

FILE DSN
which is not recommended for high concurrency situations since all users would be bottlenecked by how fast the ASII file that holds the DSN could be accessed.
The trouble with a File DSN is that every connection.open must open, read, close an ASCII file and present the data anew to the provider/driver since the ASCII file may have changed since last connection.File DSNs are bottlenecks on busy sites.

DSNLESS
which requires no server setup, just a carefully constructed connection string as demonstrated below.
DSNless connections demand that that you know the name of the file (i.e. file based databases like Access, Paradox, FoxPro, etc.) or the address of the data server (SQLserver for example). Armed with appropriate information you could open a data source without a DSN! 
This is faster than a system DSN* since it saves a trip to read the registry each attempt.

Most Connection strings are detailed @
http://www.able-consulting.com/ado_conn.htm?f=ado_conn.htm
http://support.microsoft.com/support/kb/articles/q193/3/32.asp
http://support.microsoft.com/support/kb/articles/Q191/7/54.ASP

4GuyfromRolla (a superb ASP site of unparalleled depth) has a great set of DSN articles:

* System DSN or DSNless connection @
http://www.4guysfromrolla.com/webtech/070399-1.shtml

Nifty way to make DSNless connections @
http://www.4guysfromrolla.com/webtech/070699-1.shtml 

Listing System DSNs with a FREE component:
http://www.4guysfromrolla.com/webtech/011900-1.shtml

Here is a sample nwind.asp connecting to an access database named "nwind.mdb" in the root of the web site with a DSNless connection. Note that you must know the actual filepath on the server, i.e. nwind.mdb is not good enough it needs to be "C:\thatserver\account17\nwind.mdb". Fortunately the server.mappath function can turn a filename into the proper fully qualified filename with path on the server.
   <HTML><HEAD>
   <TITLE>nwind.asp</TITLE>
   <body bgcolor="#FFFFFF"></HEAD>
   <%
   accessdb=server.mappath("nwind.mdb")
   strconn="PROVIDER=Microsoft.Jet.OLEDB.4.0;DATA SOURCE="
   strconn=strconn & accessDB & ";"
   'strconn=strconn & "USER ID=;PASSWORD=;"
   
10   mySQL="select * from customers"
11   
12   call query2table(mySQL,strconn)
13   %>

14   <!--#include virtual="/learn/test/lib_dbtable.asp"-->
15   </BODY>
16   </HTML>
17   
18   

Here is a sample sqldsn.asp connecting to an access database named "nwind.mdb" in the root of the web site with a DSNless connection.
   <HTML><HEAD>
   <TITLE>sqlserverdsn.asp</TITLE>
   <body bgcolor="#FFFFFF"></HEAD>
   <%
   strconn="DSN=student;uid=student;pwd=magic"
   mySQL="select * from publishers where state='NY'"
   
   call query2table(mySQL,strconn)
   %>

10   <!--#include virtual="/learn/test/lib_dbtable.asp"-->
11   </BODY>
12   </HTML>
13   
14   

Here is a sample sqldsnless.asp connecting to an access database named "nwind.mdb" in the root of the web site with a DSNless connection.
   <HTML><HEAD>
   <TITLE>sqlDSNless.asp</TITLE>
   <body bgcolor="#FFFFFF"></HEAD>
   <%
   strconn="PROVIDER=MSDASQL;DRIVER={SQL Server};"
   strconn=strconn & "SERVER=sql2.datareturn.com;DATABASE=;"
   strconn=strconn & "UID=student;PWD=magic;"
   
   mySQL="select * from publishers where state='NY'"
10   
11   call query2table(mySQL,strconn)
12   %>

13   <!--#include virtual="/learn/test/lib_dbtable.asp"-->
14   </BODY>
15   </HTML>
16   
17   
18   

The Include file lib_dbtable.asp looks like this:
   <%
   sub query2table(inputquery, inputDSN)
      dim conntemp, rstemp
      set conntemp=server.createobject("adodb.connection")
      conntemp.open inputDSN
      set rstemp=conntemp.execute(inputquery)
      howmanyfields=rstemp.fields.count -1%>

      <table border=1><tr>
      <% 'Put Headings On The Table of Field Names
10      for i=0 to howmanyfields %>

11                <td><b><%=rstemp(i).name%></B></TD>
12      <% next %>
13      </tr>
14      <% ' Now lets grab all the records
15      do while not rstemp.eof %>

16         <tr>
17         <% for i = 0 to howmanyfields
18            thisvalue=rstemp(i)
19            If isnull(thisvalue) then
20               thisvalue="&nbsp;"
21            end if%>

22                <td valign=top><%=thisvalue%></td>
23         <% next %>
24         </tr>
25         <%rstemp.movenext
26      loop%>

27      </table>
28      <%
29      rstemp.close
30      set rstemp=nothing
31      conntemp.close
32      set conntemp=nothing
33   end sub%>


ASP Quick Lessons written by Charles M. Carroll
http://www.learnasp.com/learn/dsn1.asp Page 71


System DSN from ASP Quick Lessons

Setting up a system DSN on Windows 95/NT
©1998, 1999 by Rob Martinson rob.martinson@directionsmag.com

The easiest way to begin learning ASP, is to install Microsoft PWS, and develop locally. To do this, you must also setup a DSN (Data Source Name) on your machine, if you wish to use any of ASP's database access abilities. This tutorial is meant to walk you through the process of setting up a system DSN on your Windows machine.

 

The first step, after you have PWS installed, is to open your control panel and select the 32bit ODBC Data Source Administrator icon (shown below).

 


ASP Quick Lessons written by Charles M. Carroll
http://www.learnasp.com/learn/dsn2.asp Page 72


System DSN from ASP Quick Lessons

Setting up a system DSN Part 2
©1998, 1999 by Rob Martinson rob.martinson@directionsmag.com

Setting up a system DSN on Windows 95/NT

Once the ODBC Data Source Administrator window is open, select the System DSN tab at the top (I'm doing a system DSN because that's what I generally use. See here for more info on the differences between system and file DSNs). This will bring you to a list of System Data Sources that are setup on your machine. It may vary from the list above. From this point, click the "Add" button and move on to the next screen.


ASP Quick Lessons written by Charles M. Carroll
http://www.learnasp.com/learn/dsn3.asp Page 73


System DSN from ASP Quick Lessons

Setting up a system DSN Part 3
©1998, 1999 by Rob Martinson rob.martinson@directionsmag.com

I began my development using Microsoft Access as I already had a copy, and it would help me to learn SQL syntax that would later be of use in larger projects. For this reason, I will choose the MS Access Database driver from this screen. If you are setting up a DSN for a different database format, select the associated driver here.


ASP Quick Lessons written by Charles M. Carroll
http://www.learnasp.com/learn/dsn4.asp Page 74


System DSN from ASP Quick Lessons

Setting up a system DSN Part 4
©1998, 1999 by Rob Martinson rob.martinson@directionsmag.com

Here we will name our DSN. For web development, I generally setup a single DSN (depending on the project of course) and then just modify the database as needed. Because of that, I almost always name mine "tables.dsn". Name it whatever you like, just remember the name. From this screen you are also able to setup various options with your DSN including default authorization (click advanced), page timeout, database location, etc. For now we will leave the default options and move on to the next screen by choosing "Ok".


ASP Quick Lessons written by Charles M. Carroll
http://www.learnasp.com/learn/dsn5.asp Page 75


System DSN from ASP Quick Lessons

Setting up a system DSN Part 5
©1998, 1999 by Rob Martinson rob.martinson@directionsmag.com

If we have not specified the location of the database associated with our DSN on the previous screen, we will be prompted to do so now. This is self explanatory I believe.


ASP Quick Lessons written by Charles M. Carroll
http://www.learnasp.com/learn/dsn6.asp Page 76


System DSN from ASP Quick Lessons

Setting up a system DSN
©1998, 1999 by Rob Martinson rob.martinson@directionsmag.com

That's it! Your System DSN is setup and running. All you need to do now is get ASP to use it (which is pretty easy).


ASP Quick Lessons written by Charles M. Carroll
http://www.learnasp.com/learn/dbfull1.asp Page 77


DBFull1 from ASP Quick Lessons

Database Full Cycle #1 --
Display Table, Edit Record, Update Record

dbfull1.asp merely displays a table like we have in other examples, except every row of the table has a hyperlink to dbfull2.asp and passes the ID to that script in a variable called whichID. After the user edits that information and presses submit, dbfull3.asp is called. It's task is to gather all input fields and construct a SQL update statement. Here is a source printout of the script that displays the table and "starts the ball rolling":

   <%
   response.buffer=true
   Response.ExpiresAbsolute = Now() - 1
   Response.AddHeader "Cache-Control", "private"
   %>

   <html><head>
   <title>authorshow.asp</title>
   <meta http-equiv="pragma" content="no-cache">
   </head><body bgcolor="#FFFFFF">
10   <%
11   myDSN="DSN=Student;uid=student;pwd=magic"
12   mySQL="select * from authors where AU_ID<100 order by author"
13   IDfield="AU_ID"
14   scriptresponder="authoredit.asp"
15   
16   set conntemp=server.createobject("adodb.connection")
17   conntemp.open myDSN
18   set rstemp=conntemp.execute(mySQL)
19   howmanyfields=rstemp.fields.count -1
20   %>

21   <table border="1">
22   <tr>
23   <td valign="top">---</td>
24   <% 'Put Headings On The Table of Field Names
25   for i=0 to howmanyfields %>

26          <td><b><%=rstemp(i).name %></b></td>
27   <% next %>
28   </tr>
29   <% ' Now lets grab all the records
30   do  while not rstemp.eof %>

31      <tr><td valign="top">
32      <%my_link=scriptresponder & "?which=" & rstemp(idfield)%>
33      <a HREF="<%=my_link%>">Edit</a></td>
34      <% for i = 0 to howmanyfields%>
35             <td valign="top"><%=rstemp(i)%></td>
36      <% next %>
37      </tr>
38      <%
39      rstemp.movenext
40   loop
41   
42   rstemp.close
43   set rstemp=nothing
44   conntemp.close
45   set conntemp=nothing
46   %>

47   </table></body></html>


ASP Quick Lessons written by Charles M. Carroll
http://www.learnasp.com/learn/dbfull2.asp Page 78


DBfull2 from ASP Quick Lessons

Database Full Cycle #2 --
Display Table, Edit Record, Update Record

Here is the script that shows one record based on being linked to from the table

   <html><head>
   <title>authoredit.asp</title>
   </head><body bgcolor="#FFFFFF">
   <%
   ' My ASP program that given an AU_ID, allows editing a record
   
   myDSN="DSN=Student;uid=student;pwd=magic"
   
   set conntemp=server.createobject("adodb.connection")
10   conntemp.open myDSN
11   form_ID=request.querystring("which")
12   
13   sqltemp="select * from authors "
14   sqltemp=sqltemp & " where AU_ID=" & form_id
15   
16   set rstemp=conntemp.execute(sqltemp)
17   
18   
19   form_auID=rstemp("AU_ID")
20   form_author=rstemp("Author")
21   form_year_born=rstemp("Year_Born")
22   
23   rstemp.close
24   set rstemp=nothing
25   conntemp.close
26   set conntemp=nothing
27   %>

28   <body>
29   <form name="myauthor" action="authoreditrespond.asp" method="POST">
30   
31   <input type="hidden" name="id" value="<%=form_auid%>">
32   
33   <p>Author ID: <%=form_auid%></p>
34   
35   <p> Author Name:
36   <input type="TEXT" name="name" value="<%=form_author%>"></p>
37   
38   <p> Year Born:
39   <input type="TEXT" name="year" value="<%=form_year_born%>"></p>
40   
41   <p> <input type="SUBMIT"> </p>
42   </form>
43   </body>


ASP Quick Lessons written by Charles M. Carroll
http://www.learnasp.com/learn/dbfull3.asp Page 79


DBFull3 from ASP Quick Lessons

Database Full Cycle #3 --
Display Table, Edit Record, Update Record

Here is the script that updates one record after the submit button is pushed on the previous script.

   <HTML><HEAD>
   <TITLE>authoreditrespond.asp</TITLE>
   <body bgcolor="#FFFFFF"></HEAD>
   <%
   on  error resume next
   form_name=request.form("name")
   form_year=request.form("year")
   form_ID=request.form("ID")
   
10   Set Conn = Server.CreateObject("ADODB.Connection")
11   conn.open "DSN=Student;uid=student;pwd=magic"
12   
13   ' change apostrophe to double apostrophe
14   form_name=Replace(form_name, "'", "''")
15   IF  instr(lcase(form_name),"<img")>0 THEN
16      form_name=""
17   END IF
18   
19   SQLstmt = "UPDATE authors SET "
20   SQLStmt = SQLstmt & "Author='" & form_name & "',"
21   SQLstmt = SQLstmt & "year_born=" & form_year
22   SQLStmt = SQLStmt & " WHERE AU_ID=" & form_id
23   
24   
25   Set RS = Conn.Execute(SQLStmt)
26   
27   If  err.number>0 then
28         response.write "VBScript Errors Occured:" & "<P>"
29         response.write "Error Number=" & err.number & "<P>"
30         response.write "Error Descr.=" & err.description & "<P>"
31         response.write "Help Context=" & err.helpcontext & "<P>"
32         response.write "Help Path=" & err.helppath & "<P>"
33         response.write "Native Error=" & err.nativeerror & "<P>"
34         response.write "Source=" & err.source & "<P>"
35         response.write "SQLState=" & err.sqlstate & "<P>"
36   end if
37   IF  conn.errors.count> 0 then
38         response.write "Database Errors Occured" & "<P>"
39         response.write SQLstmt & "<P>"
40   for counter= 0 to conn.errors.count
41         response.write "Error #" & conn.errors(counter).number & "<P>"
42         response.write "Error desc. -> " & conn.errors(counter).description & "<P>"
43   next
44   else
45         response.write "<B>Everything Went Fine. Record is updated now!</b>"
46         response.write "<br>" & SQLstmt
47   end if
48   
49   rs.close
50   set rs=nothing
51   Conn.Close
52   set conn=nothing
53   %>

54   </BODY>
55   </HTML>
56   


ASP Quick Lessons written by Charles M. Carroll
http://www.learnasp.com/learn/dbtroubleshoot2.asp Page 80


dbtroubleshoot2 ASP Quick Lessons

Troubleshooting SQL Statements by Charles Carroll

Now we will show some SQL statements (below) with mistakes and the fixes indicated in red to show how to make the statements work. The kind of fixes we deploy include:

Text fields with single quote ' cannot be placed into SQL statements unmodified. Notice how the last example below uses the VBScript replace command to transform a string that may contain embedded ' .

Statement with Flaws Improved Statement (fixes in red)
UPDATE mytableSET LocID=0007,Material=13 1/4 Description=T-shirts ListPrice=35 WHERE CusID=97               added space before SET
UPDATE mytable SET LocID='0007',Material='13 1/4', Description='T-shirts', [List Price]=35 WHERE CusID=97
INSERT INTO authors (AU_ID, author, year_born)  VALUES (7000, Joe Smith,1950) INSERT INTO authors (AU_ID, author, year_born)  VALUES (7000, 'Joe Smith',1950)
SELECT * from atable where state = MD and
year born<1955
SELECT * from atable where state = 'MD' and
and [year born]<1955
<%
key=request.querystring("id")
au=request.querystring("author")
birthyear=request.querystring("year")
SQLstmt="INSERT INTO authors (AU_ID, author, year_born)  VALUES ("
SQLstmt= SQLstmt & key & ","
SQLstmt= SQLstmt & author & ","
SQLstmt= SQLstmt &
birthyear & ")"
%>
<%
key=request.querystring("id")
au=request.querystring("author")
au=Replace(au, "'", "''")
birthyear=request.querystring("year")
SQLstmt="INSERT INTO authors (AU_ID, author, year_born)  VALUES ("
SQLstmt= SQLstmt & key & ",
'"
SQLstmt= SQLstmt & author & "
',"
SQLstmt= SQLstmt &
birthyear & ")"
%>


ASP Quick Lessons written by Charles M. Carroll
http://www.learnasp.com/learn/dbtable.asp Page 81


dbtable

Display Table on Web Page by Charles Carroll

This page demonstrates the capabilities how to display a table from a SQL statement. It illustrates not only how to display the table, but also how to detect that no records were returned from a query, and how to detect null and blank values in the data.

   <html><head>
   <TITLE>dbtable.asp</TITLE>
   </head>
   <body bgcolor="#FFFFFF">
   <%
   ' ASP program that displays a database in table form
   myDSN="DSN=Student;uid=student;pwd=magic"
   mySQL="select * from publishers where state='NY'"
   showblank="&nbsp;"
10   shownull="-null-"
11   
12   set conntemp=server.createobject("adodb.connection")
13   conntemp.open myDSN
14   set rstemp=conntemp.execute(mySQL)
15   If  rstemp.eof then
16      response.write "No records matched<br>"
17      response.write mySQL & "<br>So cannot make table..."
18      conntemp.close
19      set conntemp=nothing
20      response.end
21   end if
22   %>

23   <table border=1><tr>
24   
25   <% 'Put Headings On The Table of Field Names
26   for each whatever in rstemp.fields%>

27          <td><b><%=whatever.name%></B></TD>
28   <% next %>
29   </tr>
30   
31   <% ' Now lets grab all the records
32   DO  UNTIL rstemp.eof %>

33      <tr>
34      <% for each whatever in rstemp.fields
35         thisfield=whatever.value
36         if isnull(thisfield) then
37            thisfield=shownull
38         end if
39         if trim(thisfield)="" then
40            thisfield=showblank
41         end if%>

42                <td valign=top><%=thisfield%></td>
43      <% next %>
44      </tr>
45      <%rstemp.movenext
46   LOOP%>

47   </table>
48   
49   <%
50   rstemp.close
51   set rstemp=nothing
52   conntemp.close
53   set conntemp=nothing
54   %>

55   </body></html>


ASP Quick Lessons written by Charles M. Carroll
http://www.learnasp.com/learn/dbtablegetstring.asp Page 82


dbtable

Database Display via GetString by Charles Carroll

This page demonstrates the capabilities how to display a table from a SQL statement a very fast and scaleable way using a recordset method called GetString. GetString essentially asks the backend database to build a huge string instead of moving the data as rows and columns. It allows very limited specifications, basically what string to place between each column and row and how to display nulls. Notice the total absence of the traditional EOF loop.

Its speed and scalability advantages are explained in:
Http://www.learnasp.com/advice/whygetrows.asp

This example does require ADO 2.0 or greater which can be downloaded from:
http://www.microsoft.com/data

If you are unsure which ADO version your server has
http://www.learnasp.com/learn/versioncheck.asp
will help you determine this.

Does this approach matter for small data sets for example 9 rows x 2 columns of data? YES!!!!!!!!

My site has SQLserver scripts that run like lightning. I once needed to fill a 9 item listbox from Access and got 90 sec script timeouts with movenext. Getstring never timed out. So in a real production situation it makes weak databases feasible and of course reduces the load on more industrial back-ends so maybe the SQLserver doesn't need as many indexes or RAM upgrades.

"The Worlds Fastest Listbox"
http://www.learnasp.com/learn/speedappdata.asp
shows the only faster way to display databases.

   <TITLE>dbtablegetstring.asp</TITLE>
   <body bgcolor="#FFFFFF">
   <%
   whichDSN="DSN=Student;uid=student;pwd=magic"
   mySQL="select * from publishers where state='NY'"
   
   set conntemp=server.createobject("adodb.connection")
   conntemp.open whichDSN
   set rstemp=conntemp.execute(mySQL)
10   If  rstemp.eof then
11      response.write "No records matched<br>"
12      response.write mySQL & "<br>So cannot make table..."
13      Call CloseAll
14      response.end
15   end if
16   
17   response.write "<table border='1'><tr>"
18   'Put Headings On The Table of Field Names
19   for each whatever in rstemp.fields
20      response.write "<td><b>" & whatever.name & "</B></TD>"
21   next
22   response.write "</tr><tr><td>"
23   response.write rstemp.getstring(,, "</td><td>", "</td></tr><TR><TD>", "-null-")
24   response.write "</td></tr></table>"
25   Call CloseAll
26   
27   
28   SUB CloseALL
29      rstemp.close
30      set rstemp=nothing
31      conntemp.close
32      set conntemp=nothing   
33   END SUB
34   %>

35   </body></html>
36   
37   
38   
39   
40   
41   
42   
43   
44   


ASP Quick Lessons written by Charles M. Carroll
http://www.learnasp.com/learn/dbtablegetrows.asp Page 83


dbtable

Table Database Display via GetRows by Charles Carroll

This page demonstrates the capabilities how to display a table from a SQL statement a very fast and scaleable way using a recordset method called GetRows. GetRows that move many records and fields into a memory array. Once in the array it is accessed very fast. If you read the code closely you will notice it can free up the recordset and connection object earlier than the traditional loop thus freeing up those resources for other scripts.

The array fields are accessed by number, a script at:
http://www.learnasp.com/learn/dbtablegetrowsnamed.asp
shows how to combine the speed of getrows and simulate named fields using dictionary objects.

In terms of why this is faster and reduces server resource consumption, read:
http://www.learnasp.com/advice/whygetrows.asp
to see an in-depth explanation.

http://www.learnasp.com/learn/dbtablegetstring.asp
rips getrows to shreds speed-wise as the backend transfers one big string instead of a complex array structure but formatting is SOOOOO limited (unless you know Regexps like the back of your hand....)

"The Worlds Fastest Listbox"
http://www.learnasp.com/learn/speedappdata.asp
shows the only faster way to display databases.

Since this code relies heavily on arrays you may want to read up on them at:

   <%@enablesessionstate=false%>
   <%response.buffer=true%>
   <html><head>
   <TITLE>dbtablegetrows.asp</TITLE>
   </head>
   <body bgcolor="#FFFFFF">
   <%
   ' displays a database in table form via GetRows
   myDSN="DSN=Student;uid=student;pwd=magic"
10   mySQL="select * from publishers where state='NY'"
11   showblank="&nbsp;"
12   shownull="-null-"
13   
14   set conntemp=server.createobject("adodb.connection")
15   conntemp.open myDSN
16   set rstemp=conntemp.execute(mySQL)
17   If  rstemp.eof then
18      response.write "No records matched<br>"
19      response.write mySQL & "<br>So cannot make table..."
20      Call CloseAll
21      response.end
22   end if
23   
24   response.write "<table border='1'><tr>" & vbcrlf
25   'Put Headings On The Table of Field Names
26   for each whatever in rstemp.fields
27      response.write "<td><b>" & whatever.name & "</B></TD>" & vbcrlf
28   next
29   response.write "</tr>" & vbcrlf
30   
31   ' Now lets grab all the records
32   alldata=rstemp.getrows
33   Call CloseAll
34   
35   numcols=ubound(alldata,1)
36   numrows=ubound(alldata,2)
37   FOR rowcounter= 0 TO numrows
38      response.write "<tr>" & vbcrlf
39      FOR colcounter=0 to numcols
40         thisfield=alldata(colcounter,rowcounter)
41         if isnull(thisfield) then
42            thisfield=shownull
43         end if
44         if trim(thisfield)="" then
45            thisfield=showblank
46         end if
47         response.write "<td valign=top>"
48         response.write thisfield
49         response.write "</td>" & vbcrlf
50      NEXT
51      response.write "</tr>" & vbcrlf
52   NEXT
53   response.write "</table>"
54   %>

55   </body></html>
56   <%
57   SUB CloseAll
58      rstemp.close
59      set rstemp=nothing
60      conntemp.close
61      set conntemp=nothing
62   END SUB
63   %>

64   


ASP Quick Lessons written by Charles M. Carroll
http://www.learnasp.com/learn/dbtablegetrowsnonum.asp Page 84


dbtable

GetRows NOT BY THE Numbers by Charles Carroll

Getrows Rocks! It is lightning fast and much more scalable than the .MOVENEXT approach. See a complete explanation @
http://www.learnasp.com/advice/whygetrows.asp

Tired of accessing a getrows array by number? There is an easier way we show here below*. But below is the most straightforward ways to use names instead of numbers with a Getrows array.

* and an easier ENCAPSULATED way (easy to use, complex source code) at:
http://www.learnasp.com/learn/getrowsultimate.asp

   <%@enablesessionstate=false%>
   <%response.buffer=true%>
   <html><head>
   <TITLE>dbtablegetrowsnonum.asp</TITLE>
   </head>
   <body bgcolor="#FFFFFF">
   <%
   ' displays a database in table form via GetRows
   myDSN="DSN=Student;uid=student;pwd=magic"
10   'mySQL="select PubID, [Company Name], Address, City, State, Zip, Telephone, Fax, Comments "
11   ' above statement fails because of [company name] still researching why....
12   mySQL="select * "
13   mySQL=mySQL & " from publishers"
14   mySQL=mySQL & " where state='NY'"
15   set conntemp=server.createobject("adodb.connection")
16   conntemp.open myDSN
17   set rstemp=conntemp.execute(mySQL)
18   response.write rstemp(2).name
19   
20   If  rstemp.eof then
21      response.write "No records matched<br>"
22      response.write mySQL & "<br>So cannot make table..."
23      Call CloseAll
24      response.end
25   end if
26   
27   response.write "<table border='1'><tr>" & vbcrlf
28   'Put Headings On The Table of Field Names
29   for each whatever in rstemp.fields
30      response.write "<td><b>" & whatever.name & "</B></TD>" & vbcrlf
31   next
32   response.write "</tr>" & vbcrlf
33   
34   ' Now lets grab all the records
35   alldata=rstemp.getrows
36   Call CloseAll
37   
38   numrows=ubound(alldata,2)
39   fld_pubid=0
40   fld_Name=1
41   fld_companyname=2
42   fld_address=3
43   fld_city=4
44   fld_state=5
45   fld_zip=6
46   fld_telephone=7
47   fld_fax=8
48   fld_comments=9
49   
50   FOR rowcounter= 0 TO numrows
51      response.write "<tr>" & vbcrlf
52      pubid=alldata(fld_pubid,rowcounter)
53      name=alldata(fld_name,rowcounter)
54      companyname=alldata(fld_companyname,rowcounter)
55      address=alldata(fld_address,rowcounter)
56      city=alldata(fld_city,rowcounter)
57      state=alldata(fld_state,rowcounter)
58      zip=alldata(fld_zip,rowcounter)
59      telephone=alldata(fld_telephone,rowcounter)
60      fax=alldata(fld_fax,rowcounter)
61      comments=alldata(fld_comments,rowcounter)
62   
63      pubid=cleanfield(pubid)
64      response.write "<td valign=top>" & pubid & "</td>" & vbcrlf   
65   
66      name=cleanfield(name)
67      response.write "<td valign=top>" & name & "</td>" & vbcrlf   
68   
69      companyname=cleanfield(companyname)
70      response.write "<td valign=top>" & companyname & "</td>" & vbcrlf   
71   
72      
73      companyname=cleanfield(address)
74      response.write "<td valign=top>" & address & "</td>" & vbcrlf   
75   
76      city=cleanfield(city)
77      response.write "<td valign=top>" & city & "</td>" & vbcrlf   
78   
79      state=cleanfield(state)
80      response.write "<td valign=top>" & state & "</td>" & vbcrlf   
81   
82      zip=cleanfield(zip)
83      response.write "<td valign=top>" & zip & "</td>" & vbcrlf   
84   
85      telephone=cleanfield(telephone)
86      response.write "<td valign=top>" & telephone & "</td>" & vbcrlf   
87   
88      fax=cleanfield(fax)
89      response.write "<td valign=top>" & fax & "</td>" & vbcrlf   
90   
91      comments=cleanfield(comments)
92      response.write "<td valign=top>" & comments & "</td>" & vbcrlf   
93      
94      response.write "</tr>" & vbcrlf
95   NEXT
96   response.write "</table>"
97   %>

98   </body></html>
99   <%
100   SUB CloseAll
101      rstemp.close
102      set rstemp=nothing
103      conntemp.close
104      set conntemp=nothing
105   END SUB
106   
107   FUNCTION CleanField(parm1)
108         cleanfield=parm1
109         if isnull(parm1) then
110            cleanfield="&nbsp;"
111         end if
112         if trim(parm1)="" then
113            cleanfield="&nbsp;"
114         end if
115   END FUNCTION
116   %>

117   


ASP Quick Lessons written by Charles M. Carroll
http://www.learnasp.com/learn/dbtabledisconnected.asp Page 85


Database Display Disconnected Recordset

Display Table and Disconnect Recordset by Charles Carroll

This page demonstrates the capabilities how to display a table from a SQL statement. It illustrates not only how to display the table, but also how to detect that no records were returned from a query, and how to detect null and blank values in the data. This example disconnects the recordset so that the data will not be drawn from up to the millisecond database data BUT retrieval will be much faster.

   <%@enablesessionstate=false%>
   <%response.buffer=true%>
   <!--#include virtual="/adovbs.inc"-->
   <html><head>
   <TITLE>dbtabledisconnected.asp</TITLE>
   </head>
   <body bgcolor="#FFFFFF">
   <%
   ' displays a database in table form via GetRows
10   myDSN="DSN=Student;uid=student;pwd=magic"
11   mySQL="select * from publishers where state='NY'"
12   showblank="&nbsp;"
13   shownull="-null-"
14   
15   set conntemp=server.createobject("adodb.connection")
16   conntemp.open myDSN
17   ' to disconnect a recordset it must be created explicitly
18   set rstemp=server.createobject("adodb.recordset")
19   rstemp.cursorlocation=aduseclient
20   rstemp.open mySQL,conntemp
21   ' this line below disconnects the recordset
22   set rstemp.activeconnection=nothing
23   
24   If  rstemp.eof then
25      response.write "No records matched<br>"
26      response.write mySQL & "<br>So cannot make table..."
27      rstemp.close
28      set rstemp=nothing
29      conntemp.close
30      set conntemp=nothing
31      response.end
32   end if
33   
34   response.write "<table border='1'><tr>"
35   'Put Headings On The Table of Field Names
36   for each whatever in rstemp.fields
37      response.write "<td><b>" & whatever.name & "</B></TD>"
38   next
39   response.write "</tr>"
40   DO  UNTIL rstemp.eof
41      response.write "<tr>"
42      for each whatever in rstemp.fields
43         thisfield=whatever.value
44         if isnull(thisfield) then
45            thisfield=shownull
46         end if
47         if trim(thisfield)="" then
48            thisfield=showblank
49         end if
50         response.write "<td valign=top>" & thisfield & "</td>"
51      next
52      response.write "</tr>"
53      rstemp.movenext
54   LOOP
55   response.write "</table>"
56   %>

57   </body></html>


ASP Quick Lessons written by Charles M. Carroll
http://www.learnasp.com/learn/dbtablemore.asp Page 86


dbtable

Display database table on Web Page
Many Approaches by Charles Carroll

There are many ways to display a table on a web page. So many that we feel that a brief description of the variations and some URLs will help. A good programmer knows many ways to tackle the same problem!

Paging through arbitrary groups of records (i.e. record __ of __ ) at:
    /learn/dbtablepaged.asp

Displaying a table without using a DSN, i.e. a DSNLess connection at:
    /learn/dbopen.asp

Use the faster Getrows function to retrieve a recordset into an array:
   /learn/dbtablegetrows.asp

Use the lightning fast Getstring function to retrieve a recordset into a string:
  /learn/dbtablegetstring.asp

Using a very nice generic routine from Eli Robillard at:
  /learn/genericdb.asp

Use an excellent 3rd party component (ASPDB):
  http://www.learnasp.com/learn/aspdb.asp

Displaying a Table with many records as quick as possible is documented in depth at:
 /learn/speedtables.asp
 /learn/speedtablesall.asp

Displaying a Table using simple subroutines & includes at:
  /learn/subdbtable.asp

Displaying tables, listboxes and other arbitrary HTML at:
  /learn/subreusable.asp


ASP Quick Lessons written by Charles M. Carroll
http://www.learnasp.com/learn/genericdb.asp Page 87


ASP Speed from ASP Quick Lessons

Generic Database Display Made Easy

When you want a quick easy generic database display, go on over to:
http://www.genericdb.com

Here Eli Robillard has done a lot of work for you. You modify one ASP file that specifies your database and query specs and his ASP scripts magically do the rest.

Here is an example where I make a pubs.asp designed to plug into his ASP scripts.

   <%
      ' Generic interface to the Northwinds Employee table.
      Session("dbGenericPath") = "/learn/test/genericdb/"
      Session("dbExitPage") = "http://www.activeserverpages.com"
      Session("dbTitle") = "Pubs"
      Session("dbType") = "SQL"
      Session("dbConn") = "DSN=student;uid=student;pwd=magic"
      Session("dbRs") = "Publishers"
      Session("dbKey") = 1
10      Session("dbOrder") = 2
11      Session("dbRecsPerPage") = 10
12      Session("dbFooter") = 1
13      Session("dbDispList") = "011101000000100010"
14      Session("dbDispView") = "111111111111111111"
15      Session("dbDispEdit") = "011111111111111111"
16      Session("dbSearchFields") = "011100010010001000"
17      Session("dbDefault6") = Date()
18      Session("dbCombo11") = "LIST, ??, Unknown, CA, Canada, US, United States, DE, Denmark"
19      Session("dbDefault17") = 10
20      Session("dbWhere") = ""
21      Session("dbDebug") = 1
22      Session("dbCanEdit") = 1
23      Session("dbCanAdd") = 1
24      Session("dbCanDelete") = 1
25      Session("dbConfirmDelete") = 1
26      Session("dbViewPage") = Request.ServerVariables("PATH_INFO")
27      Response.Redirect Session("dbGenericPath") & "GenericList.asp"
28   %>

There is even a listserve supporting this great FREE script collection @
http://www.asplists.com/asplists/aspgenericdb.asp
It is not a general database troubleshooting list, instead only questions concerning these wonderful scripts are allowed.


ASP Quick Lessons written by Charles M. Carroll
http://www.learnasp.com/learn/aspgenericdb.asp Page 88


Listserrver Join aspgenericdbListserver for more info @

http://www.asplists.com/asplists/aspgenericdb.asp

Related Links:

 
Generic DB Sample @
   http://www.learnasp.com/learn/genericdb.asp
Generic DB Main Page @
   http://www.genericdb.com
Generic DB Tips @
   http://squeek.tzo.com/genericdb

Recommended Books:

Related Lists:

Mobile lists by Asplists @
   http://www.asplists.com/asplists/mobile.asp
Mobile lists by WROX @
   http://p2p.wrox.com/mobile/

Rules:

Mailing List Manners (suggested by Bob Filipiak) @
   http://db.tidbits.com/getbits.acgi?tbser=1141
Ken Shaffer's Advice on Asking For Help... @
   http://www.adopenstatic.com/personal/help.asp


ASP Quick Lessons written by Charles M. Carroll
http://www.learnasp.com/learn/dbconvert.asp Page 89


dbtablesimple from ASP Quick Lessons

Database -- Convert to Comma-Delimited File by Charles Carroll

This page demonstrates the capabilities how to write an ASCII comma-delimited file from a SQL statement.

   <html><head>
   <TITLE>dbconvert.asp</TITLE>
   </head><body bgcolor="#FFFFFF">
   <%
   whichname="/upload/tests/authors.txt"
   myDSN="DSN=Student;uid=student;pwd=magic"
   mySQL="select * from authors where au_id<100"
   showblank=""
   shownull="<null>"
10   linestart=chr(34)
11   lineend=chr(34)
12   delimiter=chr(34) & "," & chr(34)
13   delimitersub=""
14   
15   whichFN=server.mappath(whichname)
16   
17   Set fstemp = server.CreateObject("Scripting.FileSystemObject")
18   Set filetemp = fstemp.CreateTextFile(whichFN, true)
19   ' true = file can be over-written if it exists
20   ' false = file CANNOT be over-written if it exists
21   
22   set conntemp=server.createobject("adodb.connection")
23   conntemp.open myDSN
24   set rstemp=conntemp.execute(mySQL)
25   
26   ' this code detects if data is empty
27   If  rstemp.eof then
28      response.write "No data to convert for SQL statement<br>"
29      response.write mySQL & "<br>"
30      connection.close
31      set connection=nothing
32      response.end
33   end if
34   
35   DO  UNTIL rstemp.eof
36      thisline=linestart
37      for each whatever in rstemp.fields
38         thisfield=whatever.value
39         if isnull(thisfield) then
40            thisfield=shownull
41         end if
42         if trim(thisfield)="" then
43            thisfield=showblank
44         end if
45         thisfield=replace(thisfield,delimiter,delimitersub)
46             thisline=thisline & thisfield & delimiter
47      next
48      tempLen=len(thisline)
49      tempLenDelim=len(delimiter)
50      thisline=mid(thisline,1,tempLEN-tempLenDelim) & lineend
51      filetemp.WriteLine(thisline)
52      ' response.write thisline & "<br>"
53      rstemp.movenext
54   LOOP
55   filetemp.Close
56   set filetemp=nothing
57   set fstemp=nothing
58   rstemp.close
59   set rstemp=nothing
60   conntemp.close
61   set conntemp=nothing
62   
63   
64   
65   If  err.number=0 then
66      response.write "File was converted sucessfully!<br>"
67      response.write "Converted file is at <a href='"
68      response.write whichname & "'>" & whichname & "</a>"
69   else
70         response.write "VBScript Errors Occured!<br>"
71         response.write "Error Number=#<b>" & err.number & "</b><br>"
72         response.write "Error Desc. =<b>" & err.description & "</b><br>"
73         response.write "Help Path =<b>" & err.helppath & "</b><br>"
74         response.write "Native Error=<b>" & err.nativeerror & "</b><br>"
75         response.write "Error Source =<b>" & err.source & "</b><br>"
76       response.write "SQL State=#<b>" & err.sqlstate & "</b><br>"
77   end if
78   
79   
80   %>

81   </body></html>


ASP Quick Lessons written by Charles M. Carroll
http://www.learnasp.com/learn/dbSQLdelete.asp Page 90


Add Record with SQL ASP Quick Lessons

Database -- Delete Record with SQL statement

SQL statements can be used to delete data as well.

Here is a script that will add a bunch of records with the AU_ID of 200:

   <TITLE>dbaddmany.asp</TITLE>
   <body bgcolor="#FFFFFF">
   <HTML>
   <!--#include file="lib_errors.asp"-->
   <%
   on  error resume next
   myDSN = "DSN=Student;uid=student;pwd=magic"
   mySQL = "INSERT INTO authors (AU_ID,author,year_born) "
   mySQL = mySQL & "VALUES (200,'Charles M. Carroll',1964)"
10   
11   Set Conn = Server.CreateObject("ADODB.Connection")
12   conn.open myDSN
13   
14   for counter=1 to 200
15      thistask="Task #" & counter & "<br>"
16      response.write thistask
17      Conn.Execute(mySQL)
18      Call ErrorVBScriptReport(thistask)
19      Call ErrorADOReport(mySQL,conn)
20   next
21   Conn.Close
22   set conn=nothing
23   %>

24   </BODY>
25   </HTML>

Now here is a script that will delete all the records the above script added:

   <TITLE>dbdeletemany.asp</TITLE>
   <body bgcolor="#FFFFFF">
   <HTML>
   <!--#include file="lib_errors.asp"-->
   <%
   on  error resume next
   myDSN = "DSN=Student;uid=student;pwd=magic"
   mySQL = "DELETE FROM authors WHERE au_id=200"
   
10   Set Conn = Server.CreateObject("ADODB.Connection")
11   conn.open myDSN
12   
13   Conn.Execute mySQL,howmany
14   response.write "The statement " & mySQL & "<b> deleted " & howmany & " records</b><br>"
15   Call ErrorVBScriptReport("Deleting...")
16   Call ErrorADOReport(mySQL,conn)
17   
18   Conn.Close
19   set conn=nothing
20   %>

21   </BODY>
22   </HTML>

The error trapping library looks like this:

   <%
   SUB ErrorVBScriptReport(parm_msg)
      If err.number=0 then
         exit sub
      end if
      pad="&nbsp;&nbsp;&nbsp;&nbsp;"
      response.write "<b>VBScript Errors Occured!<br>"
      response.write parm_msg & "</b><br>"
      response.write pad & "Error Number= #<b>" & err.number & "</b><br>"
10      response.write pad & "Error Desc.= <b>" & err.description & "</b><br>"
11      response.write pad & "Help Context= <b>" & err.HelpContext & "</b><br>"
12      response.write pad & "Help File Path=<b>" & err.helpfile & "</b><br>"
13      response.write pad & "Error Source= <b>" & err.source & "</b><br><hr>"
14   END SUB
15   
16   SUB ErrorADOReport(parm_msg,parm_conn)
17      HowManyErrs=parm_conn.errors.count
18      IF HowManyErrs=0 then
19         exit sub
20      END IF
21      pad="&nbsp;&nbsp;&nbsp;&nbsp;"
22      response.write "<b>ADO Reports these Database Error(s) executing:<br>"
23             response.write SQLstmt & "</b><br>"
24      for counter= 0 to HowManyErrs-1
25         errornum=parm_conn.errors(counter).number
26         errordesc=parm_conn.errors(counter).description
27         response.write pad & "Error#=<b>" & errornum & "</b><br>"
28         response.write pad & "Error description=<b>"
29         response.write errordesc & "</b><p>"
30      next
31   END SUB
32   %>


ASP Quick Lessons written by Charles M. Carroll
http://www.learnasp.com/learn/accesstest.asp Page 91


dbtable

Access Scalability Notes by Charles Carroll

This page demonstrates how many Access connections can be opened by one script. Testing generally indicates a single script can only initiate 64 connections. Microsoft Tech Support has suggested a 255 limit easily disproved by this script. As a point of reference I ran this same script against a SQL7 data source and attempted 2,550 connections. All were sucessful.

Access has the following limitations:

1. Access is STA (single-threaded-apartment), NOT MTA or Free-Threaded (see http://www.learnasp.com/advice/threads.asp for thread basics). What this means is that all database requests are serialized, i.e.
user1 asks for 100 records
user2 asks for 2 records
user3 asks for 5000 records
user4 asks for 3 records
If an agile back-end (free-threaded or MTA for example SQLserver, Oracle, etc.) was handling those requests it could send user2 and user4 records before dealing with other requests. Access cannot. User 4 will receive their data AFTER the other requests have completed. Requests are handled as they come in and to completion before next low-level data access starts. So the application's pattern of retrieval makes a huge difference in whether an Access app will scale.

2. Since open connections are the issue and scripts run round-robin, see: http://www.learnasp.com/advice/roundrobin.asp  (see advice about open late/close early) http://www.learnasp.com/advice/whybuffer.asp  http://www.learnasp.com/advice/whygetrows.asp  are EXTREMELY relevant in this case.

3. Access unfortunately does not support connection pooling which can dramatically improve performance, see:
http://www.learnasp.com/learn/dbpooling.asp

4. The free answer to this problem is MSDE, a chopped down version of SQLserver that Microsoft gives away which can handle much more load, see:
http://msdn.microsoft.com/vstudio/msde/

Additional Note: ODBC connections are very flaky producing a variety of run-time error messages that OLEDB connections do not.  This sample uses an OLEDB connection hence it's "microsoft.jet.oledb...." vs. a connection string that contains "{microsoft access...}". The latter connection string/ODBC connection is far less reliable. See:
http://www.learnasp.com/learn/dbopen.asp for more connection string info.
For example: [Microsoft][ODBC Microsoft Access Driver]General error Unable to open registry key 'Temporary (volatile) Jet DSN for process 0xda8 Thread 0x49c DBC 0x254d024 Jet'. occurs when connecting to data with "{microsoft access..." connection string whereas exactly the same data can be accessed with "Jet.oledb" string fine.

   <HTML><HEAD><TITLE>accesstest.asp</TITLE></HEAD>
   <body bgcolor="#FFFFFF">
   <%
   on  error resume next
   myconn = "PROVIDER=Microsoft.Jet.OLEDB.4.0;DATA SOURCE=" & server.mappath("nwind.mdb") & ";"
   ' the above string is recommended way to connect
   ' myconn = "DRIVER={Microsoft Access Driver (*.mdb)};DBQ=" & server.mappath("nwind.mdb") & ";"
   ' the above connect string is VERY flaky
   dim test(256)
10   dim errn(256)
11   dim errd(256)
12   for counter=1 to 255
13      set test(counter)=server.createobject("adodb.connection")
14      goodconn=true
15      test(counter).open myconn
16      ' have to test error here because if conn cant be created
17      ' the errcount... line will fail
18      vbserror=err.number
19      errcount=test(counter).errors.count
20      IF errcount>0 then
21          DBErrNum=test(counter).errors(0).number
22          DBErrDes=test(counter).errors(0).description   
23       errn(counter)=DBErrNum
24         errd(counter)="ADO: " & DBErrDes
25         goodconn=false
26      END IF
27   
28      ' VBScript Error Trap
29      IF vbserror<>0 THEN
30         errn(counter)=vbserror
31         errd(counter)="VBS: " & err.description
32         goodconn=false
33      END IF
34      If goodconn=true THEN
35         errn(counter)=0
36         success=success+1
37      END IF
38      response.flush
39   NEXT
40   for counter=1 to 255
41      test(counter).close
42      set test(counter)=nothing
43   next
44   response.write "Successful connections=" & success & "<br>"
45   
46   for counter = 1 To 255
47      errnum=errn(counter)
48      IF errnum<>0 THEN
49         response.write "#" & counter & " connection failed:"
50         response.write errd(counter) & "<br>"
51      END IF
52   next
53   %>

54   </BODY></HTML>


ASP Quick Lessons written by Charles M. Carroll
http://www.learnasp.com/learn/dbtablepaged.asp Page 92


dbtablepaged

Paged Table Displays by Charles Carroll & Jeff Emrich

This page demonstrates how to retrieve a recordset divided up into pages, and to only select data from a specified page. It does not in any way store a recordset or connection in memory when the page is not accessed unlike many solutions you will read about. The ADO properties that make this magic possible are .AbsolutePage, .PageCount and .PageSize.

   <html><head>
   <TITLE>dbtablepaged.asp</TITLE>
   </head><body bgcolor="#FFFFFF">
   <!--#INCLUDE VIRTUAL="/ADOVBS.INC" -->
   <%
   connectme="DSN=Student;uid=student;pwd=magic"
   sqltemp="select * from publishers"
   
   ' Troubleshooting TIP:
10   ' if you use this code and get an error, for example:
11   '
12   ' ADODB.Recordset error 800a0cb3
13   '
14   ' The operation requested by the application is not
15   ' supported by the provider.
16   '
17   ' You may have a driver that is out of date, see:
18   ' http://www.learnasp.com/learn/connectioninfo.asp
19   ' for code that will identify what your driver version is
20   ' this script works with Access, SQLserver and Oracle
21   ' with up-to-date drivers
22   
23   If  aduseclient="" THEN
24      ref="http://www.learnasp.com/adovbs.inc"
25      response.write "You forgot to include:<br>"
26      response.write "/adovbs.inc<br>"
27      response.write "Get the file from <a href='" & ref & "'>" & ref & "<br>"
28      response.end
29   END IF
30   
31   mypage=request("whichpage")
32   If  mypage="" then
33      mypage=1
34   end if
35   mypagesize=request("pagesize")
36   If  mypagesize="" then
37      mypagesize=10
38   end if
39   mySQL=request("SQLquery")
40   IF  mySQL="" THEN
41      mySQL=SQLtemp
42   END IF
43   
44   set rstemp=Server.CreateObject("ADODB.Recordset")
45   rstemp.cursorlocation=aduseclient
46   rstemp.cachesize=5
47   tempSQL=lcase(mySQL)
48      badquery=false
49      IF instr(tempSQL,"delete")>0 THEN
50         badquery=true
51      END IF
52      IF instr(tempSQL,"insert")>0 THEN
53         badquery=true
54      END IF
55      IF instr(tempSQL,"update")>0 THEN
56         badquery=true
57      END IF
58      If badquery=true THEN
59         response.write "Not a SELECT Statement<br>"
60         response.end
61      END IF
62   
63   rstemp.open mySQL,connectme
64   rstemp.movefirst
65   rstemp.pagesize=mypagesize
66   maxpages=cint(rstemp.pagecount)
67   maxrecs=cint(rstemp.pagesize)
68   rstemp.absolutepage=mypage
69   howmanyrecs=0
70   howmanyfields=rstemp.fields.count -1
71   response.write "Page " & mypage & " of " & maxpages & "<br>"
72   response.write "<table border='1'><tr>"
73   
74   'Put Headings On The Table of Field Names
75   FOR i=0 to howmanyfields
76      response.write "<td><b>" & rstemp(i).name & "</b></td>"
77   NEXT
78   response.write "</tr>"
79   
80   ' Now loop through the data
81   DO  UNTIL rstemp.eof OR howmanyrecs>=maxrecs
82      response.write "<tr>"
83      FOR i = 0 to howmanyfields
84         fieldvalue=rstemp(i)
85         If isnull(fieldvalue) THEN
86            fieldvalue="n/a"
87         END IF
88         If trim(fieldvalue)="" THEN
89            fieldvalue="&nbsp;"
90         END IF
91         response.write "<td valign='top'>"
92         response.write fieldvalue
93         response.write "</td>"
94      next
95      response.write "</tr>"
96      rstemp.movenext
97      howmanyrecs=howmanyrecs+1
98   LOOP
99   response.write "</table><p>"
100   
101   ' close, destroy
102   rstemp.close
103   set rstemp=nothing
104   
105   ' Now make the page _ of _ hyperlinks
106   Call PageNavBar
107   
108   sub PageNavBar()
109      ' Thanks to Jeff Emrich <jeff.emrich@datafuse.com>
110         pad=""
111         scriptname=request.servervariables("script_name")
112         response.write "<table rows='1' cols='1' width='97%'><tr>"
113         response.write "<td>"
114         response.write "<font size='2' color='black' face='Verdana, Arial,Helvetica, sans-serif'>"
115         if (mypage mod 10) = 0 then
116          counterstart = mypage - 9
117         else
118          counterstart = mypage - (mypage mod 10) + 1
119         end if
120         counterend = counterstart + 9
121         if counterend > maxpages then counterend = maxpages
122         if counterstart <> 1 then
123          ref="<a href='" & scriptname
124          ref=ref & "?whichpage=" & 1
125          ref=ref & "&pagesize=" & mypagesize
126          ref=ref & "&sqlQuery=" & server.URLencode(mySQL)
127          ref=ref & "'>First</a>&nbsp;:&nbsp;"
128          Response.Write ref
129   
130   
131          ref="<a href='" & scriptname
132          ref=ref & "?whichpage=" & (counterstart - 1)
133          ref=ref & "&pagesize=" & mypagesize
134          ref=ref & "&sqlQuery=" & server.URLencode(mySQL)
135          ref=ref & "'>Previous</a>&nbsp;"
136          Response.Write ref
137         end if
138         Response.Write "["
139         for counter=counterstart to counterend
140          If counter>=10 then
141          pad=""
142          end if
143          if cstr(counter) <> mypage then
144          ref="<a href='" & scriptname
145          ref=ref & "?whichpage=" & counter
146          ref=ref & "&pagesize=" & mypagesize
147          ref=ref & "&sqlQuery=" & server.URLencode(mySQL)
148          ref=ref & "'>" & pad & counter & "</a>"
149          else
150          ref="<b>" & pad & counter & "</b>"
151          end if
152          response.write ref
153          if counter <> counterend then response.write " "
154         next
155         Response.Write "]"
156         if counterend <> maxpages then
157          ref="&nbsp;<a href='" & scriptname
158          ref=ref & "?whichpage=" & (counterend + 1)
159          ref=ref & "&pagesize=" & mypagesize
160          ref=ref & "&sqlQuery=" & server.URLencode(mySQL)
161          ref=ref & "'>Next</a>"
162          Response.Write ref
163   
164   
165          ref="&nbsp;:&nbsp;<a href='" & scriptname
166          ref=ref & "?whichpage=" & maxpages
167          ref=ref & "&pagesize=" & mypagesize
168          ref=ref & "&sqlQuery=" & server.URLencode(mySQL)
169          ref=ref & "'>Last</a>"
170          Response.Write ref
171         end if
172         response.write "<br></font>"
173         response.write "</td>"
174         response.write "</table>"
175   end sub
176   %>

177   </body></html>


ASP Quick Lessons written by Charles M. Carroll
http://www.learnasp.com/learn/dbmaxrecs.asp Page 93


dbmaxrecs

ADO Techniques -- The .maxrecords property

This page demonstrates the capabilities how to display a table from a SQL statement but limit the output to a specific number of records.

   <html><head>
   <TITLE>dbmaxrecs.asp</TITLE>
   </head><body bgcolor="#FFFFFF">
   <!--#INCLUDE VIRTUAL="/ADOVBS.INC" -->
   <%
   set rstemp=Server.CreateObject("adodb.Recordset")
   rstemp.maxrecords=15
   connectme="DSN=Student;uid=student;pwd=magic"
   rstemp.open "select * from titles", _
10          connectme,adopenstatic
11   ' table display
12   howmanyfields=rstemp.fields.count -1
13   %>

14   <table border=1><tr>
15   <%
16   for i=0 to howmanyfields %>

17          <td><b><%=rstemp(i).name %></B></TD>
18   <% next %>
19   </tr>
20   <%
21   do  while not rstemp.eof %>

22   <tr>
23   <% for i = 0 to howmanyfields%>
24          <td valign=top><% = rstemp.fields(i).value %>&nbsp;</td>
25   <% next %>
26   </tr>
27   <%
28   rstemp.movenext
29   loop
30   rstemp.close
31   set rstemp=nothing
32   %>

33   </table></body></html>


ASP Quick Lessons written by Charles M. Carroll
http://www.learnasp.com/learn/dbcount.asp Page 94


Count Records by Juan Llibre, Charles Carroll

This script counts the records in a database. Many people who attempt to use the .recordcount property have the value -1 returned to them. In a nutshell, -1 means "I don't know how many records this query/table contains". It happens since the default cursor type is AdOpenforwardonly (see below for explanation of all cursor types). Here is the script that counts the query results and WILL NOT return -1:

   <head><html>
   <TITLE>dbcount.asp</TITLE>
   </head><body bgcolor="#FFFFFF">
   <!--#INCLUDE VIRTUAL="/ADOVBS.INC" -->
   <%
   ' change these for your site
   connectme="DSN=Student;uid=student;pwd=magic"
   sqltemp="select * from publishers where state='NY'"
   set rstemp=Server.CreateObject("adodb.Recordset")
10   rstemp.open sqltemp, connectme, adopenstatic
11   howmanyrecs=rstemp.recordcount
12   response.write howmanyrecs & " records in<br>" & sqltemp
13   rstemp.close
14   set rstemp=nothing
15   %>

16   </body></html>
17   

The critical part here is having a cursor type that supports it (Adopenforward only is the default cursor type and it does NOT support counting records) and including adovbs.inc to define the cursor types. The file adovbs.inc can be obtained from http://www.learnasp.com/adovbs.inc

If you open the database and are able to obtain an accurate record count is by nature a slower connection; it is a burden on a recordset that it must know exact record counts upon demand. The additional overhead and limitations of a adopendynamic or adopenstatic cursor may be a glacially slow way to retrieve the data even though they count accurately. If you must count AND retrieve, you can't go wrong using GetRows (see http://www.learnasp.com/learn/dbtablegetrow.asp) because:

Here is a description of the significance of each cursor type:

Adopenstatic cursor
   The data is dead. If you retrieve a million records for example at 9:00am and it takes 6 minutes to read the data, at the 6th minute you will not be retrieving fresh or recently added data. It is like a snapshot of the data. Recordsets opened this way WILL contain an accurate recordcount.

Adopenforwardonly cursor (the default)
   The data is alive but you can only move forward. Attempts to move backward or to specific record numbers will fail.. Recordsets opened this way WILL NOT contain an accurate recordcount, instead returning -1.

Adopenkeyset cursor
  
The data is alive and any record read will be the most recent data.  f you retrieve a million records for example at 9:00am and it takes 6 minutes to read the data, at the 6th minute you will still be retrieving fresh data but NOT data added or deleted since 9am. Recordsets opened this way WILL NOT contain an accurate recordcount, instead returning -1.

Adopendynamic cursor
   The data is alive and additions will be noticed. If you retrieve a million records for example at 9:00am and it takes 6 minutes to read the data, at the 6th minute you will still be retrieving fresh data and records added to the end of the data.  Recordsets opened this way WILL contain an accurate recordcount.


ASP Quick Lessons written by Charles M. Carroll
http://www.learnasp.com/learn/adocursortypes.asp Page 95


ADO Cursor Types from ASP Quick Lessons

ADO Cursor Types by Phil Paxton (juggler@iquest.net)

ADO cursor types affects the properties and methods that are available as this table illustrates.

Property Forward-Only Dynamic Keyset Static
AbsolutePage N/A N/A R/W R/W
AbsolutePosition N/A N/A R/W R/W
ActiveConnection R/W R/W R/W R/W
BOF R/O R/O R/O R/O
Bookmark N/A N/A R/W R/W
CacheSize R/W R/W R/W R/W
CursorLocation R/W R/W R/W R/W
CursorType R/W R/W R/W R/W
EditMode R/O R/O R/O R/O
EOF R/O R/O R/O R/O
Filter R/W R/W R/W R/W
LockType R/W R/W R/W R/W
MarshalOptions R/W R/W R/W R/W
MaxRecords R/W R/W R/W R/W
PageCount N/A N/A R/O R/O
PageSize R/W R/W R/W R/W
RecordCount N/A N/A R/O R/O
Source R/W R/W R/W R/W
State R/O R/O R/O R/O
Status R/O R/O R/O R/O
Method        
AddNew Yes Yes Yes Yes
CancelBatch Yes Yes Yes Yes
CancelUpdate Yes Yes Yes Yes
Clone N/A N/A Yes Yes
Close Yes Yes Yes Yes
Delete Yes Yes Yes Yes
GetRows Yes Yes Yes Yes
Move Yes Yes Yes Yes
MoveFirst Yes Yes Yes Yes
MoveLast N/A Yes Yes Yes
MoveNext Yes Yes Yes Yes
MovePrevious N/A Yes Yes Yes
NextRecordset Yes Yes Yes Yes
Open Yes Yes Yes Yes
Requery Yes Yes Yes Yes
Resync N/A N/A Yes Yes
Supports Yes Yes Yes Yes
Update Yes Yes Yes Yes
UpdateBatch Yes Yes Yes Yes

Legend:
R/W = Read/Write
R/O = Read-Only
N/A = Not Available or Supported
Yes = Available/Supported


ASP Quick Lessons written by Charles M. Carroll
http://www.learnasp.com/learn/dbnewrec.asp Page 96


Database New Record Form ASP Quick Lessons

Database -- Form to Input a New Record

This page demonstrates the capabilities how to setup a simple form for a new database record. The script:

   <html><head>
   <title>dbnewrec.asp</title>&
   <body bgcolor="#FFFFFF">
   <% ' My ASP program that allows you to append a record %>
   <form name="myauthor" action="dbnewrecSQL.asp" method="GET">
   <p>Author ID: <input type="TEXT" name="id"></p>
   <p> Author Name: <input type="TEXT" name="name"></p>
   <p> Year Born: <input type="TEXT" name="year"></p>
   <p> <input type="SUBMIT"> </p>
10   </form></body></html>


ASP Quick Lessons written by Charles M. Carroll
http://www.learnasp.com/learn/dbnewSQL.asp Page 97


Add Record with SQL ASP Quick Lessons

Database -- Add New Record with SQL statement

This page demonstrates the capabilities how to add a record to a database with a SQL statement. To double check it is in the database try:  <Test Script Below>

If the script doesn't work when adapting it to YOUR database, see:
http://www.activeserverpages.com/learn/dbtroubleshoot.asp to determine what the trouble is.

The script is:

   <TITLE>dbnewrecSQL.asp</TITLE>
   <body bgcolor="#FFFFFF">
   <HTML>
   <%
   'on error resume next
   auname=request.querystring("name")
   auyear=request.querystring("year")
   auID=request.querystring("ID")
   If  auid<9000 then
10      auid=auid+9000
11   end if
12   Set Conn = Server.CreateObject("ADODB.Connection")
13   conn.open "DSN=Student;uid=student;pwd=magic"
14   SQLStmt = "INSERT INTO authors (AU_ID,author,year_born) "
15   SQLStmt = SQLStmt & "VALUES (" & auid
16   SQLStmt = SQLStmt & ",'" & auname & "'"
17   SQLStmt = SQLStmt & "," & int(auyear) & ")"
18   Set RS = Conn.Execute(SQLStmt)
19   set rs=nothing
20   If  err.number>0 then
21         response.write "VBScript Errors Occured:" & "<P>"
22         response.write "Error Number=" & err.number & "<P>"
23         response.write "Error Descr.=" & err.description & "<P>"
24         response.write "Help Context=" & err.helpcontext & "<P>"
25         response.write "Help Path=" & err.helppath & "<P>"
26         response.write "Native Error=" & err.nativeerror & "<P>"
27         response.write "Source=" & err.source & "<P>"
28         response.write "SQLState=" & err.sqlstate & "<P>"
29   else
30         response.write "No VBScript Errors Occured" & "<P>"
31   end if
32   IF  conn.errors.count> 0 then
33      response.write "Database Errors Occured" & "<br>"
34      response.write "<b>" & SQLstmt & "</b><P>"
35      for counter= 0 to conn.errors.count
36         response.write "Error #" & conn.errors(counter).number & "<P>"
37         response.write "Error desc. -> " & conn.errors(counter).description & "<P>"
38      next
39   else
40         response.write "No Database Errors Occured!" & "<P>"
41   end if
42   Conn.Close
43   set conn=nothing
44   %>

45   </BODY>
46   </HTML>


ASP Quick Lessons written by Charles M. Carroll
http://www.learnasp.com/learn/dbnewADO.asp Page 98


Databases Add Record ADO ASP Quick Lessons

Add New Record with ADO

This page demonstrates the capabilities how to add a record to a database using ADO instead of SQL. The script is:

   <html><head>
   <title>dbnewrec.asp</title>&
   <body bgcolor="#FFFFFF">
   <% ' My ASP program that allows you to append a record %>
   <form name="myauthor" action="dbnewADOrespond.asp" method="GET">
   <p>Author ID: <input type="TEXT" name="id"></p>
   <p> Author Name: <input type="TEXT" name="name"></p>
   <p> Year Born: <input type="TEXT" name="year"></p>
   <p> <input type="SUBMIT"> </p>
10   </form></body></html>

The form responder looks like this:

   <TITLE>dbnewADO.asp</TITLE>
   <body bgcolor="#FFFFFF">
   <HTML>
   <!--#INCLUDE VIRTUAL="/ADOVBS.INC" -->
   <!--#INCLUDE VIRTUAL="/learn/test/lib_errors.asp" -->
   <%
   on  error resume next
   auname=request.querystring("name")
   auyear=request.querystring("year")
10   auID=request.querystring("ID")
11   If  auid<9000 then
12      auid=auid+9000
13   end if
14   conn="DSN=Student;uid=student;pwd=magic"
15   Set RS = Server.CreateObject("ADODB.Recordset")
16   RS.Open "authors",Conn,adopenstatic,adlockoptimistic
17   RS.AddNew
18   'RS("AU_ID")=auid
19   RS("Author") = auname
20   RS("Year_Born")= int(auyear)
21   RS.Update
22   Call ErrorVBscriptReport("Adding Record")
23   Call ErrorADOReport("Adding Record",RS.activeconnection)
24   RS.Close
25   set rs=nothing
26   %>

27   </BODY>
28   </HTML>
29   
30   
31   
32   

Here is the include file that displays appropriate errors:

   <%
   SUB ErrorVBScriptReport(parm_msg)
      If err.number=0 then
         exit sub
      end if
      pad="&nbsp;&nbsp;&nbsp;&nbsp;"
      response.write "<b>VBScript Errors Occured!<br>"
      response.write parm_msg & "</b><br>"
      response.write pad & "Error Number= #<b>" & err.number & "</b><br>"
10      response.write pad & "Error Desc.= <b>" & err.description & "</b><br>"
11      response.write pad & "Help Context= <b>" & err.HelpContext & "</b><br>"
12      response.write pad & "Help File Path=<b>" & err.helpfile & "</b><br>"
13      response.write pad & "Error Source= <b>" & err.source & "</b><br><hr>"
14   END SUB
15   
16   SUB ErrorADOReport(parm_msg,parm_conn)
17      HowManyErrs=parm_conn.errors.count
18      IF HowManyErrs=0 then
19         exit sub
20      END IF
21      pad="&nbsp;&nbsp;&nbsp;&nbsp;"
22      response.write "<b>ADO Reports these Database Error(s) executing:<br>"
23             response.write SQLstmt & "</b><br>"
24      for counter= 0 to HowManyErrs-1
25         errornum=parm_conn.errors(counter).number
26         errordesc=parm_conn.errors(counter).description
27         response.write pad & "Error#=<b>" & errornum & "</b><br>"
28         response.write pad & "Error description=<b>"
29         response.write errordesc & "</b><p>"
30      next
31   END SUB
32   %>


ASP Quick Lessons written by Charles M. Carroll
http://www.learnasp.com/learn/dbtablelists.asp Page 99


Listing Tables within DBs from ASP Quick Lessons

Listing Tables within Databases by Charles Carroll DRAFT

SQL Server allows you to list tables like this:

   <HEAD><TITLE>sqlservertablelist.asp</TITLE></HEAD>
   <HTML><body bgcolor="#FFFFFF">
   <%
   whichDSN="DSN=student;uid=student;pwd=magic"
   
   call query2table("select name,type from sysobjects where type='U'", whichDSN)
   %>

   <!--#include virtual="/learn/test/lib_dbtable.asp"-->
   </BODY></HTML>

Access allows you to list tables like this (assuming you allow system objects to be visible within the database on the Access side):

   <HEAD><TITLE>accesstablelist.asp</TITLE></HEAD>
   <HTML><body bgcolor="#FFFFFF">
   <%
   whichDSN="DRIVER={Microsoft Access Driver (*.mdb)}; "
   whichDSN=whichDSN & "DBQ=" & server.mappath("/learn/test/biblio.mdb")
   call query2table("select * from MsysObjects WHERE type = 1",whichDSN)
   %>

   <!--#include virtual="/learn/test/lib_dbtable.asp"-->
   </BODY></HTML>

The Include file looks like this:

   <%
   sub query2table(inputquery, inputDSN)
      dim conntemp, rstemp
      set conntemp=server.createobject("adodb.connection")
      conntemp.open inputDSN
      set rstemp=conntemp.execute(inputquery)
      howmanyfields=rstemp.fields.count -1%>

      <table border=1><tr>
      <% 'Put Headings On The Table of Field Names
10      for i=0 to howmanyfields %>

11                <td><b><%=rstemp(i).name%></B></TD>
12      <% next %>
13      </tr>
14      <% ' Now lets grab all the records
15      do while not rstemp.eof %>

16         <tr>
17         <% for i = 0 to howmanyfields
18            thisvalue=rstemp(i)
19            If isnull(thisvalue) then
20               thisvalue="&nbsp;"
21            end if%>

22                <td valign=top><%=thisvalue%></td>
23         <% next %>
24         </tr>
25         <%rstemp.movenext
26      loop%>

27      </table>
28      <%
29      rstemp.close
30      set rstemp=nothing
31      conntemp.close
32      set conntemp=nothing
33   end sub%>


ASP Quick Lessons written by Charles M. Carroll
http://www.learnasp.com/learn/dbschemas.asp Page 100


ADO schemas from ASP Quick Lessons

ADO Schemas to list tables & fields

You can examine a Schema for the table names and column names and column detail information.

   <html><head>
   <TITLE>dbschemas.asp</TITLE>
   </head>
   <body bgcolor="#FFFFFF">
   <!--#INCLUDE VIRTUAL="/ADOVBS.INC" -->
   <!--#INCLUDE VIRTUAL="/learn/test/lib_fieldtypes.asp" -->
   <%
   myDSN="DSN=Student;uid=student;pwd=magic"
   
10   set conntemp=server.createobject("adodb.connection")
11   conntemp.open myDSN
12   
13   Set rsSchema = conntemp.OpenSchema(adSchemaColumns)
14   thistable=""
15   pad="&nbsp;&nbsp;&nbsp;"
16   DO  UNTIL rsSchema.EOF
17      prevtable=thistable
18      thistable=rsSchema("Table_Name")
19      thiscolumn=rsSchema("COLUMN_NAME")
20      IF thistable<>prevtable THEN
21         response.write "Table=<b>" & thistable & "</b><br>"
22         response.write "TABLE_CATALOG=<b>" & rsSchema("TABLE_CATALOG") & "</b><br>"
23         response.write "TABLE_SCHEMA=<b>" & rsSchema("TABLE_SCHEMA") & "</b><p>"
24      END IF
25      response.write "<br>" & pad & "Field=<b>" & thiscolumn & "</b><br>"
26      response.write pad & "Type=<b>" & fieldtypename(rsSchema("DATA_TYPE")) & "</b><br>"
27   
28   
29      DIM colschema(27)
30      colschema(0)="TABLE_CATALOG"
31      colschema(1)="TABLE_SCHEMA"
32      colschema(2)="TABLE_NAME"
33      colschema(3)="COLUMN_NAME"
34      colschema(4)="COLUMN_GUID"
35      colschema(5)="COLUMN_PROP_ID"
36      colschema(6)="ORDINAL_POSITION"
37      colschema(7)="COLUMN_HASDEFAULT"
38      colschema(8)="COLUMN_DEFAULT"
39      colschema(9)="COLUMN_FLAGS"
40      colschema(10)="IS_NULLABLE"
41      colschema(11)="DATA_TYPE"
42      colschema(12)="TYPE_GUID"
43      colschema(13)="CHARACTER_MAXIMUM_LENGTH"
44      colschema(14)="CHARACTER_OCTET_LENGTH"
45      colschema(15)="NUMERIC_PRECISION"
46      colschema(16)="NUMERIC_SCALE"
47      colschema(17)="DATETIME_PRECISION"
48      colschema(18)="CHARACTER_SET_CATALOG"
49      colschema(19)="CHARACTER_SET_SCHEMA"
50      colschema(20)="CHARACTER_SET_NAME"
51      colschema(21)="COLLATION_CATALOG"
52      colschema(22)="COLLATION_SCHEMA"
53      colschema(23)="COLLATION_NAME"
54      colschema(24)="DOMAIN_NAME"
55      colschema(25)="DOMAIN_CATALOG"
56      colschema(26)="DOMAIN_SCHEMA"
57      colschema(27)="DESCRIPTION"
58   
59      ON ERROR RESUME NEXT
60      FOR counter=4 to 27
61         thisColInfoType=colschema(counter)
62         thisColInfo=rsSchema(thisColInfoType)
63         If err.number<>0 then
64            thiscolinfo="-error-"
65            err.clear
66         END IF
67         IF thisColInfo<>"" THEN
68            response.write pad & pad & pad & thiscolinfotype
69            response.write "=<b>" & thiscolinfo & "</b><br>"
70         END IF
71      NEXT
72      response.flush
73      rsSchema.MoveNext
74   LOOP
75   
76   rsSchema.Close
77   set rsSchema=nothing
78   
79   conntemp.close
80   set conntemp=nothing
81   %>

82   </body></html>

Here is the contents of lib_fieldtypes.asp which is included to make this example work:

   <%
   FUNCTION fieldtypename(parm1)
      SELECT CASE Parm1
      CASE 0
         fieldtypename="adEmpty"
      CASE 16
         fieldtypename="adTinyInt"
      CASE 2
         fieldtypename="adSmallInt"
10      CASE 3
11         fieldtypename="adInteger"
12      CASE 20
13         fieldtypename="adBigInt"
14      CASE 17
15         fieldtypename="adUnsignedTinyInt"
16      CASE 18
17         fieldtypename="adUnsignedSmallInt"
18      CASE 19
19         fieldtypename="adUnsignedInt"
20      CASE 21
21         fieldtypename="adUnsignedBigInt"
22      CASE 4
23         fieldtypename="adSingle"
24      CASE 5
25         fieldtypename="adDouble"
26      CASE 6
27         fieldtypename="adCurrency"
28      CASE 14
29         fieldtypename="adDecimal"
30      CASE 131
31         fieldtypename="adNumeric"
32      CASE 11
33         fieldtypename="adBoolean"
34      CASE 10
35         fieldtypename="adError"
36      CASE 132
37         fieldtypename="adUserDefined"
38      CASE 12
39         fieldtypename="adVariant"
40      CASE 9
41         fieldtypename="adIDispatch"
42      CASE 13
43         fieldtypename="adIUnknown"
44      CASE 72
45         fieldtypename="adGUID"
46      CASE 7
47         fieldtypename="adDate"
48      CASE 133
49         fieldtypename="adDBDate"
50      CASE 134
51         fieldtypename="adDBTime"
52      CASE 135
53         fieldtypename="adDBTimeStamp"
54      CASE 8
55         fieldtypename="adBSTR"
56      CASE 129
57         fieldtypename="adChar"
58      CASE 200
59         fieldtypename="adVarChar"
60      CASE 201
61         fieldtypename="adLongVarChar"
62      CASE 130
63         fieldtypename="adWChar"
64      CASE 202
65         fieldtypename="adVarWChar"
66      CASE 203
67         fieldtypename="adLongVarWChar"
68      CASE 128
69         fieldtypename="adBinary"
70      CASE 204
71         fieldtypename="adVarBinary"
72      CASE 205
73         fieldtypename="adLongVarBinary"
74      CASE ELSE
75         fieldtypename="Undefined by ADO"
76      END SELECT
77   END FUNCTION
78   %>


ASP Quick Lessons written by Charles M. Carroll
http://www.learnasp.com/learn/dbschemasall.asp Page 101


ADO schemas from ASP Quick Lessons

ADO Schemas/listing tables and fields

You can examine a Schema for the table names and column names and column detail information.

   <html><head>
   <TITLE>dbschemasall.asp</TITLE>
   </head>
   <body bgcolor="#FFFFFF">
   <!--#INCLUDE VIRTUAL="/ADOVBS.INC" -->
   <!--#INCLUDE VIRTUAL="/learn/test/lib_schemas.asp" -->
   <%
      myDSN="DSN=Student;uid=student;pwd=magic"
   
10      DIM colschema(30)
11      colschema(0)=adSchemaProviderSpecific
12      colschema(1)=adSchemaAsserts
13      colschema(2)=adSchemaCatalogs
14      colschema(3)=adSchemaCharacterSets
15      colschema(4)=adSchemaCollations
16      colschema(5)=adSchemaColumns
17      colschema(6)=adSchemaCheckConstraints
18      colschema(7)=adSchemaConstraintColumnUsage
19      colschema(8)=adSchemaConstraintTableUsage
20      colschema(9)=adSchemaKeyColumnUsage
21      colschema(10)=adSchemaReferentialContraints
22      colschema(11)=adSchemaTableConstraints
23      colschema(12)=adSchemaColumnsDomainUsage
24      colschema(13)= adSchemaIndexes
25      colschema(14)=adSchemaColumnPrivileges
26      colschema(15)=adSchemaTablePrivileges
27      colschema(16)=adSchemaUsagePrivileges
28      colschema(17)=adSchemaProcedures
29      colschema(18)=adSchemaSchemata
30      colschema(19)=adSchemaSQLLanguages
31      colschema(20)=adSchemaStatistics
32      colschema(21)=adSchemaTables
33      colschema(22)=adSchemaTranslations
34      colschema(23)=adSchemaProviderTypes
35      colschema(24)=adSchemaViews
36      colschema(25)=adSchemaViewColumnUsage
37      colschema(26)=adSchemaViewTableUsage
38      colschema(27)=adSchemaProcedureParameters
39      colschema(28)=adSchemaForeignKeys
40      colschema(29)=adSchemaPrimaryKeys
41      colschema(30)=adSchemaProcedureColumns
42   
43      FOR counter=1 to 30
44         thisSchema=colSchema(counter)
45         Call Schema2Table(myDSN,thisSchema)
46         response.write "<p>"
47      NEXT
48   %>

49   </body></html>

The include file lib_schemas.asp looks like this:

   <%
   FUNCTION schemaName(parm1)
      SELECT CASE parm1
      CASE adSchemaProviderSpecific
         schemaname="adSchemaProviderSpecific"
      CASE adSchemaAsserts
         schemaName="adSchemaAsserts"      
      CASE adSchemaCatalogs
         schemaName="adSchemaCatalogs"
10      CASE adSchemaCharacterSets
11         schemaName="adSchemaCharacterSets"
12      CASE adSchemaCollations
13         schemaName="adSchemaCollations"
14      CASE adSchemaColumns
15         schemaName="adSchemaColumns"
16      CASE adSchemaCheckConstraints
17         schemaName="adSchemaCheckConstraints"
18      CASE adSchemaConstraintColumnUsage
19         schemaName="adSchemaConstraintColumnUsage"
20      CASE adSchemaConstraintTableUsage
21         schemaName="adSchemaConstraintTableUsage"
22      CASE adSchemaKeyColumnUsage
23         schemaName="adSchemaKeyColumnUsage"
24      CASE adSchemaReferentialContraints
25         schemaName="adSchemaReferentialContraints"
26      CASE adSchemaTableConstraints
27         schemaName="adSchemaTableConstraints"
28      CASE adSchemaColumnsDomainUsage
29         schemaName="adSchemaColumnsDomainUsage"
30      CASE adSchemaIndexes
31         schemaName="adSchemaIndexes"
32      CASE adSchemaColumnPrivileges
33         schemaName="adSchemaColumnPrivileges"
34      CASE adSchemaTablePrivileges
35         schemaName="adSchemaTablePrivileges"
36      CASE adSchemaUsagePrivileges
37         schemaName="adSchemaUsagePrivileges"
38      CASE adSchemaProcedures
39         schemaName="adSchemaProcedures"
40      CASE adSchemaSchemata
41         schemaName="adSchemaSchemata"
42      CASE adSchemaSQLLanguages
43         schemaName="adSchemaSQLLanguages"
44      CASE adSchemaStatistics
45         schemaName="adSchemaStatistics"
46      CASE adSchemaTables
47         schemaName="adSchemaTables"
48      CASE adSchemaTranslations
49         schemaName="adSchemaTranslations"
50      CASE adSchemaProviderTypes
51         schemaName="adSchemaProviderTypes"
52      CASE adSchemaViews
53         schemaName="adSchemaViews"
54      CASE adSchemaViewColumnUsage
55         schemaName="adSchemaViewColumnUsage"
56      CASE adSchemaViewTableUsage
57         schemaName="adSchemaViewTableUsage"
58      CASE adSchemaProcedureParameters
59         schemaName="adSchemaProcedureParameters"
60      CASE adSchemaForeignKeys
61         schemaName="adSchemaForeignKeys"
62      CASE adSchemaPrimaryKeys
63         schemaName="adSchemaPrimaryKeys"
64      CASE adSchemaProcedureColumns
65         schemaName="adSchemaProcedureColumns"
66      CASE ELSE
67         schemaName="-unknown-"
68      END SELECT
69   END FUNCTION
70   
71   SUB Schema2Table(parmDSN, parmSchemaName)
72         set conntemp=server.createobject("adodb.connection")
73         conntemp.open parmDSN
74   
75         on error resume next
76         set rsSchema=conntemp.OpenSchema(parmSchemaName)
77   
78         IF err.number=3251 THEN
79            response.flush
80            response.write "<b>" & SchemaName(parmSchemaName)
81            response.write "</b><br> is not supported<br>"
82            err.clear
83         ELSE
84            Call Schema2Table(thisSchema)
85            response.write "<P><b>" & schemaName(parmSchemaName) & "</b><br>"
86            response.write "<table border=1><tr>"
87            'Put Headings On The Table of Field Names
88            for each whatever in rsSchema.fields
89             response.write "<td><b>" & whatever.name & "</b></td>"
90            next
91            response.write "</tr>"
92            DO UNTIL rsSchema.eof
93               response.write "<tr>"
94                     for each whatever in rsSchema.fields
95                      thisfield=whatever.value
96                      if isnull(thisfield) then
97                     thisfield="&nbsp;"
98                  end if
99                  if trim(thisfield)="" then
100                     thisfield="&nbsp;"
101                  end if
102                      response.write "<td valign=top>" & thisfield & "</td>"
103                   next
104               response.write "</tr>"
105               rsSchema.MoveNext
106            LOOP
107            response.write "</table><br>"
108            response.flush
109         END IF
110      
111      rsSchema.Close
112      set rsSchema=nothing
113   
114      conntemp.close
115      set conntemp=nothing
116   END SUB
117   %>


ASP Quick Lessons written by Charles M. Carroll
http://www.learnasp.com/learn/db1parm.asp Page 102


Databases Table Display 1 Parm from User

Displaying A Table/User Supplied Query Input

This page demonstrates the capabilities how to display a table from a SQL statement using one input variable from a user. The script to display a specified record in the table is:

   <TITLE>db1parm.asp</TITLE>
   <body bgcolor="#FFFFFF">
   <%
   ' My ASP program that talks to a database
   set conntemp=server.createobject("adodb.connection")
   conntemp.open "DSN=Student;uid=student;pwd=magic"
   p1=request.querystring("ID")
   temp="select * from authors where AU_ID=" & p1
   set rstemp=conntemp.execute(temp)
10   howmanyfields=rstemp.fields.count -1
11   %>

12   <table border=1>
13   <tr>
14   <% 'Put Headings On The Table of Field Names
15   for i=0 to howmanyfields %>

16          <td><b><%=rstemp(i).name %></B></TD>
17   <% next %>
18   </tr>
19   <% ' Now lets grab all the records
20   do  while not rstemp.eof %>

21   <tr>
22   <% for i = 0 to howmanyfields%>
23          <td valign=top><% = rstemp(i) %></td>
24   <% next %>
25   </tr>
26   <% rstemp.movenext
27   loop
28   rstemp.close
29   set rstemp=nothing
30   conntemp.close
31   set conntemp=nothing%>

32   </table>
33   </body>
34   </html>


ASP Quick Lessons written by Charles M. Carroll
http://www.learnasp.com/learn/dbupdate.asp Page 103


Update 1 Record ASP Quick Lessons

Database -- Update Record

This page demonstrates the capabilities to update an existing record in a database with a SQL statement.

The script is:
   <TITLE>dbupdate.asp</TITLE>
   <body bgcolor="#FFFFFF">
   <HTML>
   <%
   on  error resume next
   auname=request.querystring("name")
   auyear=request.querystring("year")
   auID=request.querystring("ID")
   Set Conn = Server.CreateObject("ADODB.Connection")
10   conn.open "DSN=Student;uid=student;pwd=magic"
11   SQLstmt = "UPDATE authors "
12   SQLStmt = SQLstmt & "SET Author='" & auname & "',"
13   SQLstmt = SQLstmt & "year_born=" & auyear
14   SQLStmt = SQLStmt & " WHERE AU_ID=" & auid
15   Set RS = Conn.Execute(SQLStmt)
16   If  err.number>0 then
17         response.write "VBScript Errors Occured:" & "<P>"
18         response.write "Error Number=" & err.number & "<P>"
19         response.write "Error Descr.=" & err.description & "<P>"
20         response.write "Help Context=" & err.helpcontext & "<P>"
21         response.write "Help Path=" & err.helppath & "<P>"
22         response.write "Native Error=" & err.nativeerror & "<P>"
23         response.write "Source=" & err.source & "<P>"
24         response.write "SQLState=" & err.sqlstate & "<P>"
25   else
26         response.write "No problems occured!" & "<P>"
27   end if
28   IF  conn.errors.count> 0 then
29         response.write "Database Errors Occured" & "<P>"
30   for counter= 0 to conn.errors.count
31         response.write "Error #" & conn.errors(counter).number & "<P>"
32         response.write "Error desc. -> " & conn.errors(counter).description & "<P>"
33   next
34   else
35         response.write SQLstmt
36         response.write "Everything Went Fine. Author is updated now!" & "<P>"
37   end if
38   set rstemp=nothing
39   Conn.Close
40   set conntemp=nothing
41   %>

42   </BODY>
43   </HTML>


ASP Quick Lessons written by Charles M. Carroll
http://www.learnasp.com/learn/dbtroubles.asp Page 104


Databases Trouble Resources from ASP Quick Lessons

Databases  Troubleshooting Resources

When your database code does not work, we actually manage a listserv you can write to send in your code and have your colleagues from around the world on the listserv help you fix it. People having trouble with ASP code communicating with a specific database should try their questions on one of these lists:

ALL Oracle Lists
ALL RDS (Remote Data Services) Lists
ALL SQL Server Lists
[aspngdata] ASP+/ADO+, Templates, Lists, Repeaters
[aspsqlhowto] SQL: Joins, complex queries, shaping
[aspAccess] MS-Access
[aspAcc2SQL] MS-Access to SQLserver migration
[aspAcc2SQL] Tough ASP + MS-Access Questions only
[aspBtrieve] Btrieve and ASP
[aspCOMTICICS] COMTI and CICS w/ASP
[aspDB2as400] DB2 and/or AS400
[aspDbase] Dbase
[aspFileMaker] FileMaker & ASP
[aspFox] Fox/Visual FoxPro
[aspGenericdb] FREE code to display/edit data
[aspInformix] Informix
[aspMSDE] Asp with free MSDE Engine
[aspmySQL] MySQL and ASP
[aspParadox] Paradox
[aspreports] Reports/Printing (Crystal, PDF, etc.)
[aspSAP] SAP + ASP can mix
[aspSybase] Sybase


ASP Quick Lessons written by Charles M. Carroll
http://www.learnasp.com/learn/dbtroubles2.asp Page 105


Databases Trouble Resources from ASP Quick Lessons

Databases  Troubleshooting Resources Part 2

The web is replete with many database resources that we think people should read up on.

Error Catcher Server=216.87.1.71
Code=
Number=-2146828275
Source=
Category=Microsoft VBScript runtime
Filename=/learn/dbtroubles2.asp
Line#=18
Column#=-1
Description=Type mismatch: 'listlinks'
ASP description=


ASP Quick Lessons written by Charles M. Carroll
http://www.learnasp.com/learn/SQL.asp Page 106


Section Contents

SQL Basics, Searching Databases
        SQL Troubles (SQLtroubles.asp) - Page 107
        SQL: Example Tables (SQLexamples.asp) - Page 108
        SQL: Where Clause Basics (SQLwhere.asp) - Page 109
        SQL: Where Clause Examples (SQLwhere2.asp) - Page 110
        SQL: Search Forms #1 (SQLwhereform1.asp) - Page 111
        SQL: Search Forms #2 (SQLwhereform2.asp) - Page 112
        SQL: Search Forms #3 (SQLwhereform3.asp) - Page 113
        SQL: Search AND/OR Operators (SQLandor.asp) - Page 114
        SQL: Search AND/OR Examples (SQLandor2.asp) - Page 115
        SQL: COUNT, GROUPBY (SQLcount.asp) - Page 116
        SQL: SUM, MIN, AVE, MAX (SQLaggregate.asp) - Page 117
        SQL Joins by Aaron Alexander (dbjoin.asp) - Page 118


ASP Quick Lessons written by Charles M. Carroll
http://www.learnasp.com/learn/SQLtroubles.asp Page 107


Databases Trouble Resources from ASP Quick Lessons

SQL Troubleshooting Resources

We also run a listserve for helping you setup complex SQL queries (Joins, multiple ands/ors, etc.)
Unlike the list above, it is not a general database troubleshooting list, instead only complex SQL questions are allowed.

Undergoing renovation - SUB ListServSignup

General Database questions (i.e. code that is broken, non SQL database issues) needs to be sent to our database listserv, see:
/learn/dbtroubles.asp


ASP Quick Lessons written by Charles M. Carroll
http://www.learnasp.com/learn/SQLexamples.asp Page 108


SQLexamples from ASP Quick Lessons

Search Database #2 (SQL Where clause examples)

For our next examples, knowing the structures of the tables will be helpful.

The authors database has a structure like this:

Au_ID Author Year_Born

The titles database has a structure like this:

Title Year_Published ISBN PubID Description Notes Subject Comments

The Title_Author table looks like this:

ISBN Au_ID

The publisher' database has a structure like this:

PubID Name Company_Name Address City State Zip Telephone Fax Comments


ASP Quick Lessons written by Charles M. Carroll
http://www.learnasp.com/learn/SQLwhere.asp Page 109


SQLWhere from ASP Quick Lessons

Search Database #1 (SQL Where clauses)

There are several ways to search the data using pure SQL once we review the simple rules of how a WHERE clause works.

These basic WHERE clause guidelines above are the fundamental building block of searches.

It is also helpful to utilize the equality operators, i.e.

<> not equal
> greater than
< less than
>= greater than OR equal
<= less than or equal


ASP Quick Lessons written by Charles M. Carroll
http://www.learnasp.com/learn/SQLwhere2.asp Page 110


SQLwhere2 from ASP Quick Lessons

SQL Where Examples by Charles Carroll

Here are some where statements and their results.

   <HEAD><TITLE>SQLwhere1.asp</TITLE></HEAD>
   <HTML><body bgcolor="#FFFFFF">
   <%
   call query2table("select * from publisher where name like 'A%%'")
   %>

   <!--#include virtual="/learn/test/subdbtable.inc"-->
   </BODY></HTML>
   
   

   <HEAD><TITLE>SQLwhere2.asp</TITLE></HEAD>
   <HTML><body bgcolor="#FFFFFF">
   <%
   call query2table("select * from titles where Year_Published >= 1994")
   %>

   <!--#include virtual="/learn/test/subdbtable.inc"-->
   </BODY></HTML>

   <HEAD><TITLE>SQLwhere3.asp</TITLE></HEAD>
   <HTML><body bgcolor="#FFFFFF">
   <%
   call query2table("select * from publishers where fax like '212%%'")
   %>

   <!--#include virtual="/learn/test/subdbtable.inc"-->
   </BODY></HTML>

   <HEAD><TITLE>sqlwhere4.asp</TITLE></HEAD>
   <HTML><body bgcolor="#FFFFFF">
   <%
   call query2table("select * from publishers where state<> 'NY'")
   %>

   <!--#include virtual="/learn/test/subdbtable.inc"-->
   </BODY></HTML>

The Include file looks like this:

   <%
   sub query2table(inputquery)
      set conntemp=server.createobject("adodb.connection")
      conntemp.open "DSN=Student;uid=student;pwd=magic"
      set rstemp=conntemp.execute(inputquery)
      howmanyfields=rstemp.fields.count -1%>

      <table border=1><tr>
      <% 'Put Headings On The Table of Field Names
      for i=0 to howmanyfields %>

10                <td><b><%=rstemp(i).name%></B></TD>
11      <% next %>
12      </tr>
13      <% ' Now lets grab all the records
14      do while not rstemp.eof %>

15         <tr>
16         <% for i = 0 to howmanyfields
17            thisvalue=rstemp(i)
18            If isnull(thisvalue) then
19               thisvalue="&nbsp;"
20            end if%>

21                <td valign=top><%=thisvalue%></td>
22         <% next %>
23         </tr>
24         <%rstemp.movenext
25      loop%>

26      </table>
27      <%
28      rstemp.close
29      set rstemp=nothing
30      conntemp.close
31      set conntemp=nothing
32   end sub%>


ASP Quick Lessons written by Charles M. Carroll
http://www.learnasp.com/learn/SQLwhereform1.asp Page 111


SQLWhere2 from ASP Quick Lessons

Search Database (SQL Where Form examples)

In the previous page we introduced the WHERE clause, but now we will see several examples of the WHERE clause in typical forms. This example allows users to choose a city:

The form that they can enter a city in:

   <HEAD><TITLE>sqlwhereform1.asp</TITLE></HEAD>
   <HTML><body bgcolor="#FFFFFF">
   <Form action = "sqlwhereForm1respond.asp" method=GET>
   Choose A State:<p>
   State: <Input NAME="st" MaxLength="2" size="3"><P>
   <Input type="submit" value="Get Data">&nbsp;<Input type="reset" value="Clear State"></form>
   </BODY></HTML>

The responder that deals with that form:

   <HEAD><TITLE>sqlwhereform1respond.asp</TITLE></HEAD>
   <HTML><body bgcolor="#FFFFFF">
   <%
   myDSN="DSN=student;uid=student;pwd=magic"
   
   mystate=request.querystring("st")
   SQLtemp="select * from publishers where state='"
   SQLtemp=SQLtemp & mystate & "'"
   
10   call query2table(SQLtemp,myDSN)
11   %>

12   <!--#include virtual="/learn/test/lib_dbtable.asp"-->
13   </BODY></HTML>

The library file lib_dbtable.asp looks like this:

   <%
   sub query2table(inputquery, inputDSN)
      dim conntemp, rstemp
      set conntemp=server.createobject("adodb.connection")
      conntemp.open inputDSN
      set rstemp=conntemp.execute(inputquery)
      howmanyfields=rstemp.fields.count -1%>

      <table border=1><tr>
      <% 'Put Headings On The Table of Field Names
10      for i=0 to howmanyfields %>

11                <td><b><%=rstemp(i).name%></B></TD>
12      <% next %>
13      </tr>
14      <% ' Now lets grab all the records
15      do while not rstemp.eof %>

16         <tr>
17         <% for i = 0 to howmanyfields
18            thisvalue=rstemp(i)
19            If isnull(thisvalue) then
20               thisvalue="&nbsp;"
21            end if%>

22                <td valign=top><%=thisvalue%></td>
23         <% next %>
24         </tr>
25         <%rstemp.movenext
26      loop%>

27      </table>
28      <%
29      rstemp.close
30      set rstemp=nothing
31      conntemp.close
32      set conntemp=nothing
33   end sub%>


ASP Quick Lessons written by Charles M. Carroll
http://www.learnasp.com/learn/SQLwhereform2.asp Page 112


SQLWhere2 from ASP Quick Lessons

Search Database (SQL Where Form examples)

We will now present a form that allows people to choose a city but also supports inexact searches using LIKE are supported:

   <HEAD><TITLE>SQLwhereform2.asp</TITLE></HEAD>
   <HTML><body bgcolor="#FFFFFF">
   <Form action = "SQLwhereForm2respond.asp" method=GET>
   Choose A City:<p>
   City: <Input NAME="cy" MaxLength="20" size="23"><P>
   <input TYPE="checkbox" NAME="ExactSearch" CHECKED>Exact Search<P>
   *  note if Exact Search is -> NOT CHECKED <-<br>You can use % as a wildcard<p>
   <Input type="submit" value="Get Data">&nbsp;<Input type="reset" value="Clear City"></form>
   </BODY></HTML>

   <HTML><HEAD>
   <TITLE>sqlwhereform2respond.asp</TITLE>&
   <body bgcolor="#FFFFFF">
   <%
   myDSN="DSN=student;uid=student;pwd=magic"
   mycity=request.querystring("cy")
   myexactsearch=request.querystring("exactsearch")
   SQLtemp="select * from publishers where city"
   If  myexactsearch="on" then
10      SQLtemp=SQLtemp & " ='"
11   Else
12      SQLtemp=SQLtemp & " LIKE '"
13   End If
14   SQLtemp=SQLtemp & mycity & "'"
15   'response.write SQLtemp
16   call query2table(SQLtemp,myDSN)
17   %>

18   <!--#include virtual="/learn/test/lib_dbtable.asp"-->
19   </BODY></HTML>

The file lib_dbtable.asp looks like this:

   <%
   sub query2table(inputquery, inputDSN)
      dim conntemp, rstemp
      set conntemp=server.createobject("adodb.connection")
      conntemp.open inputDSN
      set rstemp=conntemp.execute(inputquery)
      howmanyfields=rstemp.fields.count -1%>

      <table border=1><tr>
      <% 'Put Headings On The Table of Field Names
10      for i=0 to howmanyfields %>

11                <td><b><%=rstemp(i).name%></B></TD>
12      <% next %>
13      </tr>
14      <% ' Now lets grab all the records
15      do while not rstemp.eof %>

16         <tr>
17         <% for i = 0 to howmanyfields
18            thisvalue=rstemp(i)
19            If isnull(thisvalue) then
20               thisvalue="&nbsp;"
21            end if%>

22                <td valign=top><%=thisvalue%></td>
23         <% next %>
24         </tr>
25         <%rstemp.movenext
26      loop%>

27      </table>
28      <%
29      rstemp.close
30      set rstemp=nothing
31      conntemp.close
32      set conntemp=nothing
33   end sub%>


ASP Quick Lessons written by Charles M. Carroll
http://www.learnasp.com/learn/SQLwhereform3.asp Page 113


SQLWhere3 from ASP Quick Lessons

Search Database (SQL Where Form #3)

Ideally, the perfect "pick a city" example would show people a list of items so they can't choose wrong:

   <HEAD><TITLE>SQLwhereform3.asp</TITLE></HEAD>
   <HTML><body bgcolor="#FFFFFF">
   <Form action = "SQLwhereForm3respond.asp" method=GET>
   Choose A City:<p>
   City:
   <%
   call query2list("select distinct city from publishers", _
         "cy","DSN=student;uid=student;pwd=magic")
   %>

10   <P>
11   <Input type="submit" value="Get Data">&nbsp;<Input type="reset" value="Clear City"></form>
12   </BODY></HTML>
13   <!--#include virtual="/learn/test/lib_dblist.asp"-->

   <html><head><TITLE>sqlwhereform3respond.asp</TITLE></head>
   <body bgcolor="#FFFFFF">
   <%
   myDSN="DSN=student;uid=student;pwd=magic"
   mycity=request.querystring("cy")
   myexactsearch=request.querystring("exactsearch")
   SQLtemp="select * from publishers where city"
   If  myexactsearch="on" then
      SQLtemp=SQLtemp & " ='"
10   Else
11      SQLtemp=SQLtemp & " LIKE '"
12   End If
13   SQLtemp=SQLtemp & mycity & "'"
14   'response.write SQLtemp
15   call query2table(SQLtemp,myDSN)
16   %>

17   <!--#include virtual="/learn/test/lib_dbtable.asp"-->
18   </body></html>

The file lib_dbtable.asp looks like this:

   <%
   sub query2table(inputquery, inputDSN)
      dim conntemp, rstemp
      set conntemp=server.createobject("adodb.connection")
      conntemp.open inputDSN
      set rstemp=conntemp.execute(inputquery)
      howmanyfields=rstemp.fields.count -1%>

      <table border=1><tr>
      <% 'Put Headings On The Table of Field Names
10      for i=0 to howmanyfields %>

11                <td><b><%=rstemp(i).name%></B></TD>
12      <% next %>
13      </tr>
14      <% ' Now lets grab all the records
15      do while not rstemp.eof %>

16         <tr>
17         <% for i = 0 to howmanyfields
18            thisvalue=rstemp(i)
19            If isnull(thisvalue) then
20               thisvalue="&nbsp;"
21            end if%>

22                <td valign=top><%=thisvalue%></td>
23         <% next %>
24         </tr>
25         <%rstemp.movenext
26      loop%>

27      </table>
28      <%
29      rstemp.close
30      set rstemp=nothing
31      conntemp.close
32      set conntemp=nothing
33   end sub%>

The file lib_dblist.asp looks like this:

   <%sub query2list(myquery,myname,myDSN)
      dim conntemp, rstemp
      set conntemp=server.createobject("adodb.connection")
      conntemp.open myDSN
      set rstemp=conntemp.execute(myquery)
      %>

      <Select name="<%=myname%>">
      <%
      do while not rstemp.eof
10         thisfield=trim(RStemp(0))
11         if isnull(thisfield) or thisfield="" then
12            ' ignore
13         else
14            response.write "<option>" & thisfield & "</option>"
15         end if
16         rstemp.movenext
17      loop
18          %>

19      </select>
20      <%rstemp.close
21      set rstemp=nothing
22      conntemp.close
23      set conntemp=nothing
24   end sub%>


ASP Quick Lessons written by Charles M. Carroll
http://www.learnasp.com/learn/SQLandor.asp Page 114


SQLWhere from ASP Quick Lessons

SQL OR Search Example by Charles Carroll

AND and OR operators expand the power of the WHERE clause and provide a powerful tool to check multiple conditions. The Basic Guidelines are as follows:  

If your goal is that several if conditions must ALL BE TRUE to suceed, this is the Role of the AND within a WHERE clause, i.e.
"select * from publishers where state='MD' and city='Rockville'
"select * from authors where Year_Born>1960 and Year_Born<1970'

If several conditions can indivually be true this is the Role of an OR within a WHERE clause, i.e.
"select * from publishers where state='MD' OR state='NY'

   <HEAD><TITLE>SQLcities.asp</TITLE></HEAD>
   <HTML><body bgcolor="#FFFFFF">
   <Form action = "SQLcitiesrespond.asp" method="POST">
   Choose City (or Cities):<p>
   <%
   call query2listm("select distinct city from publishers", _
         "cy","DSN=student;uid=student;pwd=magic")
   %>

   <P>
10   <Input type="submit" value="Get Data">&nbsp;<Input type="reset" value="Clear City"></form>
11   </BODY></HTML>
12   <!--#include virtual="/learn/test/lib_dblistm.asp"-->
13   

The responder looks like this:

   <HEAD><TITLE>sqlcitiesrespond.asp</TITLE></HEAD>
   <HTML><body bgcolor="#FFFFFF">
   <%
   citycount=request.form("cy").count
   If  citycount=0 then%>

      <B>You never choose a city!</b><br>
      <a href="sqlcities.asp">Choose City</a>
   <%
      response.end
10   end if
11   firstcity=request.form("cy")(1)
12   SQLtemp="select * from publishers "
13   SQLtemp = SQLtemp & " where city='" & firstcity & "'"
14   for counter=2 to citycount
15      whichcity=request.form("cy")(counter)
16      SQLtemp = SQLtemp & " or city='" & whichcity & "' "
17   next
18   response.write SQLtemp
19   call query2table(SQLtemp,"DSN=student;uid=student;pwd=magic")
20   %>

21   <!--#include virtual="/learn/test/lib_dbtable.asp"-->
22   </BODY></HTML>

The file lib_dbtable.asp looks like this:

   <%
   sub query2table(inputquery, inputDSN)
      dim conntemp, rstemp
      set conntemp=server.createobject("adodb.connection")
      conntemp.open inputDSN
      set rstemp=conntemp.execute(inputquery)
      howmanyfields=rstemp.fields.count -1%>

      <table border=1><tr>
      <% 'Put Headings On The Table of Field Names
10      for i=0 to howmanyfields %>

11                <td><b><%=rstemp(i).name%></B></TD>
12      <% next %>
13      </tr>
14      <% ' Now lets grab all the records
15      do while not rstemp.eof %>

16         <tr>
17         <% for i = 0 to howmanyfields
18            thisvalue=rstemp(i)
19            If isnull(thisvalue) then
20               thisvalue="&nbsp;"
21            end if%>

22                <td valign=top><%=thisvalue%></td>
23         <% next %>
24         </tr>
25         <%rstemp.movenext
26      loop%>

27      </table>
28      <%
29      rstemp.close
30      set rstemp=nothing
31      conntemp.close
32      set conntemp=nothing
33   end sub%>

The file lib_dblistm.asp looks like this:

   <%
   SUB query2listm(myquery,myname,myDSN)
      dim conntemp, rstemp
      set conntemp=server.createobject("adodb.connection")
      conntemp.open myDSN
      set rstemp=conntemp.execute(myquery)
      %>

      <Select name="<%=myname%>" multiple>
      <%
10      do while not rstemp.eof
11         thisfield=trim(RStemp(0))
12         if isnull(thisfield) or thisfield="" then
13            ' ignore
14         else
15            response.write "<option>" & thisfield & "</option>"
16         end if
17         rstemp.movenext
18      loop
19          %>

20      </select>
21      <%rstemp.close
22      set rstemp=nothing
23      conntemp.close
24      set conntemp=nothing
25   END SUB
26   %>


ASP Quick Lessons written by Charles M. Carroll
http://www.learnasp.com/learn/SQLandor2.asp Page 115


SQLWhere from ASP Quick Lessons

SQL And/OR Examples by Charles Carroll

Here are some examples of the AND plus OR operators and INLIST in typical ASP scripts.

DRAFT -- NOT READY YET

COMING SOON!


ASP Quick Lessons written by Charles M. Carroll
http://www.learnasp.com/learn/SQLcount.asp Page 116


SQL Count from ASP Quick Lessons

SQL Count Syntax/Examples

SQL can count items. There are a few variations on the syntax and some simple rules to remember:

   <HEAD><TITLE>SQLcount1.asp</TITLE></HEAD>
   <HTML><body bgcolor="#FFFFFF">
   <%
   call query2table("select count(*) from publishers where state='NY'")
   %>

   <!--#include virtual="/learn/test/subdbtable.inc"-->
   </BODY></HTML>

   <HEAD><TITLE>SQLcount2.asp</TITLE></HEAD>
   <HTML><body bgcolor="#FFFFFF">
   <%
   call query2table("select count(city),city from publishers group by city")
   %>

   <!--#include virtual="/learn/test/subdbtable.inc"-->
   </BODY></HTML>

   <HEAD><TITLE>SQLcount3.asp</TITLE></HEAD>
   <HTML><body bgcolor="#FFFFFF">
   <%
   call query2table("select count(city) as howmany,city from publishers group by city")
   %>

   <!--#include virtual="/learn/test/subdbtable.inc"-->
   </BODY></HTML>

   <HEAD><TITLE>SQLcount4.asp</TITLE></HEAD>
   <HTML><body bgcolor="#FFFFFF">
   <%
   call query2table("select count(*),city,state from publishers group by city,state")
   %>

   <!--#include virtual="/learn/test/subdbtable.inc"-->
   </BODY></HTML>

The Include file looks like this:

   <%
   sub query2table(inputquery)
      set conntemp=server.createobject("adodb.connection")
      conntemp.open "DSN=Student;uid=student;pwd=magic"
      set rstemp=conntemp.execute(inputquery)
      howmanyfields=rstemp.fields.count -1%>

      <table border=1><tr>
      <% 'Put Headings On The Table of Field Names
      for i=0 to howmanyfields %>

10                <td><b><%=rstemp(i).name%></B></TD>
11      <% next %>
12      </tr>
13      <% ' Now lets grab all the records
14      do while not rstemp.eof %>

15         <tr>
16         <% for i = 0 to howmanyfields
17            thisvalue=rstemp(i)
18            If isnull(thisvalue) then
19               thisvalue="&nbsp;"
20            end if%>

21                <td valign=top><%=thisvalue%></td>
22         <% next %>
23         </tr>
24         <%rstemp.movenext
25      loop%>

26      </table>
27      <%
28      rstemp.close
29      set rstemp=nothing
30      conntemp.close
31      set conntemp=nothing
32   end sub%>


ASP Quick Lessons written by Charles M. Carroll
http://www.learnasp.com/learn/SQLaggregate.asp Page 117


SQLAggregate from ASP Quick Lessons

SQL Aggregate Syntax/Examples

SQL can also compute various aggregate items (MIN, MAX, AVERAGE are the most popular).


ASP Quick Lessons written by Charles M. Carroll
http://www.learnasp.com/learn/dbjoin.asp Page 118


dbtable

Database -- Inner Joins by Aaron Alexander

In this demonstration I will explain to you how joins between tables work in SQL. I will use the verbose SQL rather than the shortcuts due to the fact that the shortcuts differ between databases.

I would first like to define some terms that I will be using:

Primary Key(PK): This is the unique field in your table that is used to identify each record. (Ex: RecID)

Foreign Key(FK): This is a column that references a primary key of another table. It can have duplicate values.

We have 2 tables defined:

Customer

CustomerID(PK)

CustomerName

1

Joe Schmoe

2

Fred Flintstone

Sales

ID(PK)

CustomerID(FK)

SalesAmount

3

1

$1.00

4

1

$22.00

5

1

$3.00

6

20

$22.00

Inner Joins

When joining two tables there are two ways to do it. The most common way is the inner join.

The inner join will return all data where all joined data exists.

Lets look at this example of an inner-join:

SELECT Customer.CustomerName, Sales.SalesAmount FROM Customer INNER JOIN Sales ON customer.CustomerID = Sales.CustomerID

In our example above, we are selecting all the Customer Names and amount of the sale where the customer numbers exist in both tables. The result of the query is this:

CustomerName

SalesAmount

Joe Schmoe

$1.00

Joe Schmoe

$22.00

Joe Schmoe

$3.00

 

Note that record ID 6 in the sales table with customer ID of 20 is not in our result. Since that joined data does not exist we do not see the data.

Note: The SQL above can be written a lot simpler, doing it this way will avoid confusion when other tables are added:

SELECT Customer.CustomerName, Sales.SalesAmount FROM Customer , Sales where customer.CustomerID = Sales.CustomerID

Outer Joins

The outer join is useful when we want to return all data from one table, and also return linked data from another, when it exists, but here is where we differ from the inner join, we want to return all data from table 1 no matter what.

In our example we want to return all sales, even if there isn’t a valid customer associated with it.

Here is what our SQL will look like:

SELECT Customer.CustomerName, Sales.SalesAmount FROM Customer RIGHT JOIN Sales ON Customer.CustomerID = Sales.CustomerID

Our results will look like this:

CustomerName

SalesAmount

Joe Schmoe

$1.00

Joe Schmoe

$22.00

Joe Schmoe

$3.00

$22.00

Notice we did a right join. We chose to select all the data from the right table in our join statement. What would it look like if we changed to this:

SELECT Customer.CustomerName, Sales.SalesAmount FROM Customer LEFT JOIN Sales ON Customer.CustomerID = Sales.CustomerID;

Our results:

CustomerName

SalesAmount

Joe Schmoe

$1.00

Joe Schmoe

$22.00

Joe Schmoe

$3.00

Fred Flintstone

The results gave us all the records from the left table (Customer) and the linked data from the right.

As with the inner join there are shortcuts for joins, but that depends on which database you are using. Writing the verbose SQL statement will work on all databases.

I hope this helps clear things up.

Aaron Alexander


ASP Quick Lessons written by Charles M. Carroll
http://www.learnasp.com/learn/rsfast.asp Page 119


Section Contents

RSFAST: Lightning Fast Database Library
        RSFast Library Introduction (rsfast-intro.asp) - Page 120
        Table Display Fast (rsfast-table.asp) - Page 121
        Table Display Fast + Caching (rsfast-table-cached.asp) - Page 122
        Listbox Display Fast (rsfast-lists.asp) - Page 123
        Listbox Display Fast + Caching (rsfast-lists-cached.asp) - Page 124
        Templates for any look Fast (rsfast-templates.asp) - Page 125
        Debug Info helps troubleshoot (rsfast-lists-debug.asp) - Page 126
        Library Source Code (rsfast-lib.asp) - Page 127
        caching Method Explained (rsfast-cache.asp) - Page 128
        New Features for Future Versions (rsfast-newfeatures.asp) - Page 129


ASP Quick Lessons written by Charles M. Carroll
http://www.learnasp.com/learn/rsfast-intro.asp Page 120


dbtable

Overview: RSFast - Intro
by Charles Carroll

The Short Explanation
Everybody knows Getstring and Getrows is the fastest way to fetch data (see: http://www.learnasp.com/advice/whygetrows.asp) but people don't like to re-write their code or have the heartache of the ugliness of the code.

Rsfast is a library that makes fetching data easier. It looks easy on the outside. You just tell it how you want the data to look an under the covers it does highly optimized getstrings and then parses the strings and combines it with your formatting.

Easy for you, hard for the library. This is very complex internally but you never have to worry about that. Just call it. It works.

The Long Explanation (skip it and goto samples if you want)

There are many ways to retrieve data. 

This "Rsfast" library is the best of all worlds and is a suitable replacement for any database display mentioned above. It provides re-usability, lightning fast data fetching and supports every kind of formatting desired so that it can be used in many situations. In addition to any custom formatting, it provides support for listboxes, tables, page n of n tables, nth row formatting, hyperlink, and date-formatting. The feature that provides massive application speed up is that it can cache data for a specified duration. Even if the formatting applied is totally different, the data, not the format is cached. Imagine 1,000 people hit your server in 1 minute period. Instead of 1,000 queries, only the first user that minute would fetch the data. Other 999 users get same exact data. Cache can be expressed in seconds, minutes or hours. (only in minutes in this version, next version supports richer caching options).

If a long cache duration is required yet data freshness needs to be assured some caching "rules" ensure that fresh data will trigger a cache update at instance data appears.


ASP Quick Lessons written by Charles M. Carroll
http://www.learnasp.com/learn/rsfast-table.asp Page 121


dbtable

Overview: RSFast - Table Example
by Charles Carroll

the library Rsfast can make tables in a simple way. Here is the code:

   <%@ enablesessionstate=false%>
   <%option explicit%>
   <%
   response.buffer=true
   server.scripttimeout=40
   %>

   <!--#include file="lib_rsfast.asp"-->
   <html>
   <head>
10   <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
11   <title>RsFast Tables</title>
12   </head>
13   <body bgcolor="#FFFFFF">
14   <%
15      dim rsparms, conntest
16      conntest="DSN=student;uid=student;pwd=magic"
17         set rsparms=server.CreateObject("Scripting.Dictionary")
18         rsparms.Add "conn", conntest
19         rsparms.add "sql", "select * from publishers where state='NY'"
20         rsparms.add "template", "table"
21         Call RsFast(rsparms)
22         ' Include below line if you want to see millisecond timing
23         'Call PerfDisplay(rsparms)
24         set rsparms=nothing
25   %>

26   </body>
27   </html>

The library file that does all the work is at:
http://www.learnasp.com/learn/rsfast-lib.asp
so go there to cut and paste the include file if needed.


ASP Quick Lessons written by Charles M. Carroll
http://www.learnasp.com/learn/rsfast-table-cached.asp Page 122


dbtable

Overview: RSFast - Table + Caching Example
by Charles Carroll

The library Rsfast can make tables in a simple way. Here is the code:

   <%@ enablesessionstate=false%>
   <%option explicit%>
   <%
   response.buffer=true
   server.scripttimeout=40
   %>

   <!--#include file="lib_rsfast.asp"-->
   <html>
   <head>
10   <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
11   <title>rsfast-table-cache</title>
12   </head>
13   <body bgcolor="#FFFFFF">
14   <%
15      dim rsparms,conntest
16      conntest="DSN=student;uid=student;pwd=magic"
17         set rsparms=server.CreateObject("Scripting.Dictionary")
18         rsparms.Add "conn", conntest
19         rsparms.add "sql", "select * from publishers where state='NY'"
20         rsparms.add "template", "table"
21         rsparms.add "cachename", "nydata"
22         rsparms.add "cachemin", 5
23         Call RsFast(rsparms)
24         response.flush
25            Call PerfDisplay(rsparms)
26   %>

27   </body></html>

The library file that does all the work is at:
http://www.learnasp.com/learn/rsfast-lib.asp
so go there to cut and paste the include file if needed.


ASP Quick Lessons written by Charles M. Carroll
http://www.learnasp.com/learn/rsfast-lists.asp Page 123


dbtable

Overview: RSFast - Lists Example
by Charles Carroll

the library Rsfast can make tables in a simple way. Here is the code:

   <%@ enablesessionstate=false%>
   <%option explicit%>
   <%
   response.buffer=true
   server.scripttimeout=40
   %>

   <!--#include file="lib_rsfast.asp"-->
   <html>
   <head>
10   <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
11   <title>rsfast-lists</title>
12   </head>
13   <body bgcolor="#FFFFFF">
14   <%
15      dim rsparms,conntest
16      conntest="DSN=student;uid=student;pwd=magic"
17         set rsparms=server.CreateObject("Scripting.Dictionary")
18   
19         rsparms.Add "conn", conntest
20   
21         rsparms.add "sql", "select distinct city from publishers"
22         rsparms.add "template", "list"
23         rsparms.add "templatename", "city"
24         Call RsFast(rsparms)
25         'Call PerfDisplay(rsparms)
26         response.flush
27   
28         rsparms.item("sql")="select distinct state from publishers"
29         rsparms.item("templatename")="state"
30         Call RsFast(rsparms)
31         'Call PerfDisplay(rsparms)
32         response.flush
33   
34         rsparms.item("sql")="select distinct zip from publishers"
35         rsparms.item("templatename")="zip"
36         Call RsFast(rsparms)
37         'Call PerfDisplay(rsparms)
38         response.flush
39      
40   set rsparms=nothing
41   %>

42   </body>
43   </html>

The library file that does all the work is at:
http://www.learnasp.com/learn/rsfast-lib.asp
so go there to cut and paste the include file if needed.


ASP Quick Lessons written by Charles M. Carroll
http://www.learnasp.com/learn/rsfast-lists-cached.asp Page 124


dbtable

Overview: RSFast - Lists Cached Example
by Charles Carroll

Here are some listboxes combined with caching features. Here is the code:

   <%@ enablesessionstate=false%>
   <%option explicit%>
   <%
   response.buffer=true
   server.scripttimeout=40
   %>

   <!--#include file="lib_rsfast.asp"-->
   <html>
   <head>
10   <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
11   <title>rsfast-lists-cache</title>
12   </head>
13   <body bgcolor="#FFFFFF">
14   <%
15      dim rsparms,conntest
16      conntest="DSN=student;uid=student;pwd=magic"
17         set rsparms=server.CreateObject("Scripting.Dictionary")
18         rsparms.add "conn", conntest
19         rsparms.add "sql", "select distinct city from publishers"
20         rsparms.add "template", "list"
21      rsparms.add "templatename", "city"
22         Call RsFast(rsparms)
23         response.flush
24   
25         rsparms.item("sql")="select distinct state from publishers"
26         rsparms.item("templatename")="state"
27         rsparms.item("cachename")="liststate"
28         rsparms.item("cachemin")=10
29         Call RsFast(rsparms)
30         response.flush
31   
32         rsparms.item("sql")="select distinct zip from publishers"
33         rsparms.item("templatename")="zip"
34         rsparms.item("cachename")="listzip"
35         rsparms.item("cachemin")=10
36         Call RsFast(rsparms)
37         response.flush
38   
39      set rsparms=nothing
40   %>

41   </body>
42   </html>

The library file that does all the work is at:
http://www.learnasp.com/learn/rsfast-lib.asp
so go there to cut and paste the include file if needed.


ASP Quick Lessons written by Charles M. Carroll
http://www.learnasp.com/learn/rsfast-templates.asp Page 125


dbtable

Overview: RSFast - Templates Example
by Charles Carroll

The library Rsfast can use a template you supply to format data any way. Here is the code:

   <%@ enablesessionstate=false%>
   <%option explicit%>
   <%
   response.buffer=true
   server.scripttimeout=40
   %>

   <!--#include file="lib_rsfast.asp"-->
   <html>
   <head>
10   <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
11   <title>rsfast-templates</title>
12   </head>
13   <body bgcolor="#FFFFFF">
14   <%
15      dim rsparms,conntest
16      conntest="DSN=student;uid=student;pwd=magic"
17      set rsparms=server.CreateObject("Scripting.Dictionary")
18   
19         rsparms.Add "conn", conntest
20         rsparms.add "sql", "select * from publishers where state='NY'"
21         rsparms.add "template_header", "<table border=1>"
22         rsparms.add "template_row_header", "<tr>"
23         rsparms.add "template_row_footer", "</tr>"
24         rsparms.add "template_col_header", "<td>"
25         rsparms.add "template_col_footer", "</td>"
26         rsparms.add "template_footer", "</table>"
27         rsparms.add "fieldnull", "&nbsp;"
28         rsparms.add "fieldblank", "&nbsp;"
29         rsparms.add "fld_city", "<td bgcolor='lightblue'><b>{0}</b><br></td>"
30         rsparms.add "fld_state", "<td><b>{0}</b><br></td>"
31         rsparms.add "colnames", "display"
32         Call RsFast(rsparms)
33         Call PerfDisplay(rsparms)
34      set rsparms=nothing
35   %>

36   </body>
37   </html>

The library file that does all the work is at:
http://www.learnasp.com/learn/rsfast-lib.asp
so go there to cut and paste the include file if needed.


ASP Quick Lessons written by Charles M. Carroll
http://www.learnasp.com/learn/rsfast-lists-debug.asp Page 126


dbtable

Overview: RSFast - Debug Example
by Charles Carroll

If the library Rsfast is misbehaving due to bad info supplied you can turn on lots of debugging info. We will turn this on in a working file to see it in action. Here is the code:

   <%@ enablesessionstate=false%>
   <%option explicit%>
   <%
   response.buffer=true
   server.scripttimeout=40
   %>

   <!--#include file="lib_rsfast.asp"-->
   <html>
   <head>
10   <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
11   <title>rsfast-lists</title>
12   </head>
13   <body bgcolor="#FFFFFF">
14   <%
15      dim rsparms,conntest
16      conntest="DSN=student;uid=student;pwd=magic"
17         set rsparms=server.CreateObject("Scripting.Dictionary")
18      rsparms.add "debug", true
19         rsparms.Add "conn", conntest
20         rsparms.add "sql", "select distinct city from publishers"
21         rsparms.add "template", "list"
22         rsparms.add "templatename", "city"
23         Call RsFast(rsparms)
24         Call PerfDisplay(rsparms)
25         response.flush
26   
27         rsparms.item("sql")="select distinct state from publishers"
28         rsparms.item("templatename")="state"
29         Call RsFast(rsparms)
30         Call PerfDisplay(rsparms)
31         response.flush
32   
33         rsparms.item("sql")="select distinct zip from publishers"
34         rsparms.item("templatename")="zip"
35         Call RsFast(rsparms)
36         Call PerfDisplay(rsparms)
37         response.flush
38      
39   set rsparms=nothing
40   %>

41   </body>
42   </html>

The library file that does all the work is at:
http://www.learnasp.com/learn/rsfast-lib.asp
so go there to cut and paste the include file if needed.


ASP Quick Lessons written by Charles M. Carroll
http://www.learnasp.com/learn/rsfast-lib.asp Page 127


dbtable

Overview: RSFast - Library Printout
by Charles Carroll

Here is the the library file that does all the work:

   <%
   ' fix 1: removed some extra code that wasn't executing in this version
   ' fix 2: fixed .add "colnames", "display" so it works correctly
   SUB RSfast(byref parmdict)
      DIM totalstart, totalend, totalelapsed
      totalstart=timer()
   
      ' Access database build OLEDB connection string START
      If parmdict.item("accdb")="" THEN
10         ' nothing to do   
11      ELSE
12         parmdict.item("conn")="PROVIDER=Microsoft.Jet.OLEDB.4.0;DATA SOURCE=" & server.mappath(parmdict.item("accdb")) & ";"
13      END IF
14         
15      ' Caching and Data-Fetching START
16      DIM cachename,cachems,cachesec,cachemin,cacheday
17      DIM CacheIsRelevant,cacheduration
18      cachename=parmdict.item("cachename")
19      cachems=parmdict.item("cachems")
20      cachesec=parmdict.item("cachesec")
21      cachemin=parmdict.item("cachemin")
22      cacheday=parmdict.item("cacheday")
23      
24      DIM thedata,thefields, cachedata
25      parmdict.item("cachegrab")="no"
26      parmdict.item("cachebuild")="no"
27      CacheIsRelevant=CacheCheck(parmDict)
28      SELECT CASE CacheIsRelevant
29      CASE False
30         Call DataFetch(parmDict,thedata,thefields)
31      CASE True
32         If application(cachename & "_building")=TRUE THEN
33            Call DataFetch(parmDict,thedata,thefields)
34         ELSE
35            IF cacheExpired(parmDict)=TRUE THEN
36               Call CacheBuild(parmDict)
37            END IF
38            IF cacheEmpty(parmDict)=TRUE THEN
39               Call CacheBuild(parmDict)
40            END IF
41            Call CacheGrab(parmDict,cachedata,thefields)
42            thedata=split(cachedata,"#r#" & vbcrlf)
43         END IF
44      END SELECT
45      Call DataDisplay(parmDict,thedata,thefields)
46   
47      totalend=timer()
48      totalelapsed=totalend-totalstart
49      parmDict.item("timetotalms")=totalelapsed*1000
50   
51      ' Now calculate further stats
52      ' Thanks to Mike "micro-optimization" Shaffer
53          parmdict.item("timeopensec")=parmdict.item("timeopenms") \ 1000
54          parmdict.item("timequerysec")=parmdict.item("timequeryms") \ 1000
55          parmdict.item("timefetchsec")=parmdict.item("timefetchms") \ 1000
56          parmdict.item("timedisplaysec")=parmdict.item("timedisplayms") \ 1000
57          parmdict.item("timetotalsec")=parmdict.item("timetotalms") \ 1000
58   
59          parmdict.item("timeopenmin")=parmdict.item("timeopenms") \ 60000
60          parmdict.item("timequerymin")=parmdict.item("timequeryms") \ 60000
61          parmdict.item("timefetchmin")=parmdict.item("timefetchms") \ 60000
62          parmdict.item("timedisplaymin")=parmdict.item("timedisplayms") \ 60000
63          parmdict.item("timetotalmin")=parmdict.item("timetotalms") \ 60000
64   
65      ' reset cache should NEVER remember between calls
66      parmdict.item("cachename")=""
67      parmdict.item("cachemin")=""
68   END SUB
69   
70   SUB Cache2Array(byref parmDict,byref theArray())
71      If parmdict.item("debug")=true THEN   
72         response.write "Cache2Array called"
73         response.flush
74      END IF
75      ' Now transfer cache to Array
76      thearray=split(application(cachename & "_cachedata"),"#r#" & vbcrlf)
77   END SUB
78   
79   SUB CacheBuild(parmDict)
80      If parmdict.item("debug")=true THEN   
81         response.write "CacheBuild called<br>"
82         response.flush
83      END IF
84      DIM cachename,cachedata,cachefields
85      application(cachename & "_building")=true
86      cachename=parmdict.item("cachename")
87      
88      parmdict.item("cachefetch")=true
89      Call DataFetch(parmDict,cachedata,cachefields)
90      parmdict.item("cachefetch")=false
91   
92      application(cachename & "_cachedata")=cachedata
93      application(cachename & "_cachefields")=cachefields
94      ' Now Expire The Cache
95      ' cachename_cacheExpires
96      application(cachename & "_cachecreated")=now()
97      application(cachename & "_cachemin")=parmdict.item("cachemin")
98      If parmdict.item("debug")=true THEN   
99         response.write "Cachecreated=" & application(cachename & "_cachecreated") & "<br>" & "<br>"
100         response.write "cachemin=" & application(cachename & "_cachemin") & "<br>"
101         response.flush
102      END IF
103      parmdict.item("cachebuild")="yes"
104      application(cachename & "_building")=false
105   END SUB   
106   
107   SUB CacheGrab(byref parmDict,byref ParmData,byref parmFields)
108      If parmdict.item("debug")=true THEN   
109         response.write "CacheGrab called<br>"
110         response.flush
111      END IF
112      
113      DIM cachename
114      cachename=parmdict.item("cachename")
115      parmData=application(cachename & "_cachedata")
116      parmFields=application(cachename & "_cachefields")
117      parmdict.item("cachegrab")="yes"
118   END SUB
119   
120   FUNCTION cacheEmpty(parmDict)
121      If parmdict.item("debug")=true THEN   
122         response.write "CacheEmpty called<br>"
123         response.flush
124      END IF
125      DIM cachename, cachedatakey, cachedata
126      cachename=parmdict.item("cachename")
127      ' If cache is filled with data, return TRUE
128      cachedatakey=cachename & "_cachedata"
129      cachedata=application(cachedatakey)
130      If cachedata="" THEN
131         cacheEmpty=True
132      ELSE
133         cacheEmpty=False
134      END IF
135      If parmdict.item("debug")=true AND cacheempty=True THEN   
136         response.write "CacheEmpty=TRUE<br>"
137         response.flush
138      END IF
139      If parmdict.item("debug")=true AND cacheempty=False THEN   
140         response.write "CacheEmpty=False<br>"
141         response.flush
142      END IF
143   END FUNCTION
144   
145   FUNCTION cacheExpired(parmDict)
146      ' If cache is out of date return TRUE
147      DIM whenexpires, cachename, cachemin, cachecreated
148      cachename=parmdict.item("cachename")
149      cachemin=application(cachename & "_cachemin")
150      cachecreated=application(cachename & "_cachecreated")
151      whenexpires=dateadd("n",cachemin,cachecreated)
152      cacheExpired=false
153      If now()>=whenexpires THEN
154         cacheExpired=True
155      END IF
156      If cachecreated="" AND cachemin="" THEN
157         cacheExpired=False
158      END IF
159      If parmdict.item("debug")=true AND cacheExpired=True THEN   
160         response.write "whenexpires=" & whenexpires & "<br>"
161         response.write "CacheExpired=TRUE<br>"
162         response.flush
163      END IF
164      If parmdict.item("debug")=true AND cacheExpired=False THEN   
165         response.write "CacheExpired=FALSE<br>"
166         response.flush
167      END IF
168   END FUNCTION
169      
170   FUNCTION cacheCheck(parmDict)
171      ' Returns True/False whether data is cache affected
172      DIM cachename
173      cachename=parmdict.item("cachename")
174      If cachename="" THEN
175         cachecheck=False
176      ELSE
177         cachecheck=True
178      END IF
179   END FUNCTION
180   
181   SUB DataFetch(parmDict, parmArray,parmFields)
182      If parmdict.item("debug")=true THEN   
183         response.write "DataFetch called<br>"
184         response.flush
185      END IF
186   
187      ' used for timing
188      DIM openst, openend, openelapsed
189      DIM queryst, queryend, queryelapsed
190      DIM fetchst, fetchelapsed
191      DIM conntemp, rstemp
192      
193      DIM howmany,counter,thename,tempSTRdata,tempSTR
194      Dim tempSTRfields,thefields
195   
196      openst = timer
197      ' Open and check for EOF
198      set conntemp=server.createobject("adodb.connection")
199      conntemp.open parmdict.item("conn")
200         openend = timer
201         openelapsed = openend - openst
202   
203            parmdict.item("timeopenms")=openelapsed
204   
205        If parmdict.item("debug")=true THEN   
206         response.write "Conn=" & parmdict.item("conn") & "<br>"
207         response.write "Database Opened in " & openelapsed & "ms<br>"
208         response.flush
209      END IF
210       
211      ' If recordset is paged must be opened special
212      queryst=timer
213      IF cint(parmdict.item("pagesize"))>0 THEN
214         set rstemp=Server.CreateObject("ADODB.Recordset")
215         aduseclient=3
216         rstemp.cursorlocation=aduseclient
217         rstemp.cachesize=parmdict.item("pagesize")
218         rstemp.open parmdict.item("sql"),parmdict.item("conn")
219         rstemp.absolutepage=parmdict.item("page")
220         pagemax=cint(rstemp.pagecount)
221         parmdict.add "pagemax", pagemax
222         paged=true
223          If parmdict.item("debug")=true THEN   
224            response.write "SQL=" & parmdict.item("sql") & "<br>"
225            response.write "Recordset Opened for Paging!<br>"
226            response.flush
227         END IF
228      ELSE
229         set rstemp=conntemp.execute(parmdict.item("sql"))
230      END IF
231         queryend = timer
232         queryelapsed = queryend - queryst
233   
234            parmdict.item("timequeryms")=openelapsed
235   
236      fetchst=timer
237        If parmdict.item("debug")=true THEN   
238         response.write "SQL=" & parmdict.item("sql") & "<br>"
239         response.write "Query Executed: " & queryelapsed & "ms<br>"
240         response.flush
241      END IF
242      If rstemp.eof then
243         parmdict.item("errordesc")="No records matched"
244         parmdict.item("errornum")=1
245         rstemp.close
246         set rstemp=nothing
247         conntemp.close
248         set conntemp=nothing
249          If parmdict.item("debug")=true THEN   
250            response.write "EOF encountered!" & queryelapsed & "ms<br>"
251            response.flush
252         END IF
253         EXIT SUB
254      end if
255      
256      ' Now Fill The Array
257      ' Rockville#c#MD#c#20849#r#<vbcrlf>
258      ' Dallas#c#TX#c#XXXXX#r#<vbcrlf>
259      tempSTRdata=rstemp.getstring(,, "#c#","#r#" & vbcrlf,"#n#")
260   
261      ' Now Fill The FieldMaps
262      ' City#c#State#c#Zip#r#<vbcrlf>
263      howmany=rstemp.fields.count
264      for counter=0 to howmany-1
265         thename=rstemp(counter).name
266         tempstr=tempSTR & thename & "#c#"
267      next
268      tempSTRfields=tempSTR
269      rstemp.close
270      set rstemp=nothing
271      conntemp.close
272      set conntemp=nothing   
273      If parmdict.item("cachefetch")=true THEN
274         parmarray=TempSTRdata
275      ELSE
276         parmArray=split(tempSTRdata,"#r#" & vbcrlf)
277      END IF
278      parmFields=tempSTRfields
279        If parmdict.item("debug")=true THEN   
280         response.write "Data Before Split=<br>" & tempSTRdata & "<hr><br>"
281         response.write "Fields Before Split=<br>" & tempSTRfields & "<hr><br>"
282         response.flush
283      END IF
284      fetchelapsed=timer-fetchst
285      parmdict.item("timefetchms")=fetchelapsed
286   END SUB
287   
288   SUB DataDisplay(parmDict, parmData(),parmFields)
289      DIM displayst,displayelapsed
290      displayst=timer
291      
292      If parmdict.item("debug")=true THEN   
293         response.write "DataDisplay called<br>"
294         response.flush
295      END IF
296   
297         DIM cellcount,cellspersecond
298      DIM template_header,   template_footer
299      DIM rowheader,rowfooter,colheader,colfooter
300      DIM fieldnull,fieldblank,template
301      
302      ' used for looping through query results
303      DIM alldata, coldisplay,counter,howmany,rsinfo,thename,colcounter
304      
305      DIM rstemp, conntemp,rowcount,colcount
306      
307      DIM therow, fldname,fldnumb,fldvalue,fldtemplate
308      DIM thisrow, datarow
309      DIM whatever
310      DIM parmtemplate, parmtemplatename
311   
312      parmtemplate=lcase(parmdict.item("template"))
313      parmtemplatename=parmdict.item("templatename")
314      ' Templates Are Applied As Needed START
315      ' Probably need to replace dictionary items ONLY if they don't exist
316   
317      template=false
318      SELECT CASE parmtemplate
319      CASE "list", "listm"
320          template_header="<select name='" & parmtemplatename
321          If parmtemplate="listm" THEN
322                template_header=template_header & " multiple "
323          END IF
324          template_header=template_header & "'>"
325          rowheader="<option>"
326          rowfooter="</option>"
327          template_footer="</select><br>"
328          fieldnull="&nbsp;"
329          fieldblank="&nbsp;"
330          template=True
331         CASE "table","tablepaged"
332          template_header="<table border=1>"
333          rowheader="<tr>"
334          rowfooter="</tr>"
335          colheader="<td>"
336          colfooter="</td>"
337          template_footer="</table>"
338          fieldnull="&nbsp;"
339          fieldblank="&nbsp;"
340          parmdict.item("colnames")="display"
341          template=true
342      CASE ELSE
343         ' nothing to do
344      END SELECT
345   
346      IF template=false    THEN
347         template_header=parmdict.item("template_header")   
348         template_footer=parmdict.item("template_footer")   
349         ' Load dictionary items into simple variable to avoid
350         ' doing so many times in loop
351         rowheader=parmdict.item("template_row_header")
352         rowfooter=parmdict.item("template_row_footer")
353         colheader=parmdict.item("template_col_header")
354         colfooter=parmdict.item("template_col_footer")
355         fieldnull=parmdict.item("fieldnull")
356         fieldblank=parmdict.item("fieldblank")
357      END IF
358   
359      ' Page x of x displays may need to appear in header/footer
360      template_header=replace(template_header,"{page}",cstr(parmdict.item("page")))
361      template_footer=replace(template_footer,"{page}",cstr(parmdict.item("page")))
362      template_header=replace(template_header,"{pagemax}",cstr(parmdict.item("pagemax")))
363      template_footer=replace(template_footer,"{pagemax}",cstr(parmdict.item("pagemax")))
364   
365   
366      DIM highcount
367        If parmdict.item("debug")=true THEN   
368         response.write "ParmData Array Data=<Br>"
369         highcount=ubound(parmData)
370         response.write "Parm Data ubound=" & highcount & "<p>"
371       for counter=0 to highcount
372                   response.write "<b>ParmData(" & counter & ")</b>="
373          response.write parmData(counter) & "<br>"
374       next
375       response.write "<hr>"
376         response.write "ParmFields " & parmfields & "<br>"
377         response.flush
378      END IF
379      
380      DIM datafields
381      datafields=split(parmFields,"#c#")
382      
383        If parmdict.item("debug")=true THEN   
384         response.write "DataFields Data<Br>"
385         highcount=ubound(datafields)
386         response.write "DataFields ubound=" & highcount & "<p>"
387       for counter=0 to highcount
388                   response.write "<b>DataFields(" & counter & ")</b>="
389          response.write DataFields(counter) & "<br>"
390       next
391       response.write "<hr>"
392       response.write "<b>formatting info</b><br>"
393       response.write "template_header=" & server.htmlencode(template_header) & "<br>"
394       response.write "template_footer=" & server.htmlencode(template_footer) & "<br>"
395       response.write "rowheader=" & server.htmlencode(rowheader) & "<br>"
396       response.write "rowfooter=" & server.htmlencode(rowfooter) & "<br>"
397       response.write "colheader=" & server.htmlencode(colheader) & "<br>"
398       response.write "colfooter=" & server.htmlencode(colfooter) & "<br>"
399       response.write "<hr>"
400       for each whatever in parmdict
401             IF instr(whatever, "fld_")>0 THEN
402                response.write whatever & "=" & server.htmlencode(parmdict.item(whatever)) & "<br>"
403             END IF
404       next
405       response.write "<hr>"
406      END IF
407   
408      ' Page x of x displays may need to appear in header/footer
409      template_header=replace(template_header,"{page}",cstr(parmdict.item("page")))
410      template_footer=replace(template_footer,"{page}",cstr(parmdict.item("page")))
411   
412      template_header=replace(template_header,"{pagemax}",cstr(parmdict.item("pagemax")))
413      template_footer=replace(template_footer,"{pagemax}",cstr(parmdict.item("pagemax")))
414   
415      colcount=ubound(datafields)
416      response.write template_header
417   
418      If parmdict.item("colnames")="display" THEN
419         coldisplay=true
420         response.write rowheader
421      END IF
422   
423      FOR colcounter=0 TO colcount-1
424         thename=datafields(colcounter)
425         If coldisplay=TRUE THEN
426            response.write colheader
427            response.write "<b>" & thename & "</b>"
428            response.write colfooter
429         END IF
430      NEXT   
431      If coldisplay=TRUE THEN
432            response.write rowfooter
433      END IF
434      
435      rowcount=ubound(parmData)
436      ' suck display out of cache
437      FOR therow=0 TO rowcount-1
438         response.write vbcrlf & rowheader
439         thisrow=parmdata(therow)
440         datarow=split(thisrow,"#c#")
441         FOR colcounter=0 TO colcount-1
442            fldname=lcase(datafields(colcounter))
443            fldvalue=datarow(colcounter)
444            IF trim(fldvalue)="#n#" THEN
445               fldvalue=fieldnull
446            END IF
447            IF trim(fldvalue)="" THEN
448               fldvalue=fieldblank
449            END IF
450            
451            fldtemplate=parmdict.item("fld_" & fldname)
452            If fldtemplate<>"" THEN
453               fldvalue=replace(fldtemplate,"{0}",fldvalue)
454               response.write fldvalue
455            ELSE
456               response.write vbcrlf & colheader
457               response.write fldvalue
458               response.write colfooter & vbcrlf
459            END IF
460            cellcount=cellcount+1
461         NEXT
462         response.write rowfooter & vbcrlf
463      NEXT
464      response.write template_footer   
465      
466      displayelapsed=timer-displayst
467   
468      parmdict.item("timedisplayms")=displayelapsed
469      parmdict.item("cellcount")=cellcount   
470   END SUB
471   
472   SUB PerfDisplay(parmDict)
473      dim linebreak
474      linebreak="<Br>" & vbcrlf
475      
476      response.write "cachegrab=" & parmdict.item("cachegrab") & linebreak
477      response.write "cachebuild=" & parmdict.item("cachebuild") & linebreak
478      
479         Response.write "total ms=" & parmDict.item("timetotalms") & linebreak
480         Response.write "open ms=" & parmDict.item("timeopenms") & linebreak
481         Response.write "query ms=" & parmDict.item("timequeryms") & linebreak
482         Response.write "fetch ms=" & parmDict.item("timefetchms") & linebreak
483         Response.write "display ms=" & parmDict.item("timedisplayms") & linebreak
484         Response.write "cellcount=" & parmDict.item("cellcount") & linebreak
485         response.write "<hr>"
486   
487         Response.write "total sec=" & parmDict.item("timetotalsec") & linebreak
488         Response.write "open sec=" & parmDict.item("timeopensec") & linebreak
489         Response.write "query sec=" & parmDict.item("timequerysec") & linebreak
490         Response.write "fetch sec=" & parmDict.item("timefetchsec") & linebreak
491         Response.write "display sec=" & parmDict.item("timedisplaysec") & linebreak
492         response.write "<hr>"
493   
494         Response.write "total min=" & parmDict.item("timetotalmin") & linebreak
495         Response.write "open min=" & parmDict.item("timeopenmin") & linebreak
496         Response.write "query min=" & parmDict.item("timequerymin") & linebreak
497         Response.write "fetch min=" & parmDict.item("timefetchmin") & linebreak
498         Response.write "display min=" & parmDict.item("timedisplaymin") & linebreak
499         response.write "<hr>"
500   END SUB
501   %>


ASP Quick Lessons written by Charles M. Carroll
http://www.learnasp.com/learn/rsfast-cache.asp Page 128


dbtable

Overview: RSFast - Caching System
by Charles Carroll

The current caching method is extremely lightweight and scalable. It merely fills in 2 app variables with 2 strings (the data and field map) and has 2 other application variables (one holds date/time of cache creation, and duration in minutes)

It uses delimited strings, i.e. the data string would be stored as:

' Rockville#c#MD#c#20849#r#<vbcrlf>
' Dallas#c#TX#c#XXXXX#r#<vbcrlf>

and the fieldmap string would be stored as:

' City#c#State#c#Zip#c#

This means cache take up little memory. Since the data is cached not the format, even if it is formatted for a total different "look and feel" the data still comes from the cache.


ASP Quick Lessons written by Charles M. Carroll
http://www.learnasp.com/learn/rsfast-newfeatures.asp Page 129


dbtable

Overview: RSFast - New Fatures in the Works
by Charles Carroll

The following features will appear in next versions of Rsfast. We mention then now so you can see if we addressed any limit you found. Join the listserver on next page if you want help on using Rsfast or want to discuss these features implementations or features you would like us to add.

http://www.asplists.com/asplists/asprsfast.asp
is location of listserver where we discuss this library.


ASP Quick Lessons written by Charles M. Carroll
http://www.learnasp.com/learn/editors.asp Page 130


Section Contents

Editors Used With ASP
        ASPExpress: HOT ASP Editor (aspexpress.asp) - Page 131
        Visual Interdev + Admunsen Resources (admunsen.asp) - Page 132
        Visual Interdev Listserver (aspvisualinterdev.asp) - Page 133
        Homesite: HTML editor (homesite.asp) - Page 134
        DreamWeaver: HTML and Script Editor (dreamweaver.asp) - Page 135


ASP Quick Lessons written by Charles M. Carroll
http://www.learnasp.com/learn/aspexpress.asp Page 131


dbtable

ASPExpress - ASP Editor

This is a very ASP centric HTML editor. Unlike homesite which claims ASP functionality but doesn't have it, or wizard/DTC based beasts like Visual Interdev this tool truly helps you write ASP Code with:

I personally use it instead of Visual Interdev.

Take a look at the screenshots @
http://www.aspexpress.com/screenShots/screenshots.asp

Of course I am biased, because the author is a student of mine (we hold classes, see www.asptraining.com) and whenever I send him a dozen items no ASP editor does and I want, within a month or two, a new editor arrives with all the nifty features I dreamed of.

http://www.aspexpress.com
is the place to get it. You will be blown away by the phenomenal tools that no other editor has to make ASPy tasks a snap.


ASP Quick Lessons written by Charles M. Carroll
http://www.learnasp.com/learn/admunsen.asp Page 132


ASPCommerce from www.asplists.com

Interdev Guru Michael Amundsen's listserver is the first place you should go with Interdev questions.

http://www.amundsen.com/vinterdev/join/vi6talk.htm
is his awesome Visual Interdev listserve. One of the best in the world.

We of course have an active Visual-Interdev listserver - not as good as his - but hey we are trying @ http://www.asplists.com/asplists/aspvisualinterdev.asp

http://www.amundsen.com/mskb/Default.htm
is his knowledge base Assistant.

He offers Interdev Training, see:
http://www.amundsen.com/training/default.htm

There is a healthy assortment of FREE stuff there too.

 


ASP Quick Lessons written by Charles M. Carroll
http://www.learnasp.com/learn/aspvisualinterdev.asp Page 133


Listserrver Join aspvisualinterdevListserver for more info @

http://www.asplists.com/asplists/aspvisualinterdev.asp

Related Links:

 
King Interdev/Michael Admunsen @
   http://www.amundsen.com/vinterdev/default.htm

Recommended Books:

Related Lists:

Mobile lists by Asplists @
   http://www.asplists.com/asplists/mobile.asp
Mobile lists by WROX @
   http://p2p.wrox.com/mobile/

Rules:

Mailing List Manners (suggested by Bob Filipiak) @
   http://db.tidbits.com/getbits.acgi?tbser=1141
Ken Shaffer's Advice on Asking For Help... @
   http://www.adopenstatic.com/personal/help.asp


ASP Quick Lessons written by Charles M. Carroll
http://www.learnasp.com/learn/homesite.asp Page 134


dbtable

Homesite - Popular HTML Editor

This is a very popular HTML editor from
http://www.allaire.com/products/homesite/

If you are using it with ASP I recommend checking out:
http://www.wilk4.com/asp4hs
which focuses on how people using Homesite can edit their ASP scripts even easier.


ASP Quick Lessons written by Charles M. Carroll
http://www.learnasp.com/learn/dreamweaver.asp Page 135


dbtable

Dreamweaver - HTML and Script Editor

This is a very popular HTML editor from Macromedia @
http://www.dreamweaver.com

If you are using it with ASP I recommend checking out:

http://web.gmg.ch/zoomout/

which focuses on how people using Dreamweaver can edit their ASP scripts even easier.


ASP Quick Lessons written by Charles M. Carroll
http://www.learnasp.com/learn/components.asp Page 136


Section Contents

Essential Commercial Components
        ASPDB: Displaying Data (aspdb1.asp) - Page 137
        ASPDB: Editing, Adding Data (aspdb2.asp) - Page 138
        BrowserHawk: Determing Browser Type (bhbrowtype.asp) - Page 139
        AOL detection w/BrowserHawk (bhaol.asp) - Page 140
        MS-Wallet w/BrowserHawk (bhwallet.asp) - Page 141
        Reverse DNS lookups w/BrowserHawk (bhresolveip.asp) - Page 142
        BrowserHawk - Frame support (bhframes.asp) - Page 143
        Flash Detection w/BrowserHawk (bhflash.asp) - Page 144
        ServerObject Mail: Simple Example (serverobjectsmail.asp) - Page 145
        ServerObject: Mailing Form w/ASPMail (formsendmail.asp) - Page 146
        3rd Party Mail, CDO/CDONTS Listserver (aspmail.asp) - Page 147
        SA: File Upload, Simple Example (uploadsimple.asp) - Page 148
        SA: File Upload, Multi-part form (uploadmultipart.asp) - Page 149
        SA: File Upload, Limit Size (uploadlimitsize.asp) - Page 150
        SA: File Upload, Many Files (uploadmanyfiles.asp) - Page 151
        Upload/Soft-Artisans Listserver (aspsoftartisans.asp) - Page 152
        Perf Counters on ASP page (perfcounters.asp) - Page 153


ASP Quick Lessons written by Charles M. Carroll
http://www.learnasp.com/learn/aspdb1.asp Page 137


dbtable

ASPDB: Databases with No Work!

This page demonstrates the capabilities how the third party component ASPDB from http://www.aspdb.com makes database programming simple. Here we will show the code to display a gorgeous table of the customers database just be starting the component and setting a few properties:

   <% response.buffer=true %>
   <HTML>
   <Head><Title>ASPdb1.asp</Title></Head>
   <%
       Set MyDb = Server.CreateObject("ASPdb.Pro")
       MyDb.dbUnit = 1000
       MyDb.dbMDB=Server.MapPath("/learn/test/nwind.mdb")
       MyDb.dbColor = "11"
       MyDb.dbGridTableTag = "border=3"
10       MyDb.dbMode= "Grid"
11       MyDb.dbSQL = "Select * FROM Customers"
12       MyDb.dbNavigationItem = "top, bottom, next, prev, filter"
13       MyDb.ASPdbPro
14       set myDB=nothing
15   %>

16   </BODY>
17   </HTML>
18   
19   

Now we will display publishers:

   <% response.buffer=true %>
   <HTML>
   <Head><Title>ASPdb1.asp</Title></Head>
   <%
       Set MyDb = Server.CreateObject("ASPdb.Pro")
       MyDb.dbUnit = 1000
       MyDb.dbMDB=Server.MapPath("/learn/test/biblio.mdb")
       MyDb.dbColor = "11"
       MyDb.dbGridTableTag = "border=3"
10       MyDb.dbMode= "Grid"
11       MyDb.dbSQL = "Select * FROM Publishers"
12       MyDb.dbNavigationItem = "top, bottom, next, prev, filter"
13       MyDb.ASPdbPro
14       set myDB=nothing
15   %>

16   </BODY>
17   </HTML>
18   
19   


ASP Quick Lessons written by Charles M. Carroll
http://www.learnasp.com/learn/aspdb2.asp Page 138


dbtable

ASPDB: Database Editing with A Million Options!

This page demonstrates the capabilities how the third party component ASPDB from http://www.aspdb.com makes database programming powerful and removes you worrying about how and rather what it looks like. Here we will show the code to display a gorgeous editable table by starting the component and setting dozens of properties:

   <% response.buffer=true %>
   <HTML>
   <HEAD><title>ASPdb2.asp</title>
   </HEAD>
   <FONT FACE="Arial,Helvetica" Color=Black Size=3>
   
   <%
   Set MyDb = Server.CreateObject("AspDB.Pro")
   MyDb.dbUnit = 1101
10   B=Request("ASPdbBut_1101") ' this is NOT case sensitive
11   L9=Left(B,9)
12   UL9=UCASE(L9)
13   L12=Left(B,12)
14   UL12=UCASE(L12)
15   if  UL9 <> "ASPDBEDIT" then
16       response.write("<CENTER><B>Welcome to the ASP-db&#153; PRO Test Page.</B><P>")
17       response.write("For the benefit of others, please do not delete all of the records. Thanks.<P>")
18       response.write("<B>Click on the [Add New] button to see how ASP-db can put default values in certain fields.")
19   
20       response.write("<HR WIDTH=66% Size=1>")
21   end if
22   
23   ' Is it an ASPdbEditUpdate? If so, show user the Name in the "current" record.
24   THISNAME = Session("ASPdb_1101_Name")
25   
26   if  UL12 = "ASPDBEDITUPD" then
27         MSG1 = "<CENTER><FONT SIZE=4 COLOR=Black><B>"
28         MSG1 = MSG1 + "Please Update the Information for: " + THISNAME
29         MSG1 = MSG1 + "</B></FONT><P>"
30         response.write(MSG1)
31   end if
32   
33   if  UL12 = "ASPDBEDITDEL" then
34         MSG1 = "<CENTER><FONT SIZE=4 COLOR=red><B>"
35         MSG1 = MSG1 + "You are about to DELETE all of the Information for: " + THISNAME
36         MSG1 = MSG1 + "</B></FONT><P>"
37         response.write(MSG1)
38   end if
39   
40   if  UL12 = "ASPDBEDITEDI" then
41         MSG1 = "<CENTER><FONT SIZE=4 COLOR=red><B>"
42         MSG1 = MSG1 + "You are about to EDIT all of the Information for: " + THISNAME
43         MSG1 = MSG1 + "</B></FONT><P>"
44         response.write(MSG1)
45   end if
46   
47   Mydb.dbMDB = Server.MapPath("Pro-Demo.mdb") ' Has fields: Name, Age, Salary, NetWorth
48   
49   MyDb.DBColor = "11,auto,white"
50   MyDb.dbGridTableTag = "border=3 cellspacing=3 cellpadding=3"
51   MyDb.dbFormTableTag = "border=3 cellspacing=3 cellpadding=3"
52   MyDb.dbGridDisplayFlds = "Name,Age,Salary,NetWorth"
53   MyDb.DbMode = "dual-horiz"
54   MyDb.dbGridInc = 10
55   MyDb.dbButtonAnchor=false
56   MyDb.dbExportFlds = "Name"
57   
58   Mydb.dbFilterDropFlds = "Name,,People,Name,,,,,Distinct; Salary,,People,Salary,,,,,Distinct"
59   
60   Mydb.dbEditDropFlds = "Salary,,,9250.75/11000/15000/21000/25000/32000/38000/44000/75000"
61   
62   Mydb.dbEditFlds = "Name,Age[10],Salary,NetWorth[123]" ' added Name 07-27-98
63   MyDb.dbEditUpdateROFlds = "Name" ' ***** NEW!!!!! *****
64   
65   EP  = "TableName=People,BookMarkFlds=0,TableTag=Border=2"
66   EP  = EP & ",RecordScope=single,CriteriaSize=4x25,EditSemiColon=;"
67   Mydb.dbEditParams = EP
68   
69   MyDb.dbSQL = "Select * from People"
70   
71   MyDb.dbMagicCell = _
72          "1, align=Left , <font size=2 face=ARIAL color=black><I><B>#1#</B></I>;" & _
73          "2, align=Center, <font size=2 face=ARIAL color=black> #2#;" & _
74          "3, align=right , <font size=2 face=ARIAL color=black>format=[currency];" & _
75          "4, align=right , <font size=2 face=ARIAL color=black>format=[currency];"
76   
77   MyDb.dbImageDir="images/"
78   Mydb.dbNavigation="both"
79   Mydb.dbNavigationItem="Next, Prev, Gridrow, Filter, add, update, edit, delete"
80   Mydb.dbNavigationIcon="std"
81   
82   MyDb.aspDBPro
83   set mydb=nothing
84   %>

85   
86   </HTML>
87   
88   
89   
90   


ASP Quick Lessons written by Charles M. Carroll
http://www.learnasp.com/learn/bhbrowtype.asp Page 139


Determining the Browser Type and Version

How to Determine the Browser Type and Version

Often you will want to send content to the client only if you know their browser can support it. You may already have created pages that are designed to work only in IE and Netscape, version 4 or greater.  Or for example you may have situations where a specific browser type and or version creates a page layout problem.  In this lesson we present the technique used to detect specific browsers that you want to handle things differently for.

For starters, assume you receive complaints that your favorite shade of blue used for some font text on your page is extremely difficult to read when viewed on WebTV (colors are typically an issue with WebTV due to contrast and other problems).   What are you do to - remove the blue color all together?  Change it for a boring share of grey? Of course not!

The trick here is first finding a alternative color suitable for viewing on WebTV, and only using that color when the visitor is using a WebTV browser.   Otherwise you use your blue font as originally planned.  Here's how you would implement that:

   <%
       set bh = server.createobject("cyScape.browserObj")
       if (bh.browser = "WebTV") then
          fontColor = "003366" 'a suitable alternate color for WebTV folks only
       else
          fontColor = "000066" 'your favorite shade of blue for all folks
       end if
   %>

   <html>
10   
11   <head>
12   <title></title>
13   </head>
14   
15   <body>
16   
17   <p>Welcome to my page. The <font color="<%=fontColor%>important" text</font>is highlighted
18   for your convenience. </p>
19   </font>
20   </body>
21   </html>


This technique of testing for a specific browser type is also useful if you have specific tags and scripts that only work with certain browsers.  For example, say you had certain pages that required Netscape or IE versions 4 or higher. Instead of going through and conditionally including all the v4-only tags, scripts and objects, this example will show how to use this technique to detect when a browser is not Netscape or IE v4 or higher, and redirect the user to an alternate page suitable for the other browsers.

   <%
       set bh = server.createobject("cyScape.browserObj")
       if (bh.majorver >=4 ) and (bh.Browser ="IE" or bh.Browser ="Netscape") then
       else
          response.redirect("PageForNonIEorNNv4.asp")
       end if
       set bh = nothing
       %>

       <html><body> </body></html>
10   

Remember that the response.redirect code should go before any of the HTML content on the page. You can keep this check script in a separate file, and include it at the top of all pages within an application.

Another example is the title attribute for HTML elements which, currently, is only supported by IE 4 or greater. While the title attribute degrades fine in other browsers, it is sometimes desirable to limit the amount of superfluous code being sent to the browser... regardless of how insignificant it may seem. This example will show you a quick and easy way to let BrowserHawk decide for you whether or not to use that title attribute.

Here is an example of the title attribute. Since you are using IE4 or greater, if you hold your mouse over the following link for a few seconds, you will see a tooltip, similar to the kind you see when you hold your mouse over a button on an application's toolbar. This allows you to include a lot more information in a small space, such as a navigation frame or a slim table cell.

Using two methods of BrowserHawk, we can quickly and easily check if the visitor is using a browser which supports the title element (namely, that it is Internet Explorer AND that it is version 4 or greater). Here is what the code looks like:

   <%
       set bh = server.createobject("cyScape.browserObj")
       if bh.version>=4 and bh.browser="IE" then
       %>

          <a href='x.asp' title=' This is the alternate text. '>
       <% else %>
   </a>
          <a href='x.asp'>
       <%
10       end if
11       set bh = nothing
12       %>

13       <p>
14       Hover here</a>
15   

This logic could be used for any feature that you know is only supported by certain browser versions. Sometimes it is worth it to prevent the waste of bandwidth caused by adding elements and features to a page when they can't be viewed anyway. But more likely then not, you'll use this approach to avoid inconsistencies with layout and scripting across browsers.

Need a copy of BrowserHawk? See our section on Getting Started.

Copyright (c) 1999 cyScape, Inc.  All rights reserved.  This material may not be published, distributed, or reprinted without written consent from cyScape.


ASP Quick Lessons written by Charles M. Carroll
http://www.learnasp.com/learn/bhaol.asp Page 140


Detecting AOL browsers and versions

Detect AOL browsers and versions

Many people ask about how to detect which version of an AOL browser is being used, particularly AOL version 3.0 and earlier.  This is because they find that certain form submissions may not work properly, or specific functionality, such as Macromedia Flash, will not work properly for their audience.

Regardless of the reason, should you find it necessary to check for the AOL version number, you can easily use the following script to do so.

   <%
   set bh = Server.CreateObject("cyScape.browserObj")
   aolVer = bh.AOLVersion
   if  aolVer > 0 AND aolVer <= 3 then
         response.redirect "noaol3.asp"
   end if
   'Or for example, if you wanted to check for AOL Version 4 you would do this:
   ' if bh.AOLVersion = 4 then ...
   
10   %>

11   <html>
12   
13   <head>
14   <title>AOL check script</title>
15   </head>
16   
17   <body>
18   
19   <p>You are not using AOL v3 or lower</p>
20   </body>
21   </html>

Need a copy of BrowserHawk? See our section on Getting Started.

Copyright (c) 1999 cyScape, Inc.  All rights reserved.  This material may not be published, distributed, or reprinted without written consent from cyScape.


ASP Quick Lessons written by Charles M. Carroll
http://www.learnasp.com/learn/bhwallet.asp Page 141


Detecting if the MS Wallet is supported

Detecting if the MS Wallet is supported

Many developers are chosing to use the Microsoft Wallet for securely taking customer credit card / payment information for their e-commerce site.  The MS Wallet is implemented as a client-side ActiveX control.  This means that in order for your customers to purchase using the MS Wallet, their browser needs to support ActiveX controls.

Unfortunately not all browsers have this ability, including several popular browsers such those from Netscape and Opera (not even in the latest versions).  Therefore if you are implementing the MS Wallet in your site, you'll want to make sure to provide an alternative form of secure payment for those visitors without support for this component.

Microsoft provides useful scripts for implementing the Wallet in your ASP code.  Unfortunately their scripts rely on the MS browser capability component, which frequently misidentifies browsers and ActiveX support in particular.  Therefore relying on the MS component for this information will result in situations where you send the Wallet to those who can not handle it, and  several cases where you do not send it to users when you should have..

To work around this problem, simply search through the MS scripts related to the Wallet and change all occurances of the class string "MSWC.BrowserType" in the CreateObject statements in the scripts to "cyScape.browserObj".  This will ensure that you accurately identify which users can support the Wallet and provide alternatives for those who can not.

For simple demonstration purposes, the following code snippet is provided.  For real-world uses of this technique start with the scripts available for MS Wallet and change the class string as instructed above.

   <html>
   
   <head>
   <title>Purchase</title>
   </head>
   
   <body>
   
   <p>Payment info:<br>
10   <%
11   set bh = Server.CreateObject("cyScape.browserObj")
12   if  bh.ActiveXControls then
13         response.write "... send MS Wallet control"
14   else
15         response.write "... send alternative code for collecting payment info"
16   end if
17   %>
</p>
18   
19   <p>%&gt;</p>
20   </body>
21   </html>

Need a copy of BrowserHawk? See our section on Getting Started.

Copyright (c) 1999 cyScape, Inc.  All rights reserved.  This material may not be published, distributed, or reprinted without written consent from cyScape.


ASP Quick Lessons written by Charles M. Carroll
http://www.learnasp.com/learn/bhresolveip.asp Page 142


How to resolve IP address to host names

How to resolve IP address to host names

Have you ever looked at an IP address and wondered where the user came from?  Take 198.137.240.91 for example.  Certainly "www.whitehouse.gov" has quite a lot more meaning.

At one time or another you'll likely find yourself wanting to resolve IP addresses to host names.  This is known in the biz as "reverse DNS lookups".  So why would someone want to resolve an IP address?  Well there are several possible uses for this information, but for this example we'll talk about using this information to help reduce fraud on your web site.

For example, consider for a moment the issue of credit card fraud.  Certainly providing fraudulent credit card information (or using someone elses card) over the Internet seems much easier than doing the same in person.  This is because it seems easy to hide behind the anonymous nature of an HTTP connection.  What the user may not realize, however, is that based on their IP address you can likely determine who their their employer or ISP is - and can use that information to track down someone providing fradulent credit card information or abusing your site in other ways.

The host name, therefore, can serve as a decent deterrent by showing the host name to the visitor.  This way they realize it is possibly that their identify could be determined based on this information.  For example, showing someone with dishonest intentions that you know they are connected through "pop5.erols.net" may make them think twice before entering fraudulent credit card information.  Afterall, it may not prove all that difficult for the authorities to obtain records from their ISP to determine their identity.

As was mentioned earlier, there are several possible uses for this information. Whatever your reasons may be, BrowserHawk makes it easy to to obtain the host name for the current visitor or for any other IP address you'd like to look up.

To determine the host name for the current site visitor, simply call the BrowserHawk ResolveIP method as demonstrated in the example below:

   <html>
   
   <head>
   <title>Resolve IP</title>
   </head>
   
   <body>
   
   <p>Hello user connected from <%
10   set bh = Server.CreateObject("cyScape.browserObj")
11   hostname = bh.ResolveIP
12   if  hostname <> "" then
13         response.write hostname
14   else
15         response.write "Unknown"
16   end if
17   %>
</p>
18   
19   <p>%&gt;</p>
20   </body>
21   </html>

Similarly, you can also obtain the host name for any given IP address as well.   You simply call the ResolveIP method and pass in the IP address to be resolved as a parameter to the method.  This is demonstrated in the example below:

   <html>
   
   <head>
   <title>Resolve IP</title>
   </head>
   
   <body>
   <%
   ipToLookup = "198.137.240.91"
10   %>

11   
12   <p>The host name for <%=ipToLookup%> is <%
13   set bh = Server.CreateObject("cyScape.browserObj")
14   hostname = bh.ResolveIP(ipToLookup)
15   if  hostname <> "" then
16         response.write hostname
17   else
18         response.write "Unknown"
19   end if
20   %>
</p>
21   
22   <p>%&gt;</p>
23   </body>
24   </html>

Copyright (c) 1999 cyScape, Inc.  All rights reserved.  This material may not be published, distributed, or reprinted without written consent from cyScape.


ASP Quick Lessons written by Charles M. Carroll
http://www.learnasp.com/learn/bhframes.asp Page 143


Handling browsers that do not support frames

Handling browsers that do not support frames

Just about all "modern" browsers today support frames.  Unfortunately though there are still several browsers in use today that do not.  Just which ones do and which ones don't?  Well, that's a tricky questions - but fortunately we don't need to concern ourselves with that.

Instead, we simply ask BrowserHawk to determine this for us at run-time, based on the particular browser that a user visits with.  If the browser supports frames, we load the frames set as expected and all is peachy.

If the browser does not support frames, you have a couple of choices on how to handle this.  The easiest thing to do of course is just display a page that tells the user that their browser does not support frames and ask them to upgrade their browser.  Unfortunately this is the least elegant and can leave your visitor soured.   As a result, many developers have two versions of their web site - one that is frames enabled and one that is not.

In this case you use BrowserHawk to determine whether the visitor can support frames.   If they can, you simply load the frameset and off they go.  If they do not support frames, however, then we redirect them to the no frames version of the site. The following code demonstrates this approach.  For simplicity sake we will display text that says to "load the frameset here" rather than actually load a frameset.

   <%
   set bh = Server.CreateObject("cyScape.browserObj")
   if  not bh.frames then 'note: this could also be written as "if bh.frames = false"
         response.redirect "noframes.asp"
   end if
   %>

   <html>
   
   <head>
10   <title></title>
11   </head>
12   
13   <body>
14   
15   <p>HTML code to load your frameset goes here </p>
16   </body>
17   </html>

Need a copy of BrowserHawk? See our section on Getting Started.

Copyright (c) 1999 cyScape, Inc.  All rights reserved.  This material may not be published, distributed, or reprinted without written consent from cyScape.


ASP Quick Lessons written by Charles M. Carroll
http://www.learnasp.com/learn/bhflash.asp Page 144


Detecting Flash plug

Detecting Flash plug-in support

The Macromedia Flash plug-in provides a great way to liven up your web site.  With Flash you can make fancy splash screens, animated graphics, interactive presentations, and much more.  The downside?  Not all of your visitors will have the Flash plug-in installed, and therefore will not experience your site as you'd expect. :(

While it's true that Internet Explorer will automatically attempt to download and install the Flash player if not already installed, many people find this to be highly intrusive. As a result, developers prefer only to serve Flash content to Flash capable browsers.  In addition, this automatic download isn't an option for users of other popular browsers, such as Netscape Communicator.

By using the approach demonstrated here, however, you can have an alternative plan up your sleeve, and be ready to serve non Flash folks with a suitable alternative.

Let's assume you have a fancy Flash animation on your home page waiting to dazzle your visitors, and that this animation requires the Flash 4 plug-in to be installed. To make sure that visitors without Flash 4 will not be left staring at a blank home page, you'll want to provide an alternative such as an image where the Flash animation would normally go.

Here is a summary of the steps needed to implement this approach:

The toughest part of this approach is determining whether the visitor has the Flash 4 player installed in their browser.  Fortunately BrowserHawk 2000 makes detecting Flash support as simple as calling a single method and checking the Plugin_Flash property.

   <%
   set bh = Server.CreateObject("cyScape.browserObj")
   bh.GetExtProperties "BGCOLOR=#FFFFFF"
   
   'Note: The above method must be called before the HTML tag.
   'Pass in the background color used by your site as shown above
   'for best results. See the BrowserHawk documentation for more
   'details on using this method.
   %>

10   
11   <HTML><HEAD><TITLE>Flowers 'n Things Home Page (Demo)</TITLE></HEAD>
12   <BODY>
13   <CENTER><H3>Welcome to Flowers 'n Things!</H3></CENTER>
14   
15   <%
16   flashVer = bh.Plugin_Flash
17   
18       if flashVer >=4 then %>

19   
20       <!-- Code for Flash 4 users goes here -->
21   
22       <CENTER>
23       <OBJECT classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"
24         codebase="http://active.macromedia.com/flash2/cabs/swflash.cab#version=4,0,0,0"
25         ID=Flower WIDTH=360 HEIGHT=360>
26         <PARAM NAME=movie VALUE="Flower.swf"> <PARAM NAME=quality VALUE=high> <PARAM NAME=bgcolor VALUE=#FFFFFF> <embed src="Flower.swf" quality="high" bgcolor="#FFFFFF" WIDTH="360" HEIGHT="360" TYPE="application/x-shockwave-flash" PLUGINSPAGE="http://www.macromedia.com/shockwave/download/index.cgi?P1_Prod_Version=ShockwaveFlash">
27       </OBJECT><BR>
28       </CENTER>
29       <HR WIDTH=400>
30       <CENTER><TABLE WIDTH=400><TR><TD>
31       Lesson note: This is the page shown to all visitors with the Flash 4 plug-in or higher installed. If they
32       did not have Flash 4 installed, we would have presented <A HREF="flower.gif" WIDTH=360 HEIGHT=360>this image</A>
33       instead of the Flash animation above. This script uses cyScape's <A HREF="http://www.cyscape.com/products/">BrowserHawk</A> to determine whether Flash is installed.
34       </TD></TR></TABLE></CENTER>
35   
36   <% else %>
37   
38   <!-- Code for Non-Flash 4 users goes here -->
39   
40       <CENTER><IMG SRC="flower.gif" WIDTH=360 HEIGHT=360></CENTER><BR>
41       <CENTER><FONT SIZE=-1>Best viewed with <A HREF="http://www.macromedia.com/shockwave/download/?P1_Prod_Version=ShockwaveFlash">Macromedia Flash 4</A></FONT></CENTER>
42       <HR WIDTH=400>
43       <CENTER><TABLE WIDTH=400><TR><TD>
44       <%
45       msg = ""
46       if flashVer = 0 then
47          msg = "You do not have Flash installed."
48       elseif flashVer = -1 then
49          msg = "It is not possible with your browser/platform to detect whether your Flash is installed."
50       else
51          msg = "You have Flash version " & flashVer & " installed."
52       end if
53       %>

54       Lesson note: <% =msg%> This is the page shown to all visitors without the Flash 4 plug-in or higher installed. Since
55       their browser does not support Flash, we provide them with this alternative graphic for the home
56       page. This script uses cyScape's <A HREF="http://www.cyscape.com/products/">BrowserHawk</A> to determine whether Flash is installed.
57       </TD></TR></TABLE></CENTER>
58   
59   <% end if %>
60   
61   </BODY></HTML>

Need a copy of BrowserHawk? See our section on Getting Started.

Copyright (c) 2000 cyScape, Inc.  All rights reserved.  This material may not be published, distributed, or reprinted without written consent from cyScape.


ASP Quick Lessons written by Charles M. Carroll
http://www.learnasp.com/learn/serverobjectsmail.asp Page 145


ASPMail by ServerObjects.com

ASPMail™ by Server Objects

www.serverobjects.com is a great place to get a variety of components. Here we will give you a simple script utilizing genusa mail that e-mails me each time you run the page.

http://www.activeserverpages.com/learn/test/serverobjectsmail.asp
is the page you can test this at.

   <html><head>
   <title>serverobjectsmail.asp</title>
   </head><body bgcolor="#FFFFFF">
   <%
   ' ASPMail(tm) from www.serverobjects.com
   ' is not part of ASP per se,
   ' but a third party utility from serverobjects.com
   Set Mailer = Server.CreateObject("SMTPsvg.Mailer")
   Mailer.RemoteHost = "mail.innerhost.com"
10   
11   Mailer.FromName = "Some Student"
12   Mailer.FromAddress = "somestudent@activeserverpages.com"
13   Mailer.AddRecipient "Charles Carroll","selfdestruct@learnasp.com"
14   Mailer.AddBCC "Sally Jones","selfdestruct@learnasp.com"
15   Mailer.Subject = "ASPMail Tutorial"
16   
17   Mailer.BodyText = "Hi. Just trying the mail example" & vbCrLf
18   Mailer.BodyText = "Line 2"
19   Mailer.BodyText = "Line 3"
20   If  Mailer.SendMail then
21      Msg = "mail sent sucessfully!"
22   Else
23      Msg = "mail <b>not</b> sent sucessfully"
24      msg = msg & "<br>" & mailer.response
25   End If
26   response.write Msg
27   
28   set mailer=nothing
29   %>

30   </body></html>


ASP Quick Lessons written by Charles M. Carroll
http://www.learnasp.com/learn/formsendmail.asp Page 146


Forms Send Mail from ASP Quick Lessons

Forms - Sending Results via EMail by Charles Carroll

Sometimes it makes sense to just email all the form results to someone. But the "mailto:" method used by many Web developers is not the best way as it has the following serious limitations:

Server side mail has none of these limitations. Here is a form that will be sent to you provided you change the variables at the top of the code. This example uses ASPmail, which is available for a modest price at: http://www.serverobjects.com

Here is a sample form that will be sent via email:

   <%
   ' change these to reflect where form should go
   fromName="Whoever"
   fromAddress="somestudent@activeserverpages.com"
   toName="Charles M. Carroll"
   toAddress="cc@thebestweb.com"
   subject="form send mail tutorial"
   relay="mail.innerhost.com"
   %>

10   <html><head>
11   <title>FormToBeMailed.asp</title>
12   </head><body bgcolor="#FFFFFF">
13   <form action="FormToBeMailedrespond.asp" method="GET">
14   Fill Out This Form For Us:<p>
15   First Name -&gt; <input NAME="NameFirst" size="20"><br>
16   Last Name -&gt; <input NAME="NameLast" size="20"><br>
17   Country -&gt; <input NAME="Country" value="USA" size="20"><br>
18   State -&gt; <input NAME="State" MaxLength="2" size="2"><br>
19   email copy to -&gt; <input NAME="emailcopy" MaxLength="40" size="40"><br>
20   
21   <input type="submit"><input type="reset">
22   
23   <% ' do not touch these lines. Needed to send mail! %>
24   <input type="hidden" name="mail-from" value="<%=fromName%>">
25   <input type="hidden" name="mail-fromAddress" value="<%=fromAddress%>">
26   <input type="hidden" name="mail-to" value="<%=ToName%>">
27   <input type="hidden" name="mail-toaddress" value="<%=toaddress%>">
28   <input type="hidden" name="mail-subject" value="<%=subject%>">
29   <input type="hidden" name="mail-relay" value="<%=relay%>">
30   </form>
31   </body></html>

Here is the generic form responder that can be used with this or any form:

   <html><head>
   <title>serverobjectsmailrespond.asp</title>
   </head><body bgcolor="#FFFFFF">
   <%
   ' ASPMail(tm) from http://www.serverobjects.com
   ' is not part of ASP per se,
   ' but a excellent third party component
   
   my_from=request("mail-fromName")
10   my_fromAddress=request("mail-fromaddress")
11   my_to=request("mail-toName")
12   my_toAddress=request("mail-toaddress")
13   my_subject=request("mail-subject")
14   my_relay=request("mail-relay")
15   
16   Set Mailer = Server.CreateObject("SMTPsvg.Mailer")
17   Mailer.RemoteHost = my_relay
18   
19   Mailer.FromName = my_from
20   Mailer.FromAddress = my_fromAddress
21   Mailer.AddRecipient my_to, my_toaddress
22   Mailer.Subject = my_subject
23   
24   for each whatever in request.querystring
25      If instr(whatever,"mail-")=0 then
26         Mailer.BodyText = whatever & "=" & vbcrlf
27         Mailer.BodyText = request.querystring(whatever) & vbcrlf & vbcrlf
28      end if
29   next
30   
31   for each whatever in request.form
32      If instr(whatever,"mail-")=0 then
33         Mailer.BodyText = whatever & "=" & vbcrlf
34         Mailer.BodyText = request.form(whatever) & vbcrlf & vbcrlf
35      end if
36   next
37   
38   my_emailcopy=request("emailcopy")
39   If  my_emailcopy="" then
40   else
41      Mailer.AddRecipient "form filler",my_emailcopy
42   end if
43   
44   If  Mailer.SendMail then
45      Msg = "mail sent sucessfully!"
46   Else
47      Msg = "mail was not sent sucessfully<br>"
48      msg = msg & mailer.response & "<br>"
49   End If
50   response.write Msg
51   %>

52   </body></html>


ASP Quick Lessons written by Charles M. Carroll
http://www.learnasp.com/learn/aspmail.asp Page 147


Listserrver Join aspexchangeoutlookListserver for more info @

http://www.asplists.com/asplists/aspexchangeoutlook.asp

Related Links:

 
CDO Download @
   http://www.microsoft.com/exchange/55/downloads/CDO.htm
PRB: Permission Denied While Using CDONTS to Send Mail with Exchange @
   http://support.microsoft.com/support/kb/articles/q228/4/65.asp
Formatting Mail as HTML @
   http://msdn.microsoft.com/library/psdk/cdo/amsmtp_52an.htm
4guys Tutorial Attachments with CDO @
   http://www.4guysfromrolla.com/webtech/112298-1.shtml
Configure SMNTP server with MMC for CDO @
   http://support.microsoft.com/support/kb/articles/Q186/2/04.ASP
PRB: Error: MAPI_E_FAILONEPROVIDER (8004011D) Using CDO @
   http://support.microsoft.com/support/kb/articles/Q195/8/49.ASP
ASP101 CDO tutorial @
   http://www.asp101.com/samples/email_cdo.asp
A SUPERB, Insightful ADSI/CDO book @
   http://www.learnasp.com/books/wroxadsicdoasp.asp
MS CDO Session Object Docs @
   http://msdn.microsoft.com/library/psdk/cdo/amsmtp_3qcf.htm
MS Sample of CDO Send Method @
   http://msdn.microsoft.com/library/psdk/cdo/amsmtp_4grj.htm
CDO Resources @
   http://www.cdolive.com
SlipStick Exchange Resources @
   http://www.slipstick.com
send HTML formatted emails w/pictures and attachments @
   http://msdn.microsoft.com/library/partbook/asp20/usingcdofornts.htm
Attachments and CDO @
   http://www.aspfree.com/devlinks/search.asp?file404=attach;cdo
Checking for Mail with CDO @
   http://msdn.microsoft.com/library/psdk/cdo/_olemsg_checking_for_new_mail.htm
PRB: Path Not Found When Using CDONTS with IMC @
   http://support.microsoft.com/support/kb/articles/Q235/6/81.ASP
IMAP4 for ASP @
   http://www.infradig.com/index.shtml
Sending Automated Newsletters @
   http://www.siteexperts.com/tips/backend/ts12/page1.asp
ServerObjects AspMail Tutorial @
   http://www.learnasp.com/learn/formsendmail.asp
Jmail @
   http://www.dimac.net/
PRB: ASP Running CDONTS Applications Out of Process Fails @
   http://support.microsoft.com/support/kb/articles/Q184/2/70.ASP
Accessing Microsoft Exchange and Outlook Data as database @
   http://msdn.microsoft.com/library/techart/olexcoutlk.htm
PRB: Problems Sending Many Messages Using Multiple Threads @
   http://support.microsoft.com/support/kb/articles/q181/6/97.asp
Where to Acquire CDO Libraries @
   http://support.microsoft.com/support/kb/articles/q171/4/40.asp
Scheduled Mailing @
   http://swynk.com/friends/jones/articles/manage_web_server.asp

Recommended Books:

        

Related Lists:

Mobile lists by Asplists @
   http://www.asplists.com/asplists/mobile.asp
Mobile lists by WROX @
   http://p2p.wrox.com/mobile/

Rules:

Mailing List Manners (suggested by Bob Filipiak) @
   http://db.tidbits.com/getbits.acgi?tbser=1141
Ken Shaffer's Advice on Asking For Help... @
   http://www.adopenstatic.com/personal/help.asp


ASP Quick Lessons written by Charles M. Carroll
http://www.learnasp.com/learn/uploadsimple.asp Page 148


Uploading with SA-FileUp: A Simple Upload

Uploading with SA-FileUp -- Simple Example

by David Wihl

SA-FileUp is an Active Server component that allows users with a web browser to transmit files from their local hard disk to a Microsoft Internet Information Server (IIS) web server.

Scripting the Upload

Your file upload script(s) will consist of two parts:

To try SA-FileUp, browse to select a small file on you system and hit Upload File.

   <HTML><HEAD>
   <TITLE>uploadsimple.asp by softwareartisans.com</TITLE>
   </HEAD><body bgcolor="#FFFFFF">
   <form enctype="multipart/form-data" method="post" action="uploadsimplerespond.asp">
   <TABLE WIDTH="100%">
   <TR>
      <TD ALIGN="RIGHT" VALIGN="TOP">Filename:</TD>
   
      <TD ALIGN="LEFT"><INPUT TYPE="FILE" NAME="FILE1">
10      </TD>
11   </TR>
12   <TR>
13      <TD ALIGN="RIGHT">&nbsp;</TD>
14      <TD ALIGN="LEFT"><INPUT TYPE="SUBMIT" NAME="SUB1" VALUE="Upload File"></TD>
15   </TR>
16   <TR>
17      <TD ALIGN="RIGHT">&nbsp;</TD>
18      <TD ALIGN="LEFT">
19      <B><I><SMALL>Note: if a button labeled "Browse..." does not appear, then your
20      browser does not support File Upload. For Internet Explorer 3.02 users, a
21      free add-on is available from Microsoft. If you <b>do not see a Browse... button</b>
22      <A HREF="http://www.microsoft.com/msdownload/ieplatform/iewin95/iewin95.asp" TARGET="_new">click here to go to Microsoft's Site and get your free file upload add-on</A>.
23      Select "Internet Explorer 3.02 File Upload Add-On for Windows 95 & NT".
24      </SMALL></I></B>
25      </TD>
26   </TR>
27   </TABLE>
28   </form>
29   </BODY></HTML>

The Form Definition

To enable file upload, include an INPUT tag of <TYPE="FILE"> in your HTML form.

When using a form to upload files, you must set the following attributes:

  • The FORM tag must include the attribute ENCTYPE="multipart/form-data".
  • The <INPUT TYPE="FILE"> must include the NAME attribute.

The Server-side Processing

The responder to the form will look like this:

   <HTML><HEAD>
   <TITLE>Uploadsimplerespond.asp by softwareartisans.com</TITLE>
   </HEAD><BODY>
   Thank you for uploading your file.<br>
   <% Set upl = Server.CreateObject("SoftArtisans.FileUp")
   upl.Path = Server.Mappath ("/upload/tests")
   upl.SaveAs "upload.tst"%>
<BR>
   Total Bytes Written: <%=upl.TotalBytes%>
   </BODY></HTML>

To process the upload on the server,

  • In the response page (in this case, uploadsimplerespond.asp) create an instance of the SA-FileUp object.
    <% Set upl = Server.CreateObject("SoftArtisans.FileUp") %>
  • Save the file in a directory on the web server.
    <% upl.SaveAs "C:\temp\upload.out" %>

The TotalBytes property contains the size in bytes of the uploaded file.

The directory on the web server must have Read, Write, and Delete NTFS permissions for the anonymous or authenticated user. Otherwise, SA-FileUp will not be able to write files into that directory. Talk to your web master about setting the appropriate permissions.


ASP Quick Lessons written by Charles M. Carroll
http://www.learnasp.com/learn/uploadmultipart.asp Page 149


Uploading with SA-FileUp: Accessing Multiple Form Elements

Uploading with SA-FileUp -- Accessing Multiple Form Elements

Form and FormEx

You can usually use ASP's Request.Form object to access form values. However, when uploading files, you must change the form's encoding type to "multipart/form-data". The ASP Request.Form object does not understand data transmitted using this encoding type.

SA-FileUp includes two objects that provide the functionality of the ASP Request.Form object, but can understand the encoding type that is specific to file uploads. The two objects are Form and FormEx.

Form is used to access the values of solitary form elements. FormEx handles collections of form elements (e.g., listboxes, radio buttons, multiple files, etc.). Using FormEx to access solitary form elements may produce an error. To prevent errors, use each object only in its appropriate context. Syntactically, FormEx may only be used as follows,

  • In a "For...Each" statement, i.e., "For each item in upl.FormEx(multipart)"
  • With collection index numbers, i.e., "FormEx("name").index"

The Form Definition

To submit information with the upload, include additional <INPUT> tags. The form defined below contains a text input for the file description.

   <html>   
   <head>
   <title>Please Upload Your File</title>
   </head>
   <body>
      <form enctype=multipart/form-data method=post action=multipartformrespond.asp>
      <table>
      <tr>
         <td>Enter file description:</td>
10         <td><input type=text name=descrip></td>
11      </tr>
12      <tr>
13         <td>Select file:</td>
14         <td><input type=file name=f1></td>
15      </tr>
16      <tr>
17         <td><input type=submit value="Submit"></td>
18         <td></td>
19      </tr>
20      </table>
21      </form>
22   </body>
23   </html>
24   

The Server-side Processing

To access a form value using SA-FileUp's Form object, refer to it explicitly by name, as in the following example.

   <HTML><HEAD>
   <TITLE>Multipartformrespond.asp by softwareartisans.com</TITLE>
   </HEAD><BODY>
   Thank you for uploading your file.<br><br>
   <%
   Set upl = Server.CreateObject("SoftArtisans.FileUp")
   upl.Path = Server.Mappath ("/upload") & "/" & "tests"
   upl.Save
   strFilename = Mid(upl.UserFilename, InstrRev(upl.UserFilename, "\") + 1)%>

10   File name: <%=strFilename%><br><br>
11   File description: <%=upl.form("descrip")%>
12   </BODY></HTML>

Note: Since the form contains only one <INPUT> of TYPE="FILE", you do not have to refer to it by name.


ASP Quick Lessons written by Charles M. Carroll
http://www.learnasp.com/learn/uploadlimitsize.asp Page 150


Uploading with SA-FileUp: Limiting File Size and Type

Limiting the Upload Size

SA-FileUp's MaxBytes property allows you to limit the size of files uploaded to your server. If MaxBytes is set, SA-FileUp will stop writing to the hard disk when the value of MaxBytes is reached. For example, if MaxBytes = 1000, only 1000KB of a 100,000KB file will be written to the server hard disk.

Set MaxBytes once and it will apply to all files in the current upload, limiting each of them to the value that you specify.

Using MaxBytes, you can prevent malicious users from filling your web server's hard disk.

   
      <html>
      <head>
      <title>Limit File Size</title>
      </head>
      <body>
      Thank you for uploading your file.<br>
      <% Set upl = Server.CreateObject(SoftArtisans.FileUp) %>
      <% upl.MaxBytes = 1000 '--- limit the upload size to 1000 bytes %>
10      The maximum file size that you are permitted to upload is <%=upl.MaxBytes%> bytes.<br>
11      <% upl.SaveAs C:\temp\upload.out %>
12      Total Bytes Written: <%=upl.TotalBytes%><br>
13      Server File Name: <%=upl.ServerName%><br>
14      Total Bytes Transmitted: <%=Request.TotalBytes%>
15      </body>
16      </html>

Restricting File Types

Use SA-FileUp's ContentType property and a Select condition to save only files of a specific type.

   <html>
   <head>
   <title>Limit File Type</title>
   </head>
   <body>
      <% Set upl = Server.CreateObject("SoftArtisans.FileUp")
   
      '--- Parse out the file name
      FName = Mid(upl.UserFilename, InstrRev(upl.UserFilename, \) + 1)
10   
11      '--- Retrieve the file's content type and assign it to a variable
12      FCONT = upl.ContentType
13   
14      '--- Restrict the file types saved using a Select condition
15      Select Case LCase(FCONT)
16      Case "image/gif"
17         upl.Save
18         Response.Write <P> & FName & has been saved.
19      
20      Case image/pjpeg
21         upl.Save
22         Response.Write <P> & FName & has been saved.
23      
24      Case Else
25         upl.delete
26         Response.Write <P> & You may only upload gif and jpeg files.<BR>
27         Response.End
28      End Select
29   
30      %>

31   </body>
32   </html>


ASP Quick Lessons written by Charles M. Carroll
http://www.learnasp.com/learn/uploadmanyfiles.asp Page 151


Uploading with SA-FileUp: Uploading Multiple Files

Uploading with SA-FileUp -- Uploading Multiple Files

The Form Definition

To upload multiple files, include multiple <INPUT> tags of TYPE=FILE.

   <html>
   <head>
   <title>Please upload two files</title>
   </head>
   <body>
      <form enctype=multipart/form-data action=multifilerespond.asp method=post>
      <table>
      <tr>
      <td>Enter first file:</td>
10      <td><input type=file name=f1></td>
11      </tr>
12      <tr>
13      <td>Enter second file:</td>
14      <td><input type=file name=f2></td>
15      </tr>
16      <tr>
17      <td></td>
18      <td align=right><input type=submit value="Submit"></td>
19      </tr>
20      </table>
21      </form>
22   </body>
23   </html>
24   

While multiple inputs work well for a small number of files, uploading through a form that includes more than a few file inputs is time-consuming. If you want to allow your users to upload numerous files, consider using a client-side tool, like SA-JFile or SA-XFile.

The Server-side Processing

When processing the upload of multiple files, refer to each by name, as follows.

   <html>
   <head>
   <title>Multiple File Upload Results</title>
   </head>
   <body>
      Thank you for uploading your files.<br>
      <% Set upl = Server.CreateObject(SoftArtisans.FileUp) %>
      <% upl.Form(f1).SaveAs C:\temp\upload1.out %>
      Total Bytes Written for File 1: <%=upl.Form(f1).TotalBytes%><br>
10      <% upl.Form(f2).SaveAs C:\temp\upload2.out %>
11      Total Bytes Written for File 2: <%=upl.Form(f2).TotalBytes%><br>
12   </body>
13   </html>
14   


ASP Quick Lessons written by Charles M. Carroll
http://www.learnasp.com/learn/aspsoftartisans.asp Page 152


Listserrver Join aspsoftartisansListserver for more info @

http://www.asplists.com/asplists/aspsoftartisans.asp

Related Links:

 
Upload: Simple Example @
   http://www.learnasp.com/learn/uploadsimple.asp
SA File-UP FAQ @
   http://www.softartisans.com/softartisans/freqasques.html
SA File-UP Code Samples @
   http://www.softartisans.com/softartisans/samcod.html

Recommended Books:

Related Lists:

Mobile lists by Asplists @
   http://www.asplists.com/asplists/mobile.asp
Mobile lists by WROX @
   http://p2p.wrox.com/mobile/

Rules:

Mailing List Manners (suggested by Bob Filipiak) @
   http://db.tidbits.com/getbits.acgi?tbser=1141
Ken Shaffer's Advice on Asking For Help... @
   http://www.adopenstatic.com/personal/help.asp


ASP Quick Lessons written by Charles M. Carroll
http://www.learnasp.com/learn/perfcounters.asp Page 153


subdates from ASP Quick Lessons

Performance Counter monitoring via a Web Page
using PerfCounter component from www.softwing.com

The following script monitors the officially undocumented error counters that were unofficially documented in:
http://www.15seconds.com/Issue/981015.htm.

The following code setup the monitor:

   <html>
   
   <head>
   <title>perfcountersetup.asp</title>
   </head><body>
   <%
   Set objQPerfCnt = CreateObject("Softwing.AspQPerfCounters")
   bResult = objQPerfCnt.OpenQuery()
   bResult = objQPerfCnt.AddCounter("\\.\Active Server Pages\Errors During Script Runtime")
10   bResult = objQPerfCnt.CollectQueryData()
11   varResult = objQPerfCnt.GetFormattedCounterVal(_
12         "\\.\Active Server Pages\Errors During Script Runtime", 0)
13   bResult = objQPerfCnt.CloseQuery()
14   %>

15   </body>
16   </html>

The following code displays that monitor:

   <html><head>
   <title>perfcounterswatcherror.asp</title>
   </head><body>
   <%
   ' counters to watch
   Dim arrFriendlyName,arrCounterPath
   arrFriendlyName = Array("Total failed requests","Errors per second (current)",_
      "Runtime errors (total)", "Script compiler errors (total)", _
      "ASP preprocessor errors (total)")
10   arrCounterPath = Array("\\.\Active Server Pages\Requests Failed Total", _
11         "\\.\Active Server Pages\Errors/Sec", _
12         "\\.\Active Server Pages\Errors During Script Runtime",_
13         "\\.\Active Server Pages\Errors From Script Compilers", _
14         "\\.\Active Server Pages\Errors From ASP Preprocessor")
15   Dim objQPerfCnt, bResult, varResult, i
16   Set objQPerfCnt = CreateObject("Softwing.AspQPerfCounters")
17   bResult = objQPerfCnt.OpenQuery()
18   for i = 0 to UBound(arrCounterPath)
19      bResult = objQPerfCnt.AddCounter(arrCounterPath(i))
20   next
21   bResult = objQPerfCnt.CollectQueryData()
22   for i=0 to UBound(arrCounterPath)
23      varResult = objQPerfCnt.GetFormattedCounterVal(arrCounterPath(i), 0)
24      Response.Write "<b>" & arrFriendlyName(i) & "</b>: "
25      Response.Write varResult & "<br>" & vbCrLf
26   next
27   %>

28   </body>
29   </html>

Questions about this component can be directed to:

Undergoing renovation - SUB ListServSignup


ASP Quick Lessons written by Charles M. Carroll
http://www.learnasp.com/learn/authenticate.asp Page 154


Section Contents

Authentication & Security
        Authenticate: Overview by Kevin Flick (authenticateoverview.asp) - Page 155
        Authenticate: Comparison by Kevin Flick (authenticatecomparisons.asp) - Page 156
        Authenticate: NT Challenge/Response by Kevin Flick (authenticatentcr.asp) - Page 157
        Authenticate: Basic Authentication by Kevin Flick (authenticatebasic.asp) - Page 158
        Authenticate: Cookies by Kevin Flick (authenticatecookies.asp) - Page 159
        Authenticate: Certificates by Kevin Flick (authenticatecertificate.asp) - Page 160
        Authenticate: Build Your Own by Kevin Flick (authenticatebuild.asp) - Page 161
        Authenticate: Protect Pages via Login #1 (security.asp) - Page 162
        Authenticate: Protect Pages via Login #2 (security2.asp) - Page 163
        Authenticate: 3rd Party by Kevin Flick (authenticate3rdparty.asp) - Page 164
        Authentix Flicks Support Listserver (aspflicks.asp) - Page 165


ASP Quick Lessons written by Charles M. Carroll
http://www.learnasp.com/learn/authenticateoverview.asp Page 155


Authentication Overview from ASP Quick Lessons

Authentication Overview
written and ©1998, 99 by Kevin Flick www.flicks.com creator of Authentix

What is Authentication?

Let's assume you want to restrict access to selected portions of your website. For example, you might have valuable information, such as real-time stock quotes (like Reuters or Datastream), or you want to charge a monthly fee in order to access your database.
In these cases, you want to let people in, but only after checking that visitors have used an authorized username and password. Additionally, you might want to provide access to the bulk of your website for the simple price of a visitor's email address, creating an effective method for tracking visitors.

Asking a visitor for their username and password (or their credentials) is called Authentication. On the world wide web, the oldest and most widely supported authentication method is Basic Authentication.

What are my choices?

Assuming you have the latest and greatest IIS, you have several choices when working with authentication including:


ASP Quick Lessons written by Charles M. Carroll
http://www.learnasp.com/learn/authenticatecomparisons.asp Page 156


Authentication Comparison from ASP Quick Lessons

Authentication Comparison
written and ©1998, 99 by Kevin Flick www.flicks.com creator of Authentix

Which should I use?

In deciding which type of Authentication to use, it's important to keep the following points in mind:

Which Type Why use it? Why not use it? How to use it.
IIS NT Challenge Response Why
Happyface.gif Happyface.gif Happyface.gif
Why not
sad_face.gif sad_face.gif sad_face.gif sad_face.gif
How
sad_face.gif sad_face.gif
IIS Basic Authentication Why
sad_face.gif
Why not
sad_face.gif sad_face.gif sad_face.gif sad_face.gif sad_face.gif
How
sad_face.gif sad_face.gif
A Third Party Basic Authentication filter Why
Happyface.gif Happyface.gif Happyface.gif Happyface.gif
Why not
sad_face.gif
How
Happyface.gif
Write your own Basic Authentication filter Why
Happyface.gif Happyface.gif Happyface.gif
Why not
sad_face.gif sad_face.gif sad_face.gif sad_face.gif
How
sad_face.gif sad_face.gif sad_face.gif sad_face.gif
Cookie Based Authentication with ASP pages Why
Happyface.gif Happyface.gif Happyface.gif
Why not
sad_face.gif sad_face.gif sad_face.gif
How
sad_face.gif sad_face.gif sad_face.gif
Self-authenticating scripts Why
Happyface.gif Happyface.gif
Why not
sad_face.gif sad_face.gif sad_face.gif
How
sad_face.gif sad_face.gif
Certificate based authentication. Why
Happyface.gif Happyface.gif
Why not
sad_face.gif sad_face.gif sad_face.gif
How
sad_face.gif sad_face.gif sad_face.gif


ASP Quick Lessons written by Charles M. Carroll
http://www.learnasp.com/learn/authenticatentcr.asp Page 157


Authentication NT Challenge/Response from ASP Quick Lessons

Authentication -- NT Challenge/Response
written and ©1998, 99 by Kevin Flick www.flicks.com creator of Authentix

Using NT Challenge Response is an obvious choice, and is included as one of the options when you set up each IIS directory. Any directory you want to protect must be on a NTFS partition.

NTFS is the way to go if you are on a Windows Network. For intranets NTCR can be an ideal solution with these conditions:

You won't want to use NTFS if

Definitions

How to set up NTCR

In Internet Service Manager (IIS1-3) or the Microsoft Management Console for IIS (IIS4 and up) select the directory you want to protect. Make sure Basic (Clear Text) is off and Windows NT Challenge Response is on. You can leave Allow Anonymous on.

Create an account for each user you want to provide access, remove the permissions for "IUSR_machinename" from the directory, and add permissions for the added users. Alternatively, you could set up a group, permit access to that group, and add permitted users to the group. Remember, the user will need execute rights if the directory has any ASP, ISAPI extensions, counters, and so on.
Note that when the user returns to a non-protected page, they will be prompted for their username and password again, unless you have also granted them read-access to non-protected pages. However cancelling the prompt will let them in, disconcerting though this may be.
If the user has permission to access the directory but is in a different domain than the IIS machine, the user will have to prepend the domain name, so IIS knows where to look for the password.

Because NTCR uses a token mechanism for verifying users, the password of the currently logged in user is not available to IIS. This will have an impact if you are trying to access a resource which is not on the same machine as IIS, since IIS will not be able to login using the current user to a machine elsewhere on the LAN. For example if an NTCR protected ASP page tried to read an Access mdb file on another machine, it would fail. Similarly for SQL Server with Integrated or Mixed security. See Q166029, Q149425.


ASP Quick Lessons written by Charles M. Carroll
http://www.learnasp.com/learn/authenticatebasic.asp Page 158


Authentication Basic IIS from ASP Quick Lessons

Authentication - IIS Basic Authentication
written and ©1998, 99 by Kevin Flick www.flicks.com creator of Authentix

IIS Basic Authentication is included as an option when you set up each IIS directory. Any directory you want to protect must be on a NTFS partition.

IIS Basic Authentication is the way to go if you accept the need for SSL and don't mind paying the performance penalty. You already have a certificate or you don't mind paying for one and setting it up.

You won't want to use IIS Basic Authentication if you are concerned about the security of your NT accounts and performance. IIS calls LogonUser and ImpersonateLoggedOnUser for each and every request, which is expensive in terms of CPU cycles.

Definitions

How to set up IIS Basic Authentication

Setting up IIS Basic Authentication is similar to setting up NTCR.


ASP Quick Lessons written by Charles M. Carroll
http://www.learnasp.com/learn/authenticatecookies.asp Page 159


Authentication Coookie Based from ASP Quick Lessons

Authentication -- Cookie Based
written and ©1998, 99 by Kevin Flick www.flicks.com creator of Authentix

You can use the cookie based session variables of Active Server Pages to capture a username and password from a form, validate the username and password, then set a session variable to indicate the user has correctly logged in.

Cookie Based Authentication with ASP pages is the way to go if

 You won't want Cookie Based Authentication with ASP pages if

Definitions

How to use Cookie Based Authentication with ASP pages

   We have a example in this Tutorial on the next pages that implements session based authentication for people who want to implement this:


ASP Quick Lessons written by Charles M. Carroll
http://www.learnasp.com/learn/authenticatecertificate.asp Page 160


Authentication Certificate Based from ASP Quick Lessons

Authentication -- Certificate Based
written and ©1998, 99 by Kevin Flick www.flicks.com creator of Authentix

Client certificates are an advanced form of authentication, and at this time they are still very much in their infancy with respect to compatibility and ease of use.

Certificate based authentication is the way to go if :

You won't want Certificate based authentication if :

Definitions

How to use Certificate based authentication

Since this technology is still maturing, be sure to have the latest version of IIS4 installed on your system.

There are several good references to help understand and use Client Certificate technology. Some articles that are recommended include:


ASP Quick Lessons written by Charles M. Carroll
http://www.learnasp.com/learn/authenticatebuild.asp Page 161


Authentication Write Your Own Filter from ASP Quick Lessons

Authentication -- Write your own Filter
written and ©1998, 99 by Kevin Flick www.flicks.com creator of Authentix

Writing your own Basic Authentication filter is an option if you have the skills, resources and time to do it.

Writing your own Basic Authentication filter is the way to go if

You won't want to write your own Basic Authentication filter if

Definitions

How to write your own Basic Authentication filter

You will need to build a dll that conforms to the ISAPI filter specification and has the following entry points:

The GetFilterVersion function is the first entry point called by the Internet Information Server. In this function you set the IIS notifications that you want to receive, and any other first time setup tasks.

The HttpFilterProc function is called in response to the notifications set in GetFilterVersion and is where the work of the filter is actually done.

There are several excellent references to help develop an ISAPI filter. Recommended is Que's "Special Edition Using ISAPI", ISBN 0-7897-0913-9 (to which this writer also contributed).


ASP Quick Lessons written by Charles M. Carroll
http://www.learnasp.com/learn/security.asp Page 162


security from ASP Quick Lessons

Custom Security/Authentication #1

You can limit access to specific pages in your website using several methods documented at http://www.activeserverpages.com/learn/authenticate.asp   Here we will demonstrate how to use custom authentication and also cover session and application issues. You can try our authentication example by:

The next page details the source code for all scripts needed to implement our example but here is the list:

securitylogin.asp
securityloginrespond.asp
the login screen where someone can enter username/password and confirm security level. It is a form that submits to  securityloginrespond.asp
securitylogout.asp the screen to abandon someone's username/password and security level
securitylevel1required.asp
securitylevel2required.asp
securitylevel3required.asp
which can be included on individual pages to limit access to people with that security level, i.e/:
<!--#include file="securitylevel1required.asp"-->
securitytestlevel1.asp
securitytestlevel2.asp
securitytestlevel3.asp
which demonstrate how security is implemented. These scripts cannot be seen unless you login.
securitynotallowed.asp which anyone attempting to access a page without appropriate security level is redirected to.
/learn/test/customsecurity.mdb
Download Database
a 3 column Access database: username, password, security level. Sample data is:
user=chaz, password=chaz, securitylevel=1
user=chaz2, password=chaz2, securitylevel=2
user=chaz3, password=chaz3, securitylevel=3

In a production application, this database would be located OUTSIDE of the web structure (and accessed by DSN) so it could never be downloaded by a user.


ASP Quick Lessons written by Charles M. Carroll
http://www.learnasp.com/learn/security2.asp Page 163


security2 from ASP Quick Lessons

Custom Security/Authentication #2

To implement custom security via a database, we use the following scripts that we will present the source code for:

Here is the securitylogin.asp script:

   <html><head>
   <title>securitylogin.asp</title>
   </head><body bgcolor="#FFFFFF">
   <form action="securityloginrespond.asp" method="POST">
   Sign In Page:<p>
   Name -&gt; <input NAME="userName" size="20"><br>
   Password -&gt; <input NAME="userPassword" size="20"><br>
   <input type="submit"><input type="reset">
   </form></body></html>

Here is the securityloginrespond.asp script:

   <html><head>
   <TITLE>securityloginrespond.asp</TITLE>
   </head><body bgcolor="#FFFFFF">
   <%
   myname=request.form("username")
   mypassword=request.form("userpassword")
   set conntemp=server.createobject("adodb.connection")
   
   dbname="/learn/test/secret/customsecurity.mdb"
10   myconnect="PROVIDER=Microsoft.Jet.OLEDB.4.0;DATA SOURCE="
11   myconnect=myconnect & server.mappath(dbname)& ";"
12   
13   conntemp.Open myconnect
14   
15   sqltemp="select * from users where user='"
16   sqltemp=sqltemp & myname & "'"
17   set rstemp=conntemp.execute(SQLTemp)
18   If  rstemp.eof then%>

19      we don't have a user named <%=Myname%> on file!<br>
20      Try <A href='securitylogin.asp'>Logging in</a> again
21      <%response.end
22   end if
23   If  rstemp("Password")=mypassword then
24      session("name")=rstemp("user")
25      session("securitylevel")=rstemp("securitylevel")
26      response.write "Security Level=" & session("securitylevel")
27   else%>

28      Password Unrecognized<br>
29      Try <A href='securitylogin.asp'>Logging in</a> again
30      <%response.end
31   end if
32   rstemp.close
33   conntemp.close
34   set rstemp=nothing
35   set conntemp=nothing
36   %>

37   </body></html>

Here is the securitylogout.asp script:

   <html><head>
   <title>securitylogout.asp</title>&
   <body>
   <%
   session.abandon
   %>

   Logged out Now!!!
   </body>
   </html>

Here is the securitylevel1required.asp script:

   <%
   response.expires=0
   if  session("securitylevel")>0 then
      ' nothing to do   
   else
      response.redirect "securityunauthorized.asp"
   end if
   %>

Here is the securityunauthorized.asp script:

   <html><head>
   <title>unauthorized</title>&
   <body>
   You are unauthorized to read that page!
   </body></html>

Here is the securitytestlevel1.asp script:

   <!--#include file="securitylevel1required.asp"-->
   <html><head>
   <title>New Page </title>
   <META HTTP-EQUIV="Expires" CONTENT="Tue, 04 Dec 1993 21:29:02 GMT">
   </head><body>
   My  level 1 secret is Pretty Hot!!!<br>
   Our president may not be as honest as we believed!
   </body>
   </html>


ASP Quick Lessons written by Charles M. Carroll
http://www.learnasp.com/learn/authenticate3rdparty.asp Page 164


Authentication 3rd Party from ASP Quick Lessons

Authentication -- 3rd Party Method
written and ©1998, 99 by Kevin Flick www.flicks.com creator of Authentix

You won't want to use a third party Basic Authentication filter if

Authentix, a third party Basic Authentication filter is the way to go if

 AuthentiX is a fast, filter based third party tool for IIS authentication developed by Flicks Software (me).
It allows you to protect content directories and individual files by asking for usernames and passwords held separately from the Windows NT usernames and passwords, ensuring the the security of your NT accounts.

Definitions

 How to set up AuthentiX, a third party Basic Authentication filter

Setting up AuthentiX is easy and straighforward.

 Download the free evaluation version, unzip it and run setup.exe. Installshield will guide you through the rest of the installation process.

You can see how to set up ODBC and other advanced options by downloading the online Windows help file or checking out the online Guided Tour. Because the pace of enhancements and improvements to this product sometimes outstrips the documentation, you can find out more by working with the free evaluation download.


ASP Quick Lessons written by Charles M. Carroll
http://www.learnasp.com/learn/aspflicks.asp Page 165


Listserrver Join aspflicksListserver for more info @

http://www.asplists.com/asplists/aspflicks.asp

Related Links:

 

Recommended Books:

Related Lists:

Mobile lists by Asplists @
   http://www.asplists.com/asplists/mobile.asp
Mobile lists by WROX @
   http://p2p.wrox.com/mobile/

Rules:

Mailing List Manners (suggested by Bob Filipiak) @
   http://db.tidbits.com/getbits.acgi?tbser=1141
Ken Shaffer's Advice on Asking For Help... @
   http://www.adopenstatic.com/personal/help.asp


ASP Quick Lessons written by Charles M. Carroll
http://www.learnasp.com/learn/troubles.asp Page 166


Section Contents

Troubleshooting, Error Trapping
        Errors: Basics (errors1.asp) - Page 167
        Errors: More Ways To Trap (errors2.asp) - Page 168
        Errors: Resources Online (errormore.asp) - Page 169
        Errors: Trapping EVERY Error (dbtablewitherrortrap.asp) - Page 170
        Debug variables Easy Way (debug1.asp) - Page 171
        Errors: DB Error Information Trapping (dbtroubleshoot.asp) - Page 172
        DBFAQ: Operation must use Updatable Query (FAQdbUpdate.asp) - Page 173
        DBFAQ: User Entered ' in field (FAQdbSinglequote.asp) - Page 174
        DBFAQ: LIKE operator * not working (FAQdbLIKE.asp) - Page 175
        DBFAQ: retrieving MEMO/BLOBs generates error (FAQdbMEMO.asp) - Page 176
        DBFAQ: Syntax Error in SQL Statement (FAQdbSQLSyntax.asp) - Page 177
        SQL Debugging Made Easy (debug2.asp) - Page 178
        Errors: Trapping Open Connections (dbtroubleshootopen.asp) - Page 179
        Troubleshoot: Getting Help from Lists! (asptroubles.asp) - Page 180
        Troubleshoot: Worldwide (asptroubles2.asp) - Page 181
        Troubleshoot: Specialized (asptroubles3.asp) - Page 182
        Troubleshoot: Version of ASP Sofware (versioncheck.asp) - Page 183
        Troubleshoot: Registered Components (componentchecker.asp) - Page 184
        Troubleshoot: DB Drivers by Christophe Wille (connectioninfo.asp) - Page 185
        PWS: Personal Web Server Introduction (PWS.asp) - Page 186


ASP Quick Lessons written by Charles M. Carroll
http://www.learnasp.com/learn/errors1.asp Page 167


Dictionary objects from ASP Quick Lessons

Error Trapping #1 by Charles Carroll

Now we will demonstrate how to trap VBScript errors that occur in your scripts with code. The script below runs without incident. All the syntax in the script is correct.

   <TITLE>errordivide1.asp</TITLE>
   <body bgcolor="#FFFFFF">
   <%
   ' ASP program that works if numbers are legit
   x=7
   y=2
   z=x/y
   response.write z & "<br>"
   %>

10   </body></html>

Now even though all the syntax in the script is correct, since one of the numbers has the effect of creating a "division by zero" error the script fails.

   <TITLE>errordivide2.asp</TITLE>
   <body bgcolor="#FFFFFF">
   <%
   ' ASP program that works if numbers are legit
   x=7
   y=2 ' if changed to 0 this will crash
   z=x/y
   response.write z & "<br>"
   %>

10   </body></html>

Now we use the VBScript error trapping to present a message instead of a catastrophic script error.

   <TITLE>errordivide3.asp</TITLE>
   <body bgcolor="#FFFFFF">
   <%
   ' ASP program that works if numbers are legit
   on  error resume next
   x=7
   y=0
   z=x/y
   response.write z & "<br>"
10   
11   If  err.number=0 then
12      response.end
13   end if
14   pad="&nbsp;&nbsp;&nbsp;&nbsp;"
15   response.write "<b>VBScript Errors Occured!<br>"
16   response.write parm_msg & "</b><br>"
17   response.write pad & "Error Number= #<b>" & err.number & "</b><br>"
18   response.write pad & "Error Desc.= <b>" & err.description & "</b><br>"
19   response.write pad & "Help Context= <b>" & err.HelpContext & "</b><br>"
20   response.write pad & "Help File Path=<b>" & err.helpfile & "</b><br>"
21   response.write pad & "Error Source= <b>" & err.source & "</b><br><hr>"
22   %>

23   </body></html>


ASP Quick Lessons written by Charles M. Carroll
http://www.learnasp.com/learn/errors2.asp Page 168


Error Trapping #2 from ASP Quick Lessons

Error Trapping #2 by Charles Carroll

Errors can only be caught if your code explicitly traps them. Right?

Actually, there is an undocumented IIS feature where all errors can be logged at the server level without resorting to page level error trapping.

http://www.15seconds.com/Issue/981015.htm
explains this undocumented feature.

/learn/perfcounters.asp
shows how to use a FREE Softwing Component to actually see that logged data remotely from a browser.

In general, their debugging section @
http://www.15seconds.com/focus/Debugging.htm
is useful to read up on many deugging techniques.

People debugging various ASP Errors may find Juan Llibre's knowledge base index at http://www.asptracker.com invaluable!


ASP Quick Lessons written by Charles M. Carroll
http://www.learnasp.com/learn/errormore.asp Page 169


Text File Reading ASP Quick Lessons

Error-Trapping Debugging Resources

Error-trapping and debugging is handled in much more depth at other sites actually. Here they are:

Easy Debugging Tips by Steve Smith
http://www.asptoday.com/articles/19990421.htm

Simple ASP debugging tricks by Steven Schofield
http://www.asptoday.com/articles/19990721.htm

Undocumented Logging Features exist in ASP
http://www.15seconds.com/Issue/981015.htm

IIS5 has central error handling
http://www.asptoday.com/articles/19990308.htm

Writing to the event log
http://www.asptoday.com/articles/19990722.htm

Devising an HTTP debugging method for IIS by Marco Gregorini
http://www.asptoday.com/articles/19990324.htm

Debugging your ASP Scripts By Abd Shomad
http://www.4guysfromrolla.com/webtech/021099-1.shtml

Syntax Errors from Documentation
http://www.learnasp.com/iishelp/debug/sdbug%5F8.htm

Debugging Active Server Objects by Wayne Berry
http://www.15seconds.com/Issue/970316.htm


ASP Quick Lessons written by Charles M. Carroll
http://www.learnasp.com/learn/dbtablewitherrortrap.asp Page 170


Displaying A Table from Query with Error Trapping

Displaying A Table from Query w/Bells & Whistles

Displaying a table take very little code. A veteran will expand the basic code to deal with many errors that a novice will not have encountered until testing their web on a large scale.

   <TITLE>dbtablewitherrortrap.asp</TITLE>
   <body bgcolor="#FFFFFF">
   <!--#include file="lib_errors.asp"-->
   <%
   on  error resume next
   attempt="create connection object"
   set conntemp=server.createobject("adodb.connection")
   Call ErrorVBScriptReport(attempt)
   
10   attempt="opening DSN"
11   conntemp.open "DSN=Student;uid=student;pwd=magic"
12   Call ErrorVBScriptReport(attempt)
13   Call ErrorADOReport(attempt,conntemp)
14   
15   attempt="select * from authors where AU_ID<16"
16   set rstemp=conntemp.execute(attempt)
17   Call ErrorVBScriptReport(attempt)
18   Call ErrorADOReport(attempt,conntemp)
19   If  rstemp.eof then
20      response.write "No records matched your query" & "<P>"
21      response.write attempt
22      response.end
23   end if
24   
25   attempt="counting fields"
26   howmanyfields=rstemp.fields.count -1
27   Call ErrorVBScriptReport(attempt)
28   Call ErrorADOReport(attempt,conntemp)
29   %>

30   <table border=1>
31   <tr>
32   <% 'Put Headings On The Table of Field Names
33   for i=0 to howmanyfields %>

34          <td><b><%=rstemp(i).name %></B></TD>
35   <% next %>
36   </tr>
37   
38   <% ' Now lets grab all the records
39   do  while not rstemp.eof %>

40      <tr>
41      <% for i = 0 to howmanyfields%>
42                <td valign=top><%=rstemp.fields(i)%></td>
43      <% next %>
44      </tr>
45      <%
46      rstemp.movenext
47   loop
48   rstemp.close
49   set rstemp=nothing
50   conntemp.close
51   set conntemp=nothing
52   %>

53   </table>
54   </BODY>
55   </HTML>

The error trapping library looks like this:

   <%
   SUB ErrorVBScriptReport(parm_msg)
      If err.number=0 then
         exit sub
      end if
      pad="&nbsp;&nbsp;&nbsp;&nbsp;"
      response.write "<b>VBScript Errors Occured!<br>"
      response.write parm_msg & "</b><br>"
      response.write pad & "Error Number= #<b>" & err.number & "</b><br>"
10      response.write pad & "Error Desc.= <b>" & err.description & "</b><br>"
11      response.write pad & "Help Context= <b>" & err.HelpContext & "</b><br>"
12      response.write pad & "Help File Path=<b>" & err.helpfile & "</b><br>"
13      response.write pad & "Error Source= <b>" & err.source & "</b><br><hr>"
14   END SUB
15   
16   SUB ErrorADOReport(parm_msg,parm_conn)
17      HowManyErrs=parm_conn.errors.count
18      IF HowManyErrs=0 then
19         exit sub
20      END IF
21      pad="&nbsp;&nbsp;&nbsp;&nbsp;"
22      response.write "<b>ADO Reports these Database Error(s) executing:<br>"
23             response.write SQLstmt & "</b><br>"
24      for counter= 0 to HowManyErrs-1
25         errornum=parm_conn.errors(counter).number
26         errordesc=parm_conn.errors(counter).description
27         response.write pad & "Error#=<b>" & errornum & "</b><br>"
28         response.write pad & "Error description=<b>"
29         response.write errordesc & "</b><p>"
30      next
31   END SUB
32   %>


ASP Quick Lessons written by Charles M. Carroll
http://www.learnasp.com/learn/debug1.asp Page 171


dbtable

Easy Debugging of Variables by Charles Carroll

This page demonstrates how you can print several variables in one step without resorting to:
<%
    response.write "fname=<b>" & fname & "</b><br>"
    response.write "lname=<b>" & lname & "</b><br>"
    response.write "x=<b>" & x & "</b><br>"
    response.write "y=<b>" & y & "</b><br>"
%>

by taking advantage of VB Eval and encapsulating it into a subroutine to do all the work for you.

   <html><head>
   <title>debug1.asp</title>
   </head><body bgcolor="#FFFFFF">
   <%
   fname="Jennifer"
   lname="Jones"
   x=9
   y=7
   Call ShowVars("fname,lname,x,y")
10   %>

11   </body></html>
12   <!--#include file="lib_debug1.asp"-->

The library that does the work:

   <%
   SUB ShowVars(parmVars)
         dim myparameters
         myparameters=SPLIT(parmVars,",")
         parmcount=ubound(myparameters)
         for counter=0 to parmcount
            thisvar=myparameters(counter)
            strexec=thisvar
            strexec=eval(strexec)
10            strall=strall & "<b>" & thisvar & "</b>=" & strexec & "<br>"
11         next
12         response.write strall
13   END SUB
14   %>


ASP Quick Lessons written by Charles M. Carroll
http://www.learnasp.com/learn/dbtroubleshoot.asp Page 172


dbtroubleshoot ASP Quick Lessons

Error Trapping Database Code (by Charles Carroll)

Before you use http://www.asplists.com and send a mail to get your question answered let us take a couple of minutes and try the following and see if it identifies your problem. There are tons of frightening messages that come up like:

Microsoft OLE DB Provider for ODBC Drivers error '80040e07' [Microsoft][ODBC Microsoft Access 97 Driver] Data type mismatch in criteria expression.
/somewhere/something.asp, line 12
Error #-2147217900
Error desc. -> [Microsoft][ODBC SQL Server Driver][SQL Server]Line 1: Incorrect syntax near ','.
Error #-2147217900
Error desc. -> [Microsoft][ODBC Microsoft Access 97 Driver] Syntax error in UPDATE statement.

Here are our guidelines for getting to the heart of the matter. First add some error code to the script to display the messages and bad SQL that causes the problem, for example:

   <html><head>
   <title>dbtroubleshoot.asp</title>&
   <body>
   <!--#include file="lib_errors.asp"-->
   <%
   on  error resume next
   Set Conn = Server.CreateObject("ADODB.Connection")
   conn.open "DSN=student;uid=student;password=magic"
   
10   SQLstmt = "INSERT INTO junk (city,state,zip) VALUES ('Rockville','MD','20849')"
11   Set RS = Conn.Execute(SQLStmt)
12   
13   Call ErrorVBScriptReport("Insert Statement")
14   Call ErrorADOReport(SQLstmt,conn)
15   
16   rs.close
17   set rs=nothing
18   Conn.Close
19   set conn=nothing%>

20   
21   </body></html>

Here is the include file that displays appropriate errors:

   <%
   SUB ErrorVBScriptReport(parm_msg)
      If err.number=0 then
         exit sub
      end if
      pad="&nbsp;&nbsp;&nbsp;&nbsp;"
      response.write "<b>VBScript Errors Occured!<br>"
      response.write parm_msg & "</b><br>"
      response.write pad & "Error Number= #<b>" & err.number & "</b><br>"
10      response.write pad & "Error Desc.= <b>" & err.description & "</b><br>"
11      response.write pad & "Help Context= <b>" & err.HelpContext & "</b><br>"
12      response.write pad & "Help File Path=<b>" & err.helpfile & "</b><br>"
13      response.write pad & "Error Source= <b>" & err.source & "</b><br><hr>"
14   END SUB
15   
16   SUB ErrorADOReport(parm_msg,parm_conn)
17      HowManyErrs=parm_conn.errors.count
18      IF HowManyErrs=0 then
19         exit sub
20      END IF
21      pad="&nbsp;&nbsp;&nbsp;&nbsp;"
22      response.write "<b>ADO Reports these Database Error(s) executing:<br>"
23             response.write SQLstmt & "</b><br>"
24      for counter= 0 to HowManyErrs-1
25         errornum=parm_conn.errors(counter).number
26         errordesc=parm_conn.errors(counter).description
27         response.write pad & "Error#=<b>" & errornum & "</b><br>"
28         response.write pad & "Error description=<b>"
29         response.write errordesc & "</b><p>"
30      next
31   END SUB
32   %>

There is a set of links to Microsoft ADO knowledge base articles @
http://www.asptracker.com/demo/adokb1.asp
which may prove invaluable.


ASP Quick Lessons written by Charles M. Carroll
http://www.learnasp.com/learn/FAQdbUpdate.asp Page 173


ASPDatabase FAQ from www.asplists.com

Database listservers for help!

FAQ #1:Operation must  use an updateable query.
I get this error message when adding or modifying data

Microsoft OLE DB Provider for ODBC Drivers error '80004005'
Database Error: [Microsoft][ODBC Microsoft Access Driver] Operation must use an updateable query.

is a very common error message when updating Access databases. Since Access is file based any attempt to update the database by an ASP script can only modify the Access databases if permissions are established correctly.

Go to the parent directory where the database is stored. Click on the folder permissions and set IUSER_xxxxx to 'change' where xxxxx is the machine name. Make sure the file is also set so the ISUSER_xxxx can change the file.

http://support.microsoft.com/support/kb/articles/Q175/1/68.ASP
shows some other causes besides permissions
.


ASP Quick Lessons written by Charles M. Carroll
http://www.learnasp.com/learn/FAQdbSinglequote.asp Page 174


ASPDatabase FAQ from www.asplists.com

Database listservers for help!

FAQ #2: A user attempted to edit or add data to the database that had a single quote in the name (for example Bill's Fish Shop or O'Reilly). Now the form gives an error when adding or updating.

This is a very common error message when updating or adding to databases. Let us look at 3 SQL statements:

UPDATE customer FIELDS (Name,City,State,Zip) _
    VALUES ('Acme Inc.','Rockville','MD','20849') _
    WHERE custid=20

works fine!

UPDATE customer FIELDS (Name,City,State,Zip) _
    VALUES ('Acme's Store','Rockville','MD','20849') _
    WHERE custid=20

will fail because it the single ' confuses the SQL parser.

UPDATE customer FIELDS (Name,City,State,Zip) _
    VALUES ('Acme''s Store','Rockville','MD','20849') _
    WHERE custid=20
will succeed because it the single ' was entered as '' which satisfies the SQL parser.

UPDATE customer FIELDS (Name,City,State,Zip) _
    VALUES ('Ledos','Pike's Peak','CO','000000') _
    WHERE custid=20

will fail because it the single ' confuses the SQL parser.

UPDATE customer FIELDS (Name,City,State,Zip) _
    VALUES ('Ledos','Pike''s Peak','CO','000000') _
    WHERE custid=20

will succeed because it the single ' was entered as '' which satisfies the SQL parser.

In your code you may be building your SQL statement from variables, i.e.

co=request("company")
cy=request("city")
st=request("state")
id=request("keycust")
mySQL = "UPDATE customer FIELDS ("
mySQL = MySQL & "Name,City,State,Zip) "
mySQL = MySQL & "VALUES ('" & co & "',"
mySQL = MySQL & "'" & cy & "',"
mySQL = MySQL & "'" & st & "',"
mySQL = MySQL & "'" & zip & "'"
mySQL = MySQL & "WHERE keycust=" & id

and this will work fine as long as the user never enter an ' in the data. But to be robust, you should use a built-in function called replace that can find characters in a string and replace them with alternate characters. For example the code above could be replaced with:

co=request("company")
cy=request("city")
st=request("state")
id=request("keycust")
co=replace(co,"'","''")
cy=replace(cy,"'","''")
mySQL = "UPDATE customer FIELDS ("
mySQL = MySQL & "Name,City,State,Zip) "
mySQL = MySQL & "VALUES ('" & co & "',"
mySQL = MySQL & "'" & cy & "',"
mySQL = MySQL & "'" & st & "',"
mySQL = MySQL & "'" & zip & "'"
mySQL = MySQL & "WHERE keycust=" & id

and it would work even if the user input ' in the company or city field because they would be doubled up and acceptable to the SQL parser.

Additional Information:

Check MS knowledgebase article Q178070 (HOWTO : Handle Quotes and Pipes in Concatenated SQL Literals) which suggests all pipe characters be replaced with chr(124)

The article can be found at http://support.microsoft.com/support/kb/articles/q178/0/70.asp


ASP Quick Lessons written by Charles M. Carroll
http://www.learnasp.com/learn/FAQdbLIKE.asp Page 175


ASPDatabase FAQ from www.asplists.com

Database listservers for help!

FAQ #3: I have a query utilizing LIKE that works great in Access but produces an error in ASP.

This is a very common error message when querying databases and the person learned to query in Access. Access uses * for multiple character wildcards and ? for individual character wildcards.

Access ASP/ADO
* %
? _

Let us look at 2 typical Access Query statements:

SELECT * from customer where city LIKE "N*"
works fine in Access!  produces an error in ASP.

SELECT * from customer where city LIKE "N%"
works fine in ASP.

SELECT * from customer where phrase LIKE "N?w"
works fine in Access!  produces an error in ASP.

SELECT * from customer where phrase LIKE "N_w"
works fine in ASP.


ASP Quick Lessons written by Charles M. Carroll
http://www.learnasp.com/learn/FAQdbMEMO.asp Page 176


ASPDatabase FAQ from www.asplists.com

Database listservers for help!

FAQ #4: My memo fields are not working. I get the error message:
Microsoft OLE DB Provider for ODBC Drivers error '8002000
9' or other errors

Let us look at a typical problem Query and the solution:

SELECT * from cargo where city LIKE "New York"
produces errors if the memo fields are retrieved.

(for the sake of this example the memo fields are marked in red
CargoID, CargoName, Comments, Street,  City, State,Zip, ShippingNotes and DueDate)

Memo fields have the following issues

Issue #1: Memo fields may only be reliably fetched once.

If Len(rstemp("comments"))=0 THEN
   ....
END IF %>
the comment was <%=rstemp("comments")%>!

is likely to fail because an attempt to fetch it more than once was made.

memo_comments=rstemp("comments")
If LEN(memo_comments)=0 THEN
   ....
END IF %>
the comment was <%=memo_comments%>!

 

Issue #2: Memo Fields must be listed last in the query.

MEMO/BLOBS must be listed last explictly.

SELECT CargoID,CargoName, Street,City, State,Zip,DueDate,ShippingNotes,Comments
from cargo where city LIKE "New York"
produces no errors since the memo fields are listed last.

Check out http://support.microsoft.com/support/kb/articles/q175/2/39.asp   as well for more details.


ASP Quick Lessons written by Charles M. Carroll
http://www.learnasp.com/learn/FAQdbSQLSyntax.asp Page 177


ASPDatabase FAQ from www.asplists.com

Database listservers for help!

FAQ #5: Syntax Error in Database Statement

90% of the problems submitted to the listserves could be solved by systematically checking your code against these guidelines. If you complete all of these steps, then submit it to the list, but most people will solve their problem without the list!

Step 1: did you write the SQL statement to the browser?

....code...
conn.execute(SQLstuff)
....code...

needs to be converted to:

....code...
response.write SQLstuff
conn.execute(SQLstuff)
....code...

The SQLstatement written to the browser will allow Step 2 and Step 3 to be checked. The code tells you little about the syntax error until you write what the code assembles.

Step 2: Are the field names a problem?

a. Forbidden/cantankerous field names

Do not name a field date. It will create problems.

A query like
select * from employees where date=#1/17/98#
will fail even though it is syntactically correct because date is a forbidden name.

Rename the field, so the query could look like
"select * from employees where hiredate=#1/17/98#
and you are "out of the woods"

b. Field names with spaces

A field name that has embedded spaces will create problems if you don't surround it with square brackets when referencing it in the query.

A query like
select * from employees where state of residence='MD'
will fail even though it is syntactically correct because state of residence is a field with spaces in the name.

A query like
select * from employees where [state of residence]='MD'
will succeed because the fieldname is delimited properly.

Step 3: Check for these common Syntax Errors?

a. Text Fields get surrounded by  ' ' and numeric fields do not!

A query like:
select * from employees where city=Rockville and State=MD and yearsresiding>9
will fail because the text fields were not delimited properly.

A query like:
select * from employees where city='Rockville' and State='MD' and yearsresiding>9
succeeds.

b. Date fields get surrounded by  # #

A query like:
select * from employees where birthdate>1/1/1966
will fail because the date fields were not delimited properly.

A query like:
select * from employees where birthdate>#1/1/1966#
succeeds.


ASP Quick Lessons written by Charles M. Carroll
http://www.learnasp.com/learn/debug2.asp Page 178


dbtable

Debug SQL Easily by Charles Carroll

This page demonstrates how you can format a SQL statement to help pinpoint common errors. Common errors are discussed @

Common SQL Errors
http://www.learnasp.com/learn/dbtroubleshoot2.asp

Syntax Error in SQL Statement
http://www.learnasp.com/learn/FAQdbSQLSyntax.asp

by encapsulating ADO error trapping and display the SQL in an attractive form that separates components onto separate lines and makes debugging simpler (missing commas, single-quotes and like).

   <html><head>
   <title>debug2.asp</title>
   </head><body bgcolor="#FFFFFF">
   <%
   on   error resume next
   myDSN = "DSN=Student;uid=student;pwd=magic"
   Set Conn = Server.CreateObject("ADODB.Connection")
   conn.open myDSN
   
10   SQL="update test set fname='Ted',lname='Wilson',city='Rockville',state='MD',zip='20849',rank=7,datehire='1/15/92', SSN='219-92-2677' WHERE personid=7"
11   Conn.Execute SQL,howmany
12   IF  howmany="" THEN
13      howmany=0
14   END IF
15   response.write "Affected <b>" & howmany & "</b> records<br>"
16   Call SQLerrorreport(SQL,conn)
17   
18   SQL="Insert Into junk (fname,lname,city,state,zip,rank,datehire,ssn) VALUES ('ted','wilson','rockville', 'md', '20849',7,'1/15/92','219-92-2677')"
19   Conn.Execute SQL,howmany
20   IF  howmany="" THEN
21      howmany=0
22   END IF
23   response.write "Affected <b>" & howmany & "</b> records</b><br>"
24   Call SQLerrorreport(SQL,conn)
25   
26   Conn.Close
27   set conn=nothing
28   %>

29   </body></html>
30   <!--#include file="lib_debug2.asp"-->

The library that does the work:

   <%
   SUB SQLErrorReport(parmSQL,parm_conn)
      HowManyErrs=parm_conn.errors.count
      IF HowManyErrs=0 then
         exit sub
      END IF
      pad="&nbsp;&nbsp;&nbsp;&nbsp;"
      lb="<br>" & vbcrlf
      comma="<font color=red>"
10      squote="<font color=blue>"
11      SQLstmt=parmSQL
12      SQLstmt=replace(SQLstmt,",", "<b>" & comma & ",</b></font>" & lb)
13      SQLstmt=replace(SQLstmt,"'","<b>" & squote & "'</b></font>")
14      SQLstmt=replace(SQLstmt,"(",lb & "(")
15      SQLstmt=replace(SQLstmt,")",")" & lb)
16   
17            response.write "SQL statement attempted:<br>"
18            response.write SQLstmt & "<br>"
19      response.write "ADO Error(s) executing:<br>"
20      for counter= 0 to HowManyErrs-1
21         errornum=parm_conn.errors(counter).number
22         errordesc=parm_conn.errors(counter).description
23         response.write pad & "Error#=<b>" & errornum & "</b><br>"
24         response.write pad & "Error description=<b>"
25         response.write errordesc & "</b><p>"
26      next
27   END SUB
28   %>


ASP Quick Lessons written by Charles M. Carroll
http://www.learnasp.com/learn/dbtroubleshootopen.asp Page 179


dbtroubleshoot ASP Quick Lessons

Database Error Trapping: Opening Database
by Charles Carroll

Many people want to intercept specific errors and replace them with friendly messages. Here is some sample code that catches mispelled DSNs and bad login/user ids:

   <html><head>
   <title>dbtroubleshoot.asp</title>&
   <body>
   <%
   on  error resume next
   Set Conn = Server.CreateObject("ADODB.Connection")
   my_DSN="DSN=student;uid=student;password=magic2"
   conn.open my_DSN
   Call CheckOpen
10   
11   Conn.Close
12   set conn=nothing
13   
14   SUB CheckOpen
15      If err.number>0 then%>

16       <b>VBScript Errors Occured:</b><br>
17       Error Number=<%=err.number%><br>
18       Error Descr.=<%=err.description%><br>
19       Help Context=<%=err.helpcontext%><br>
20       Help Path=<%=err.helppath%><br>
21       Native Error=<%=err.nativeerror%><br>
22       Source=<%=err.source%><br>
23       SQLState=<%=err.sqlstate%><P>
24      <%else%>
25         No VBScript problems occured!<p>
26      <%end if
27      IF conn.errors.count> 0 then%>

28          <b>ADO Reports these Database Error(s):</b><br>
29          <%
30          maxerrors=conn.errors.count-1
31          for counter= 0 to maxerrors
32                DBErrorNum=conn.errors(counter).number
33               DBErrorDesc=conn.errors(counter).description
34               SELECT CASE DBErrorNum
35                  CASE -2147467259
36                     response.write "Problem => <b>Bad DSN</b><br>"
37                     response.write "DSN => <b>" & my_DSN & "</b><br>"
38                  CASE -2147217843
39                     response.write "Problem => <b>Bad Login Info</b><br>"
40                     response.write "DSN => <b>" & my_DSN & "</b><br>"
41                     exit sub
42                  CASE ELSE%>

43                     Error # = <b><%=DBErrorNum%></b><br>
44                     Error description = <b><%=DBerrorDesc%></b><p>
45                  <%END SELECT
46          next
47      else%>

48         Everything Went Fine
49      <%
50      end if
51      
52   END SUB%>

53   </body></html>


ASP Quick Lessons written by Charles M. Carroll
http://www.learnasp.com/learn/asptroubles.asp Page 180


ASP Troubleshooting Resources from ASP Quick Lessons

ASP  Troubleshooting Resources Part1

When your Active Server Page code does not work, we actually manage a listserv you can write to send in your code and have your colleagues from around the world on the listserv help you fix it. Warning: One of listservers -- [aspfreeforall] -- is quite noisy (40-50 messages a day) with many people helping each other.

People having trouble with ASP code communicating with a specific database should try their questions on one of these lists:

ALL Oracle Lists
ALL RDS (Remote Data Services) Lists
ALL SQL Server Lists
[aspngdata] ASP+/ADO+, Templates, Lists, Repeaters
[aspsqlhowto] SQL: Joins, complex queries, shaping
[aspAccess] MS-Access
[aspAcc2SQL] MS-Access to SQLserver migration
[aspAcc2SQL] Tough ASP + MS-Access Questions only
[aspBtrieve] Btrieve and ASP
[aspCOMTICICS] COMTI and CICS w/ASP
[aspDB2as400] DB2 and/or AS400
[aspDbase] Dbase
[aspFileMaker] FileMaker & ASP
[aspFox] Fox/Visual FoxPro
[aspGenericdb] FREE code to display/edit data
[aspInformix] Informix
[aspMSDE] Asp with free MSDE Engine
[aspmySQL] MySQL and ASP
[aspParadox] Paradox
[aspreports] Reports/Printing (Crystal, PDF, etc.)
[aspSAP] SAP + ASP can mix
[aspSybase] Sybase

People having trouble with ASP and does not have code communicating with a specific database can sign up for one of our general listservers

[aspfreeforall] ANY questions
[aspnotnewbie] NO beginners
[aspadvanced] ONLY toughest questions
note- Strict Rules for advanced lists
[aspinstall] Installing,Upgrading PWS & ASP


ASP Quick Lessons written by Charles M. Carroll
http://www.learnasp.com/learn/asptroubles2.asp Page 181


ASP Troubleshooting Resources from ASP Quick Lessons

ASP  Troubleshooting Resources (Worldwide)

When your Active Server Page code does not work, we actually manage many listserves that provide help and are run entirely in non-English languages. You can write to send in your code and have your colleagues from around the world on the listserv help you fix it in your native language.

[aspArabic]
[aspBengali]
[aspChinese]
[aspDanish]
[aspDutch]
[aspFarsi]
[aspFinnish]
[aspFrench]
[aspGerman] German ASP Help
[aspdeJobs] German Jobs
[aspdecoffeehouse] German Coffee House
[aspdebeginners] German ASP Beginners
[aspdedatabase] German ASP Databases
[aspdeadministration] German ASP Server Admin
[aspdeDOTNET] German ASP+ / DOT NET
[aspDEXML] German ASP XML
[aspgreek] Greek
[asphebrew] Hebrew
[aspHindi] Hindi
[aspIndonesian] Indonesian
[aspIcelandic]
[aspItalian]
[aspJapanese]
[aspKorean]
[aspMalay]
[aspNepali]
[aspNorweigan]
[aspPolish]
[aspPortugese]
[aspRussian]
[aspSpanish]
[aspSwedish]
[aspSwedishAdvanced]
[aspTamil]
[aspTurkish]
[aspThai]
[aspUrdu]


ASP Quick Lessons written by Charles M. Carroll
http://www.learnasp.com/learn/asptroubles3.asp Page 182


ASP Troubleshooting Resources from www.asplists.com

ASP Troubleshooting Resources Part 3

Sometimes your problem is tough and requires multiple mails to resolve and the answers becomes quite complex and/or obscure. Such problems don't get solved well on general lists like [aspfreeforall] or [aspdatabases]. However, we have some lists where specialized topics thrive. All the best people hang out there, the archives are devoid of general questions, game is plentiful, and the sun shines and nary a cloud appears. Here is a master list of all the specialized listserves we run. They will NOT FLOOD YOUR MAILBOX since the topic scope is so narrow.

ASP Troubleshooting Resources from www.asplists.com

Beginners to Intermediate Lists

article.gif (248 bytes) ASPFreeForAll [aspfreeforall]
The worlds noisiest and helpful ASP list -- 20-40 posts per day and any questions are allowed. It is the only unmoderated list we run.

signup form at
http://www.activeserverpages.com/aspfreeforall

article.gif (248 bytes) ASPDatabaseFreeForAll [aspfreeforall]
Noisy, but an ideal place for database beginners. 1/2 the noise of [aspfreeforall] since only database questions are allowed.

signup form at
http://www.activeserverpages.com/aspdatabasefreeforall

article.gif (248 bytes) ADSI [aspadsi]
beginners and all level of ADSI questions welcomed here.

signup form at
http://www.activeserverpages.com/aspadsi

article.gif (248 bytes) Ecommerce w/ASP [ecommerce]
This list is to discuss credit cards, HTTPS://, shopping carts and the ASP topics that intersect with commerce. Non-commerce questions will be rejected.
signup form at http://www.activeserverpages.com/aspcommerce

article.gif (248 bytes)Index Server [aspindexserver]
Index Server only. No ASP general scripting questions allowed!
signup form at http://www.activeserverpages.com/aspindexserver

article.gif (248 bytes) International/Multilingual ASP [aspinternational]
This list is to discuss multilingual websites (including multi-byte character sets, FEPs, translation services, etc.) and non-English ASP issues, secure and international encryption issues, etc.  Questions that don't deal with international or multilingual issues will be rejected.
signup form at http://www.activeserverpages.com/aspinternational

article.gif (248 bytes) Jscript ASP [jscript]
This list is to discuss server Jscript and client Jscript occasionally. Frames would not be out of the question here, as all the "right" type of people are there to answer.
signup form at http://www.activeserverpages.com/aspjscript

article.gif (248 bytes) PerlScript w/ASP [aspPerlscript]
This list is to discuss Perlscript only.
signup form at http://www.activeserverpages.com/aspPerlscript

article.gif (248 bytes) ASP Site Server [aspsiteserver]
This list is to discuss Site Server issues only. General ASP questions will be rejected.
signup form at http://www.activeserverpages.com/aspsiteserver

Component Building (including MTX, MSMQ)

article.gif (248 bytes) Visual Basic ASP component building [vbcomponents]
This list is to discuss Visual Basic component building only. Of course MTX and MSMQ with components is right on topic too. General ASP scripting questions will be rejected here.
signup form at http://www.activeserverpages.com/aspvbcomponents

article.gif (248 bytes) Delphi ASP component building [aspDelphi]
This list is to discuss Delphi component building only. Of course MTX and MSMQ with components is right on topic too. General ASP scripting questions will be rejected here.
signup form at http://www.activeserverpages.com/aspdelphi

article.gif (248 bytes) C++ low-level component building [low-levelcomponents]
This list is to discuss C++ component building only. Of course MTX and MSMQ with components is right on topic too. General ASP scripting questions will be rejected here.
signup form at http://www.activeserverpages.com/asplowlevelcomponents

article.gif (248 bytes) VB WebClasses [aspvbwebclasses]
This list is to discuss IIS webclasses only. These are specific types of VB6 apps that are optimized to work with ASP. General scripting questions not allowed.
signup form at http://www.activeserverpages.com/aspvbwebclasses

Databases

article.gif (248 bytes) ASP SQL How-To [aspSQLhowto]
This list is to discuss complex joins, complex queries, and how to do certain complex tasks involving SQL. It is not a troubleshooting list and broken code questions and questions that are newbie in nature are always rejected.
signup form at http://www.activeserverpages.com/aspsqlhowto

article.gif (248 bytes) ASP Databases [aspdatabases]
This list is to discuss database troubleshooting but is not a beginner's lists. Many beginners questions ( ' questions, permissions, how do I edit a database) will be rejected as to not distract from the tough issues being discussed.
signup form at http://www.activeserverpages.com/aspdatabases

article.gif (248 bytes) ASP Reporting from Databases [aspreporting]
This list is to discuss reports with tools like PDF, Crystal Reports, Chilisoft Reports, etc.
No database questions or ASP questions will be allowed if reports are not part of the topic.
signup form at http://www.activeserverpages.com/aspreporting

article.gif (248 bytes) ASP RDS (Remote Data Services) [aspRDS]
This list is to discuss Remote Data Service and how they can be integrated into ASP sites.
signup form at http://www.activeserverpages.com/asprds

Databases/Vendor Specific

article.gif (248 bytes)DB2AS400 [aspdb2as400]
Only to discuss drivers, stored procedures, SQL variations, and vendor specific issues concerning ASP pages and components communication with IBM DB2/AS400 databases.
signup form at http://www.activeserverpages.com/aspdb2as400

article.gif (248 bytes)Informix [aspinformix]
Only to discuss drivers, stored procedures,  SQL variations, and vendor specific issues concerning ASP pages and components communication with Informix databases.
signup form at http://www.activeserverpages.com/aspinformix

article.gif (248 bytes) Oracle [asporacle]
Only to discuss drivers, stored procedures,  SQL variations, and vendor specific issues concerning ASP pages and components communication with Oracle databases.
signup form at http://www.activeserverpages.com/asporacle

article.gif (248 bytes) Sybase [aspsybase]
Only to discuss drivers, stored procedures,  SQL variations, and vendor specific issues concerning ASP pages and components communication with Sybase databases.
signup form at http://www.activeserverpages.com/aspsybase

article.gif (248 bytes) SQLserver7 [aspsqlserver7]
Only to discuss drivers, stored procedures,  SQL variations, and vendor specific issues concerning ASP pages and components communication with SQLServer 7 databases.
signup form at http://www.activeserverpages.com/aspsqlserver7

Editors

article.gif (248 bytes) ASP with Visual Interdev [aspvisualinterdev]
This list is to discuss Visual Interdev editor issues only. As long as you are editing your code with Interdev, this is the list for you!
signup form at http://www.activeserverpages.com/aspvisualinterdev

article.gif (248 bytes) ASP with Drumbeat/Drumbeat 2000 [aspDrumbeat]
This list is to discuss Drumbeat issues only. As long as you are editing your code with Drumbeat, this is the list for you!
signup form at http://www.activeserverpages.com/aspdrumbeat

article.gif (248 bytes) ASP with NetObjects Fusion [aspnetobjects]
This list is to discuss Netobject editor issues only. As long as you are editing your code with Netobjects, this is the list for you!
signup form at http://www.activeserverpages.com/aspnetobjects

Non-Technical Lists

article.gif (248 bytes) ASP Jobs [jobs/consult]
This list is to post jobs, or indicate your availablity for jobs. Consulting assignments, full time jobs and resumes are the only topics allowed here; no how-to allowed.
signup form at http://www.activeserverpages.com/aspjobs

article.gif (248 bytes) ASP Gripes [aspgripe]
This list is for readers to complain about ASP products they bought and were unhappy with to share their experiences!
signup form at http://www.activeserverpages.com/aspgripe

article.gif (248 bytes) ASP Convention [aspconvention]
This list is to discuss the many www.aspconvention.com events that occur throughout the year.
signup form at http://www.activeserverpages.com/aspconvention

article.gif (248 bytes) ASP Training [asptraining]
This list is to discuss people who need training and companies who offer training can post their classes here too and interact with potential customers.
signup form at http://www.activeserverpages.com/asptraining

article.gif (248 bytes) Free Code & Components [aspfreecodecomponents]
This list is to offer FREE code and components. No how-to allowed, just send the list the FREE code or component URLs you are giving away.
signup form at http://www.activeserverpages.com/aspfreecodecomponents

Server Admin

article.gif (248 bytes) Crashed/Hung Servers [aspcrash]
Only crashes and hung servers and mysterious error messages are discussed here. No scripting how-to or server admin allowed.
signup form at http://www.activeserverpages.com/aspcrash

article.gif (248 bytes) Installing ASP [aspinstall]
Only installs, service pack upgradees are allowed here. No scripting how-to allowed.
signup form at http://www.activeserverpages.com/aspinstall

article.gif (248 bytes) Server Admin [aspserver]
This list is to discuss IIS, NT, and MMC from a network administrators standpoint as they work with ASP coders.
signup form at http://www.activeserverpages.com/aspserver

3rd Party Products

article.gif (248 bytes) ASPDB Product Support [aspdbmajormicro]
This list is to discuss using the ASPDB component. General ASP questions not allowed.
signup form at http://www.activeserverpages.com/aspdbmajormicro

article.gif (248 bytes) ServerObjects.com Support [aspserverobjectscom]
This list is to discuss using components from www.serverobjects.com on your site. General ASP questions not allowed.
signup form at http://www.activeserverpages.com/aspserverobjectscom

article.gif (248 bytes) SoftArtisans Product Support [aspsoftartisans]
This list is to discuss using components made by www.softartisans.com. General ASP questions not allowed.
signup form at http://www.activeserverpages.com/aspsoftartisans

article.gif (248 bytes) WROX Readers Support [aspwroxreaders]
This list is to discuss questions and coding issues arising from reading books published by WROX -- i.e. the code in Chapter 13 has this problem etc. If your question didn't originate because of code in a WROX book it will be rejected.
signup form at http://www.activeserverpages.com/aspwroxreaders

Technology Specific

article.gif (248 bytes) LDAP [aspldap]
Communicating with LDAP stores by any mechanism (whether using ADSI, APIs, etc.) is the only topic allowed in this list.
signup form at http://www.activeserverpages.com/aspLDAP

article.gif (248 bytes) Lotus Notes [asplotusnotes]
signup form at http://www.activeserverpages.com/asplotusnotes

article.gif (248 bytes) MAIL from ASP: Outlook, Exchange, CDO, 3rd Party [aspmail]
only getting mail out of ASP pages and interface to mail and appointment stores are discussed here.

signup form at
http://www.activeserverpages.com/aspmail

article.gif (248 bytes) MSOffice and ASP [aspmsoffice]
automating Word,Excel,Powerpoint, Project with ASP is the only topic here.
signup form at http://www.activeserverpages.com/aspmsoffice

Advanced Listserves

article.gif (248 bytes) ASP FastCode [aspFastCode]
This list is to discuss speeding up code. Broken code or how-to is not the topic. Basically your code must work, but you want to make it faster.
signup form at http://www.activeserverpages.com/aspfastcode

article.gif (248 bytes) ASP NotNewbie [aspnotnewbie]
This list is for people who don't want to be on a beginners list but are not super-advanced yet. Beginners posts will be rejected always.
signup form at http://www.activeserverpages.com/aspnotnewbie

article.gif (248 bytes) ASP Advanced ADSI [aspadvadsi]
This list is to discuss the ADSI issues no other list has  resolved after much research.
signup form at http://www.activeserverpages.com/aspadvadsi


ASP Quick Lessons written by Charles M. Carroll
http://www.learnasp.com/learn/versioncheck.asp Page 183


Server Variables from ASP Quick Lessons

Version Check by Charles Carroll DRAFT

This checks what software you are using on your server.
   <%@ language=vbscript%>
   <HTML>
   <HEAD>
   <TITLE>versioncheck.asp</TITLE>
   </HEAD>
   <body bgcolor="#FFFFFF">
   <script language=jscript runat=server>
   response.write ("scripting engine=<b>" + ScriptEngine() + "</b><br>");
   response.write ("buildversion=<b>" + ScriptEngineBuildVersion() + "</b><br>");
10   response.write ("majorversion=<b>" + ScriptEngineMajorVersion() + "</b><br>");
11   response.write ("minorversion=<b>" + ScriptEngineMinorVersion() + "</b><br>");
12   </script>
13   
14   <%
15   response.write "<hr><br>"
16   response.write "scripting engine=<b>" & scriptengine() & "</b><br>"
17   response.write "buildversion=<b>" & scriptenginebuildversion() & "</b><br>"
18   response.write "majorversion=<b>" & scriptenginemajorversion() & "</b><br>"
19   response.write "minorversion=<b>" & scriptengineminorversion() & "</b><br>"
20   
21   response.write "<hr><br>"
22   set tempconn=server.createobject("adodb.connection")
23   response.write "ado version=<b>"
24   response.write tempconn.version & "</b><br>"
25   set tempconn=nothing
26   
27   response.write "<hr><br>"
28   serversoftware=request.servervariables("server_software")
29   response.write "server software=<b>"
30   response.write serversoftware & "</b><br>"
31   
32   Response.Write "Script Timeout = <b>" & Server.ScriptTimeout & " seconds</b><br>"
33   Response.Write "Session Timeout = <b>" & Session.Timeout & " minutes</b><br>"
34   %>

35   
36   </BODY></HTML>


ASP Quick Lessons written by Charles M. Carroll
http://www.learnasp.com/learn/componentchecker.asp Page 184


Component Checker from ASP Quick Lessons

Component Checker by Charles Carroll
determine what components are on your server

The script reads the component.ini file we created and reports whether each of the components in that file can be created.

   <%response.buffer=true%>
   <TITLE>componentchecker.asp</TITLE>
   <body bgcolor="#FFFFFF">
   <%
   dim successSTR, FailSTR, checkSTR
   whichfile=server.mappath("component.ini")
   Set fs = CreateObject("Scripting.FileSystemObject")
   Set thisfile = fs.OpenTextFile(whichfile, 1, False)
   
10   counter=0
11   
12   do  UNTIL thisfile.AtEndOfStream
13      counter=counter+1
14      thisline=thisfile.readline
15         attempt=trim(thisline)
16      pad="&nbsp;&nbsp;&nbsp;&nbsp;"
17      DO WHILE attempt="" AND thisfile.atendofStream=false
18         thisline=thisfile.readline
19          attempt=trim(thisline)
20      LOOP
21      If mid(thisline,1,1)="[" then
22         ' ignore
23         CheckSTR=CheckSTR & thisline & " "
24         lastcategory=category
25         category=lcase(thisline)
26         oldcategory=mid(category,1,Len(category)-1)   
27         category=replace(category,"www.","<a href='http://www.")
28         IF instr(category,"href")>0 then
29            category=mid(category,2)
30            category=category & "'>" & oldcategory & "]</a>"
31         END IF
32         group= "<b>" & category & " component group</b><br>"
33         successcount=0
34         failcount=0
35         thisline=thisfile.readline
36         attempt=thisline
37         response.flush
38      end if
39      on error resume next
40      set tempobject=server.createobject(attempt)
41      eol="<br>" & vbcrlf
42      whicherr=err.number
43      If whicherr=0 then
44         if successcount=0 then
45            successSTR=successSTR & group
46         end if
47         vleft="&nbsp;(ver="
48         vright=")&nbsp;"
49         SELECT CASE lcase(attempt)
50            CASE "adodb.connection"
51               version= vleft & tempobject.version & vright
52            CASE ELSE
53               version=""
54         END SELECT
55   
56         successSTR= successSTR & pad & "<b>" & attempt & version & "</b> successfull!" & eol
57         successcount=successcount+1
58      else
59         if failcount=0 then
60            FailSTR=FailSTR & group
61         end if
62         IF whicherr=-2147221005 THEN
63            msg = " is not registered!"
64         ELSE
65            msg = " failed. Error #" & whicherr
66         END IF
67         FailSTR= failSTR & pad & "<b>" & attempt & "</b>" & msg & eol
68         failcount=failcount+1
69      end if
70      set tempobject=nothing
71   loop
72   
73   thisfile.Close
74   set thisfile=nothing
75   set fs=nothing
76   
77   response.write "Checked: " & checkSTR & "<hr>"
78   response.write successSTR & "<hr>"
79   response.write failSTR
80   %>

This component.ini file contains a list of typical server components, grouped by type. Type is indicated within [ ] codes. Here is the contents of the current component.ini:

   [standard]
   mswc.browsertype
   mswc.nextlink
   scripting.dictionary
   scripting.filesystemobject
   
   [ado]
   adodb.recordset
   adodb.connection
10   adodb.command
11   
12   [cdo]
13   CDONTS.NewMail
14   
15   [cyscape]
16   cyScape.browserObj
17   
18   [indexserver]
19   ixsso.Query
20   ixsso.Util
21   
22   [Lyris]
23   Lyris.LCP
24   
25   [http://msdn.microsoft.com/scripting]
26   Wscript.Shell
27   
28   [msfreebies]
29   iissample.asp2htm
30   iissample.contentrotator
31   iissample.registry
32   iissample.summaryinfos
33   iissample.tracer
34   mswc.adrotator
35   mswc.counters
36   mswc.myinfo
37   MSWC.PageCounter
38   MSWC.PermissionChecker
39   mswc.tools
40   mswc.loadbalance
41   
42   [msXML]
43   microsoft.XMLHTTP
44   microsoft.XMLDOM
45   
46   [www.aspdb.com]
47   ASPdb.Free
48   ASPdb.View
49   ASPdb.Pro
50   ASPdb.EP
51   
52   [www.serverobjects.com]
53   ASPChart.Chart
54   AspConv.Expert
55   AspDNS.Lookup
56   AspFile.FileObj
57   AspHTTP.Conn
58   AspImage.Image
59   AspInet.FTP
60   AspMX.Lookup
61   AspNNTP.Conn
62   AspPager.Pager
63   SMTPsvg.Mailer
64   
65   [www.softartisans.com]
66   SoftArtisans.FileUp
67   SoftArtisans.SACheck
68   SoftArtisans.SASessionPro
69   SoftArtisans.FileManager
70   EZsite.Calender
71   EZsite.CalendarManager
72   EZsite.WebNotes
73   
74   [www.active4.com]
75   ActiveLaunch.Control
76   ActiveSAR.SearchAndReplace
77   ActiveShopper.Cart
78   ActiveShopper.BasketItem
79   FileTouch.Control
80   PCAuthX.Authorizer
81   Prt2Disk.Control
82   SemClient.Control
83   SPrinterPro.Object
84   TimeSpan.Control
85   WWWPrint.Client
86   
87   [Zaks Software]
88   ZaksPop3.Server
89   JavaPop3.Mailer
90   
91   [www.persits.com]
92   Persits.MailSender
93   
94   [www.oceantek.com]
95   ASPL.Login
96   
97   [www.able-consulting.com]
98   ACI.WhoIs
99   
100   [www.softwing.com]
101   Softwing.EventLogReader
102   Softwing.OdbcRegTool
103   w3info.w3info.1
104   InetCtls.Inet.1
105   Softwing.AspQPerfCounters
106   SQLOLE.SQLServer
107   SOFTWING.ASPEventlog
108   SOFTWING.ASPtear
109   SOFTWING.EDConverter
110   SOFTWING.EventLogReader
111   SOFTWING.FileCache.1
112   SOFTWING.OdbcRegTool
113   SOFTWING.LocaleFormatter
114   SOFTWING.Profiler
115   
116   [www.dougdean.com]
117   EZsite.EZuploadLite
118   
119   [www.algonet.se/~jekman]
120   lightcom.xBrowser
121   lightcom.xContent
122   lightcom.xPop3
123   lightcom.xSMTP
124   lightcom.xTree
125   lightcom.xBrowser
126   JESoftware.xContent
127   JESoftware.xPop3
128   JESoftware.xSMTP
129   JESoftware.xTree
130   
131   [tech.dimac.net]
132   Socket.TCP
133   
134   [www.de-info.com]
135   checkemail.maccheckemail
136   
137   [www.pstruh.cz]
138   TCPIP.Trace
139   TCPIP.DNS
140   
141   [www.dana-net.com/products/aspcomponents/magicregistry]
142   MagicRegistry.Tricks


ASP Quick Lessons written by Charles M. Carroll
http://www.learnasp.com/learn/connectioninfo.asp Page 185


Connection Info by Christophe Wille

Connection Info by Christophe Wille
Christoph.Wille@softwing.com  http://www.softwing.com/iisdev

If you want to know what drivers and other vital details are being used for a DSN, here is some code to the rescue.

   <html><head>
   <title>connectioninfo.asp by Christophe Wille http://www.softwing.com</title>
   </head>
   <!--#include file="lib_connectioninfo.asp"-->
   <body>
   <%
   response.write "<hr>SQL Server Connection"
   Call DSNinfo("DSN=student;uid=student;pwd=magic")
   response.write "<hr>Access Connection Connection"
10   theDSN="DRIVER={Microsoft Access Driver (*.mdb)};DBQ="
11   theDSN=theDSN & server.mappath("/learn/test/biblio.mdb")
12   Call DSNInfo(theDSN)
13   %>

14   </body>
15   </html>

The Include file looks like this:

   <%
   SUB DSNInfo(strDSN)
   Set cnn1 = Server.CreateObject("ADODB.Connection")
   Set rsQuery = Server.CreateObject("ADODB.RecordSet")
   cnn1.open strDSN
   
   response.write "ADO Version: " & cnn1.Version
   response.write "<BR>" & vbcrlf
   response.write strVersionInfo & "DBMS Name: " & cnn1.Properties("DBMS Name")
10   response.write "<BR>" & vbcrlf
11   response.write "DBMS Version: " & cnn1.Properties("DBMS Version")
12   response.write "<BR>" & vbcrlf
13   response.write "OLE DB Version: " & cnn1.Properties("OLE DB Version")
14   response.write "<BR>" & vbcrlf
15   response.write "Provider Name: " & cnn1.Properties("Provider Name")
16   response.write "<BR>" & vbcrlf
17   response.write "Provider Version: " & cnn1.Properties("Provider Version")
18   response.write "<BR>" & vbcrlf
19   response.write "Provider Friendly Name: " & cnn1.Properties("Provider Friendly Name")
20   response.write "<BR>" & vbcrlf
21   
22   If  0 = Instr(LCase(cnn1.Properties("Provider Name")),"oledb") then
23      ' ### no OLE DB Provider used, therefore :
24      response.write "Driver Name: " & cnn1.Properties("Driver Name")
25          response.write "<BR>" & vbcrlf
26      response.write "Driver Version: " & cnn1.Properties("Driver Version")
27          response.write "<BR>" & vbcrlf
28      response.write "Driver ODBC Version: " & cnn1.Properties("Driver ODBC Version")
29      response.write "<BR><BR>"
30   end if
31   
32   Set rsQuery = nothing
33   Set cnn1 = nothing
34   
35   
36   END SUB
37   %>


ASP Quick Lessons written by Charles M. Carroll
http://www.learnasp.com/learn/PWS.asp Page 186


Personal Web Server from ASP Quick Lessons

Personal Web Server (PWS) by Charles Carroll

The Personal Web Server is a marvellous tool because it lets you develop and test websites

The address of your personal web server is:

http://127.0.0.1

It has other aliases, like http://localhost but it true reliable name is the one above.


ASP Quick Lessons written by Charles M. Carroll
http://www.learnasp.com/learn/qualitycode.asp Page 187


Section Contents

Code w/all ASP Features. Quality, Re-usable Code
        Strings: Core Functions (strings.asp) - Page 188
        Strings: SPLIT Function (stringsplit.asp) - Page 189
        Strings: REPLACE Function (stringreplace.asp) - Page 190
        Strings: JOIN Function (stringjoin.asp) - Page 191
        Arrays: Basics (arrays.asp) - Page 192
        Arrays: Variable Size (arrays2.asp) - Page 193
        Arrays: Best Way To Load (arrays3.asp) - Page 194
        Arrays: Resources Online (arraysmore.asp) - Page 195
        Dictionary Objects (dictionary.asp) - Page 196
        Getrows Ultimate! (getrowsultimate.asp) - Page 197
        Subroutine: Working with Dates #1 (subdates.asp) - Page 198
        Subroutine: Working with Dates #2 (subdates2.asp) - Page 199
        Subroutine: Query2Table (subdbtable.asp) - Page 200
        Subroutine: Query2List (subdblist.asp) - Page 201
        Subroutine: Highly Reusable (subreusable.asp) - Page 202
        Subroutines w/Dictionary Objects (subdictionary.asp) - Page 203
        Getrows Ultimate! (getrowsultimate.asp) - Page 204
        Subroutine: List Box w/optional params (subDBlistbest.asp) - Page 205
        Subroutine: Abstract HTML by Phil Paxton (libhtml.asp) - Page 206
        Function: Working Days (functionworkingdays.asp) - Page 207
        New Features in VBScript version5 (vbs5.asp) - Page 208
        Text Files: Reading Them off Server (txtread.asp) - Page 209
        Text Files: Writing Them on Server (txtwrite.asp) - Page 210
        Text Files: Meyers-Briggs parsing #1 (mb1.asp) - Page 211
        Text Files: Meyers-Briggs parsing #2 (mb2.asp) - Page 212
        Text Files: Meyers-Briggs parsing #3 (mb3.asp) - Page 213
        XML/XLST Myers-Briggs example (xmlmb.asp) - Page 214
        Content Linker: Prev/Next Page (cl.asp) - Page 215
        Content Linker: Table of Contents (cl2.asp) - Page 216
        Content Linker: Listbox of contents (cl3.asp) - Page 217
        Content Linker Library (contentlinker.asp) - Page 218
        File Objects: Read Directory (fileobjects.asp) - Page 219
        File Objects: Display Directory as Links/Graphics (fileobjects2.asp) - Page 220
        File Objects: Read Disk Drive by Steven Harper (fileobjects3.asp) - Page 221
        File Objects: Show Dir List by Tim Foster (fileobjects4.asp) - Page 222
        Graphic Size Detector (graphicdetect.asp) - Page 223


ASP Quick Lessons written by Charles M. Carroll
http://www.learnasp.com/learn/strings.asp Page 188


String Functions ASP Quick Lessons

String Functions by Charles Carroll

String functions are very useful for parsing data from ASCII files, formatting output in complex ways and parsing form input. The following scripts provides a sample of some crucial VBScript string functions in action. The string functions demonstrated are:

Instr(string,searchstring)
returns a numeric position where search string was found

Mid(string,start,length)
chops string at a start position for a fixed number of characters.

Mid(string,start)
results in a string that has all characters before startpos removed.

Trim(string)
removes all spaces from a string.

   <html><head>
   <title>citystatezip.asp</title>
   </head><body bgcolor="#FFFFFF">
   <Form action = "citystatezipRespond.asp" method="post">
   Enter City <b>,</b> State Zip<p>
   <Input NAME="CSZ" size ="40"><p>
   <Input type="submit" value="Here is my Data!">
   </form>
   </body></html>

The user can enter a city, state and Zip, i.e.
Rockville, MD 20849
San Fransisco, CA xxxxx
Pike's Peak, CO xxxxx
and the program can use these functions to separate the data.

   <html><head>
   <title>citystateziprespond.asp</title>
   </head><body>
   <%
   alldata=request("csz")
   IF  instr(alldata,",")=0 THEN%>

      You need a comma<br>,<br>between city and state!<p>
      <%response.end
   END IF
10   
11   findcomma=instr(alldata,",")
12   city=mid(alldata,1,findcomma-1)
13   leftover=trim(mid(alldata,findcomma+1))
14   
15   findspace=instr(leftover," ")
16   state=mid(leftover,1,findspace)
17   leftover=mid(leftover,findspace+1)
18   
19   zip=leftover
20   
21   response.write "city=" & city & "<br>"
22   response.write "state=" & state & "<br>"
23   response.write "zip=" & zip & "<br>"
24   
25   
26   %>

27   </body></html>


ASP Quick Lessons written by Charles M. Carroll
http://www.learnasp.com/learn/stringsplit.asp Page 189


String Functions ASP Quick Lessons

SPLIT String Function by Charles Carroll

The various string functions can be used interchangeably often. We will write the same script using SPLIT, REPLACE and JOIN to demonstrate all 3 functions and how they often are used for similar tasks. However, your programming situations may be especially suited for 1 out of 3 of the functions.

SPLIT(string,delimiter)
is a function that returns an array with as many elements as are separated by delimiters within the string.

The user can enter a state or multiple states. We write the program utilizing SPLIT to demonstrate how this can be  used.

statesplit.asp

   <html><head>
   <title>states.asp</title>
   </head><body bgcolor="#FFFFFF">
   <form action="statesplitrespond.asp" method="post">
   Enter State (or many states separated by <b>,<b><p>
   <input NAME="states" size="40"><p>
   <input type="submit" value="Get The Publishers!">
   </form>
   </body></html>

statesplitrespond.asp

   <!--#include virtual="/learn/test/lib_dbtable.asp"-->
   <html><head>
   <title>statesrespond.asp</title>&
   <body>
   <%
   mySQL="select * from publishers " & whereclause
   myDSN="DSN=student;uid=student;pwd=magic"
   public allstates
   tempinput=request("states")
10   allstates=split(tempinput,",")
11   
12   maxcounter=ubound(allstates)
13   
14   whereclause=" where state='" & allstates(0) & "'"
15   FOR counter=1 TO maxcounter
16      thisstate=allstates(counter)
17      whereclause=whereclause & " OR state='" & thisstate & "'"
18   NEXT
19   mySQL=mySQL & whereclause
20   Call Query2Table(mySQL,myDSN)
21   %>

22   </body></html>


ASP Quick Lessons written by Charles M. Carroll
http://www.learnasp.com/learn/stringreplace.asp Page 190


String Functions ASP Quick Lessons

Replace String Functions by Charles Carroll

The various string functions can be used interchangeably often. We will write the same script using SPLIT, REPLACE and JOIN to demonstrate all 3 functions and how they often are used for similar tasks. However, your programming situations may be especially suited for 1 out of 3 of the functions.

REPLACE(string,oldvalue,newvalue)
results in a string that has all occurences of oldvalue replaced with a newvalue.

The user can enter a state or multiple states. We write the program utilizing REPLACE to demonstrate how this  function can be used.

statereplace.asp

   <html><head>
   <title>statereplace.asp</title>
   </head><body bgcolor="#FFFFFF">
   <form action="statereplacerespond.asp" method="post">
   Enter State (or many states separated by <b>,<b><p>
   <input NAME="states" size="40"><p>
   <input type="submit" value="Get The Publishers!">
   </form>
   </body></html>

statereplacerespond.asp

   <!--#include virtual="/learn/test/lib_dbtable.asp"-->
   <html><head>
   <title>statesrespond.asp</title>&
   <body>
   <%
   mySQL="select * from publishers " & whereclause
   myDSN="DSN=student;uid=student;pwd=magic"
   
   tempinput=request("states")
10   
11   whereclause=" where state='" & tempinput
12   whereclause=replace(whereclause, ",","' OR state='")
13   whereclause=whereclause & "'"
14   
15   mySQL=mySQL & whereclause
16   response.write mySQL
17   Call Query2Table(mySQL,myDSN)
18   %>

19   </body></html>


ASP Quick Lessons written by Charles M. Carroll
http://www.learnasp.com/learn/stringjoin.asp Page 191


String Functions ASP Quick Lessons

JOIN String Functions by Charles Carroll

The various string functions can be used interchangeably often. We will write the same script using SPLIT, REPLACE and JOIN to demonstrate all 3 functions and how they often are used for similar tasks. However, your programming situations may be especially suited for 1 out of 3 of the functions.

JOIN(array,delimiter)
takes an array and converts it to one string with delimiters.

The user can enter a state or multiple states. We write the program using the JOIN function to demonstrate how this function can be used.

statejoin.asp

   <html><head>
   <title>statejoin.asp</title>
   </head><body bgcolor="#FFFFFF">
   <form action="statejoinrespond.asp" method="post">
   Enter State (or many states separated by <b>,<b><p>
   <input NAME="states" size="40"><p>
   <input type="submit" value="Get The Publishers!">
   </form>
   </body></html>

statejoinrespond.asp

   <!--#include virtual="/learn/test/lib_dbtable.asp"-->
   <html><head>
   <title>statejoinrespond.asp</title>&
   <body>
   <%
   mySQL="select * from publishers "
   myDSN="DSN=student;uid=student;pwd=magic"
   public allstates
   tempinput=request("states")
10   allstates=split(tempinput,",")
11   
12   whereclause=" where state='" & JOIN(allstates, "' OR state='") & "'"
13   
14   mySQL=mySQL & whereclause
15   response.write mySQL
16   Call Query2Table(mySQL,myDSN)
17   %>

18   </body></html>


ASP Quick Lessons written by Charles M. Carroll
http://www.learnasp.com/learn/arrays.asp Page 192


Arrays Part 1 from ASP Quick Lessons

Arrays to store data Part #1 by Charles Carroll

Here would be a code sample without arrays:
   <html><head>
   <title>arraysnot.asp</title>
   </head><body bgcolor="#FFFFFF">
   <%
   dim x,y,z
   
   x=7
   y=20
   z=x+y
10   
11   response.write z
12   %>

13   </body></html>

Here is the same example with arrays
   <html><head>
   <title>arrays.asp</title>
   </head><body bgcolor="#FFFFFF">
   <%
   dim allstuff(3)
   
   allstuff(0)=7
   allstuff(1)=20
   allstuff(2)=allstuff(0)+allstuff(1)
10   
11   response.write allstuff(2)
12   %>

13   </body></html>

http://www.activeserverpages.com/learn/subdates.asp
has a good example of arrays in a practical context.


ASP Quick Lessons written by Charles M. Carroll
http://www.learnasp.com/learn/arrays2.asp Page 193


Arrays Part 2 from ASP Quick Lessons

Arrays to store data Part #2 by Charles Carroll

Assigning an array size with a variable produces a variable unless the Redim command is used.

   <html><head>
   <title>arraysredim.asp</title>
   </head><body bgcolor="#FFFFFF">
   <%
      ' this code
          dim a_array(100)
   
          ' this code will fail
          x=100
10      dim my_array(x)
11   
12   %>

13   </body></html>

Assigning an array size with a variable produces an error unless the Redim command is used.

   <html><head>
   <title>arraysredimcorrect.asp</title>
   </head><body bgcolor="#FFFFFF">
   <%
          dim my_array()
      x=100
      redim preserve my_array(x)
          my_array(20)="Hi!"
      my_array(40)="How are You"
10      
11      lowcount=lbound(my_array)
12      highcount=ubound(my_array)
13      response.write "lowcount=" & lowcount & ";highcount=" & highcount & "<p>"
14      for counter=lowcount to highcount
15         response.write counter & "&nbsp;&nbsp;&nbsp;"
16         response.write my_array(counter) & "<br>"
17      next
18   
19   %>

20   </body></html>


ASP Quick Lessons written by Charles M. Carroll
http://www.learnasp.com/learn/arrays3.asp Page 194


Arrays Part 3 from ASP Quick Lessons

Arrays to store data Part 3 by Charles Carroll

There is a code intensive way to load an array and a less intensive one. For example, here is the code intensive one:
   <html><head>
   <title>arraysload.asp</title>
   </head><body bgcolor="#FFFFFF">
   <%
   dim my_months(13)
   
   my_months(0)=""
   my_months(1)="Jan"
   my_months(2)="Feb"
10   my_months(3)="Mar"
11   my_months(4)="Apr"
12   my_months(5)="May"
13   my_months(6)="Jun"
14   my_months(7)="Jul"
15   my_months(8)="Aug"
16   my_months(9)="Sep"
17   my_months(10)="Oct"
18   my_months(11)="Nov"
19   my_months(12)="Dec"
20   
21   lowcount=lbound(my_months)
22   highcount=ubound(my_months)
23   response.write "lowcount=" & lowcount & ";highcount=" & highcount & "<p>"
24   for counter=lowcount to highcount
25         response.write my_months(counter) & "<br>"
26   next
27   %>

28   </body></html>

Here is the less code intense one:
   <html><head>
   <title>arraysloadbest.asp</title>
   </head><body bgcolor="#FFFFFF">
   <%
   dim my_months
   
   my_months=array("Jan","Feb","Mar","Apr", _
      "May","Jun","Jul","Aug", _
      "Sep","Oct","Nov","Dec")
10   
11   ' finally here is how you loop through an array
12   lowcount=lbound(my_months)
13   highcount=ubound(my_months)
14   response.write "lowcount=" & lowcount & ";highcount=" & highcount & "<p>"
15   for counter=lowcount to highcount
16      response.write my_months(counter) & "<br>"
17   next
18   %>

19   </body></html>


ASP Quick Lessons written by Charles M. Carroll
http://www.learnasp.com/learn/arraysmore.asp Page 195


Text File Reading ASP Quick Lessons

Arrays Resources

Arrays are handled in much more depth at other sites actually so rather than re-invent the wheel here is a list:

Sorting Arrays
http://4guysfromrolla.com/webtech/012799-2.shtml

Sorting 2-D Arrays
http://www.4guysfromrolla.com/webtech/012799-3.shtml

Passing Arrays from Page to Page
http://www.4guysfromrolla.com/webtech/101999-1.shtml

Randomly Re-ordering an Array, for example one from Getrows
http://www.4guysfromrolla.com/webtech/110800-1.shtml

Sorting Alogorithms in general @
http://www-lsi.upc.es/~rbaeza/handbook/sort_a.html

Translate arrays into javascript arrays @
http://aspfree.com/authors/anandv/vb2jsarray.asp

How can I quickly determine if a string exists within an array?
http://www.aspfaqs.com/aspfaqs/ShowFAQ.asp?FAQID=93

Filtering Arrays
http://www.4guysfromrolla.com/webtech/111300-1.shtml

Dynamic Arrays Made Easy
http://www.4guysfromrolla.com/webtech/032800-1.shtml

FAQs by Scott Mitchell, Bill Wilkinson, Richard Lowe, and Ben Kubs
http://www.aspfaqs.com/aspfaqs/ShowCategory.asp?CatID=1

Remas Wojciechowski Array Notes @
http://www.aspalliance.com/remas/Library/Arrays/


ASP Quick Lessons written by Charles M. Carroll
http://www.learnasp.com/learn/dictionary.asp Page 196


Dictionary objects from ASP Quick Lessons

Dictionary objects by Charles Carroll

Dictionary objects are an elegant object to use in your coding. The dictionary items can be removed individually (without leaving holes) unlike array elements. Read up on http://www.learnasp.com/advice/threadsafe.asp if you want to use it at session or application level. The base documentation is at:
http://www.learnasp.com/iishelp/VBScript/htm/vbs388.htm.

A clever moderately complex practical dictionary example is @
http://www.4guysfromrolla.com/webtech/072899-1.shtml

This is how to create and place items into a dictionary objects and display the contents:

   <html><head>
   <title>dictionarybasics.asp</title>
   </head><body bgcolor="#FFFFFF">
   <%
   set mysample=server.CreateObject("Scripting.Dictionary")
   
   mysample.Add "haircolor", "brown"
   mysample.add "eyecolor" , "blue"
   mysample.add "dateofbirth", "5/13/64"
10   
11   for each whatever in mysample
12      response.write whatever & "="
13      response.write mysample.item(whatever) & "<br>"
14   next
15   set mysample=nothing
16   %>

17   </body></html>

This is a sample of how to make an array of dictionary objects.

   <html><head>
   <title>dictionaryarrays.asp</title>
   </head><body bgcolor="#FFFFFF">
   <%
   dim people(3)
   
   Set people(0) = server.CreateObject("Scripting.Dictionary")
   people(0).Add "fname", "Jane"
   people(0).Add "lname", "Doe"
10   people(0).Add "haircolor", "brown"
11   people(0).add "eyecolor" , "blue"
12   people(0).add "dateofbirth", "1/10/60"
13   
14   Set people(1) = server.CreateObject("Scripting.Dictionary")
15   people(1).Add "fname", "Reginald"
16   people(1).Add "mname", "Elton"
17   people(1).Add "lname", "Dwight"
18   people(1).Add "haircolor", "red"
19   people(1).add "eyecolor" , "dusty"
20   people(1).add "dateofbirth", "1/10/60"
21   
22   Set people(2) = server.CreateObject("Scripting.Dictionary")
23   people(2).Add "fname", "Hitoshi"
24   people(2).Add "lname", "Yoshitsugu"
25   
26   ' print out one item
27   for each whatever in people(1)
28      response.write whatever & "="
29      response.write people(1).item(whatever) & "<br>"
30   next
31   
32   for counter=0 to 2
33      set people(counter)=nothing
34   next
35   %>

36   </body></html>


ASP Quick Lessons written by Charles M. Carroll
http://www.learnasp.com/learn/getrowsultimate.asp Page 197


dbtable

Ultimate GetRows by Charles Carroll

Sure GetRows is fast and improves scalability. I discussed why
http://www.learnasp.com/advice/whygetrows.asp
But it is a pain because it transfers the recordset into a multi-dimensional array and the code to walk the array is complex and re-usability is low. Well thanks to the magic of dictionaries we can produce clever templates that interact with GetRows and never have to worry again.

"The Worlds Fastest Listbox"
http://www.learnasp.com/learn/speedappdata.asp
shows the only faster way to display databases.

Here is the sample that shows publisher data in a table:

   <!--#include file="lib_rsfast.asp"-->
   <%response.buffer=true%>
   <html>
   <head>
   <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
   <title>RsFast Demo</title>
   </head>
   <body bgcolor="#FFFFFF">
   <%
10      set rsparms=server.CreateObject("Scripting.Dictionary")
11      with rsparms
12         .Add "conn", "dsn=student;uid=student;pwd=magic"
13         .add "sql", "select * from publishers where state='NY'"
14         .add "debug", false
15         .add "template_header", "<table border=1>"
16         .add "template_row_header", "<tr>"
17         .add "template_row_footer", "</tr>"
18         .add "template_col_header", "<td>"
19         .add "template_col_footer", "</td>"
20         .add "template_footer", "</table>"
21         .add "fieldnull", "&nbsp;"
22         .add "fieldblank", "&nbsp;"
23         .add "fld_city", "<td bgcolor='lightblue'><b>{0}</b><br></td>"
24         .add "fld_state", "<td><b>{0}</b><br></td>"   
25         .add "colnames", "display"   
26      end with   
27         Call RsFast(rsparms)
28         set rsparms=nothing
29   %>

30   </body>
31   </html>

Here is the sample that shows listboxes drawn from the publisher data:

   <!--#include file="lib_rsfast.asp"-->
   <%response.buffer=true%>
   <html>
   <head>
   <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
   <title>RsFast Demo</title>
   </head>
   <body bgcolor="#FFFFFF">
   <%
10      set rsparms=server.CreateObject("Scripting.Dictionary")
11      WITH rsparms
12   
13         .Add "conn", "dsn=student;uid=student;pwd=magic"
14         .add "sql", "select distinct city from publishers"
15         .add "debug", false
16         .add "template_header", "<select name='city'>"
17         .add "template_row_header", "<option>"
18         .add "template_row_footer", "</option>"
19         .add "template_footer", "</select><br>"
20         .add "fieldnull", "&nbsp;"
21         .add "fieldblank", "&nbsp;"
22         Call RsFast(rsparms)
23         response.flush
24   
25      .item("sql")="select distinct state from publishers"
26      .item("template_header")="<select name='state'>"
27      Call RsFast(rsparms)
28      response.flush
29   
30      .item("sql")="select distinct zip from publishers"
31      .item("template_header")="<select name='zip'>"
32      Call RsFast(rsparms)
33      response.flush
34   
35      END WITH
36          set rsparms=nothing
37   %>

38   </body>
39   </html>

Here is a sample that pages the publisher data:

   <!--#include file="lib_rsfast.asp"-->
   <%response.buffer=true%>
   <html>
   <head>
   <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
   <title>RsFast Demo</title>
   </head>
   <body bgcolor="#FFFFFF">
   <%
10      set rsparms=server.CreateObject("Scripting.Dictionary")
11      with rsparms
12         .Add "conn", "dsn=student;uid=student;pwd=magic"
13         .add "sql", "select * from publishers"
14         .add "page", 3
15         .add "pagesize", 4
16         
17         .add "debug", false
18         .add "template_header", "Page {page} of {pagemax} <table border=1>"
19         .add "template_row_header", "<tr>"
20         .add "template_row_footer", "</tr>"
21         .add "template_col_header", "<td>"
22         .add "template_col_footer", "</td>"
23         .add "template_footer", "</table>"
24         .add "fieldnull", "&nbsp;"
25         .add "fieldblank", "&nbsp;"
26         .add "fld_city", "<td bgcolor='lightblue'><b>{0}</b><br></td>"
27         .add "fld_state", "<td><b>{0}</b><br></td>"   
28         .add "colnames", "display"   
29      end with   
30         Call RsFast(rsparms)
31         set rsparms=nothing
32   %>

33   </body>
34   </html>

Here is the sample that shows the northwind customer data in a table:

   <!--#include file="lib_rsfast.asp"-->
   <%response.buffer=true%>
   <html>
   <head>
   <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
   <title>RsFast Demo</title>
   </head>
   <body bgcolor="#FFFFFF">
   <%
10      set rsparms=server.CreateObject("Scripting.Dictionary")
11      with rsparms
12         .add "accessdb", "nwind.mdb"
13         .add "sql", "select * from customers"
14         .add "debug", false
15         .add "template_header", "<table border=1>"
16         .add "template_row_header", "<tr>"
17         .add "template_row_footer", "</tr>"
18         .add "template_col_header", "<td>"
19         .add "template_col_footer", "</td>"
20         .add "template_footer", "</table>"
21         .add "fieldnull", "&nbsp;"
22         .add "fieldblank", "&nbsp;"
23         .add "fld_contactname", "<td bgcolor='lightblue'><b>{0}</b></td>"
24         .add "fld_city", "<td bgcolor='orange'><b>{0}</b></td>"   
25         .add "colnames", "display"   
26      end with   
27         Call RsFast(rsparms)
28         set rsparms=nothing
29   %>

30   </body>
31   </html>

Here is the the library lib_rsfast.asp that does all the work:

   <%
   SUB RSfast(parmdict)
      parmConn=parmdict.item("conn")
      parmSQL=parmdict.item("sql")
      parmdbg=parmdict.item("debug")
      fieldnull=parmdict.item("fieldnull")
      fieldblank=parmdict.item("fieldblank")
      accdb=parmdict.item("accessdb")
      page=cint(parmdict.item("page"))
10      pagesize=cint(parmdict.item("pagesize"))
11      If parmdict.item("colnames")="display" THEN
12         coldisplay=true
13      END IF
14   
15      If accdb="" THEN
16         ' nothing to do   
17      ELSE
18         parmConn="PROVIDER=Microsoft.Jet.OLEDB.4.0;DATA SOURCE="
19         parmConn=parmConn & server.mappath(accdb) & ";"
20      END IF
21   
22      If parmdbg=true THEN   
23         response.write "parmconn=" & parmConn & "<br>"
24         response.write "parmSQL=" & parmSQL & "<br>"
25      END IF
26      
27      response.flush
28         
29      ' Open and check for EOF
30      set conntemp=server.createobject("adodb.connection")
31      conntemp.open parmConn
32      IF pagesize>0 THEN
33         set rstemp=Server.CreateObject("ADODB.Recordset")
34         aduseclient=3
35         rstemp.cursorlocation=aduseclient
36         rstemp.cachesize=pagesize
37         rstemp.open parmSQL,parmconn
38         rstemp.absolutepage=page
39         pagemax=cint(rstemp.pagecount)
40         parmdict.add "pagemax", pagemax
41         paged=true
42      ELSE
43         set rstemp=conntemp.execute(parmSQL)
44      END IF
45      If rstemp.eof then
46         response.write "No records matched<br>"
47         response.write mySQL & "<br>So cannot make table..."
48         rstemp.close
49         set rstemp=nothing
50         conntemp.close
51         set conntemp=nothing
52         response.end
53      end if
54      template_header=parmdict.item("template_header")   
55      template_footer=parmdict.item("template_footer")   
56      template_header=replace(template_header,"{page}",cstr(page))
57      template_footer=replace(template_footer,"{page}",cstr(page))
58      template_header=replace(template_header,"{pagemax}",cstr(pagemax))
59      template_footer=replace(template_footer,"{pagemax}",cstr(pagemax))
60   
61      response.write template_header
62      If coldisplay THEN
63         response.write parmdict.item("template_row_header")   
64      END IF
65      ' fill dictionary with field names/numbers
66      howmany=rstemp.fields.count
67      set rsinfo=server.CreateObject("Scripting.Dictionary")
68      for counter=0 to howmany-1
69         thename=rstemp(counter).name
70         If coldisplay THEN
71            response.write parmdict.item("template_col_header")   
72         END IF   
73         rsinfo.add lcase(thename), counter
74         If coldisplay THEN
75            response.write "<b>" & thename & "</b>"
76            response.write parmdict.item("template_col_footer")   
77         END IF
78      next
79      If coldisplay THEN
80         response.write parmdict.item("template_row_footer")   
81      END IF
82   
83      ' Now lets grab all the records
84      If paged=true THEN
85         alldata=rstemp.getrows(pagesize)
86      ELSE
87         alldata=rstemp.getrows()
88      END IF
89      rstemp.close
90      set rstemp=nothing
91      conntemp.close
92      set conntemp=nothing
93      rowcount=ubound(alldata,2)
94      colcount=ubound(alldata,1)
95   
96      If parmdbg=true THEN   
97         response.write "rowcount=" & rowcount & "<br>"
98         response.write "colcount=" & colcount & "<br>"
99         response.flush
100      END IF
101      
102      FOR therow=0 TO rowcount
103         response.write parmdict.item("template_row_header")
104            FOR EACH whatever IN rsinfo
105               fldname=whatever
106               fldnumb=rsinfo.item(fldname)
107               fldvalue=alldata(fldnumb,therow)
108               IF isnull(fldvalue) THEN
109                  fldvalue=fieldnull
110               END IF
111               IF trim(fldvalue)="" THEN
112                  fldvalue=fieldblank
113               END IF
114            
115               fldtemplate=parmdict.item("fld_" & fldname)
116               
117               If fldtemplate<>"" THEN
118                  fldvalue=replace(fldtemplate,"{0}",fldvalue)
119                  response.write fldvalue
120               ELSE
121                  response.write parmdict.item("template_col_header")                  
122                  response.write fldvalue
123                  response.write parmdict.item("template_col_footer")   
124               END IF
125            NEXT
126         response.write parmdict.item("template_row_footer")
127      NEXT
128      response.write template_footer
129      set rsinfo=nothing
130   END SUB
131   %>

132   


ASP Quick Lessons written by Charles M. Carroll
http://www.learnasp.com/learn/subdates.asp Page 198


subdates from ASP Quick Lessons

Subroutines - Choosing/Validating Dates by Charles Carroll

Subroutines can be used to provide handy date entry list boxes.

   <HEAD><TITLE>subdates.asp</TITLE></HEAD>
   <HTML><body bgcolor="#FFFFFF">
   <form action="subdatesrespond.asp">
   Depart:
   <%call showdateform("depart")%>
   <br>
   Arrive:
   <%call showdateform("arrive")%>
   <input type="submit" value="Ready To Travel">
10   </form>
11   <%
12   sub showdateform(mylistname)
13      call showmonth(mylistname)
14      call showday(mylistname)
15      call showyear(mylistname)
16   end sub
17   %>

18   
19   <%sub showmonth(listname)%>
20      <select name="<%=listname%>month">
21      <%
22      dim monthname
23      monthname=array("Jan","feb","Mar","Apr", _
24            "May","Jun","Jul","Aug", _
25            "Sep","Oct","Nov","Dec")
26      for counter=0 to 11   
27         temp=monthname(counter)
28         response.write "<option value='" & counter+1
29         response.write "'>" & temp & "</option>"      
30      next%>

31      </select>
32   <%end sub%>
33   
34   <%sub showday(listname)%>
35      <select name="<%=listname%>day">
36      <%for counter=1 to 31
37         response.write "<option>" & counter & "</option>"      
38      next%>

39      </select>
40   <%end sub%>
41   
42   <%sub showyear(listname)%>
43      <select name="<%=listname%>year">
44      <%for counter=1964 to 2005
45         response.write "<option>" & counter & "</option>"      
46      next%>

47      </select>
48   <%end sub%>
49   
50   
51   </BODY></HTML>


ASP Quick Lessons written by Charles M. Carroll
http://www.learnasp.com/learn/subdates2.asp Page 199


subdates2 from ASP Quick Lessons

Subroutines - Choosing/Validating Dates #2 by Charles Carroll

The form handler for the previous example could validate and manipulate dates using some built-in VBscript date handling routines, for example:

   <HEAD><TITLE>subdatesrespond.asp</TITLE></HEAD>
   <HTML><body bgcolor="#FFFFFF">
   <%
   dday=request.querystring("departday")
   dmonth=request.querystring("departmonth")
   dyear=request.querystring("departyear")
   departdate=dday & "/" & dmonth & "/" & dyear
   
   aday=request.querystring("arriveday")
10   amonth=request.querystring("arrivemonth")
11   ayear=request.querystring("arriveyear")
12   arrivedate=aday & "/" & amonth & "/" & ayear
13   
14   If  isdate(departdate) then
15      response.write "Departure Date is Valid Date<br>"
16   else
17      response.write "Departure Date is INVALID<br>"   
18   end if
19   
20   If  isdate(arrivedate) then
21      response.write "Arrival Date is Valid Date<br>"
22   else
23      response.write "Arrival Date is INVALID<br>"   
24   end if
25   %>

26   </BODY></HTML>


ASP Quick Lessons written by Charles M. Carroll
http://www.learnasp.com/learn/subdbtable.asp Page 200


Subroutines Query2Table ASP Quick Lessons

Query2Table by Charles Carroll

Subroutines can save you having to repeat blocks of code. This code illustrates how we can build tables with minimal code in the main script and by including a file with a convenient subroutine.

   <HEAD><TITLE>subdbtable.asp</TITLE></HEAD>
   <HTML><body bgcolor="#FFFFFF">
   <%
   myDSN="DSN=student;uid=student;pwd=magic"
   mySQL="select * from publishers"
   call query2table(mySQL,myDSN)
   %>

   <!--#include virtual="/learn/test/lib_dbtable.asp"-->
   </BODY></HTML>

   <HEAD><TITLE>subdbtable2.asp</TITLE></HEAD>
   <HTML><body bgcolor="#FFFFFF">
   <%
   myDSN="DSN=student;uid=student;pwd=magic"
   mySQL="select * from titles"
   call query2table(mySQL,myDSN)
   %>

   <!--#include virtual="/learn/test/lib_dbtable.asp"-->
   </BODY></HTML>

   <HEAD><TITLE>subdbtable3.asp</TITLE></HEAD>
   <HTML><body bgcolor="#FFFFFF">
   <%
   myDSN="DSN=student;uid=student;pwd=magic"
   mySQL="select * from authors"
   call query2table(mySQL,myDSN)
   %>

   <!--#include virtual="/learn/test/lib_dbtable.asp"-->
   </BODY></HTML>

   <HEAD><TITLE>subdbtable4.asp</TITLE></HEAD>
   <HTML><body bgcolor="#FFFFFF">
   <%
   myDSN="DSN=student;uid=student;pwd=magic"
   mySQL= "SELECT Publishers.Name, Titles.Title "
   mySQL= mySQL & "FROM Publishers "
   mySQL= mySQL & "INNER JOIN Titles ON Publishers.PubID = Titles.PubID "
   mySQL= mySQL & "order by Name"
   
10   call query2table(mySQL,myDSN)
11   %>

12   <!--#include virtual="/learn/test/lib_dbtable.asp"-->
13   </BODY></HTML>

   <HEAD><TITLE>subdbtable5.asp</TITLE></HEAD>
   <HTML><body bgcolor="#FFFFFF">
   <%
   myDSN="DSN=student;uid=student;pwd=magic"
   mySQL="select * from title_author"
   call query2table(mySQL, myDSN)
   %>

   <!--#include virtual="/learn/test/lib_dbtable.asp"-->
   </BODY></HTML>

   <HEAD><TITLE>subdbtable6.asp</TITLE></HEAD>
   <HTML><body bgcolor="#FFFFFF">
   <%
   myDSN="DSN=student;uid=student;pwd=magic"
   mySQL="select name,type from sysobjects"
   call query2table(mySQL,myDSN)
   %>

   <!--#include virtual="/learn/test/lib_dbtable.asp"-->
   </BODY></HTML>

The Include file lib_dbtable.asp looks like this:

   <%
   sub query2table(inputquery, inputDSN)
      dim conntemp, rstemp
      set conntemp=server.createobject("adodb.connection")
      conntemp.open inputDSN
      set rstemp=conntemp.execute(inputquery)
      howmanyfields=rstemp.fields.count -1%>

      <table border=1><tr>
      <% 'Put Headings On The Table of Field Names
10      for i=0 to howmanyfields %>

11                <td><b><%=rstemp(i).name%></B></TD>
12      <% next %>
13      </tr>
14      <% ' Now lets grab all the records
15      do while not rstemp.eof %>

16         <tr>
17         <% for i = 0 to howmanyfields
18            thisvalue=rstemp(i)
19            If isnull(thisvalue) then
20               thisvalue="&nbsp;"
21            end if%>

22                <td valign=top><%=thisvalue%></td>
23         <% next %>
24         </tr>
25         <%rstemp.movenext
26      loop%>

27      </table>
28      <%
29      rstemp.close
30      set rstemp=nothing
31      conntemp.close
32      set conntemp=nothing
33   end sub%>


ASP Quick Lessons written by Charles M. Carroll
http://www.learnasp.com/learn/subdblist.asp Page 201


Subroutines Query2List ASP Quick Lessons

Subroutines Query2List by Charles Carroll

Subroutines can save you having to repeat blocks of code and can optionally be placed in separate files and included when needed, thus making your pages not appear to have lots of code in-line.

   <html><head>
   <TITLE>subdblist.asp</TITLE>
   </head><body bgcolor="#FFFFFF">
   <form>
   <%
   theDSN="DSN=student;uid=student;pwd=magic"
   call query2list("select distinct city from publishers","cy",theDSN)
   call query2list("select distinct state from publishers","st",theDSN)
   call query2list("select distinct zip from publishers","zp",theDSN)
10   %>

11   </form>
12   <!--#include virtual="/learn/test/subdblist.inc"-->
13   </body></html>

The include file lib_dblist.asp looks like:

   <%sub query2list(myquery,myname,myDSN)
      dim conntemp, rstemp
      set conntemp=server.createobject("adodb.connection")
      conntemp.open myDSN
      set rstemp=conntemp.execute(myquery)
      %>

      <Select name="<%=myname%>">
      <%
      do while not rstemp.eof
10         thisfield=trim(RStemp(0))
11         if isnull(thisfield) or thisfield="" then
12            ' ignore
13         else
14            response.write "<option>" & thisfield & "</option>"
15         end if
16         rstemp.movenext
17      loop
18          %>

19      </select>
20      <%rstemp.close
21      set rstemp=nothing
22      conntemp.close
23      set conntemp=nothing
24   end sub%>


ASP Quick Lessons written by Charles M. Carroll
http://www.learnasp.com/learn/subreusable.asp Page 202


Subroutines Flexible ASP Quick Lessons

Subroutines - A "Flexible Approach" by Charles Carroll

Subroutines can be very cleverly constructed so that you can use the same routine to power several different tasks instead of copying code as the following examples illustrates!

   <HEAD><TITLE>subreusabledataform.asp</TITLE></HEAD>
   <HTML><body bgcolor="#FFFFFF">
   <!--#include virtual="/learn/test/subflexible.asp"-->
   <%
   call query2entryform("select * from publishers where pubid=16")
   %>

   </BODY></HTML>

   <HEAD><TITLE>subreusabledatalist.asp</TITLE></HEAD>
   <HTML><body bgcolor="#FFFFFF">
   <!--#include virtual="/learn/test/lib_subflexible.asp"-->
   <%
   call query2list("select distinct state from publishers","thestate")
   call query2list("select distinct city from publishers","thecity")
   call query2list("select distinct zip from publishers","thezip")
   %>

   </BODY></HTML>
10   

   <HEAD><TITLE>subreusabledatatable.asp</TITLE></HEAD>
   <HTML><body bgcolor="#FFFFFF">
   <!--#include virtual="/learn/test/subflexible.asp"-->
   <%
   call query2table("select * from publishers")
   %>

   </BODY></HTML>

   <HEAD><TITLE>subreusableform.asp</TITLE></HEAD>
   <HTML><body bgcolor="#FFFFFF">
   <!--#include virtual="/learn/test/subflexible.asp"-->
   <%
   call query2form("select * from publishers")
   %>

   </BODY></HTML>

The library file lib_subflexible.asp looks like:

   <%
   dim htmlstart, htmlend
   dim rowstart, rowend
   dim fieldstart, fieldend
   dim namestart, nameend
   dim fieldnames
   fieldnames=false
   
   sub query2list(myquery,listname)
10      htmlstart="<select name='" & listname & "'>"
11      htmlend="</select>"
12      rowstart="<option>"
13      rowend="</option>"
14      fieldstart=""
15      fieldend=""
16      call query2html(myquery)
17   end sub
18   
19   sub query2table(myquery)
20      htmlstart="<table border=1>"
21      htmlend="</table>"
22      rowstart="<tr>"
23      rowend="</tr>"
24      fieldstart="<td valign=top>"
25      fieldend="</td>"
26      call query2html(myquery)
27   end sub
28   
29   sub query2form(myquery)
30      htmlstart=""
31      htmlend=""
32      rowstart=""
33      rowend="<hr>"
34      fieldstart=""
35      fieldend="<br>"
36      fieldnames=true
37      namestart=""
38      nameend="&nbsp;=&nbsp;"
39      call query2html(myquery)
40   end sub
41   
42   sub query2entryform(myquery)
43      htmlstart=""
44      htmlend=""
45      rowstart=""
46      rowend=""
47      fieldstart="%name%&nbsp;=&nbsp;<input type='text name='%name%' value='"
48      fieldend="' size='%size%'><br>"
49      fieldnames=false
50      namestart=""
51      nameend="&nbsp;&nbsp;="
52      call query2html(myquery)
53   end sub
54   
55   sub query2html(inputquery)
56      set conntemp=server.createobject("adodb.connection")
57      conntemp.open "DSN=Student;uid=student;pwd=magic"
58      set rstemp=conntemp.execute(inputquery)
59      howmanyfields=rstemp.fields.count -1
60      redim fsa(howmanyfields)
61      redim fea(howmanyfields)
62      for i = 0 to howmanyfields
63         tempstart=replace(fieldstart,"%name%",rstemp(i).name)
64         tempend=replace(fieldend,"%name%",rstemp(i).name)
65         tempstart=replace(tempstart,"%size%",rstemp(i).actualsize)
66         tempend=replace(tempend,"%size%",rstemp(i).actualsize)
67         fsa(i)=tempstart
68         fea(i)=tempend
69      next
70      response.write htmlstart & vbcrlf
71      counter=0
72      do until rstemp.eof
73         response.write rowstart & vbcrlf
74         for i = 0 to howmanyfields
75            if fieldnames=true then
76               response.write namestart & rstemp(i).name & nameend
77            end if
78            response.write fsa(i) & rstemp(i) & fea(i) & vbcrlf
79         next
80         response.write rowend & vbcrlf
81         counter=counter+1
82         rstemp.movenext
83         if response.isclientconnected=false then
84            exit do
85         end if
86      loop
87   rstemp.close
88   set rstemp=nothing
89   conntemp.close
90   set conntemp=nothing
91   response.write htmlend
92   end sub
93   %>


ASP Quick Lessons written by Charles M. Carroll
http://www.learnasp.com/learn/subdictionary.asp Page 203


Subroutines w/Dictionary Objects from LearnASP

Subroutines w/Dictionary Objects by Charles Carroll

Subroutines using traditional parameters cannot support optional or variable parameters. Thanks to the wonders of dictionary objects, see:
http://www.learnasp.com/learn/dictionary.asp
subroutines can accept merely one dictionary objects which can contain simple variables, objects and other items to pass in. 

   <!--#include file="lib_mailtool.asp"-->
   <%response.buffer=true%>
   <html>
   <head>
   <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
   <title>MailTool Demo</title>
   </head>
   <body bgcolor="#FFFFFF">
   <%
10      set mailparms=server.CreateObject("Scripting.Dictionary")
11      mailparms.Add "goodmailmsg", ""
12      
13      mailparms.Add "who", "Sith Lord"
14      mailparms.Add "whoemail", "darthcarroll@asplists.com"
15         
16      mailparms.Add "whofrom","Anakin Skywalker"
17      mailparms.Add "whofromemail", "jedi@senate.com"
18      
19      mailparms.Add "subject", "need help?"
20   
21      BodyOfMail="I am thinking about"
22      BodyOfMail=BodyOfMail & vbcrlf & "the dark side!!!"
23      BodyOfMail=BodyOfMail &   vbcrlf & "Let me know if you need a hand!"
24   
25      mailparms.Add "body", BodyOfMail
26      
27      Call MailThat(mailparms)
28      set mailparms=nothing
29   %>

30   </body>
31   </html>
32      

The Include file lib_mailtool.asp looks like this:

   <%
   SUB MailThat(Dictparm)
      goodmailmsg=Dictparm.item("goodmailmsg")
      who=Dictparm.item("who")
      whoemail=Dictparm.item("whoemail")
      
      whofrom=Dictparm.item("whofrom")
      whofromemail=Dictparm.item("whofromemail")
      
10      whobcc=Dictparm.item("whobcc")
11      whobccemail=Dictparm.item("whobccemail")
12      
13      subject=Dictparm.item("subject")
14      mailbody=Dictparm.item("body")
15   
16      
17      IF instr(whoemail,"@") >0 THEN
18         goodemail=true
19      ELSE
20         goodemail=false
21         reason="bad target mail:" & whoemail & " "
22         tempSUBJ="bad signup"
23      END IF
24   
25      Set Mailer = Server.CreateObject("SMTPsvg.Mailer")
26      Mailer.RemoteHost = "mail.innerhost.com"
27      Mailer.FromName = whofrom
28      Mailer.FromAddress = whofromemail
29      Mailer.AddRecipient who, whoemail
30      Mailer.AddBCC whobcc,whobccemail
31      mailer.subject = subject
32      Mailer.BodyText = mailbody
33      If goodemail=false THEN
34         response.write "<p align='left'><font face='Comic Sans MS' color='#8000FF'>"
35         response.write "<big>Errors in processing request!<br>"
36         response.write "Your email address was invalid<br>"
37         response.write "<a href='/search'>Search Is Here</a> If You Wanted That!<br>"
38         response.write "OR Enter Correct Email address in previous form</big></font></p>"
39      END IF
40      
41      IF Mailer.SendMail and goodemail=TRUE THEN
42         If goodmailmsg="" THEN
43            response.write "mail sent to " & who & "(" & whoemail & ")"
44         ELSE
45            response.write goodmailmsg
46         END IF
47      ELSE
48         IF goodemail=TRUE THEN
49            badmailsend=TRUE
50         END IF
51      END IF
52      
53      
54      IF badmailsend=TRUE THEN
55         response.write "Error Sending Mail!<br>"
56         response.write mailer.response & reason
57         response.write "<br>Sorry! Try Later...<br>"
58      END IF
59   End Sub
60   %>


ASP Quick Lessons written by Charles M. Carroll
http://www.learnasp.com/learn/getrowsultimate.asp Page 204


dbtable

Ultimate GetRows by Charles Carroll

Sure GetRows is fast and improves scalability. I discussed why
http://www.learnasp.com/advice/whygetrows.asp
But it is a pain because it transfers the recordset into a multi-dimensional array and the code to walk the array is complex and re-usability is low. Well thanks to the magic of dictionaries we can produce clever templates that interact with GetRows and never have to worry again.

"The Worlds Fastest Listbox"
http://www.learnasp.com/learn/speedappdata.asp
shows the only faster way to display databases.

Here is the sample that shows publisher data in a table:

   <!--#include file="lib_rsfast.asp"-->
   <%response.buffer=true%>
   <html>
   <head>
   <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
   <title>RsFast Demo</title>
   </head>
   <body bgcolor="#FFFFFF">
   <%
10      set rsparms=server.CreateObject("Scripting.Dictionary")
11      with rsparms
12         .Add "conn", "dsn=student;uid=student;pwd=magic"
13         .add "sql", "select * from publishers where state='NY'"
14         .add "debug", false
15         .add "template_header", "<table border=1>"
16         .add "template_row_header", "<tr>"
17         .add "template_row_footer", "</tr>"
18         .add "template_col_header", "<td>"
19         .add "template_col_footer", "</td>"
20         .add "template_footer", "</table>"
21         .add "fieldnull", "&nbsp;"
22         .add "fieldblank", "&nbsp;"
23         .add "fld_city", "<td bgcolor='lightblue'><b>{0}</b><br></td>"
24         .add "fld_state", "<td><b>{0}</b><br></td>"   
25         .add "colnames", "display"   
26      end with   
27         Call RsFast(rsparms)
28         set rsparms=nothing
29   %>

30   </body>
31   </html>

Here is the sample that shows listboxes drawn from the publisher data:

   <!--#include file="lib_rsfast.asp"-->
   <%response.buffer=true%>
   <html>
   <head>
   <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
   <title>RsFast Demo</title>
   </head>
   <body bgcolor="#FFFFFF">
   <%
10      set rsparms=server.CreateObject("Scripting.Dictionary")
11      WITH rsparms
12   
13         .Add "conn", "dsn=student;uid=student;pwd=magic"
14         .add "sql", "select distinct city from publishers"
15         .add "debug", false
16         .add "template_header", "<select name='city'>"
17         .add "template_row_header", "<option>"
18         .add "template_row_footer", "</option>"
19         .add "template_footer", "</select><br>"
20         .add "fieldnull", "&nbsp;"
21         .add "fieldblank", "&nbsp;"
22         Call RsFast(rsparms)
23         response.flush
24   
25      .item("sql")="select distinct state from publishers"
26      .item("template_header")="<select name='state'>"
27      Call RsFast(rsparms)
28      response.flush
29   
30      .item("sql")="select distinct zip from publishers"
31      .item("template_header")="<select name='zip'>"
32      Call RsFast(rsparms)
33      response.flush
34   
35      END WITH
36          set rsparms=nothing
37   %>

38   </body>
39   </html>

Here is a sample that pages the publisher data:

   <!--#include file="lib_rsfast.asp"-->
   <%response.buffer=true%>
   <html>
   <head>
   <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
   <title>RsFast Demo</title>
   </head>
   <body bgcolor="#FFFFFF">
   <%
10      set rsparms=server.CreateObject("Scripting.Dictionary")
11      with rsparms
12         .Add "conn", "dsn=student;uid=student;pwd=magic"
13         .add "sql", "select * from publishers"
14         .add "page", 3
15         .add "pagesize", 4
16         
17         .add "debug", false
18         .add "template_header", "Page {page} of {pagemax} <table border=1>"
19         .add "template_row_header", "<tr>"
20         .add "template_row_footer", "</tr>"
21         .add "template_col_header", "<td>"
22         .add "template_col_footer", "</td>"
23         .add "template_footer", "</table>"
24         .add "fieldnull", "&nbsp;"
25         .add "fieldblank", "&nbsp;"
26         .add "fld_city", "<td bgcolor='lightblue'><b>{0}</b><br></td>"
27         .add "fld_state", "<td><b>{0}</b><br></td>"   
28         .add "colnames", "display"   
29      end with   
30         Call RsFast(rsparms)
31         set rsparms=nothing
32   %>

33   </body>
34   </html>

Here is the sample that shows the northwind customer data in a table:

   <!--#include file="lib_rsfast.asp"-->
   <%response.buffer=true%>
   <html>
   <head>
   <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
   <title>RsFast Demo</title>
   </head>
   <body bgcolor="#FFFFFF">
   <%
10      set rsparms=server.CreateObject("Scripting.Dictionary")
11      with rsparms
12         .add "accessdb", "nwind.mdb"
13         .add "sql", "select * from customers"
14         .add "debug", false
15         .add "template_header", "<table border=1>"
16         .add "template_row_header", "<tr>"
17         .add "template_row_footer", "</tr>"
18         .add "template_col_header", "<td>"
19         .add "template_col_footer", "</td>"
20         .add "template_footer", "</table>"
21         .add "fieldnull", "&nbsp;"
22         .add "fieldblank", "&nbsp;"
23         .add "fld_contactname", "<td bgcolor='lightblue'><b>{0}</b></td>"
24         .add "fld_city", "<td bgcolor='orange'><b>{0}</b></td>"   
25         .add "colnames", "display"   
26      end with   
27         Call RsFast(rsparms)
28         set rsparms=nothing
29   %>

30   </body>
31   </html>

Here is the the library lib_rsfast.asp that does all the work:

   <%
   SUB RSfast(parmdict)
      parmConn=parmdict.item("conn")
      parmSQL=parmdict.item("sql")
      parmdbg=parmdict.item("debug")
      fieldnull=parmdict.item("fieldnull")
      fieldblank=parmdict.item("fieldblank")
      accdb=parmdict.item("accessdb")
      page=cint(parmdict.item("page"))
10      pagesize=cint(parmdict.item("pagesize"))
11      If parmdict.item("colnames")="display" THEN
12         coldisplay=true
13      END IF
14   
15      If accdb="" THEN
16         ' nothing to do   
17      ELSE
18         parmConn="PROVIDER=Microsoft.Jet.OLEDB.4.0;DATA SOURCE="
19         parmConn=parmConn & server.mappath(accdb) & ";"
20      END IF
21   
22      If parmdbg=true THEN   
23         response.write "parmconn=" & parmConn & "<br>"
24         response.write "parmSQL=" & parmSQL & "<br>"
25      END IF
26      
27      response.flush
28         
29      ' Open and check for EOF
30      set conntemp=server.createobject("adodb.connection")
31      conntemp.open parmConn
32      IF pagesize>0 THEN
33         set rstemp=Server.CreateObject("ADODB.Recordset")
34         aduseclient=3
35         rstemp.cursorlocation=aduseclient
36         rstemp.cachesize=pagesize
37         rstemp.open parmSQL,parmconn
38         rstemp.absolutepage=page
39         pagemax=cint(rstemp.pagecount)
40         parmdict.add "pagemax", pagemax
41         paged=true
42      ELSE
43         set rstemp=conntemp.execute(parmSQL)
44      END IF
45      If rstemp.eof then
46         response.write "No records matched<br>"
47         response.write mySQL & "<br>So cannot make table..."
48         rstemp.close
49         set rstemp=nothing
50         conntemp.close
51         set conntemp=nothing
52         response.end
53      end if
54      template_header=parmdict.item("template_header")   
55      template_footer=parmdict.item("template_footer")   
56      template_header=replace(template_header,"{page}",cstr(page))
57      template_footer=replace(template_footer,"{page}",cstr(page))
58      template_header=replace(template_header,"{pagemax}",cstr(pagemax))
59      template_footer=replace(template_footer,"{pagemax}",cstr(pagemax))
60   
61      response.write template_header
62      If coldisplay THEN
63         response.write parmdict.item("template_row_header")   
64      END IF
65      ' fill dictionary with field names/numbers
66      howmany=rstemp.fields.count
67      set rsinfo=server.CreateObject("Scripting.Dictionary")
68      for counter=0 to howmany-1
69         thename=rstemp(counter).name
70         If coldisplay THEN
71            response.write parmdict.item("template_col_header")   
72         END IF   
73         rsinfo.add lcase(thename), counter
74         If coldisplay THEN
75            response.write "<b>" & thename & "</b>"
76            response.write parmdict.item("template_col_footer")   
77         END IF
78      next
79      If coldisplay THEN
80         response.write parmdict.item("template_row_footer")   
81      END IF
82   
83      ' Now lets grab all the records
84      If paged=true THEN
85         alldata=rstemp.getrows(pagesize)
86      ELSE
87         alldata=rstemp.getrows()
88      END IF
89      rstemp.close
90      set rstemp=nothing
91      conntemp.close
92      set conntemp=nothing
93      rowcount=ubound(alldata,2)
94      colcount=ubound(alldata,1)
95   
96      If parmdbg=true THEN   
97         response.write "rowcount=" & rowcount & "<br>"
98         response.write "colcount=" & colcount & "<br>"
99         response.flush
100      END IF
101      
102      FOR therow=0 TO rowcount
103         response.write parmdict.item("template_row_header")
104            FOR EACH whatever IN rsinfo
105               fldname=whatever
106               fldnumb=rsinfo.item(fldname)
107               fldvalue=alldata(fldnumb,therow)
108               IF isnull(fldvalue) THEN
109                  fldvalue=fieldnull
110               END IF
111               IF trim(fldvalue)="" THEN
112                  fldvalue=fieldblank
113               END IF
114            
115               fldtemplate=parmdict.item("fld_" & fldname)
116               
117               If fldtemplate<>"" THEN
118                  fldvalue=replace(fldtemplate,"{0}",fldvalue)
119                  response.write fldvalue
120               ELSE
121                  response.write parmdict.item("template_col_header")                  
122                  response.write fldvalue
123                  response.write parmdict.item("template_col_footer")   
124               END IF
125            NEXT
126         response.write parmdict.item("template_row_footer")
127      NEXT
128      response.write template_footer
129      set rsinfo=nothing
130   END SUB
131   %>

132   


ASP Quick Lessons written by Charles M. Carroll
http://www.learnasp.com/learn/subDBlistbest.asp Page 205


Subroutines Query2ListBest ASP Quick Lessons

Subroutines Db2list "Best" Approach  by Charles Carroll

Subroutines could be considerably more useful if they took optional parameters. Since they don't we can jury rig a system whereby a subroutine is invoked with two parameters: a delimiter and a string. And the string itself contains the various parameters. This approach implements a more optional parameter "like" solution.

   <html><head>
   <TITLE>subdblistbest.asp</TITLE>
   </head><body bgcolor="#FFFFFF">
   <form>
   <%call db2list("^","select distinct city from publishers^city^New York")%>
   <%call db2list("^","select distinct state from publishers^state^NY^table^DSN=student;uid=student;pwd=magic")%>
   <%call db2list("^","select distinct zip from publishers^Zip Code^^table")%>
   </form>
   <!--#include virtual="/learn/test/lib_dblistbest.asp"-->
10   

The include file lib_dblistbest.asp looks like:

   <%
   sub db2list(mydelim,myparm)
   
   dim myparameters
   myparameters=SPLIT(myparm,mydelim)
   parmcount=ubound(myparameters)
   myquery=myparameters(0)
   label=myparameters(1)
   default=myparameters(2)
10   if  parmcount>2 then
11      format=lcase(myparameters(3))
12   end if
13   if  parmcount>3 then
14      connstring=myparameters(4)
15   else
16      connstring="DSN=Student;uid=student;pwd=magic"
17   end if
18   
19   set conntemp=server.createobject("adodb.connection")
20   conntemp.open connstring
21   set rstemp=conntemp.execute(myquery)
22   If  format="table" then%>

23      <table width="100%" border="0" cellspacing="1"><td>
24   <%end if
25   response.write label
26   If  format="table" then%>

27      </td><td>
28   <%end if%>
29   <Select>
30   <option value="<%=default%>" selected><%=default%></option>
31   <%
32   do  while not rstemp.eof %>

33          <option><%=RStemp(0)%></option>
34   <%
35   rstemp.movenext
36   loop
37   conntemp.close
38   %>

39   </select>
40   <%If format="table" then%>
41      </td><tr></table>
42   <%end if
43   end sub%>

44   


ASP Quick Lessons written by Charles M. Carroll
http://www.learnasp.com/learn/libhtml.asp Page 206


HTML Library from ASP Quick Lessons

Library of HTML Commands by Phil Paxton
©1999,2000 by Phil Paxton

Subroutines and Functions can be used, for example, to provide a layer of abstraction over HTML.

   <!--#include virtual="/learn/test/lib_htmlstuff.asp"-->
   <html><head>
   <title>libhtmldemo.asp by Phil Paxton</title>&
   <body>
   <form action="lib_htmldemorespond.asp">
   <%
      Call Form_TextBox("first name","Fname",20,20,"")
      response.write "<br>"
      Call Form_TextBox("Last Name","Lname",20,20,"")
10      response.write "<br>"
11      Call Form_TextBox("City","cy",20,20,"")
12      response.write "<br>"
13      Call Form_TextBox("State","st",2,2,"")
14      response.write "<br>"
15      Call Form_TextBox("Zip Code","zp",10,10,"")
16      response.write "<br>"
17      Call Form_SubmitButton("Register Me","register")
18   %>

19   </form>
20   </body>
21   </html>

The library that enables this (named lib_htmlstuff.asp) looks like:

   <%
    Sub Display( Text )
          Response.Write( Text )
         End Sub
   
         '----------------------------------------------------------------
   
    Sub HTML( Text )
          Response.Write( Text )
10         End Sub
11   
12         '----------------------------------------------------------------
13   
14    Sub Test( Text )
15          Response.Write( Text )
16         End Sub
17   
18         '----------------------------------------------------------------
19   
20    Sub Form_HiddenField( Name, Value )
21   
22          HTML "<INPUT "
23          Form_Parm_Type "Hidden"
24          Form_Parm_Name Name
25          Form_Parm_Value Value
26          HTML ">"
27   
28         End Sub
29   
30         '----------------------------------------------------------------
31   
32    Sub Form_Label( Label, Control )
33   
34          If Len(Label) > 0 Then
35          HTML "<label "
36          HTML "for=" & Control
37          HTML ">"
38          HTML "<strong>"
39          Display Label
40          HTML "</strong>"
41          HTML "</label>"
42          End If
43   
44         End Sub
45   
46         '----------------------------------------------------------------
47   
48    Sub Form_TextBox( Label, Name, MaxLength, Size, Value )
49   
50          Form_Label Label, Name
51   
52          HTML "<input "
53          Form_Parm_Type "text"
54          Form_Parm_Name Name
55          Form_Parm_Size Size
56          Form_Parm_ID Name
57          Form_Parm_MaxLength MaxLength
58          Form_Parm_Value Value
59          HTML ">"
60   
61         End Sub
62   
63         '----------------------------------------------------------------
64   
65    Sub Form_Password( Label, Name, MaxLength, Size, Value )
66   
67          Form_Label Label, Name
68   
69          HTML "<input "
70          Form_Parm_Type "password"
71          Form_Parm_Name Name
72          Form_Parm_Size Size
73          Form_Parm_ID Name
74          Form_Parm_MaxLength MaxLength
75          Form_Parm_Value Value
76          HTML ">"
77   
78         End Sub
79   
80         '----------------------------------------------------------------
81   
82    Sub Form_ScrollingText( Label, Name, Rows, Cols, Value )
83   
84          Form_Label Label, Name
85   
86          HTML "<textarea "
87          Form_Parm_Name Name
88          If Len(Rows) > 0 Then
89          HTML "rows=" & Rows & " "
90          End If
91          If Len(Cols) > 0 Then
92          HTML "cols=" & Cols & " "
93          End If
94          Form_Parm_ID Name
95          HTML ">"
96   
97          If Len(Value) > 0 Then
98          Display Value
99          End If
100   
101          HTML "</textarea>"
102   
103         End Sub
104   
105         '----------------------------------------------------------------
106   
107    Sub Form_ResetButton( Name, Value )
108   
109          HTML "<input "
110          Form_Parm_Type "reset"
111          Form_Parm_Value Value
112          Form_Parm_Name Name
113          HTML ">"
114   
115         End Sub
116   
117         '----------------------------------------------------------------
118   
119    Sub Form_CommandButton( Name, Value )
120   
121          HTML "<input "
122          Form_Parm_Type "button"
123          Form_Parm_Value Value
124          Form_Parm_Name Name
125          HTML ">"
126   
127         End Sub
128   
129         '----------------------------------------------------------------
130   
131    Sub Form_SubmitButton( Name, Value )
132          HTML "<input "
133          Form_Parm_Type "submit"
134          Form_Parm_Value Value
135          Form_Parm_Name Name
136          HTML ">"
137         End Sub
138   
139         '----------------------------------------------------------------
140   
141    Sub Form_RadioButton( Label, Name, Value, Checked )
142   
143          HTML "<input "
144          Form_Parm_Type "radio"
145          Form_Parm_Value Value
146          Form_Parm_Name Name
147          Form_Parm_ID Name & Value
148          If Len(Checked) > 0 Then
149          If Checked Then
150          HTML " checked "
151          End If
152          End If
153          HTML ">"
154   
155          Form_Label Label, Name & Value
156   
157         End Sub
158   
159         '----------------------------------------------------------------
160   
161    Sub Form_Checkbox( Label, Name, Value, Checked )
162   
163          Form_Label Label, Name
164   
165          HTML "<INPUT "
166          Form_Parm_Type "checkbox"
167          Form_Parm_Name Name
168          Form_Parm_Value Value
169          If Len( Checked ) > 0 Then
170          If Checked = True Then
171          HTML " checked "
172          End If
173          End If
174          HTML ">"
175          '
176         End Sub
177   
178         '----------------------------------------------------------------
179   
180    Sub Form_Begin( Action )
181   
182          HTML "<form "
183          HTML "method=post "
184          HTML "action =" & Chr(39) & Action & Chr(39) & " "
185          HTML ">"
186   
187         End Sub
188   
189         '----------------------------------------------------------------
190   
191    Sub Form_End( Name, Value )
192   
193          Form_HiddenField Name, Value
194          HTML "</FORM>"
195   
196         End Sub
197   
198         '----------------------------------------------------------------
199   
200    Sub Form_Table_Begin( Border, Width )
201          HTML "<table "
202          If Len(Border) > 0 Then
203          HTML "border=" & Chr(39) & Border & Chr(39) & " "
204          End If
205          Form_Parm_Width Width
206          HTML ">"
207         End Sub
208   
209         '----------------------------------------------------------------
210   
211    Sub Form_Table_End()
212          HTML "</table>"
213         End Sub
214   
215         '----------------------------------------------------------------
216   
217    Sub Form_Table_Row_Begin( Dummy, Align, VAlign )
218          HTML "<tr "
219          Form_Parm_Align Align
220          Form_Parm_VAlign VAlign
221          HTML ">"
222         End Sub
223   
224         '----------------------------------------------------------------
225   
226    Sub Form_Table_Row_End( Dummy )
227          HTML "</tr>"
228         End Sub
229   
230         '----------------------------------------------------------------
231   
232    Sub Form_Table_Cell_Begin( Dummy, Width, Align, VAlign )
233          HTML "<td "
234          Form_Parm_Width Width
235          Form_Parm_Align Align
236          Form_Parm_VAlign VAlign
237          HTML ">"
238         End Sub
239   
240         '----------------------------------------------------------------
241   
242   
243    Sub Form_Table_Cell_End( Dummy )
244          HTML "</td>"
245         End Sub
246   
247   
248         '----------------------------------------------------------------
249   
250   
251    Sub Form_ComboBox_Begin( Label, Name, Size, Multiple )
252          Form_Label Label, Name
253          HTML "<select "
254          Form_Parm_Name Name
255          Form_Parm_Size Size
256          If Len(Multiple) > 0 Then
257          If Multiple Then
258          HTML " multiple "
259          End If
260          End If
261          HTML ">"
262         End Sub
263       
264         '----------------------------------------------------------------
265       
266    Sub Form_ComboBox_Item( Value, Selected )
267          HTML "<option "
268          Form_Parm_Value Value
269          If Len(Selected) > 0 Then
270          If Selected Then
271          HTML " selected "
272          End If
273          End If
274          HTML ">"
275         End Sub
276   
277         '----------------------------------------------------------------
278       
279    Sub Form_ComboBox_End()
280          HTML "</select>"
281         End Sub
282   
283         '----------------------------------------------------------------
284       
285    Sub Form_Title( Title )
286          HTML "<title>"
287          Display Title
288    HTML "</title>&
289         End Sub
290       
291   
292         '----------------------------------------------------------------
293   
294    Sub Form_Center( Text )
295          HTML "<p align=" & Chr(39) & "center" & Chr(39) & ">"
296          Display Text
297          HTML "</p>"
298         End Sub
299   
300         '----------------------------------------------------------------
301   
302    Sub Form_Left( Text )
303          HTML "<p align=" & Chr(39) & "left" & Chr(39) & ">"
304          Display Text
305          HTML "</p>"
306         End Sub
307   
308         '----------------------------------------------------------------
309   
310    Sub Form_Right( Text )
311          HTML "<p align=" & Chr(39) & "right" & Chr(39) & ">"
312          Display Text
313          HTML "</p>"
314         End Sub
315       
316         '----------------------------------------------------------------
317       
318    Sub Form_Parm_Align( Align )
319          If Len(Align) > 0 Then
320          Select Case UCase(Align)
321          Case "L", "LEFT"
322          Display " align=" & Chr(39) & "left" & Chr(39) & " "
323          Case "C", "CENTER"
324          Display " align=" & Chr(39) & "center" & Chr(39) & " "
325          Case "R", "RIGHT"
326          Display " align=" & Chr(39) & "right" & Chr(39) & " "
327          Case Else
328          End Select
329          End If
330         End Sub
331   
332         '----------------------------------------------------------------
333       
334    Sub Form_Parm_VAlign( VAlign )
335          If Len(VAlign) > 0 Then
336          Select Case UCase(VAlign)
337          Case "T", "TOP"
338          Display " align=" & Chr(39) & "top" & Chr(39) & " "
339          Case "C", "CENTER"
340          Display " align=" & Chr(39) & "center" & Chr(39) & " "
341          Case "B", "BOTTOM"
342          Display " align=" & Chr(39) & "bottom" & Chr(39) & " "
343          Case Else
344          End Select
345          End If
346         End Sub
347       
348         '----------------------------------------------------------------
349       
350    Sub Form_Parm_Name( Name )
351          If Len(Name) > 0 Then
352          Display " name=" & Chr(39) & Name & Chr(39) & " "
353          End If
354         End Sub
355       
356         '----------------------------------------------------------------
357       
358    Sub Form_Parm_Value( Value )
359          If Len(Value) > 0 Then
360          Display " value=" & Chr(39) & Value & Chr(39) & " "
361          End If
362         End Sub
363   
364         '----------------------------------------------------------------
365       
366    Sub Form_Parm_Type( TypeValue )
367          If Len(TypeValue) > 0 Then
368          Display " type=" & Chr(39) & TypeValue & Chr(39) & " "
369          End If
370         End Sub
371       
372         '----------------------------------------------------------------
373   
374    Sub Form_Parm_Size( Size )
375          If Len(Size) > 0 Then
376          Display " size=" & Size & " "
377          End If
378         End Sub
379       
380         '----------------------------------------------------------------
381   
382    Sub Form_Parm_ID( ID )
383          If Len(ID) > 0 Then
384          Display " id=" & Chr(39) & ID & Chr(39) & " "
385          End If
386         End Sub
387   
388         '----------------------------------------------------------------
389   
390    Sub Form_Parm_MaxLength( MaxLength )
391          If Len(MaxLength) > 0 Then
392          Display " maxlength=" & MaxLength
393          End If
394         End Sub
395   
396         '----------------------------------------------------------------
397       
398    Sub Form_Parm_Length( Length )
399          If Len(Length) > 0 Then
400          Display " length=" & Length
401          End If
402         End Sub
403   
404         '----------------------------------------------------------------
405   
406    Sub Form_Parm_Width( Width )
407          If Len(Width) > 0 Then
408          Display " width=" & Width
409          End If
410         End Sub
411       
412         '----------------------------------------------------------------
413       
414    Sub Anchor_Display( TextToDisplay, HRef )
415          HTML "<a href=" & Chr(39) & HRef & Chr(39) & ">"
416          Display TextToDisplay
417          HTML "</a>"
418         End Sub
419   
420         '----------------------------------------------------------------
421       
422    Sub MenuItem ( TextToDisplay, HRef )
423          HTML "<ul>"
424          HTML "<li>"
425          HTML "<p "
426          Form_Parm_Align "Left"
427          Form_Parm_VAlign "Bottom"
428          HTML ">"
429          Anchor_Display TextToDisplay, HRef
430          HTML "</p>"
431          HTML "</li>"
432          HTML "</ul>"
433         End Sub
434   
435         '----------------------------------------------------------------
436       
437    Function FormatMoney( Amount )
438          '
439          ' Standard constants from the MS web site but not built
440          ' into VBScript's default constants.
441          '
442          Const TristateTrue = -1
443          Const TristateFalse = 0
444          Const TristateUseDefault = -2
445          '
446          If IsNull( Amount ) Then
447          FormatMoney = vbNullString
448          Else
449          FormatMoney = FormatCurrency( Amount, 2, TristateTrue _
450          , False, TristateTrue)
451          End If
452          '
453         End Function
454       
455         '----------------------------------------------------------------
456   %>


ASP Quick Lessons written by Charles M. Carroll
http://www.learnasp.com/learn/functionworkingdays.asp Page 207


functionworkingdays ASP Quick Lessons

Functions -- The WorkingDays function

This page demonstrates how to make a function and display it's results in your page.

   <title>functionworkingdays.asp</title>
   <body bgcolor="#FFFFFF">
   <%
   response.write "3 working days from today is " & dtaddWorkingDays(now(),3) & "<p>"
   %>

   2  working days from today is <%=dtaddWorkingDays(now(),2)%>
   </body>
   <%Function dtAddWorkingDays(dtStartDate, nDaystoAdd)
         'Adds working days based on a five day week
10         
11         Dim dtEndDate
12         Dim iLoop
13         
14         'First add whole weeks
15         dtEndDate=DateAdd("ww",Int(nDaysToAdd/5),dtStartDate)
16         
17         'Add any odd days
18         For iLoop = 1 To (nDaysToAdd Mod 5)
19          dtEndDate=DateAdd("d",1,dtEndDate)
20          'If Saturday increment to following Monday
21          If WeekDay(dtEndDate)=vbSaturday Then
22          'Increment date to following Monday
23          dtEndDate=DateAdd("d",2,dtEndDate)
24          End If
25         Next
26   dtAddWorkingDays=dtEndDate
27   End Function
28   %>


ASP Quick Lessons written by Charles M. Carroll
http://www.learnasp.com/learn/vbs5.asp Page 208


Subroutines Query2Table ASP Quick Lessons

VBScript 5 Highlights by Charles Carroll

Subroutines can save you having to repeat blocks of code. This code illustrates how we can build tables with minimal code in the main script and by including a file with a convenient subroutine.

Eval function

   <html><head>
   <title>vbs5eval.asp</title>
   </head>
   <body>
   <%
   x="2+2*3"
   response.write eval(x)
   %>

   </body>
10   </html>

Classes:

   <html><head>
   <title>vb5classes.asp</title>
   </head>
   <body>
   <%
   ' Create a myCustomer variable
   Dim myCustomer
   ' Create a new instance of the Customer Class
   ' and set the value of myCustomer to be that instance
10   set myCustomer = new Customer
11   ' Add a new customer
12   myCustomer.Add "Charles","Carroll"
13   ' Set their Email address
14   myCustomer.EmailName = "charlescarroll@aspalliance.com"
15   ' Set their credit limit
16   myCustomer.CreditLimit = 5000
17   ' Display the customers fullname
18   response.write myCustomer.FullName
19   
20   Class Customer
21         Public FirstName, LastName
22         Private nCreditLimit
23         Private strEmailName
24         Property Get EmailName
25          EmailName = strEmailName
26         End Property
27         Property Let EmailName ( strName)
28          StrEmailName = strName
29         End Property
30         Property Get FullName
31          FullName= FirstName & " " & LastName
32         End Property
33         Property Let CreditLimit ( s )
34          if s >= 0 then
35          nSalary = s
36          End If
37         End Property
38         Property Get CreditLimit
39          Salary = nSalary
40         End Property
41    Sub Add( First, Last )
42          FirstName = First
43          LastName = Last
44         End Sub
45    Function RaiseCreditLimit( Amount )
46          nCreditLimit = nCreditLimit + Amount
47          RaiseSalary = nSalary
48         End Function
49   End Class
50   %>

51   </body>
52   </html>

Execute Function:

   <html><head>
   <title>vbs5execute.asp</title>
   </head>
   <body>
   <%
   S  = "Sub Hi" & vbCrLf
   S  = S & " Response.write ""Hi""" & vbCrLf
   S  = S & "End Sub"
   Execute S
10   Call Hi()
11   %>

12   </body>
13   </html>

Regular Expressions

   <html><head>
   <title>vbs5reg.asp</title>&
   <body>
   <%
   
   address="joe@aol.com"
   validmail=checkemail(address)
   IF  validmail THEN
      response.write address & " is good!"
10   ELSE
11      response.write address & " is bad!"
12   END IF
13   
14   address="sallyaol.com"
15   validmail=checkemail(address)
16   IF  validmail THEN
17      response.write address & " is good!"
18   ELSE
19      response.write address & " is bad!"
20   END IF
21   
22   
23   FUNCTION CheckEmail(parmaddress)
24         set myRegExp = new RegExp
25         ' Set the pattern to check for a word followed by
26         ' an @ followed by a word
27         myRegExp.pattern = "\w+\@[.\w]+"
28         if myRegExp.Test(parmaddress) then
29          CheckEmail=True
30         else
31          CheckEmail=false
32         end if
33   END FUNCTION
34   %>

35   </body>
36   </html>

With

   <html><head>
   <title>vbs5with.asp</title>
   </head>
   <body>
   <%
   with response
      .write "Hi<br>"
      .write "how are you doing?<br>"
      .write "see you around"
10   end with
11   %>

12   </body>
13   </html>


ASP Quick Lessons written by Charles M. Carroll
http://www.learnasp.com/learn/txtread.asp Page 209


Text File Reading ASP Quick Lessons

Text File Reading

   <html><head>
   <TITLE>txtread.asp</TITLE>
   </head><body bgcolor="#FFFFFF">
   <%
   whichfile=server.mappath("/aspheader.asp")
   
   Set fs = CreateObject("Scripting.FileSystemObject")
   Set thisfile = fs.OpenTextFile(whichfile, 1, False)
   
10   counter=0
11   do  while not thisfile.AtEndOfStream
12      counter=counter+1
13      thisline=thisfile.readline
14      response.write thisline & "<br>"
15   loop
16   
17   thisfile.Close
18   set thisfile=nothing
19   set fs=nothing
20   %>

21   </body></html>


ASP Quick Lessons written by Charles M. Carroll
http://www.learnasp.com/learn/txtwrite.asp Page 210


Text File Writing from ASP Quick Lessons

Text File Writing by Charles Carroll

The following code snippets adds several lines to an ASCII file.

   <html><head>
   <TITLE>txtwrite.asp</TITLE>
   </head><body bgcolor="#FFFFFF">
   <%
   whichFN=server.mappath("/upload/tests/tempfile.txt")
   
   ' first, create the file out of thin air
   Set fstemp = server.CreateObject("Scripting.FileSystemObject")
   Set filetemp = fstemp.CreateTextFile(whichFN, true)
10   ' true = file can be over-written if it exists
11   ' false = file CANNOT be over-written if it exists
12   
13   filetemp.WriteLine("This is a brand new file!!!!")
14   filetemp.writeblanklines(3)
15   filetemp.WriteLine("This is the last line of the file we created!")
16   filetemp.Close
17   
18   ' Now open it and add some lines
19   forappending =8
20   set filetemp=fstemp.OpentextFile(whichFN, forappending)
21   filetemp.writeline "a line we added later"
22   filetemp.writeline "another line we added later..."
23   filetemp.close
24   
25   set filetemp=nothing
26   set fstemp=nothing
27   
28   If  err.number=0 then
29         response.write "File was appended sucessfully!"
30   else
31         response.write "VBScript Errors Occured!<br>"
32         response.write "Error Number=#<b>" & err.number & "</b><br>"
33         response.write "Error Desc. =<b>" & err.description & "</b><br>"
34         response.write "Help Path =<b>" & err.helppath & "</b><br>"
35         response.write "Native Error=<b>" & err.nativeerror & "</b><br>"
36         response.write "Error Source =<b>" & err.source & "</b><br>"
37         response.write "SQL State=#<b>" & err.sqlstate & "</b><br>"
38   end if
39   
40   
41   %>

42   </body></html>

This code displays the file we created:

   <html><head>
   <TITLE>txtwritedisplay.asp</TITLE>
   </head><body bgcolor="#FFFFFF">
   <%
   whichname="tempfile.txt"
   whichdir=Server.Mappath ("/upload/tests/")
   whichFN=whichdir & whichname
   forreading=1
   
10   Set fs = CreateObject("Scripting.FileSystemObject")
11   Set thisfile = fs.OpenTextFile(whichFN, forreading, False)
12   counter=0
13   do  while not thisfile.AtEndOfStream
14      counter=counter+1
15      thisline=thisfile.readline
16      response.write thisline & "<br>"
17   loop
18   thisfile.Close
19   
20   set thisfile=nothing
21   set fs=nothing
22   
23   %>

24   </body></html>


ASP Quick Lessons written by Charles M. Carroll
http://www.learnasp.com/learn/mb1.asp Page 211


Reading Parsing ASCII from ASP Quick Lessons

Reading/Parsing an ASCII File by Charles Carroll

Let us say you have an ASCII file of questions that you want to convert to HTML (listing below). The next page will show you the typical parsing code used for such a task.

   EI  At a party do you - interact with many, including strangers / interact with a few, known to you
   SN  Are you more - realistic than speculative / speculative than realistic
   SN  It is worse to - have your "head in the clouds" / be "in a rut"
   TF  Are you more impressed by - principles / emotions
   TF  Are you more drawn toward the - convincing / touching
   JP  Do you prefer to work - to deadlines / just "whatever"
   JP  Do you tend to choose - rather carefully / somewhat impulsively
   EI  At parties do you - stay late, with increasing energy / leave early, with decreased energy
   SN  Are you more attracted to - sensible people / imaginative people
10   SN  Are you more interested in - what is actual / what is possible
11   TF  In judging others are you more swayed by - laws than circumstances / circumstances than laws
12   TF  In approaching others is your inclination to be - objective / personal
13   JP  Are you more - punctual / leisurely
14   JP  Does it bother you more having things - incomplete / completed
15   EI  In your social groups do you - keep abreast of other's happenings / get behind on the news
16   SN  In doing ordinary things are your more likely to - do it the usual way / do it your own way
17   SN  Writers should - "say what they mean and mean what they say" / express things more by use of analogy
18   TF  Which appeals to you more - consistency of thought / harmonious human relationships
19   TF  Are you more comfortable in making - logical judgments / value judgmants
20   JP  Do you want things - settled and decided / unsettled and undecided
21   JP  Would you say you are more - serious and determined / easy-going
22   EI  In phoning do you - rarely question that it will all be said / rehearse what you'll say
23   SN  Facts - "speak for themselves" / illustrate principles
24   SN  Are visinaries - somewhat annoying / rather fascinating
25   TF  Are you more often - a cool-headed person / a warm-hearted person
26   TF  Is it worse to be - unjust / merciless
27   JP  Should one usually let events occur - by careful selection and choice / randomly and by chance
28   JP  Do you feel better about - having purchased / having the option to buy
29   EI  In company do you - initiate conversation / wait to be approached
30   SN  Common sense is - rarely questionable / frequently questionable
31   SN  Children often do not - make themselves useful enough / exercise their fantasy enough
32   TF  In making decisions do you feel more comfortable with - standards / feelings
33   TF  Are you more - firm than gentle / gentle than firm
34   JP  Which is more admirable - the ability to organize and be methodical / the ability to adapt and make do
35   JP  Do you put more value on the - definite / open-ended
36   EI  Does new and non routine interaction with others - stimulate and energize you / tax your reserves
37   SN  Are you more frequently - a practical sort of person / a fanciful sort of person
38   SN  Are you more likely to - see how others are useful / see how others see
39   TF  Which is more satisfying - to discuss an issue thoroughly / to arrive at agreement on an issue
40   TF  Which rules you more - your head / your heart
41   JP  Are you more comfortable with work that is - contracted / done on a casual basis
42   JP  Do you tend to look for - the orderly / whatever turns up
43   EI  Do you prefer - many friends with brief contact / a few friends with more lengthy contact
44   SN  Do you go more by - facts / principles
45   SN  Are you more interested in -production and distribution / design and research
46   TF  Which is more of a compliment - "There is a very logical person." / "There is a very sentimental person."
47   TF  Do you value in yourself more that you are - unwavering / devoted
48   JP  Do you more often prefer the - final and unalterable statement / tentative and preliminary statement
49   JP  Are you more comfortable - after a decision / before a decision
50   EI  Do you - speak easily and length with strangers / find little to say to strangers
51   SN  Are you more likely to trust your - experience / hunch
52   SN  Do you feel - more practical than ingenious / more ingenious than practical
53   TF  Which person is more to be complimented - one of clear reason / strong feeling
54   TF  Are you inclined more to be - fair minded / sysmpathetic
55   JP  Is it preferable mostly to -make sure things are arranged / just let things happen
56   JP  In relationships should most things to - renegotiable / random and circumstantial
57   EI  When the phone rings do you - hasten to get to it first / hope someone else will answer
58   SN  Do you prize more in yourself - a strong sense of reality / a vivid imagination
59   SN  Are you drawn more to - fundamentals / overtones
60   TF  Which seems the greater error - to be too passionate / to be too objective
61   JP  Do you see yourself as basically - the structured and scheduled / the unstructured and unscheduled
62   JP  Are you a person that is more - routinized than whimsical / whimsical than routinized
63   EI  Are you inclined to be - easy to approach / somewhat reserved
64   SN  In writings do you prefer - the more literal / the more figurative
65   SN  Is it harder for you to - identify with others / utilize others
66   TF  Which do you wish more for yourself - clarity of reason / strength of compassion
67   TF  Which is the greater fault - being indiscriminate / being critical
68   EI  Do you prefer the - planned event / unplanned event
69   JP  Do you tend to be more - deliberate than spontaneous / spontaneous than deliberate


ASP Quick Lessons written by Charles M. Carroll
http://www.learnasp.com/learn/mb2.asp Page 212


Reading Parsing ASCII from ASP Quick Lessons

Reading/Parsing an ASCII File #2 by Charles Carroll

Here is one implementation of parsing the file and converting it to on-the-fly HTML.

   <%option explicit%>
   <html>
   
   <head>
   <title>mb.asp</title>
   </head>
   
   <body bgcolor="#FFFFFF">
   
10   <form method="post" action="mbrespond.asp">
11   <%
12   dim answer1, answer2
13   dim char1, char2, counter
14   Dim fs, findslash, findhyphen
15   dim rest
16   Dim thisfile, thisline
17   dim question
18   dim whichfile
19   whichfile=server.mappath("mb.txt")
20   Set fs = CreateObject("Scripting.FileSystemObject")
21   Set thisfile = fs.OpenTextFile(whichfile, 1, False)
22   counter=0
23   do  while not thisfile.AtEndOfStream
24      counter=counter+1
25      thisline=thisfile.readline
26      char1=mid(thisline,1,1)
27      char2=mid(thisline,2,1)
28      rest=mid(thisline,3)
29   
30      findhyphen=instr(thisline,"-")
31      question=mid(rest,1,findhyphen-2)
32   
33      rest=mid(rest,findhyphen)
34      findslash=instr(rest,"/")
35      answer1=mid(rest,1,findslash-1)
36      answer2=mid(rest,findslash+1)
37   
38      'response.write char1 & "<br>"
39      'response.write char2 & "<br>"
40      'response.write rest & "<p>"
41      response.write question & "<br>"
42      'response.write answer1 & "<br>"
43      'response.write answer2 & "<p>"
44      %>

45       <p><input TYPE="radio" name="Q<%=counter%>" VALUE="U" CHECKED>Undecided<br>
46       <input TYPE="radio" name="Q<%=counter%>" VALUE="<%=char1%>"><%=answer1%><br>
47       <input TYPE="radio" name="Q<%=counter%>" VALUE="<%=char2%>"><%=answer2%></p>
48       <p><%
49   loop
50   thisfile.Close
51   set fs=nothing
52   %>
<input type="submit"></p>
53   </form>
54   </body>
55   </html>


ASP Quick Lessons written by Charles M. Carroll
http://www.learnasp.com/learn/mb3.asp Page 213


Reading Parsing ASCII from ASP Quick Lessons

Reading/Parsing an ASCII File #3 by Charles Carroll

Here is one implementation of scoring the HTML file.

   <%option explicit%>
   <html>
   
   <head>
   <title>mbrespond.asp</title>
   </head>
   <%
   dim key
   dim ecount, icount
10   dim scount, ncount
11   dim tcount, fcount
12   dim jcount, pcount
13   dim ucount
14   For Each Key in Request.Form
15      SELECT CASE request.form(key)
16      CASE "E"
17         ecount=ecount+1
18      CASE "I"
19         icount=icount+1
20      CASE "S"
21         scount=scount+1
22      CASE "N"
23         ncount=ncount+1
24      CASE "T"
25         tcount=tcount+1
26      CASE "F"
27         fcount=fcount+1
28      CASE "J"
29         jcount=jcount+1
30      CASE "P"
31         pcount=pcount+1
32      CASE "U"
33         ucount=ucount+1
34      END SELECT
35   Next
36   Response.write "E=" & ecount & "<br>"
37   Response.write "I=" & icount & "<br>"
38   Response.write "S=" & scount & "<br>"
39   Response.write "N=" & ncount & "<br>"
40   Response.write "T=" & tcount & "<br>"
41   Response.write "F=" & fcount & "<br>"
42   Response.write "J=" & jcount & "<br>"
43   Response.write "P=" & pcount & "<br>"
44   Response.write "U=" & ucount & "<br>"
45   %>

46   
47   <body bgcolor="#FFFFFF">
48   </body>
49   </html>


ASP Quick Lessons written by Charles M. Carroll
http://www.learnasp.com/learn/xmlmb.asp Page 214


dbtable

Myers Brigg Implemented with XLST
by Jelks Cabaniss jelks@jelks.nu

Parsing an ASCII file ala:

is a process improved considerably by XML as this replacement example written with XLST demonstrates.

You need MSXML3.  The May version was released yesterday: http://msdn.microsoft.com/downloads/webtechnology/xml/msxml.asp Click on the link that says "Download the May 2000 MSXML Technology Preview Release" (don't bother with the SDK from the other link).  It will download a file called "msxmlwr.exe", a self-extracting archive.  Right-click on it and extract the files into a temp folder.  From that temp folder, run "xmlinst.exe". Reboot. That will allow XSLT 1.0 stylesheets to run (replacing the old MS-XSL preview in IE5).

mbxml.asp is the main script. Simple enough.

   <!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>
   <title>mbxml.asp</title>
   <style type="text/css"><!--
   @media screen, projection {
       body { font-family: verdana, sans-serif; margin: 2% 5%; }
       h1 { font: 2.3em garamond, georgia, serif; color: maroon; }
10       p { font-size: .9em; margin-left: 2em; color: navy; }
11   }
12   -->
</style>
13   
14   </head>
15   <body>
16   <h1>Myer-Briggs Test</h1>
17   <form method="post" action="mbrespond.asp">
18   <%
19   Call ShowTest("mb.xml","mb.xsl")
20   
21   Function ShowTest(strXML,strStyleSheet)
22         Set objXML = CreateObject("MSXML.DOMDocument")
23         Set objXSL = CreateObject("MSXML.DOMDocument")
24         objXML.load(Server.MapPath(strXML))
25         objXSL.load(Server.MapPath(strStyleSheet))
26         Response.Write objXML.transformNode (objXSL)
27         Set objXML = Nothing
28         Set objXSL = Nothing
29   End Function
30   %>

31   <p><input type="submit" value="Check Scores!" /></p>
32   </form>
33   </body>
34   </html>
35   
36   

mb.xsl is the style sheet to style the questionare.

   <?xml version="1.0"?>
   <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
          version="1.0">
   
   <xsl:output method="xml" indent="yes"
          omit-xml-declaration="yes" />
   
   <xsl:template match="/">
       <xsl:for-each select="/questionairre/item">
10          <xsl:variable name="Pos" select="position()" />
11          <xsl:variable name="Num" select="concat('Q',$Pos)" />
12          <p><xsl:value-of select="concat($Pos,'. ', question)" />
13          &#8212;<br /><br />
14          <input type="radio" name="{$Num}" value="U"
15          checked="checked" />Undecided<br />
16          <xsl:for-each select="answer">
17          <input type="radio" name="{$Num}" value="{@code}" />
18          <xsl:value-of select="." /><br />
19          </xsl:for-each>
20          </p>
21       </xsl:for-each>
22   </xsl:template>
23   
24   </xsl:stylesheet>
25   

mb.xml is the data that powers the questionare.

   <?xml version="1.0"?>
   <questionairre type="MB">
       <item>
          <question>At a party do you</question>
          <answer code="E">interact with many, including strangers</answer>
          <answer code="I">interact with a few, known to you</answer>
       </item>
       <item>
          <question>Are you more</question>
10          <answer code="S">realistic than speculative</answer>
11          <answer code="N">speculative than realistic</answer>
12       </item>
13       <item>
14          <question>It is worse to</question>
15          <answer code="S">have your "head in the clouds"</answer>
16          <answer code="N">be "in a rut"</answer>
17       </item>
18       <item>
19          <question>Are you more impressed by</question>
20          <answer code="T">principles</answer>
21          <answer code="F">emotions</answer>
22       </item>
23       <item>
24          <question>Are you more drawn toward the</question>
25          <answer code="T">convincing</answer>
26          <answer code="F">touching</answer>
27       </item>
28       <item>
29          <question>Do you prefer to work</question>
30          <answer code="J">to deadlines</answer>
31          <answer code="P">just "whatever"</answer>
32       </item>
33       <item>
34          <question>Do you tend to choose</question>
35          <answer code="J">rather carefully</answer>
36          <answer code="P">somewhat impulsively</answer>
37       </item>
38       <item>
39          <question>At parties do you</question>
40          <answer code="E">stay late, with increasing energy</answer>
41          <answer code="I">leave early, with decreased energy</answer>
42       </item>
43       <item>
44          <question>Are you more attracted to</question>
45          <answer code="S">sensible people</answer>
46          <answer code="N">imaginative people</answer>
47       </item>
48       <item>
49          <question>Are you more interested in</question>
50          <answer code="S">what is actual</answer>
51          <answer code="N">what is possible</answer>
52       </item>
53       <item>
54          <question>In judging others are you more swayed by</question>
55          <answer code="T">laws than circumstances</answer>
56          <answer code="F">circumstances than laws</answer>
57       </item>
58       <item>
59          <question>In approaching others is your inclination to be</question>
60          <answer code="T">objective</answer>
61          <answer code="F">personal</answer>
62       </item>
63       <item>
64          <question>Are you more</question>
65          <answer code="J">punctual</answer>
66          <answer code="P">leisurely</answer>
67       </item>
68       <item>
69          <question>Does it bother you more having things</question>
70          <answer code="J">incomplete</answer>
71          <answer code="P">completed</answer>
72       </item>
73       <item>
74          <question>In your social groups do you</question>
75          <answer code="E">keep abreast of other's happenings</answer>
76          <answer code="I">get behind on the news</answer>
77       </item>
78       <item>
79          <question>In doing ordinary things are your more likely to</question>
80          <answer code="S">do it the usual way</answer>
81          <answer code="N">do it your own way</answer>
82       </item>
83       <item>
84          <question>Writers should</question>
85          <answer code="S">say what they mean and mean what they say</answer>
86          <answer code="N">express things more by use of analogy</answer>
87       </item>
88       <item>
89          <question>Which appeals to you more</question>
90          <answer code="T">consistency of thought</answer>
91          <answer code="F">harmonious human relationships</answer>
92       </item>
93       <item>
94          <question>Are you more comfortable in making</question>
95          <answer code="T">logical judgments</answer>
96          <answer code="F">value judgmants</answer>
97       </item>
98       <item>
99          <question>Do you want things</question>
100          <answer code="J">settled and decided</answer>
101          <answer code="P">unsettled and undecided</answer>
102       </item>
103       <item>
104          <question>Would you say you are more</question>
105          <answer code="J">serious and determined</answer>
106          <answer code="P">easy-going</answer>
107       </item>
108       <item>
109          <question>In phoning do you</question>
110          <answer code="E">rarely question that it will all be said</answer>
111          <answer code="I">rehearse what you'll say</answer>
112       </item>
113       <item>
114          <question>Facts</question>
115          <answer code="S">speak for themselves</answer>
116          <answer code="N">illustrate principles</answer>
117       </item>
118       <item>
119          <question>Are visionaries</question>
120          <answer code="S">somewhat annoying</answer>
121          <answer code="N">rather fascinating</answer>
122       </item>
123       <item>
124          <question>Are you more often</question>
125          <answer code="T">a cool-headed person</answer>
126          <answer code="F">a warm-hearted person</answer>
127       </item>
128       <item>
129          <question>Is it worse to be</question>
130          <answer code="T">unjust</answer>
131          <answer code="F">merciless</answer>
132   
133       </item>
134       <item>
135          <question>Should one usually let events occur</question>
136          <answer code="J">by careful selection and choice</answer>
137          <answer code="P">randomly and by chance</answer>
138       </item>
139       <item>
140          <question>Do you feel better about</question>
141          <answer code="J">having purchased</answer>
142          <answer code="P">having the option to buy</answer>
143       </item>
144       <item>
145          <question>In company do you</question>
146          <answer code="E">initiate conversation</answer>
147          <answer code="I">wait to be approached</answer>
148       </item>
149       <item>
150          <question>Common sense is</question>
151          <answer code="S">rarely questionable</answer>
152          <answer code="N">frequently questionable</answer>
153       </item>
154       <item>
155          <question>Children often do not</question>
156          <answer code="S">make themselves useful enough</answer>
157          <answer code="N">exercise their fantasy enough</answer>
158       </item>
159       <item>
160          <question>In making decisions do you feel more comfortable with</question>
161          <answer code="T">standards</answer>
162          <answer code="F">feelings</answer>
163       </item>
164       <item>
165          <question>Are you more</question>
166          <answer code="T">firm than gentle</answer>
167          <answer code="F">gentle than firm</answer>
168       </item>
169       <item>
170          <question>Which is more admirable</question>
171          <answer code="J">the ability to organize and be methodical</answer>
172          <answer code="P">the ability to adapt and make do</answer>
173       </item>
174       <item>
175          <question>Do you put more value on the</question>
176          <answer code="J">definite</answer>
177          <answer code="P">open-ended</answer>
178       </item>
179       <item>
180          <question>Does new and non routine interaction with others</question>
181          <answer code="E">stimulate and energize you</answer>
182          <answer code="I">tax your reserves</answer>
183       </item>
184       <item>
185          <question>Are you more frequently</question>
186          <answer code="S">a practical sort of person</answer>
187          <answer code="N">a fanciful sort of person</answer>
188       </item>
189       <item>
190          <question>Are you more likely to</question>
191          <answer code="S">see how others are useful</answer>
192          <answer code="N">see how others see</answer>
193       </item>
194       <item>
195          <question>Which is more satisfying</question>
196          <answer code="T">to discuss an issue thoroughly</answer>
197          <answer code="F">to arrive at agreement on an issue</answer>
198       </item>
199       <item>
200          <question>Which rules you more</question>
201          <answer code="T">your head</answer>
202          <answer code="F">your heart</answer>
203       </item>
204       <item>
205          <question>Are you more comfortable with work that is</question>
206          <answer code="J">contracted</answer>
207          <answer code="P">done on a casual basis</answer>
208       </item>
209       <item>
210          <question>Do you tend to look for</question>
211          <answer code="J">the orderly</answer>
212          <answer code="P">whatever turns up</answer>
213       </item>
214       <item>
215          <question>Do you prefer</question>
216          <answer code="E">many friends with brief contact</answer>
217          <answer code="I">a few friends with more lengthy contact</answer>
218       </item>
219       <item>
220          <question>Do you go more by</question>
221          <answer code="S">facts</answer>
222          <answer code="N">principles</answer>
223       </item>
224       <item>
225          <question>Are you more interested in</question>
226          <answer code="S">production and distribution</answer>
227          <answer code="N">design and research</answer>
228       </item>
229       <item>
230          <question>Which is more of a compliment</question>
231          <answer code="T">There is a very logical person.</answer>
232          <answer code="F">There is a very sentimental person.</answer>
233       </item>
234       <item>
235          <question>Do you value in yourself more that you are</question>
236          <answer code="T">unwavering</answer>
237          <answer code="F">devoted</answer>
238       </item>
239       <item>
240          <question>Do you more often prefer the</question>
241          <answer code="J">final and unalterable statement</answer>
242          <answer code="P">tentative and preliminary statement</answer>
243       </item>
244       <item>
245          <question>Are you more comfortable</question>
246          <answer code="J">after a decision</answer>
247          <answer code="P">before a decision</answer>
248       </item>
249       <item>
250          <question>Do you</question>
251          <answer code="E">speak easily and length with strangers</answer>
252          <answer code="I">find little to say to strangers</answer>
253       </item>
254       <item>
255          <question>Are you more likely to trust your</question>
256          <answer code="S">experience</answer>
257          <answer code="N">hunch</answer>
258       </item>
259       <item>
260          <question>Do you feel</question>
261          <answer code="S">more practical than ingenious</answer>
262          <answer code="N">more ingenious than practical</answer>
263       </item>
264       <item>
265          <question>Which person is more to be complimented</question>
266          <answer code="T">one of clear reason</answer>
267          <answer code="F">strong feeling</answer>
268       </item>
269       <item>
270          <question>Are you inclined more to be</question>
271          <answer code="T">fair minded</answer>
272          <answer code="F">sysmpathetic</answer>
273       </item>
274       <item>
275          <question>Is it preferable mostly to</question>
276          <answer code="J">make sure things are arranged</answer>
277          <answer code="P">just let things happen</answer>
278       </item>
279       <item>
280          <question>In relationships should most things to</question>
281          <answer code="J">renegotiable</answer>
282          <answer code="P">random and circumstantial</answer>
283       </item>
284       <item>
285          <question>When the phone rings do you</question>
286          <answer code="E">hasten to get to it first</answer>
287          <answer code="I">hope someone else will answer</answer>
288       </item>
289       <item>
290          <question>Do you prize more in yourself</question>
291          <answer code="S">a strong sense of reality</answer>
292          <answer code="N">a vivid imagination</answer>
293       </item>
294       <item>
295          <question>Are you drawn more to</question>
296          <answer code="S">fundamentals</answer>
297          <answer code="N">overtones</answer>
298       </item>
299       <item>
300          <question>Which seems the greater error</question>
301          <answer code="T">to be too passionate</answer>
302          <answer code="F">to be too objective</answer>
303       </item>
304       <item>
305          <question>Do you see yourself as basically</question>
306          <answer code="J">the structured and scheduled</answer>
307          <answer code="P">the unstructured and unscheduled</answer>
308       </item>
309       <item>
310          <question>Are you a person that is more</question>
311          <answer code="J">routinized than whimsical</answer>
312          <answer code="P">whimsical than routinized</answer>
313       </item>
314       <item>
315          <question>Are you inclined to be</question>
316          <answer code="E">easy to approach</answer>
317          <answer code="I">somewhat reserved</answer>
318       </item>
319       <item>
320          <question>In writings do you prefer</question>
321          <answer code="S">the more literal</answer>
322          <answer code="N">the more figurative</answer>
323       </item>
324       <item>
325          <question>Is it harder for you to</question>
326          <answer code="S">identify with others</answer>
327          <answer code="N">utilize others</answer>
328       </item>
329       <item>
330          <question>Which do you wish more for yourself</question>
331          <answer code="T">clarity of reason</answer>
332          <answer code="F">strength of compassion</answer>
333       </item>
334       <item>
335          <question>Which is the greater fault</question>
336          <answer code="T">being indiscriminate</answer>
337          <answer code="F">being critical</answer>
338       </item>
339       <item>
340          <question>Do you prefer the</question>
341          <answer code="E">planned event</answer>
342          <answer code="I">unplanned event</answer>
343       </item>
344       <item>
345          <question>Do you tend to be more</question>
346          <answer code="J">deliberate than spontaneous</answer>
347          <answer code="P">spontaneous than deliberate</answer>
348       </item>
349   </questionairre>


ASP Quick Lessons written by Charles M. Carroll
http://www.learnasp.com/learn/cl.asp Page 215


Content Linking Prev/Next

Content Linking Prev/Next

   <%
   Set NL = Server.CreateObject ("MSWC.NextLink")
   tocname="/learn/learn.txt"
   nextref=NL.GetNextURL(tocname)
   nextdes=NL.GetNextDescription(tocname)
   If  (NL.GetListIndex (tocname)>1) Then
      prevref=NL.GetPreviousURL(tocname)
      prevdes=NL.GetPreviousDescription(tocname)
   %>

10      Prev:<a href="<%=prevref%>"><%=prevdes%></a>&nbsp;&nbsp;Next:
11   <% End If %>
12   <a href="<%=nextref%>"><%=nextdes%></a>


ASP Quick Lessons written by Charles M. Carroll
http://www.learnasp.com/learn/cl2.asp Page 216


Content Linking TOC

Content Linking TOC

   <TITLE>cl2.asp</TITLE>
   <body bgcolor="#FFFFFF">
   <%
   Set TL = Server.CreateObject ("MSWC.NextLink")
   for i=1 to cint(TL.GetListCount("/learn/learn.txt"))%>

   Description:
   <%=TL.GetNthDescription ("/learn/learn.txt",i)%>,
   (URL=<%=TL.GetNthURL ("/learn/learn.txt",i)%>).
   Page <%=i%>.<p>
10   <% next%>
11   </body>
12   </html>


ASP Quick Lessons written by Charles M. Carroll
http://www.learnasp.com/learn/cl3.asp Page 217


Content Linking ListBox

Content Linking List Box by Charles Carroll

Here is a script that will turn the Content Linking elements into a pull-down list so people can arbitrarily jump from one topic to another....

   <HTML><HEAD><TITLE>cljump.asp</TITLE></HEAD>
   <body bgcolor="#FFFFFF">
   <FORM ACTION="cljumprespond.asp">
   <%
   Set TL = Server.CreateObject ("MSWC.NextLink")
   maxi= cint(TL.GetListCount("/learn/learn.txt"))
   %>

   <SELECT name="whichtopic">
   <OPTION SELECTED VALUE="">Select a Topic...
10   <%for i=1 to maxi%>
11   <OPTION value=
12   <%=TL.GetNthURL("/learn/learn.txt",i)%>
13   >
14   <%
15   desc=TL.GetNthDescription("/learn/learn.txt",i)
16   if  mid(desc,1,1)="*" then
17      desc=mid(desc,2)
18   else
19         desc="&nbsp;&nbsp;&nbsp;&nbsp;" & desc
20   end if
21   %>

22   <%=desc%>
23   <%next%>
24   </SELECT>&nbsp;&nbsp;<INPUT VALUE="Jump to Lesson" TYPE=submit></FORM>
25   </BODY>
26   </HTML>

The script named cljumprespond.asp that implements the jump looks like this:

   <%
   response.redirect request.querystring("whichtopic")
   %>


ASP Quick Lessons written by Charles M. Carroll
http://www.learnasp.com/learn/contentlinker.asp Page 218


Content Linker Library from LearnASP

Content Linker Enhanced w/Library by Charles Carroll

The Microsoft Content Linker component, see:
http://www.learnasp.com/iishelp/iis/htm/asp/comp7pmc.htm
allows you to use an ASCII file that can be used to setup previous-next page style presentations. I like it so much I created a whole top-level library to simplify using it.

Here is a sample of the library being used:

   <!--#include file="lib_toc_v4.asp"-->
   <%
   ' The Below Code is used to Test The Library if in doubt
   Call TOCpretty("/learn/learn.toc")
   ' Call TOC2Joust("/learn/learn.toc")
   ' Call TOC2Joust("/asplists/asplists.toc")
   ' x Call TOC2ColumnTable("/learn/learn.toc")
   ' Call TOCGrabSection("/learn/learn.toc","core.asp")
   ' Call TOCGrabSectionPretty("/learn/learn.toc","core.asp")
10   ' Call TOCGrabSectionLimit("/learn/learn.toc","core.asp",6)
11   ' Call TOCGrabSectionRandom("/learn/learn.toc","core.asp")
12   ' Call TOCGrabSectionRandomLimit("/learn/learn.toc","core.asp",4)
13   ' Call TOCList("/learn/learn.toc","/library/jump.asp")
14   ' response.write TOCPageType("/learn/core.asp")
15   ' response.write TOCPageType("/learn/dbtable.asp")
16   ' Call TOCSection2ListBox("/learn/learn.toc","core.asp")
17   %>

The Include file lib_toc_formats.asp looks like this:

   <%
   SELECT CASE lcase(parmformat)
   CASE "2coltoc"
      pad="&nbsp;&nbsp;&nbsp;&nbsp;"
      leftcell="<td bgcolor='#99CCFF'>"
      rightcell="<td bgcolor='#CCCCFF'>"
      linklook="<strong><B>%%linkhref%%</strong></b>"
      
      L1format="<tr>" & leftcell & linklook & "<td></tr>"
10      L2format="<tr><td>" & pad & "%%linkhref%%</td></tr>"
11      L1eformat="<tr>" & rightcell & linklook & "<td></tr>"
12      
13      TOCprefix="<table cols='1' border='1' width='50%'>"   
14      TOCsuffix="</table>"
15   CASE "joust"
16         q = chr(34)
17         linebreak=vbcrlf ' & "<br>"
18         
19         TOCprefix="<script language='JavaScript'>" & linebreak
20         TOCprefix=TOCprefix & "function initialise() {" & linebreak
21         TOCprefix=TOCprefix & "// Tell joust where to find the various index files it needs" & linebreak
22         TOCprefix=TOCprefix & "index1 = ""index.htm"";" & linebreak
23         TOCprefix=TOCprefix & "index2 = ""index2.htm"";" & linebreak
24         TOCprefix=TOCprefix & "index3 = ""index3.htm"";"   & linebreak
25         TOCprefix=TOCprefix & "theBrowser.hasDHTML=false;" & linebreak
26         TOCprefix=TOCprefix & "// Set up parameters to control menu behaviour" & linebreak
27         TOCprefix=TOCprefix & "theMenu.autoScrolling = true;" & linebreak
28         TOCprefix=TOCprefix & "theMenu.modalFolders = false;" & linebreak
29         TOCprefix=TOCprefix & "theMenu.linkOnExpand = false;" & linebreak
30         TOCprefix=TOCprefix & "theMenu.toggleOnLink = false;" & linebreak
31         TOCprefix=TOCprefix & "theMenu.showAllAsLinks = false;" & linebreak
32      TOCprefix=TOCprefix & "theMenu.focusOnLink = true;" & linebreak
33         TOCprefix=TOCprefix & "theMenu.savePage = true;" & linebreak
34         TOCprefix=TOCprefix & "theMenu.tipText = ""status"";" & linebreak
35         TOCprefix=TOCprefix & "theMenu.name = ""theMenu"";" & linebreak
36         TOCprefix=TOCprefix & "theMenu.container = ""self.menu"";" & linebreak
37         TOCprefix=TOCprefix & "theMenu.reverseRef = ""parent"";" & linebreak
38         TOCprefix=TOCprefix & "theMenu.contentFrame = 'text';" & linebreak
39         TOCprefix=TOCprefix & "theMenu.defaultTarget = 'text';" & linebreak
40         TOCprefix=TOCprefix & "// Initialise all the icons" & linebreak
41         TOCprefix=TOCprefix & "initOutlineIcons(theMenu.imgStore);" & linebreak
42         TOCprefix=TOCprefix & "// Now set up the menu with a whole lot of addMenu and addChild function calls" & linebreak
43   
44      TOCsuffix= "}" & linebreak & "</script>"
45   
46      L1format=linebreak & "var level%%sectioncount%%ID=-1;" & linebreak
47      L1format=L1format & "theMenu.addEntry(-1, "
48      L1format=L1format &   q & "folder" & q & ","
49      L1format=L1format &   q & "%%linkdesc%%" & q & ","
50      L1format=L1format &   q & q & ","
51      L1format=L1format &   q & "%%linkdesc%%" & " help" & q & ");"
52   
53      L2format="theMenu.addChild(level%%sectioncount%%" & "ID,"
54      L2format=L2format & q & "Document" & q & ","
55      L2format=L2format & q & "%%linkdesc%%" & q & ","
56      L2format=L2format & q & "%%fullurl%%?view=joust" & q & ","
57      L2format=L2format & q & "%%linkdesc%%" & " help" & q & ");"
58   
59      L1eformat=L1eformat & linebreak & "var level%%sectioncount%%ID=-1;" & linebreak
60      L1eformat=L1eformat & "theMenu.addEntry(-1, "
61      L1eformat=L1eformat &   q & "document" & q & ","
62      L1eformat=L1eformat &   q & "%%linkdesc%%" & q & ","
63      L1eformat=L1eformat &   q & "%%fullurl%%?view=joust" & q & ","
64      L1eformat=L1eformat &   q & "%%linkdesc%%" & " help" & q & ");"
65   CASE "section"
66      L1format=""
67      L2format="&nbsp;&nbsp;&nbsp;&nbsp;%%linkhref%%<br>"
68   CASE "sectionpretty"
69      pad="&nbsp;&nbsp;&nbsp;&nbsp;"
70   
71      L1format="<P><strong><B>%%linkhref%%</strong></b><br>"
72      L2format=pad & "%%linkhref%%&nbsp;(%%linkurl%%)<br>"
73   CASE "sectionplain"
74      L1format=""
75      L2format="&nbsp;&nbsp;&nbsp;&nbsp;%%linkhref%%<br>"
76   
77   CASE "listwhichtopic"
78      TOCprefix="<form action='/library/where.asp'>"
79      TOCprefix=TOCprefix & "<select name='whichtopic'>"
80      TOCsuffix="</select>"
81   
82      L1format=""
83      L2format="<option value='%%fullurl%%'>%%linkdesc%%</option>" & vbcrlf
84   CASE "listonly"
85      L1format=""
86      L2format="<option value='%%fullurl%%'>%%linkdesc%%</option>" & vbcrlf
87   CASE "pretty"
88      pad="&nbsp;&nbsp;&nbsp;&nbsp;"
89      L1format="<P><strong><B>%%linkhref%%</strong></b><br>"
90      L2format=pad & "%%linkhref%%&nbsp;(%%linkurl%%)<br>"
91   CASE ELSE
92      response.write "unknown format"
93   END SELECT
94   %>

95   

The Include file lib_toc_v4.asp looks like this:

   <%
   ' version 98
   ' bug: LimitRandom is sometimes one entry short
   ' draft: solution to caching issue, each call needs a moniker
   ' SUB TOCProcess is the Powerhouse here
   ' Almost every routine calls it
   ' It can return a string or response.write
   ' any content linker file and format output
   ' It can clip number of entries show and/or randomly arrange them
10   
11   
12   FUNCTION printview()
13      printview=False
14          printsession=lcase(session("printview"))
15          printrequest=lcase(request("printstatus"))
16      If printsession="y" OR printrequest="y" then
17         printview=True
18      end if
19   END FUNCTION
20   
21   SUB ShowTOC(parmTOC)
22      Call TOCPretty(parmTOC)
23   END SUB
24   
25   SUB TOC2ColumnTable(parmTOC)
26      Call TOCProcess(parmTOC,"","2coltoc",0,false,false,false)
27   END SUB
28   
29   SUB TOC2Joust(parmTOC)
30      Call TOCProcess(parmTOC,"","joust",0,false,false,false)
31   END SUB
32   
33   
34   SUB TOCGrabSection(parmTOC,parmTarget)
35      Call TOCProcess(parmTOC,parmTarget,"section",0,false,false,false)
36   END SUB
37   
38   SUB TOCGrabSectionLimit(parmTOC,parmTarget,parmHowMany)
39      Call TOCProcess(parmTOC,parmTarget,"section",parmHowMany,false,false,false)
40   END SUB
41   
42   SUB TOCGrabSectionPretty(parmTOC,parmTarget)
43      Call TOCProcess(parmTOC,parmTarget,"sectionpretty",0,false,false,false)
44   END SUB
45   
46   SUB TOCGrabSectionRandom(parmTOC,parmTarget)
47      Call TOCProcess(parmTOC,parmTarget,"sectionplain",0,true,false,false)
48   END SUB
49   
50   SUB TOCGrabSectionRandomLimit(parmTOC,parmTarget,parmHowmany)
51      Call TOCProcess(parmTOC,parmTarget,"sectionplain",parmHowMany,true,false,false)
52   END SUB
53   
54   SUB TOCLevel1(parmTOC)
55      Call TOCPretty(parmTOC)
56   END SUB
57   
58   SUB TOCList(parmTOC,parmForm)
59      Call TOCProcess(parmTOC,parmTarget,"listwhichtopic",0,true,false,false)
60   END SUB
61   
62   SUB TOClistshort(tocname,jumpname)
63      ' Legacy Code, rewrite or ditch
64         Set TL = Server.CreateObject ("MSWC.NextLink")
65         maxi= cint(TL.GetListCount(tocname))-1
66         adinfo="<a href='http://www.activeserverpages.com/contactus.asp'><strong>Contact Us...</strong></a>"
67         adinfo=""
68         response.write "<FORM ACTION='" & jumpname & "'>"
69      response.write "<a href='/search/'>"
70      response.write "<img src='/images/search.gif' alt='search' border='0' WIDTH='74' HEIGHT='24'></a>"
71      response.write "&nbsp;&nbsp;<a href='/contactus/index.asp'>"
72      response.write "<img src='/images/contact.gif' alt='contact' border='0' WIDTH='74' HEIGHT='24'></a>"
73        response.write "&nbsp;&nbsp;" & adinfo
74         response.write "&nbsp;&nbsp;<SELECT name='whichtopic'><OPTION SELECTED VALUE='/search>Search</option>"
75         for i=1 to maxi
76          desc=TL.GetNthDescription(tocname,i)
77          if mid(desc,1,1)="*" then
78          desc=mid(desc,2)
79          temp="<OPTION value='" & TL.GetNthURL(tocname,i) & "'>" & desc & "</option>"
80          response.write temp
81          end if
82         next
83         set TL=nothing
84      response.write "</SELECT>&nbsp;&nbsp;<INPUT VALUE='go!' TYPE='submit'>"
85         response.write "<a href='http://www.charlescarroll.com'><img src='/images/cc.gif' border='0' width='150' height='27' alt='Charles Carroll'></a></FORM>"
86   END SUB
87   
88   SUB TOCListSection(parmTOC,parmTarget)
89      Call TOCProcess(parmTOC,parmTarget,"listwhichtopic",0,false,false,false)
90   END SUB
91   
92   SUB TOCPretty(parmTOC)
93      allformat=L1format & L2Format   
94      Call TOCProcess(parmTOC,"","pretty",0,false,false,false)
95   END SUB
96   
97   SUB TOCSection2ListBox(parmTOC,parmTarget)
98      Call TOCProcess(parmTOC,parmTarget,"listonly",0,false,false,false)
99   END SUB
100   
101   SUB TOCshow(tocname)
102      printer="<img src='http://www.activeserverpages.com/learn/printer.gif' WIDTH='33' HEIGHT='29' BORDER='0'>"
103      printerlink="<a href='/learn/printswitch.asp'>" & printer & "</a>&nbsp;"
104   
105      barcolor="#CCCCFF"
106   
107      title=printer
108      title=title & "<font face='Arial'><small><strong>Tutorial Questions? write <a href='mailto:aspquicklessons@activeserverpages.com'>aspquicklessons@activeserverpages.com</a> for help!"
109      title=title & "</font></small></strong>"
110         sn=request.servervariables("script_name")
111   
112      tocname=lcase(tocname)
113      printstatus=lcase(session("printview"))
114      If request("printstatus")="y" then
115         printstatus="y"
116      end if
117         
118          if printstatus="y" then
119         imgnext="<img src='/learn/arrowright.gif' WIDTH='33' HEIGHT='14' BORDER='0'>"
120         imgprev="<img src='/learn/arrowleft.gif' WIDTH='33' HEIGHT='14' BORDER='0'>"
121         else
122         imgnext="<img src='http://www.activeserverpages.com/learn/next.gif' BORDER='0'>"
123         imgprev="<img src='http://www.activeserverpages.com/learn/previous.gif' BORDER='0'>&nbsp;"
124         end if
125         
126   
127      Set NL = Server.CreateObject ("MSWC.NextLink")
128      thispage=NL.GetListIndex(tocname)
129      lastpage=NL.GetListCount(tocname)
130      'response.write "thispage=" & thispage & "<br>"
131      If thispage=0 then
132               thisrefdesc=""
133      ELSE
134         thisrefDESC=NL.GetNthDescription(tocname,thispage)
135      END IF
136         
137          If thispage<>lastpage AND thispage<>0 then
138          nextref=NL.GetNextURL(tocname)
139          nextrefdesc=NL.GetNextDescription(tocname)
140          nextreflink="<a href='" & nextref & "'>" & nextrefdesc & "&nbsp;" & imgnext & "</a>"
141          nextlink="<a href='" & nextref & "'>" & imgnext & "</a>"
142          Else
143          imgnext=""
144          nextref=""
145          nextrefdesc=""
146          nextreflink=""
147          end if
148         
149          If (thispage>1) Then
150          prevrefdesc=NL.GetPreviousDescription(tocname)
151          prevref=NL.GetPreviousURL(tocname)
152          prevreflink="<a href='" & prevref & "'>" & imgprev & prevrefdesc & "</a>"
153          prevlink="<a href='" & prevref & "'>" & imgprev & "</a>"
154          else
155          imgprev=""
156          prevref=""
157          prevrefdesc=""
158          prevreflink=""
159          end if
160   
161      SELECT CASE printstatus
162         CASE "y"
163            ' print view!
164            host=request.servervariables("http_host")
165            host="http://www.learnASP.com"
166            response.write "<table border='0' width='100%' bgcolor='#CCCCFF'>"
167            response.write "<tr><td align='center'>" & printerlink
168            response.write "<font face='Arial'>&nbsp;<strong>"
169            response.write host & sn & "&nbsp;&nbsp;by Charles M. Carroll</strong></font><br>"
170            response.write prevlink & "&nbsp;&nbsp;"
171            response.write "<font face='Arial' size='+1'><strong>Page " & thispage & "</strong></font>"
172            response.write nextlink
173                response.write "</td></tr></table>"
174         CASE ELSE
175            response.write "<table border='0' width='100%'>"
176            response.write "<tr><td width='50%' bgcolor='#FFCC66'>"
177            response.write "<font size='+1'><strong>" & thisrefdesc & "</strong>"
178            response.write "</td>"
179            response.write "<td width='50%' bgcolor='#FFCC66'>"
180            response.write "<strong><small>"
181          customTOC=false
182            IF instr(tocname,"learn.toc")>0 THEN
183               customTOC=TRUE%>

184               <!--#include virtual="/learn/toolbar.asp"-->
185            <%END IF
186            IF instr(tocname,"asplists.toc")>0 THEN
187               customTOC=TRUE%>

188               <!--#include virtual="/asplists/toolbar.asp"-->
189            <%END IF
190            if customTOC=false THEN
191                 response.write "<a href='toc.asp'>Table of Contents</a>&nbsp;&nbsp;"
192                response.write "<a href='/library/printswitch.asp'>PrintView</a>"
193            END IF
194            response.write "</small></strong></td></tr>"
195            
196            response.write "<tr>" & "<td width='50%' bgcolor='" & barcolor & "'>"
197          response.write "<strong>" & prevreflink & "</strong></td>"
198            
199            response.write "<td width='50%' bgcolor='" & barcolor & "' align='right'>"
200            response.write "<strong>" & nextreflink & "</strong>"
201            response.write "</td></tr></table>"
202      END SELECT
203         set NL=nothing
204   end sub
205   
206   FUNCTION TOCPageType(parmPageURL)
207      ' Returns "page" or "toc"
208         whichfile=server.mappath(parmpageURL)
209         Set fs = CreateObject("Scripting.FileSystemObject")
210         If fs.fileexists(whichfile) THEN
211         ' do nothing
212         ELSE
213               response.write "Error, Non-existent File="
214               response.write whichfile & "<br>" & vbcrlf
215               exit function
216         END IF
217         Set thisfile = fs.OpenTextFile(whichfile, 1, False)
218         tempSTR=lcase(thisfile.readall)
219         TOCPageType="page"
220         IF instr("tocsubject.asp",tempSTR)>0 THEN
221               TOCpageType="toc"
222            END IF
223         IF instr(tempSTR,"mutanttoc.asp")>0 THEN
224               TOCpageType="toc"
225            END IF
226         IF instr(tempSTR,"mutantsection.asp")>0 THEN
227               TOCpageType="toc"
228            END IF
229         thisfile.Close
230         set thisfile=nothing
231         set fs=nothing   
232   END FUNCTION
233   
234   SUB TOCProcess(parmDIR,parmTargets,parmFormat,parmLimit,parmRandom,byref parmString,parmDebug)
235      ' parmDIR can be "/learn" or "/learn/learn.toc"
236      ' parmtarget can be "" or a filename i.e. "test.asp"
237      ' parmFormat
238      ' L1-<b><strong>-</b></strong><p>-
239      ' L2-&nbsp;&nbsp;&nbsp;&nbsp;-<br>-
240      ' parmLimit
241      ' maximum items (0= all)
242      ' parmRandom
243      ' True = Randomize order
244      ' False = original order
245      ' parmString
246      ' True = Assign output to passed variable
247      ' False = DisplayOutput normally
248      
249      DIM count, countmax, FullURL, Issection
250      DIM Level, Linker, LinkDesc, LinkURL, LinkHREF
251      DIM NameSection, pad
252      
253      ' First deal with parmDIR
254      tocname=lcase(parmdir)
255      IF instr(tocname,".toc")=0 THEN
256         tocname=parmDIR & parmDIR & ".toc"
257         TOCDIR=parmDIR
258      ELSE
259         tocname=parmDIR
260      END IF
261      If parmdebug=true THEN
262         response.write "TOCname=" & TOCname & "<br>"
263      END IF
264      
265      ' Now extract TOCDIR
266      TOCDir=replace(TOCDIR,".toc","")
267      findslash=instr(2,TocName,"/")
268      tocDIR=mid(TocName,1,findslash-1)
269      If parmdebug=true THEN
270         response.write "TOCdir=" & tocDIR & "<br>"
271      END IF
272      
273      ' Now extract section target
274      Sectiontarget=lcase(parmTargets)
275      If parmdebug=true THEN
276         response.write "sectiontarget=" & sectiontarget & "<br>"
277      END IF
278      
279      ' Now extract formats
280      %>

281      <!--#include file="lib_toc_formats.asp"-->
282      <%
283      IF L1format="" THEN
284         skipL1=TRUE
285      END IF
286      L1emptystring=L1eformat
287      L1string=L1format
288      L2string=L2format
289      IF L1eformat="" THEN
290         L1emptystring=L1string
291      END IF
292      
293      If parmdebug=true THEN
294         response.write "L1string=" & server.htmlencode(L1string) & "<br>"
295         response.write "L2string=" & server.htmlencode(L2string) & "<br>"
296   
297         'response.end
298         END IF
299         
300         displayoutput=true
301         If parmLimit>0 THEN
302         displayoutput=false
303      ELSE
304         parmLimit=0
305         END IF
306            If parmString=TRUE OR parmRandom=TRUE THEN
307         displayoutput=false
308      END IF
309      
310         ' Now work on the items
311         Set Linker = Server.CreateObject ("MSWC.NextLink")
312         countmax=cint(Linker.GetListCount(tocname))
313         redim preserve thelinks(countmax)
314         thelinkscount=0
315         
316         If displayoutput=TRUE THEN
317         response.write TOCprefix
318      END IF
319         for counter=1 to countmax
320         ' SETUP
321               LinkDesc=Linker.GetNthDescription(tocname,counter)
322               LinkURL =Linker.GetNthURL(tocname,counter)
323         FullURL =TocDir & "/" & LinkURL
324         
325               IF mid(Linkdesc,1,1)="*" THEN
326                     linkDesc=mid(linkDesc,2)
327                     NameSection=lcase(linkURL)
328                     docType="L1"
329                If counter<>countmax THEN
330                   LinkDescNext=Linker.GetNthDescription(tocname,counter+1)
331                    IF mid(LinkdescNext,1,1)="*" THEN
332                       doctype="L1empty"
333                  END IF
334                END IF   
335                sectioncount=sectioncount+1
336               ELSE
337               docType="L2"
338         END IF
339         IF SectionTarget="" THEN
340               ' nothing to do
341         ELSE
342            IF SectionTarget<>NameSection THEN
343               doctype="skip"
344            END IF      
345         END IF
346         
347         IF doctype="L1" AND skipL1=TRUE THEN
348            doctype="skip"
349         END IF
350         
351         LinkHREF="<a href='" & FullURL & "'>" & linkDesc & "</a>"
352         pagecounter=pagecounter+1
353         
354         ' Fixes " problem inside Desc
355         linkdesc=replace(linkdesc,"""","&quot;")
356         
357         ' Now stuff the variables
358         L1output=replace(L1string,"%%linkhref%%",LinkHREF)
359         L1output=replace(L1output,"%%linkdesc%%",LinkDesc)
360         L1output=replace(L1output,"%%linkurl%%",LinkURL)
361         L1output=replace(L1output,"%%fullurl%%",fullURL)
362         L1output=replace(L1output,"%%pagecounter%%",pagecounter)
363         L1output=replace(L1output,"%%sectioncount%%",sectioncount)
364   
365         L1emptyoutput=replace(L1emptystring,"%%linkhref%%",LinkHREF)
366         L1emptyoutput=replace(L1emptyoutput,"%%linkdesc%%",LinkDesc)
367         L1emptyoutput=replace(L1emptyoutput,"%%linkurl%%",LinkURL)
368         L1emptyoutput=replace(L1emptyoutput,"%%fullurl%%",fullURL)
369         L1emptyoutput=replace(L1emptyoutput,"%%pagecounter%%",pagecounter)
370         L1emptyoutput=replace(L1emptyoutput,"%%sectioncount%%",sectioncount)
371   
372         L2output=replace(L2string,"%%linkhref%%",LinkHREF)
373         L2output=replace(L2output,"%%linkdesc%%",LinkDesc)
374         L2output=replace(L2output,"%%linkurl%%",LinkURL)
375         L2output=replace(L2output,"%%fullurl%%",fullURL)
376         L2output=replace(L2output,"%%pagecounter%%",pagecounter)
377         L2output=replace(L2output,"%%sectioncount%%",sectioncount)
378         
379         SELECT CASE lcase(doctype)
380            CASE "l1"
381               If displayoutput=TRUE THEN
382                  response.write L1output & vbcrlf
383               END IF
384               thelinks(thelinkscount)=L1output
385               thelinkscount=thelinkscount+1
386            CASE "l1empty"
387               If displayoutput=TRUE THEN
388                  response.write L1emptyoutput & vbcrlf
389               END IF
390               thelinks(thelinkscount)=L1emptyoutput
391               thelinkscount=thelinkscount+1
392            CASE "l2"
393               IF displayoutput=TRUE THEN
394                  response.write L2output & vbcrlf
395               END IF
396               thelinks(thelinkscount)=L2output
397               thelinkscount=thelinkscount+1
398            CASE "skip"
399               ' nothing to do
400         END SELECT      
401      NEXT
402         If displayoutput=TRUE THEN
403         response.write TOCsuffix
404      END IF
405      set linker=nothing
406      
407      
408      ' Re-arrange the output array if requested
409      IF parmRandom=TRUE THEN
410         FOR shuffler=1 TO 3
411            FOR counter=0 to thelinkscount-1
412               randomize   
413               randomnum=int(rnd*thelinkscount)
414               randchoice=thelinks(randomnum)
415               lastchoice=thelinks(thelinkscount)
416               thelinks(thelinkscount)=randchoice
417               thelinks(randomnum)=lastchoice
418            NEXT
419         NEXT
420      END IF
421      
422      If parmString=TRUE THEN
423         displayoutput=false
424      END IF
425      
426      ' some calls want the string set and no display output
427      IF parmstring=TRUE THEN
428         IF parmLimit>0 THEN
429            parmstring=TOCprefix
430            FOR counter=0 TO parmLimit-1
431               parmString=parmString & thelinks(counter)
432            NEXT
433            parmString=ParmString & TOCsuffix
434         END IF
435         IF parmLimit=0 THEN
436            parmString=TOCprefix
437            FOR counter=0 to thelinkscount-1
438               parmString=parmString & thelinks(counter)
439            NEXT
440            parmString=ParmString & TOCsuffix
441         END IF
442         EXIT SUB
443      END IF
444      
445      ' Since they don't want a string lets display what they want
446      IF parmLimit>0 AND displayoutput=false THEN
447         response.write TOCprefix
448         FOR counter=0 TO parmLimit-1
449            response.write thelinks(counter) & vbcrlf
450         NEXT
451         response.write TOCsuffix
452      END IF
453      ' Show All Output If Needed
454      IF parmLimit=0 AND displayoutput=false THEN
455         response.write TOCprefix
456         FOR counter=0 TO thelinkscount-1
457            response.write thelinks(counter) & vbcrlf
458         NEXT
459         response.write TOCsuffix
460      END IF
461   END SUB
462   %>

Here is what the ASCII file it uses looks like:

   index.asp   *ASP Quick Lessons - Table of Contents
   
   credits.asp   *Credits
   
   core.asp   *Core Ideas
   whatis.asp   What is ASP? Obtaining The Software
   aspinstall.asp   AspInstall listserver
   whatisexample.asp   Simple ASP Page, Server Scripting
   docs.asp   MS Online Documentation
10   res.asp   Response: Basics
11   res2.asp   Response: Buffers, Redirect
12   res3.asp   Response: Redirection
13   res4.asp   Response: Quotes & Special Characters
14   res5.asp   Response: Encoding URLs, HTML
15   inc.asp   Include: Basics
16   includedynamic.asp   Include: Dynamic FileName
17   includeasphttp.asp   Includes: Other Sites, Dynamic FileNames
18   incwin2k.asp   Include/Redirects: New Win2k Commands
19   booksample.asp   Include: Books Sample Exercise
20   booksample2.asp   More Book Sample Exercises
21   formatnumbers.asp   Format: Numbers #1
22   formatnumbers2.asp   Format: Numbers #2
23   formatdates.asp   Format: Dates #1
24   datetime.asp   Date/Time on ASP Pages by Tony Arguelles
25   DoLoop.asp   Loops: DO WHILE/UNTIL #1
26   DoLoop2.asp   Loops: Timeouts #2
27   DoLoop3.asp   Loops: Intercepting Timeouts #3
28   server.asp   Server Variables: Popular Ones
29   server2.asp   Server Variables: Domain/Host Name
30   serverall.asp   Server Variables: Displaying All
31   randomadvice.asp   Random Content/Rotating Info
32   bc.asp   Browscap: Basics
33   bcdetails.asp   Browscap: Intricate Details
34   aspbrowserheck.asp   Listserver for Browser Problems
35   
36   statemanagement.asp   *State Management
37   stateintro.asp   State Management Introduction
38   sessionswhat.asp   What are ASP Sessions?
39   sessionsapps.asp   Application Data
40   speedappdata.asp   Application Data: Worlds Fastest ListBox
41   xmlfastlist.asp   XML, Database Caches - Fast Retrieval
42   nodbsession.asp   Say No To Databases w/Sessions or Application scope
43   sessionoverview.asp   Session Overview & Myths
44   globalproblems.asp   Sessions: Global.asa and Scalability
45   global.asp   Sessions: Global.asa Events
46   statemore.asp   Global.asa, Sessions, Custom Stats Resources
47   stateproscons.asp   State Methods: Pros and Cons
48   hidden.asp   Pass Data w/Hidden Fields
49   cookies.asp   Pass Data w/Cookies
50   statesessions.asp   Pass Data w/Session Vars
51   statedb.asp   Pass Data w/ID tied to database
52   aspstatemanagement.asp   [aspStateManagement] Listserver
53   
54   Form.asp   *Forms/Decisions
55   formintro.asp   Forms: Introduction
56   formtextbox.asp   Forms: Text Box
57   formtextarea.asp   Forms: Text Area
58   formcheckbox.asp   Forms: Check Box
59   formradio.asp   Forms: Radio Buttons
60   formlistbox.asp   Forms: List Box
61   case.asp   Forms: CASE syntax #1
62   case2.asp   Forms: CASE syntax #2
63   if.asp   Forms: IF syntax #1
64   if2.asp   Forms: IF syntax #2
65   if3.asp   Forms: IF syntax #3
66   if4.asp   Forms: IF syntax #4
67   formforeach.asp   Forms: For Each Iteration
68   formsubmitself.asp   Form - Submit To Self'
69   formactionchange.asp   Form - Change Action on Fly
70   
71   
72   database.asp   *Databases
73   dbsimple.asp   Displaying Table w/Simple Code
74   dblist.asp   List Box Displayed Generically
75   dblistmore.asp   Database to ListBox Online Resources
76   dbopen.asp   DSNLess Connections
77   dsn1.asp   DSN Setup #1 by Rob Martinson
78   dsn2.asp   DSN Setup #2 by Rob Martinson
79   dsn3.asp   DSN Setup #3 by Rob Martinson
80   dsn4.asp   DSN Setup #4 by Rob Martinson
81   dsn5.asp   DSN Setup #5 by Rob Martinson
82   dsn6.asp   DSN Setup #6 by Rob Martinson
83   dbfull1.asp   Full Cycle #1 Show/Edit/Update
84   dbfull2.asp   Full Cycle #2 Show/Edit/Update
85   dbfull3.asp   Full Cycle #3 Show/Edit/Update
86   dbtroubleshoot2.asp   SQL Mistakes Everyone Makes
87   dbtable.asp    DB: Table Displayed Generically
88   dbtablegetstring.asp   Getstring to display database table
89   dbtablegetrows.asp   Getrows to display database table
90   dbtablegetrowsnonum.asp   GetRows w/no Numbers
91   dbtabledisconnected.asp   Disconnected Recordsets, Display Table
92   dbtablemore.asp   DB: More ways To Display Tables
93   genericdb.asp   DB: Generic DB by Eli Robillard
94   aspgenericdb.asp   Generic DB Listserver
95   dbconvert.asp   DB: Converting a DB to a Comma-Delimited file
96   dbSQLdelete.asp   DB: Deleting a Record w/SQL
97   accesstest.asp   DB: Access Scalability
98   dbtablepaged.asp   ADO: Paging Records
99   dbmaxrecs.asp   ADO: Limiting Number of Records
100   dbcount.asp    ADO: Count Records in Query
101   adocursortypes.asp   ADO: Cursor Types by Phil Paxton
102   dbnewrec.asp    ADO: Input Form
103   dbnewSQL.asp    ADO: Input Form, added w/SQL
104   dbnewADO.asp    ADO: Input Form, Added w/ADO .addnew
105   dbtablelists.asp   ADO: Tables within Databases
106   dbschemas.asp   ADO: Schemas to access table lists
107   dbschemasall.asp   ADO: Schemas to access All Data
108   db1parm.asp   ADO: Show Table,1 param
109   dbupdate.asp   ADO: Update/edit Record
110   dbtroubles.asp   DB: Troubleshooting Part 1
111   dbtroubles2.asp   DB: Troubleshooting Part 2
112   
113   SQL.asp   *SQL Basics, Searching Databases
114   SQLtroubles.asp   SQL Troubles
115   SQLexamples.asp   SQL: Example Tables
116   SQLwhere.asp    SQL: Where Clause Basics
117   SQLwhere2.asp    SQL: Where Clause Examples
118   SQLwhereform1.asp   SQL: Search Forms #1
119   SQLwhereform2.asp   SQL: Search Forms #2
120   SQLwhereform3.asp   SQL: Search Forms #3
121   SQLandor.asp   SQL: Search AND/OR Operators
122   SQLandor2.asp   SQL: Search AND/OR Examples
123   SQLcount.asp   SQL: COUNT, GROUPBY
124   SQLaggregate.asp   SQL: SUM, MIN, AVE, MAX
125   dbjoin.asp   SQL Joins by Aaron Alexander
126   
127   rsfast.asp   *RSFAST: Lightning Fast Database Library
128   rsfast-intro.asp   RSFast Library Introduction
129   rsfast-table.asp   Table Display Fast
130   rsfast-table-cached.asp   Table Display Fast + Caching
131   rsfast-lists.asp   Listbox Display Fast
132   rsfast-lists-cached.asp   Listbox Display Fast + Caching
133   rsfast-templates.asp   Templates for any look Fast
134   rsfast-lists-debug.asp   Debug Info helps troubleshoot
135   rsfast-lib.asp   Library Source Code
136   rsfast-cache.asp   caching Method Explained
137   rsfast-newfeatures.asp   New Features for Future Versions
138   
139   editors.asp   *Editors Used With ASP
140   aspexpress.asp   ASPExpress: HOT ASP Editor
141   admunsen.asp   Visual Interdev + Admunsen Resources
142   aspvisualinterdev.asp   Visual Interdev Listserver
143   homesite.asp   Homesite: HTML editor
144   dreamweaver.asp   DreamWeaver: HTML and Script Editor
145   
146   components.asp   *Essential Commercial Components
147   aspdb1.asp   ASPDB: Displaying Data
148   aspdb2.asp   ASPDB: Editing, Adding Data
149   bhbrowtype.asp   BrowserHawk: Determing Browser Type
150   bhaol.asp   AOL detection w/BrowserHawk
151   bhwallet.asp   MS-Wallet w/BrowserHawk
152   bhresolveip.asp   Reverse DNS lookups w/BrowserHawk
153   bhframes.asp   BrowserHawk - Frame support
154   bhflash.asp   Flash Detection w/BrowserHawk
155   serverobjectsmail.asp   ServerObject Mail: Simple Example
156   formsendmail.asp   ServerObject: Mailing Form w/ASPMail
157   aspmail.asp   3rd Party Mail, CDO/CDONTS Listserver
158   uploadsimple.asp   SA: File Upload, Simple Example
159   uploadmultipart.asp   SA: File Upload, Multi-part form
160   uploadlimitsize.asp   SA: File Upload, Limit Size
161   uploadmanyfiles.asp   SA: File Upload, Many Files
162   aspsoftartisans.asp   Upload/Soft-Artisans Listserver
163   perfcounters.asp   Perf Counters on ASP page
164   
165   authenticate.asp   *Authentication & Security
166   authenticateoverview.asp   Authenticate: Overview by Kevin Flick
167   authenticatecomparisons.asp   Authenticate: Comparison by Kevin Flick
168   authenticatentcr.asp   Authenticate: NT Challenge/Response by Kevin Flick
169   authenticatebasic.asp   Authenticate: Basic Authentication by Kevin Flick
170   authenticatecookies.asp   Authenticate: Cookies by Kevin Flick
171   authenticatecertificate.asp   Authenticate: Certificates by Kevin Flick
172   authenticatebuild.asp   Authenticate: Build Your Own by Kevin Flick
173   security.asp   Authenticate: Protect Pages via Login #1
174   security2.asp   Authenticate: Protect Pages via Login #2
175   authenticate3rdparty.asp   Authenticate: 3rd Party by Kevin Flick
176   aspflicks.asp   Authentix Flicks Support Listserver
177   
178   troubles.asp   *Troubleshooting, Error Trapping
179   errors1.asp   Errors: Basics
180   errors2.asp   Errors: More Ways To Trap
181   errormore.asp   Errors: Resources Online
182   dbtablewitherrortrap.asp   Errors: Trapping EVERY Error
183   debug1.asp   Debug variables Easy Way
184   dbtroubleshoot.asp   Errors: DB Error Information Trapping
185   FAQdbUpdate.asp   DBFAQ: Operation must use Updatable Query
186   FAQdbSinglequote.asp   DBFAQ: User Entered ' in field
187   FAQdbLIKE.asp   DBFAQ: LIKE operator * not working
188   FAQdbMEMO.asp   DBFAQ: retrieving MEMO/BLOBs generates error
189   FAQdbSQLSyntax.asp   DBFAQ: Syntax Error in SQL Statement
190   debug2.asp   SQL Debugging Made Easy
191   dbtroubleshootopen.asp   Errors: Trapping Open Connections
192   asptroubles.asp   Troubleshoot: Getting Help from Lists!
193   asptroubles2.asp   Troubleshoot: Worldwide
194   asptroubles3.asp   Troubleshoot: Specialized
195   versioncheck.asp   Troubleshoot: Version of ASP Sofware
196   componentchecker.asp   Troubleshoot: Registered Components
197   connectioninfo.asp   Troubleshoot: DB Drivers by Christophe Wille
198   PWS.asp   PWS: Personal Web Server Introduction
199   
200   qualitycode.asp   *Code w/all ASP Features. Quality, Re-usable Code
201   strings.asp   Strings: Core Functions
202   stringsplit.asp   Strings: SPLIT Function
203   stringreplace.asp   Strings: REPLACE Function
204   stringjoin.asp   Strings: JOIN Function
205   arrays.asp   Arrays: Basics
206   arrays2.asp   Arrays: Variable Size
207   arrays3.asp   Arrays: Best Way To Load
208   arraysmore.asp   Arrays: Resources Online
209   dictionary.asp   Dictionary Objects
210   getrowsultimate.asp   Getrows Ultimate!
211   subdates.asp   Subroutine: Working with Dates #1
212   subdates2.asp   Subroutine: Working with Dates #2
213   subdbtable.asp   Subroutine: Query2Table
214   subdblist.asp   Subroutine: Query2List
215   subreusable.asp   Subroutine: Highly Reusable
216   subdictionary.asp   Subroutines w/Dictionary Objects
217   getrowsultimate.asp   Getrows Ultimate!
218   subDBlistbest.asp   Subroutine: List Box w/optional params
219   libhtml.asp   Subroutine: Abstract HTML by Phil Paxton
220   functionworkingdays.asp   Function: Working Days
221   vbs5.asp   New Features in VBScript version5
222   txtread.asp   Text Files: Reading Them off Server
223   txtwrite.asp   Text Files: Writing Them on Server
224   mb1.asp   Text Files: Meyers-Briggs parsing #1
225   mb2.asp   Text Files: Meyers-Briggs parsing #2
226   mb3.asp   Text Files: Meyers-Briggs parsing #3
227   xmlmb.asp   XML/XLST Myers-Briggs example
228   cl.asp   Content Linker: Prev/Next Page
229   cl2.asp   Content Linker: Table of Contents
230   cl3.asp   Content Linker: Listbox of contents
231   contentlinker.asp   Content Linker Library
232   fileobjects.asp   File Objects: Read Directory
233   fileobjects2.asp   File Objects: Display Directory as Links/Graphics
234   fileobjects3.asp   File Objects: Read Disk Drive by Steven Harper
235   fileobjects4.asp   File Objects: Show Dir List by Tim Foster
236   graphicdetect.asp   Graphic Size Detector
237   
238   speedscale.asp   *High Speed Code, Scalable Code...
239   speedtimer.asp   Time Tasks with Millisecond Accuracy
240   speedtips.asp   Speed: Coding Tips
241   whybuffer.asp   Why Buffer?
242   whygetrows.asp   Why GetRows or Getstring to get Data
243   speedserver.asp   Speed: Server Optimization
244   speedmore.asp   Speed/Optimize Resources
245   speedresearch.asp   Speed: [aspfastcode] listserver
246   speedtables.asp   Speed: Database Percieved Speed
247   speedtablesall.asp   Database Retrieval Speed
248   speedtablesdrivers.asp   OLEDB & ODBC Drivers differences
249   isclientconnected.asp   IsClientConnected & Stray Tasks
250   nothing.asp   Scale: Virtues of Nothing
251   dbpooling.asp   Scale: Connection Pooling
252   threads.asp   Thread Basics: What is a Thread?
253   threadsafe.asp   Thread Safety Issues
254   roundrobin.asp   Round-Robin Code Execution
255   aspscalability.asp   ASP Scalability Listserver
256   
257   buildcomponents.asp   *ASP Components Building
258   buildc.asp   C++/ATL: Component Building
259   buildjava.asp   Java ASP Components Building
260   buildvbsimple.asp   VB: Simple Component
261   buildregister.asp   VB: Registering Component
262   FAQvbDLLoverwrite.asp   VB: DLL overwrite problems
263   buildvbado.asp   VB: ADO, Run It!
264   buildvbado2.asp   VB: ADO, Build It!
265   buildvbguidelines.asp   VB: Warnings/Guidelines
266   buildvb.asp   VB: General Building Guidelines
267   buildvb2.asp   VB: Installation Requirements
268   buildvbthreads.asp   VB: Threading Models
269   
270   buildmtx.asp   *MTS - Microsoft Transaction Server
271   buildmtxoverview.asp   MTS: Overview
272   buildmtx2.asp   MTS: Essentials
273   buildmtxasp.asp   MTS: Transactional ASP pages
274   booksmtx.asp   MTS: Book
275   booksmtx2.asp   MTS: Book
276   buildmtxregister.asp   MTS: Registering Components
277   
278   advice.asp   *Advice For Better Coding!
279   dbsessionapp.asp   Database in Session or App. Say NO!
280   cachenomore.asp   advice: Cache No More by Phil Paxton
281   explicit.asp   advice:Option Explicit
282   encode.asp   advice: Encode with Redirects
283   sqlwrite.asp   advice: Write Your SQL
284   namedconstants.asp   advice: Named constants for ADO are better
285   cleanup.asp   advice: Clean Up Your Room, I mean Objects
286   pathmap.asp   advice: Server.MapPath is Good
287   nosessionobjects.asp   advice: Just Say No to Session COM objects
288   propertyexpense.asp   advice: Don't Read COM Properties Twice
289   securecode.asp   advice: Secure Code and Data
290   encapsulate.asp   advice: Encaspulate Code!
291   caseisbetter.asp   advice: CASE reads better than IF
292   errorstrategies.asp   advice: Error Trapping Strategies
293   errorsecrets.asp   advice: Error Trapping Secrets
294   shoulds.asp   advice: You Should...
295   
296   
297   overview.asp   *Appendix A: Overview of ASP Objects
298   aspobjects.asp   ASP Objects: Built In
299   aspobjects2.asp   ASP Objects: Created when Needed
300   
301   webcom.asp   *Appendix B: Related Web/Com Technologies
302   indexserver.asp   Index Server via ADO
303   commerce.asp   Commerce and ASP
304   javascript.asp   Server JavaScript: Resources
305   validationmore.asp   Validation Resources
306   listdynamic.asp   Listboxes: Linked Dynamically w/JavaScript
307   listdynamicmore.asp   Dynamic ListBox Online Examples
308   listdynamicdb.asp   Listboxes: Linked Dynamically from Database w/JavaScript
309   listdual.asp   Listboxes: Easy Choices by Bill Wilkinson
310   perlscript.asp   Server Perlscript: Resources
311   remotescripting.asp   Remote Scripting Simple Example
312   remotescriptinglist.asp   Remote Scripting Listbox
313   remotescriptingms.asp   Remote Scripting Microsoft Example
314   aspremotescripting.asp   [aspRemoteScript] list
315   rds.asp   RDS: Remote Data Services Intro
316   prothman.asp   RDS Resources by Carl Prothman
317   ADSI.asp   ADSI: Active Directory Services Interface Intro
318   MSMQ.asp   MSMQ: Overview
319   usability.asp   Usability: Resources
320   safecolors.asp   Usability: Safe Color Pallete
321   
322   oracle.asp   *Appendix C: Oracle and ASP
323   FAQOracleconnect.asp   Oracle: I can't connect
324   asporacle.asp   Oracle: Getting Help from Listserver
325   FAQOraclestoredproc.asp   Oracle: Calling Stored Procs
326   oracleoledbpooling.asp   Oracle: OLEDB Resource(Session) Pooling
327   oraclerecordsetsfromsp.asp   Oracle: Recordsets from Stored Procedures using REF CURSORs
328   oraclerecordsetsado.asp   Oracle: Returning Recordsets via ADO
329   FAQOraclebooks.asp   Oracle: Know any good books?
330   
331   research.asp   *Appendix D: ASP Books & Online Resources
332   bookcomponents.asp   Must Buy Component Building Book
333   asp101.asp   ASP101.com Scripts for your site
334   4guysfromrolla.asp   4GuysFromRolla.com Tons of ASP Material
335   asptoday.asp   ASPToday.com from WROX
336   
337   faqs.asp   *Appendix E: Frequently Asked Questions
338   FAQCommerceCertif.asp   Commerce: certificates, https://
339   FAQCommerceCharge.asp   Commerce: online charging
340   FAQCommerceCarts.asp   Commerce: components, shopping carts
341   FAQJscriptCleanUp.asp   Jscript: closing DB Connections
342   FAQJscriptRefs.asp   Jscript: online references
343   FAQJscriptDB.asp   Jscript: display databases
344   FAQvbBooks.asp   VB: Recommended books
345   
346   
347   alphaindex.asp   *Alphabetical Index
348   
349   comingsoon.asp   *Coming Soon/Very Rough Drafts!
350   types.asp   Data Types: VBScript
351   convert.asp   Data Types: Conversion
352   ForNext.asp   Loops: FOR NEXT #1
353   ForNext2.asp   Loops: FOR NEXT #2
354   ad.asp   Ad Rotator
355   cr.asp   Content Rotator
356   command.asp   DB: Command Object
357   commandquery.asp   DB: Command Object/Queries
358   commandcreate.asp   DB: Command Object/Create Tables
359   reportsimple.asp   Reporting: Simple Example
360   reportpowerful.asp   Reporting: Powerful Example
361   dictionaryadvanced.asp   Dictionaries: Different Approach #1 By Paul Rigor
362   dictionaryadvanced2.asp   Dictionaries: Different Approach #2 by Paul Rigor
363   validate.asp   Validate data
364   webjam.asp   3rd Party: WebJam
365   asptime.asp   Time Tasks: VB Component by Sunny Yu #1
366   asptimer.asp   Time Tasks: VB Component by Sunny Yu #2
367   cookiesform.asp   Cookies: Reading Them
368   cookiesformrespond.asp   Cookies: Writing Them
369   cookiesforget.asp   Cookies: Deleting Them
370   cookiesub.asp   Cookies: Simplified by Paul Rigor
371   


ASP Quick Lessons written by Charles M. Carroll
http://www.learnasp.com/learn/fileobjects.asp Page 219


fileobjects ASP Quick Lessons

FileObjects by Charles Carroll

The file object is in newer versions of VBScript.

   <html><head>
   <title>fileobjects.asp</title>
   </head><body>
   <%
   mypath="/learn/test"
   
   Set filesystem = CreateObject("Scripting.FileSystemObject")
   Set folder = filesystem.GetFolder(server.mappath(mypath))
   
10   Set filecollection = folder.Files
11   For Each file in filecollection
12          response.write file.name & "<br>"
13   Next
14   
15   set filesystem=nothing
16   set folder=nothing
17   set filecollection=nothing
18   %>

19   </body></html>


ASP Quick Lessons written by Charles M. Carroll
http://www.learnasp.com/learn/fileobjects2.asp Page 220


fileobjects ASP Quick Lessons

FileObjects Part 2 by Charles Carroll

The file object is in newer versions of VBScript. Here we use it to walk a directory and make links.

   <html><head>
   <title>fileobjectslinks.asp</title>
   </head><body>
   <%
   dirtowalk="/learn/test"
   Set fs = CreateObject("Scripting.FileSystemObject")
   Set f = fs.GetFolder(server.mappath(dirtowalk))
   Set fc = f.Files
   For Each whatever in fc
10      response.write "<A HREF='"
11          response.write whatever.name
12          response.write "'>"
13          response.write whatever.name
14          response.write "</A><br>"
15   Next
16   %>

17   </body></html>

Now we will display graphics in a directory.

   <html><head>
   <title>fileobjectsgraphics.asp</title>
   </head><body>
   <%
   dirtowalk="/images"
   Set fs = CreateObject("Scripting.FileSystemObject")
   Set f = fs.GetFolder(server.mappath(dirtowalk))
   Set fc = f.Files
   For Each whatever in fc
10      response.write "<IMG SRC='/images/"
11          response.write whatever.name
12          response.write "'>"
13          response.write whatever.name & "<br>"
14   Next
15   %>

16   </body></html>


ASP Quick Lessons written by Charles M. Carroll
http://www.learnasp.com/learn/fileobjects3.asp Page 221


fileobjects ASP Quick Lessons

FileObjects Part 3 by Steven Harper
Steven Harper@ScapaSMD.com, Internet Developer

The file object can be used to examine the disk as well as this cript submitted by a site viewer, demonstrates.

   <html><head>
   <title>fileobjectsinfo.asp</title>
   </head><body>
   <%
       disktoexamine="C:"
   
       set fs = Server.CreateObject("Scripting.FileSystemObject")
       set f = fs.GetDrive(disktoexamine)
   
10       Response.Write(" Root Folder : ")
11       Response.Write(f.RootFolder)
12       Response.Write("<BR>")
13       Response.Write(" Type of Drive : ")
14       if f.DriveType=2 then
15          Response.Write("Fixed")
16       end if
17       if f.DriveType=1 then
18          Response.Write("Removable")
19       end if
20       Response.Write("<BR>")
21       Response.Write(" File System : ")
22       Response.Write(f.FileSystem)
23       Response.Write("<BR>")
24       Response.Write(" Total Size on Server's C: &nbsp;&nbsp;")
25       Response.Write(f.TotalSize)
26       Response.Write("<BR>")
27       Response.Write(" Drive Space on Server's C: ")
28       Response.Write(f.freespace)
29       Response.Write("<BR>")
30       Response.Write(" Serial Number : ")
31       Response.Write(f.SerialNumber)
32   
33       set f=nothing
34       set fs=nothing
35   
36   %>

37   </body></html>


ASP Quick Lessons written by Charles M. Carroll
http://www.learnasp.com/learn/fileobjects4.asp Page 222


fileobjects ASP Quick Lessons

FileObjects Part 4 by "Tim Foster"tfoster@pdxinc.com

The file object examples was modified by one of our readers to support folders and clicking on them to see the contents beneath. Our readers always come up with some nice variations and new examples.

   <html><head>
   <title>fileobjectsplusdir.asp</title>
   </head><body>
   <%
   additional = request.querystring("pathh")
   folderspec = "/learn/"
   
   if  additional & "x" <> "x" then
      additional = additional & "/"
10      folderspec = folderspec & additional
11   end if
12   
13   Set fs = CreateObject("Scripting.FileSystemObject")
14   Set f = fs.GetFolder(server.mappath(folderspec))
15   Set fd = f.subfolders
16   
17   response.write "<h2>FOLDERS</h2><blockquote>"
18   For Each whatever in fd
19         response.write "<A HREF='"
20          response.write request.servervariables("script_name")
21          response.write "?pathh=" & whatever.name
22          response.write "'>"
23          response.write whatever.name & " - " & whatever.datecreated
24          response.write "</A><br>"
25   Next
26   
27   response.write "</blockquote><hr>"
28   
29      
30   response.write "<h2>FILES</h2><blockquote>"
31   
32   Set fc = f.files
33   
34   For Each whatever in fc
35         response.write "<A HREF='"
36          response.write folderspec & whatever.name
37          response.write "'>"
38          response.write whatever.name & " - " & whatever.datecreated
39          response.write "</A><br>"
40   Next
41   
42   response.write "</blockquote><hr>"
43   
44   
45   %>

46   </body></html>


ASP Quick Lessons written by Charles M. Carroll
http://www.learnasp.com/learn/graphicdetect.asp Page 223


dbtable

Detect Graphic Type/Dimensions by Daniel Gorroño

Daniel Gorroño Santurtzi danielgo@sarenet.es
Bizkaia - Euskal Herria

This ingenious piece of code demonstrates how to read a file using the file system object and extract bytes that contain the height and width.

   <!--#include virtual="/learn/test/lib_graphicdetect.asp"-->
   <html><head>
   <TITLE>dbtable.asp</TITLE>
   </head>
   <body bgcolor="#FFFFFF">
   <%
      graphic="images/learnaspiconmain.gif"
      HW = ReadImg(graphic)
      Response.Write graphic & " Dimensions: " & HW(0) & "x" & HW(1) & "<br>"
10      response.write "<img src=""/" & graphic & """"
11      response.write height=""" & HW(0) & """
12      response.write width=""" & HW(0) & "">"
13   %>

14   </body></html>
15   

The library that is included is:

   <%
   Dim HW
   
   Function AscAt(s, n)
          AscAt = Asc(Mid(s, n, 1))
   End Function
   
   Function HexAt(s, n)
          HexAt = Hex(AscAt(s, n))
10   End Function
11   
12   
13   Function isJPG(fichero)
14          If inStr(uCase(fichero), ".JPG") <> 0 Then
15          isJPG = true
16          Else
17          isJPG = false
18          End If
19   End Function
20   
21   
22   Function isPNG(fichero)
23          If inStr(uCase(fichero), ".PNG") <> 0 Then
24          isPNG = true
25          Else
26          isPNG = false
27          End If
28   End Function
29   
30   
31   Function isGIF(fichero)
32          If inStr(uCase(fichero), ".GIF") <> 0 Then
33          isGIF = true
34          Else
35          isGIF = false
36          End If
37   End Function
38   
39   
40   Function isBMP(fichero)
41          If inStr(uCase(fichero), ".BMP") <> 0 Then
42          isBMP = true
43          Else
44          isBMP = false
45          End If
46   End Function
47   
48   
49   Function isWMF(fichero)
50          If inStr(uCase(fichero), ".WMF") <> 0 Then
51          isWMF = true
52          Else
53          isWMF = false
54          End If
55   End Function
56   
57   
58   Function isWebImg(f)
59          If isGIF(f) Or isJPG(f) Or isPNG(f) Or isBMP(f) Or isWMF(f) Then
60          isWebImg = true
61          Else
62          isWebImg = true
63          End If
64   End Function
65   
66   
67   Function ReadImg(fichero)
68          If isGIF(fichero) Then
69          ReadImg = ReadGIF(fichero)
70          Else
71          If isJPG(fichero) Then
72          ReadImg = ReadJPG(fichero)
73          Else
74          If isPNG(fichero) Then
75          ReadImg = ReadPNG(fichero)
76          Else
77          If isBMP(fichero) Then
78          ReadImg = ReadPNG(fichero)
79          Else
80          If isWMF(fichero) Then
81          ReadImg = ReadWMF(fichero)
82          Else
83          ReadImg = Array(0,0)
84          End If
85          End If
86          End If
87          End If
88          End If
89   End Function
90   
91   
92   Function ReadJPG(fichero)
93       Dim fso, ts, s, HW, nbytes
94          HW = Array("","")
95          Set fso = CreateObject("Scripting.FileSystemObject")
96          Set ts = fso.OpenTextFile(Server.MapPath("/" & fichero), 1)
97          s = Right(ts.Read(167), 4)
98          HW(0) = HexToDec(HexAt(s,3) & HexAt(s,4))
99          HW(1) = HexToDec(HexAt(s,1) & HexAt(s,2))
100          ts.Close
101       ReadJPG = HW
102   End Function
103   
104   
105   Function ReadPNG(fichero)
106       Dim fso, ts, s, HW, nbytes
107          HW = Array("","")
108          Set fso = CreateObject("Scripting.FileSystemObject")
109          Set ts = fso.OpenTextFile(Server.MapPath("/" & fichero), 1)
110          s = Right(ts.Read(24), 8)
111          HW(0) = HexToDec(HexAt(s,3) & HexAt(s,4))
112          HW(1) = HexToDec(HexAt(s,7) & HexAt(s,8))
113          ts.Close
114       ReadPNG = HW
115   End Function
116   
117   
118   Function ReadGIF(fichero)
119       Dim fso, ts, s, HW, nbytes
120          HW = Array("","")
121          Set fso = CreateObject("Scripting.FileSystemObject")
122          Set ts = fso.OpenTextFile(Server.MapPath("/" & fichero), 1)
123          s = Right(ts.Read(10), 4)
124          HW(0) = HexToDec(HexAt(s,2) & HexAt(s,1))
125          HW(1) = HexToDec(HexAt(s,4) & HexAt(s,3))
126          ts.Close
127       ReadGIF = HW
128   End Function
129   
130   
131   Function ReadWMF(fichero)
132       Dim fso, ts, s, HW, nbytes
133          HW = Array("","")
134          Set fso = CreateObject("Scripting.FileSystemObject")
135          Set ts = fso.OpenTextFile(Server.MapPath("/" & fichero), 1)
136          s = Right(ts.Read(14), 4)
137          HW(0) = HexToDec(HexAt(s,2) & HexAt(s,1))
138          HW(1) = HexToDec(HexAt(s,4) & HexAt(s,3))
139          ts.Close
140       ReadWMF = HW
141   End Function
142   
143   
144   Function ReadBMP(fichero)
145       Dim fso, ts, s, HW, nbytes
146          HW = Array("","")
147          Set fso = CreateObject("Scripting.FileSystemObject")
148          Set ts = fso.OpenTextFile(Server.MapPath("/" & fichero), 1)
149          s = Right(ts.Read(24), 8)
150          HW(0) = HexToDec(HexAt(s,4) & HexAt(s,3))
151          HW(1) = HexToDec(HexAt(s,8) & HexAt(s,7))
152          ts.Close
153       ReadBMP = HW
154   End Function
155   
156   
157   Function isDigit(c)
158          If inStr("0123456789", c) <> 0 Then
159          isDigit = true
160          Else
161          isDigit = false
162          End If
163   End Function
164   
165   
166   Function isHex(c)
167          If inStr("0123456789ABCDEFabcdef", c) <> 0 Then
168          isHex = true
169          Else
170          ishex = false
171          End If
172   End Function
173   
174   
175   Function HexToDec(cadhex)
176          Dim n, i, ch, decimal
177          decimal = 0
178          n = Len(cadhex)
179          For i=1 To n
180          ch = Mid(cadhex, i, 1)
181          If isHex(ch) Then
182          decimal = decimal * 16
183          If isDigit(c) Then
184          decimal = decimal + ch
185          Else
186          decimal = decimal + Asc(uCase(ch)) - Asc("A")
187          End If
188          Else
189          HexToDec = -1
190          End If
191          Next
192          HexToDec = decimal
193   End Function
194   %>

195   


ASP Quick Lessons written by Charles M. Carroll
http://www.learnasp.com/learn/speedscale.asp Page 224


Section Contents

High Speed Code, Scalable Code...
        Time Tasks with Millisecond Accuracy (speedtimer.asp) - Page 225
        Speed: Coding Tips (speedtips.asp) - Page 226
        Why Buffer? (whybuffer.asp) - Page 227
        Why GetRows or Getstring to get Data (whygetrows.asp) - Page 228
        Speed: Server Optimization (speedserver.asp) - Page 229
        Speed/Optimize Resources (speedmore.asp) - Page 230
        Speed: [aspfastcode] listserver (speedresearch.asp) - Page 231
        Speed: Database Percieved Speed (speedtables.asp) - Page 232
        Database Retrieval Speed (speedtablesall.asp) - Page 233
        OLEDB & ODBC Drivers differences (speedtablesdrivers.asp) - Page 234
        IsClientConnected & Stray Tasks (isclientconnected.asp) - Page 235
        Scale: Virtues of Nothing (nothing.asp) - Page 236
        Scale: Connection Pooling (dbpooling.asp) - Page 237
        Thread Basics: What is a Thread? (threads.asp) - Page 238
        Thread Safety Issues (threadsafe.asp) - Page 239
        Round-Robin Code Execution (roundrobin.asp) - Page 240
        ASP Scalability Listserver (aspscalability.asp) - Page 241


ASP Quick Lessons written by Charles M. Carroll
http://www.learnasp.com/learn/speedtimer.asp Page 225


SpeedTips from ASP Quick Lessons

Speed: Measuring Code Speed
by Richard A. Lowe drahcir@home.com
  with help from Jonathan McGuire jmcguire@solutionsatimpact.com
  Gregory Lybanon glybanon@sbcsystems.com
  Charles Carroll charlescarroll@learnasp.com

Measuring speed to the millisecond was considered impossible with ASP. People built COM components that wrapped up API calls! So we called a COM component that called an API and then we distorted the measurement with overhead. Scripting has a few tricks up its sleeves yet as Richard demonstrates with the nifty Library implemented in Jscript. We will use it to time retrieving and displaying identical data three different ways:

This method is great for testing optimizations to 1 script but does not show how the script will run when many users are simultaneously executing it. Tools like the Stress Tester at:
http://homer.rte.microsoft.com
are great for simulating and recording measurements for multi-user performance.

Here we retrieve data using a traditional loop (/learn/dbtable.asp):

   <html><head>
   <TITLE>timedbtable.asp</TITLE>
   </head>
   <body bgcolor="#FFFFFF">
   <!--#include file="lib_timethis.asp"-->
   <%
   Set HttpObj = Server.CreateObject("AspHTTP.Conn")
   HttpObj.Url = "http://www.learnasp.com/learn/test/dbtable.asp"
   timeThen = milliDif()
10   strResult = HttpObj.GetURL
11   timeNow = milliDif()
12   SET HTTPobj = nothing
13   elapsed=timeNow-timeThen
14   msg="<br>Process time in ms: " & elapsed & "<br>" & elapsedpretty(elapsed)
15   bodytag="<body bgcolor=""#FFFFFF"">"
16   STRresult=replace(STRResult,bodytag,bodytag & msg)
17   
18   response.write STRresult
19   
20   %>

21   </body></html>

Here we retrieve data by fetching all the data into an array in one "gulp" (/learn/dbtablegetrows.asp):

   <html><head>
   <TITLE>timedbtablegetrows.asp</TITLE>
   </head>
   <body bgcolor="#FFFFFF">
   <!--#include file="lib_timethis.asp"-->
   <%
   Set HttpObj = Server.CreateObject("AspHTTP.Conn")
   HttpObj.Url = "http://www.learnasp.com/learn/test/dbtablegetrows.asp"
   timeThen = milliDif()
10   strResult = HttpObj.GetURL
11   timeNow = milliDif()
12   SET HTTPobj = nothing
13   elapsed=timeNow-timeThen
14   msg="<br>Process time in ms: " & elapsed & "<br>" & elapsedpretty(elapsed)
15   bodytag="<body bgcolor=""#FFFFFF"">"
16   STRresult=replace(STRResult,bodytag,bodytag & msg)
17   
18   response.write STRresult
19   
20   %>

21   </body></html>

Here we retrieve data by asking the backend to combine the data into a custom string and not even bring fields and rows, just produce 1 string (/learn/dbtablegetstring.asp):

   <html><head>
   <TITLE>timedbtablegetstring.asp</TITLE>
   </head>
   <body bgcolor="#FFFFFF">
   <!--#include file="lib_timethis.asp"-->
   <%
   Set HttpObj = Server.CreateObject("AspHTTP.Conn")
   HttpObj.Url = "http://www.learnasp.com/learn/test/dbtablegetstring.asp"
   timeThen = milliDif()
10   strResult = HttpObj.GetURL
11   timeNow = milliDif()
12   SET HTTPobj = nothing
13   elapsed=timeNow-timeThen
14   msg="<br>Process time in ms: " & elapsed & "<br>" & elapsedpretty(elapsed)
15   bodytag="<body bgcolor=""#FFFFFF"">"
16   STRresult=replace(STRResult,bodytag,bodytag & msg)
17   
18   response.write STRresult
19   
20   %>

21   </body></html>

The library that accomplishes this:

   <SCRIPT LANGUAGE=JScript RUNAT=Server>
   function y2k(number)   {
      return (number < 1000) ? number + 1900 : number;
                        }
   function milliDif()   {
      var d = new Date();
         return d.getTime()
                     }
                     
10   function elapsedpretty(parm1)
11   {
12     var elapsedsecs = 0
13     var elapsedmins = 0
14     
15     elapsedsecs=Math.floor(parm1/1000)
16     parm1=parm1%1000
17     
18     elapsedmins=Math.floor(elapsedsecs/60)
19     elapsedsecs=elapsedsecs%60
20     
21     
22   elapsedpretty=elapsedmins + " minute"
23   if(elapsedmins!=1)
24          elapsedpretty=elapsedpretty+"s"
25     
26   elapsedpretty = elapsedpretty+" " + elapsedsecs+" second"
27   if(elapsedsecs!=1)
28          elapsedpretty=elapsedpretty+"s"
29     
30   elapsedpretty = elapsedpretty+ " "+parm1+" millisecond"
31   if(parm1!=1)
32          elapsedpretty=elapsedpretty+"s"
33     
34     return elapsedpretty;
35   }  
36   </script>


ASP Quick Lessons written by Charles M. Carroll
http://www.learnasp.com/learn/speedtips.asp Page 226


SpeedTips from ASP Quick Lessons

Speed Tips by Charles Carroll

There are several ways to speed up a given ASP page. These suggestions come from a very exciting listserver we run called [aspfastcode] (http://www.asplists.com/asplists/aspfastcode.asp) . There people submit their working scripts (broken ones are not allowed) that are running too slow and the members help them speed up that sample.

#1 Any page that does not need session can benefit from this directive at the top:
<%@ enablesessionstate=false %>

#2 All pages should be buffered see /advice/whybuffer.asp for explanation. Also see /learn/speedtables.asp  to see how flushing buffer and HTML tags can improve percieved speed.

Add this to top:
<%response.buffer=true%>

#3 Pages doing database access will improve performance if the following techniques are used 

#4 Before just believing any article you read on the web or in an ASP book (many articles are not researched thoroughly) and implementing code changes TIME THE CODE BEFORE AND AFTER changes. /learn/speedtimer.asp has the needed code that will time scripts to millisecond accuracy.

#5 Eliminate any code that reads com properties twice, /learn/propertyexpense.asp has some samples of this.

#6 Just say no to VB components and/or recordsets stored at the session level. Several articles explain why:

#7 Cache frequent query results/HTML generated from databases in application variables. http://www.learnasp.com/learn/speedappdata.asp.

#8 Open database connections as late as possible, Close database connections immediately when done. Placing your code a few lines later could make a huge difference as your scripts run round-robin with other scripts, see /advice/roundrobin.asp for more whys about this.

#9 Tune your server. At least make the 20 instead of 4 thread tweak (see http://www.learnasp.com/advice/threads.asp). The articles at /learn/speedserver.asp  will tell you everything you need to know about tuning your server.

#10 Don't waste time running scripts if the user hit the "stop" button or went to different page/site. Normally scripts run started by a user run to completion whether the user is there to read output or not running invisibly on server. See: /learn/isclientconnected.asp to see how to modify your scripts appropriately.

#11 Bite the bullet and master remote scripting so your HTML and ASP scripts can communicate with ASP asynchronously and refresh portions of page without submitting page to server. Remote scripting works in both Netscape and IE; any Javascript capable browser. Some remote scripting links and a listserver to get help is at http://www.asplists.com/asplists/aspremotescripting.asp.

 


ASP Quick Lessons written by Charles M. Carroll
http://www.learnasp.com/learn/whybuffer.asp Page 227


dbtable

Buffer That Output by Charles Carroll

In my recent advanced class we recently confirmed my fanatical belief in
<%response.buffer=true%>
and cautious <%response.flush%>
something I hammer into every Intro student I teach every day of my class.

We did dozens of millisecond speed tests ala:
http://www.learnasp.com/learn/speedtimer.asp
reading 500 database records. Every change (Getrows or Getstring, One gulp, or 50 rows at a time, named or numbered fields) was timed. Many of these suboptimizations reduced a 4 second task to 2 seconds. But the buffer trick got it down to 3/10 of a second!!!! Why?????

Lets tell the waiter analogy....

A waiter comes to your table in a busy restaurant. There are 5 at your table. He asks what drink person #1 wants and THEN hops to a different table and lets them order 1 drink and then hops to a different table and asks 1 person what their main course is and then a different table to ask what dessert another person wants. Then he comes back to your table and asks person #2 what drink they want. Then hops all over again.

This story is your webserver with <%response.buffer=false%> (the default in IIS4 and IIS3). Though it might seem slower to the adjacent table for him to finish your order, overall it is faster for him to do one at a time.

Chaos, not Order

Also if a script is <%response.buffer=false%>
the number of gulps it takes to move 10k is determined by the browser and server in a chaotic very hard to determine fashion...
5 gulps of 2k
10 gulps of 1k
3 gulps of 3k + 1k gulp
It is not efficient.

But if a script is <%response.buffer=true%>
==> 1 gulp of 10k <==
If 300 people ask for that script, 300 transfers,
not 301...3000 transfers depending on many factors.

BUT, lets say you have a page like this:
<%response.buffer=true%>
... 1k of HTML ...
... 20k graphic ...
... 45k background sound ...
... 4k of HTML ...

Some facts:
- The page will serve quicker if many people hit the site. Go back to waiter analogy. 69k in 1 gulp x a couple hundred users is much easier than a couple hundred fragmented gulps.

Now the sane man compromises:

<%response.buffer=true%>
... 1k of HTML and/or ASP  ...
<%response.flush%>
... 20k graphic ...
<response.flush%>
... 45k background sound ...
... 4k of HTML  and/or ASP ...

Now:

A Simple Change to Speed Up Your Server

I once had an overloaded 100% CPU server. I changed registry so all pages were buffer=true. The server then oscillated instead of staying pegged at 100%. Proof incarnate. Users were much happier. No money spent no code changes.

When Good Pets Go Bad, err I mean...
When response.flush goes bad

Two of my students would like to add to this advice.

Rob Reno from Florida found too many response.flushes slows down his page and has diminishing returns. Code like this

<%response.buffer=true%>
... 1k of HTML and/or ASP  ...
<%do until rstemp.eof
    ... process data ...
    rstemp.movenext
    response.flush
LOOP

will show output often BUT if there is 1000 records that is 1000 response.flushes.

Change the above code to:

<%response.buffer=true%>
... 1k of HTML and/or ASP  ...
<%do until rstemp.eof
    counter=counter+1
    ... process data ...
    rstemp.movenext
    If counter MOD 200=0 THEN
        response.flush
    END IF
LOOP

will now flush at record 200, 400,600,800,1000 -- 5 flushes total.

Doug Cannon from Utah writes....

The one thing that you may not have tested for this article is how response.flush behaves on a very slow internet connection (28.8 bps, for example). Our audience on www.myfamily.com  still uses a lot of 28.8 and 33.6 modems to attach to our site. We were noticing some VERY slow speeds on many of our pages. We religiously used RESPONSE.BUFFER = TRUE on every page, and two RESPONSE.FLUSH commands per page. We found out, and Microsoft finally admitted, that the response.flush waits for the client browser to acknowledge the flush before continuing to process the ASP code. One a very fast internet connection, you don't notice the problem, but a slower modem takes longer to perform that task, and therefore a flush can be bad. We still use response.buffer=true, of course. However, we have removed all response.flush commands from the site, and we saw an instant and dramatic speed improvement.

My comment: I have used several response.flushes on 28.8 connections with success and speed BUT my servers weren't as busy as www.myfamily.com . Due to the round-robin nature of script execution (see /advice/roundrobin.asp) their servers may take longer for a response.flush than lightly loaded servers!


ASP Quick Lessons written by Charles M. Carroll
http://www.learnasp.com/learn/whygetrows.asp Page 228


dbtable

GetRows! ... Don't retrieve data any other way!

Why LOOP and Movenext? They just slow things down...

Most people write database retrieval code like his:

<%
' Open Database
Do UNTIL rs.eof
    city=rs("city")
    st=rs("state")
    zip=rs("zip")
    rs.movenext
    ... process and format data ....
LOOP
' Close database
%>

An example of such code is at:
http://www.learnasp.com/learn/dbtable.asp
and 
http://www.learnasp.com/learn/dbsimple.asp

If there are 700 records and 3 columns for example, we have 3,500 database read requests over the wire. 

+2,100 ... Each field read is a request
+700  ..... Each .movenext is +1 request
+700  ..... Each .eof test is +1 request
====
3,500 requests

Lots of round-trips. Actually I am fudging a little here.... the recordset object actually will maintain buffers in chunk sizes defined by rstemp.cachesize -- setting it will determine how many rows of data it buffers when 1 record is requested. A cachesize for example of 50 would reduce the previous examples trips to the backend database to 14 since when you asked for the first record you got 50. Until the MOVENEXT triggers record 51-101 being retrieved. But those buffers, and their attendant structures ain't free either.

How about 1 transfer instead of 3500?
A better alternative code approach is GetRows!

dim myarray
myarray=rstemp.GetRows

One transfer for seven-hundred records x 3 fields for example. We can even close Recordset and Connection BEFORE formatting or calculating and massaging our data.

Imagine the backend gets to make 1 transfer into a 2,100 element array and hand the array back

Very efficient.

Here is a real world sample:

   <%@enablesessionstate=false%>
   <%response.buffer=true%>
   <html><head>
   <TITLE>dbtablegetrows.asp</TITLE>
   </head>
   <body bgcolor="#FFFFFF">
   <%
   ' displays a database in table form via GetRows
   myDSN="DSN=Student;uid=student;pwd=magic"
10   mySQL="select * from publishers where state='NY'"
11   showblank="&nbsp;"
12   shownull="-null-"
13   
14   set conntemp=server.createobject("adodb.connection")
15   conntemp.open myDSN
16   set rstemp=conntemp.execute(mySQL)
17   If  rstemp.eof then
18      response.write "No records matched<br>"
19      response.write mySQL & "<br>So cannot make table..."
20      Call CloseAll
21      response.end
22   end if
23   
24   response.write "<table border='1'><tr>" & vbcrlf
25   'Put Headings On The Table of Field Names
26   for each whatever in rstemp.fields
27      response.write "<td><b>" & whatever.name & "</B></TD>" & vbcrlf
28   next
29   response.write "</tr>" & vbcrlf
30   
31   ' Now lets grab all the records
32   alldata=rstemp.getrows
33   Call CloseAll
34   
35   numcols=ubound(alldata,1)
36   numrows=ubound(alldata,2)
37   FOR rowcounter= 0 TO numrows
38      response.write "<tr>" & vbcrlf
39      FOR colcounter=0 to numcols
40         thisfield=alldata(colcounter,rowcounter)
41         if isnull(thisfield) then
42            thisfield=shownull
43         end if
44         if trim(thisfield)="" then
45            thisfield=showblank
46         end if
47         response.write "<td valign=top>"
48         response.write thisfield
49         response.write "</td>" & vbcrlf
50      NEXT
51      response.write "</tr>" & vbcrlf
52   NEXT
53   response.write "</table>"
54   %>

55   </body></html>
56   <%
57   SUB CloseAll
58      rstemp.close
59      set rstemp=nothing
60      conntemp.close
61      set conntemp=nothing
62   END SUB
63   %>

64   

Read:
http://www.learnasp.com/advice/roundrobin.asp
to get the full sense for the importance of closing resources early.

Get Some Real Code to Use!

If your data formatting is simple:
http://www.learnasp.com/learn/dbtablegetstring.asp
can accomplish even faster results.

Old Habits Die Hard... Do you want to be an old dog that won't learn new tricks?

The main reason that people do MOVENEXT and field at a time because that is what they learned. But let us say 300 people hit my main page and it read a database; well if I do my reads without getrows or getstrings I may need a much more powerful CPU as the scripts spin, round-robin and save their context and store their data at a low-level to serve all those users simultaneously. On a webserver every millisecond you waste in one script may be multiplied by tens of thousands of users (Amazon.com, Cnn.com) so it behooves traditional programmers to bite the bullet and throw away one at a time field reads and movenexts.

Notice how my Getrows example can close RS and CN before processing data. Lets say do LOOP and PROCESS/FORMAT in the loop. Well, if the reads take 1.5 seconds and the processing/formatting takes 2.5 seconds the database is open for 4 seconds. With Getrows the same operation retrieve might take 3/4 second and the rs and cn are closed and back in the pool for others and the formatting is done while someone else uses the connection and whatever READ locks placed on the data rows/chunks aren't affecting others while formatting is occurring.

Kyle Dyer writes us... "What about Jscript?"

And he is kind enough to supply us with the results of his research:

strSQL = "SELECT times FROM ...";
recordSet.Open(strSQL, conn);
recordSet.GetString(2,-1,"column-delim","row-delim","null");

parameters:
  1: string format: has to be 2 (must be there in JavaScript)
  2: number rows: -1 gets you all of them (must be there in JavaScript)
  3: column delim
  4: row delim
  5: nullExper

Does it matter for small amounts of data?

YES!!!!!!!!

My site has SQLserver scripts that run like lightning. I once needed to fill a 9 item listbox from Access and got 90 sec script timeouts with movenext. Getstring never timed out. So in a real production situation it makes weak databases feasible and of course reduces the load on more industrial back-ends so maybe the SQLserver doesn't need as many indexes or RAM upgrades.

Is there any faster way to retrieve data?

"The Worlds Fastest Listbox"
http://www.learnasp.com/learn/speedappdata.asp
shows the only faster way to display databases.

Aren't numbered arrays harder for people to read?

Sure so I have prepared an example where we number the fields with variables and make the code easier to read for people. see:
http://www.learnasp.com/learn/dbtablegetrowsnonum.asp

A Better MouseTrap:
A Library I call Ultimate Getrows
Finally I hunkered down and encapsulated the speed of getrows and the elegance of named field and flexible formatting ala:
http://www.learnasp.com/learn/getrowsultimate.asp
I would argue that it is the best code samples at our entire site.


ASP Quick Lessons written by Charles M. Carroll
http://www.learnasp.com/learn/speedserver.asp Page 229


SpeedTips from ASP Quick Lessons

Server Optimization by Charles Carroll

Improving server performance is not so well documented and many of the articles lean towards vague, not specific tips. Here are our tips in we hope as concrete a way as possible.

THREAD TIP: Increase threads per processor
from 4 to 20 for each CPU.

thanks to Smiling Jack for this one:
http://www.aspmagazine.com/aspmagazine/issue10kb.asp

see
http://support.microsoft.com/support/kb/articles/q196/0/16.asp

Implement the ADOFre15.reg file!
If you don't use Access, run ADO as FREE THREADED instead of both.

more details at:
http://msdn.microsoft.com/workshop/server/components/daciisperf.asp

WARNING: Access or any STA driver will not function well and may corrupt data. Do not make this change if you are running any Access code in the box.

Additional Research
We have essentially summarized the information and chosen only the clearest guidelines from the following resources:

Web Application Stress Tool
http://homer.rte.microsoft.com

Improving the Performance of Data Access Components with IIS 4.0
http://msdn.microsoft.com/workshop/server/components/daciisperf.asp

Mike Moore's Tuning IIS
http://www.microsoft.com/isn/whitepapers/tuningiis.asp

IIS4 Tuning Parameters for High Volume Sites
http://msdn.microsoft.com/workshop/server/feature/tune.asp

Hans Hugli's Seminar:
Managing Microsoft Internet Information Server 4.0 for Performance @
http://www.microsoft.com/Seminar/1033/199811131-01MaxIISPerfor(HH/Portal.htm
 

Backstage at Microsoft.com
http://www.microsoft.com/backstage/whitepaper.htm

IIS Research starts @
http://www.microsoft.com/technet/iis/default.htm

Much ASP coding tips and advice related to scalability can be found at:
http://www.learnasp.com/advice


ASP Quick Lessons written by Charles M. Carroll
http://www.learnasp.com/learn/speedmore.asp Page 230


Text File Reading ASP Quick Lessons

Speed and Optimization Resources

I can't say that I agree with all the conclusions and focus of the following articles as there is a lot of micro-management and some big-picture optimization techniques are missed. But the research is often very good if applied within context.

Top WinDNA Performance Mistakes and How to Avoid Making Them @
http://msdn.microsoft.com/msdn-online/start/features/windnamistakes.asp

Enhancing Performance in ASP - Part I By Wayne Plourde @
http://www.asptoday.com/articles/20000113.htm

Enhancing Performance in ASP - Part I By Wayne Plourde 
http://www.asptoday.com/articles/20000113.htm

Tips to Improve ASP Application Performance By Srinivasa Sivakumar 
http://www.15seconds.com/issue/000106.htm

Speed Is The Essence By Mo Morgan Part 1
http://www.4guysfromrolla.com/webtech/010300-1.shtml

Speed Is The Essence By Mo Morgan Part 2
http://www.4guysfromrolla.com/webtech/010300-1.2.shtml

Optimizing ADO Calls Using the Set Statement By Mike Shaffer
http://www.4guysfromrolla.com/webtech/120899-1.shtml

Optimizing ADO Calls By Mike Shaffer 
http://www.4guysfromrolla.com/webtech/120299-1.shtml

Cursor & LockType Performance Issues 
http://www.4guysfromrolla.com/webtech/062799-3.shtml

Cursor & LockType Performance Report
http://www.4guysfromrolla.com/webtech/062799-3.report.shtml

Are Script Engines Compilers or Not by Juan LLibre @
http://x32.deja.com/getdoc.xp?AN=557994116&CONTEXT=947880637.319225894&hitnum=16 

Benchmarking Different Approaches to Updating a Database By Geoffrey Pennington
http://www.asptoday.com/articles/19990610.htm

Improving MDAC Application Performance @
http://msdn.microsoft.com/library/psdk/dasdk/impr8l2m.htm

Tuning Your Web Server's .ASP Queue and Thread Pool 
http://www.15seconds.com/howto/pg003223.htm

Server Performance and Scalability Killers by George V. Reilly 
http://msdn.microsoft.com/workshop/server/iis/tencom.asp

15 ASP Tips to Improve Performance and Style
http://msdn.microsoft.com/workshop/server/asp/ASPtips.asp

Listboxes. Its all about performance @
http://niblack.com/kbase/listbox_x.asp

Caching Data by Ian Stallings
http://www.4guysfromrolla.com/webtech/052099-1.shtml

Got Any Cache?
http://msdn.microsoft.com/workshop/server/feature/cache.asp

.Filter property vs. SQL Query Performance
http://msdn.microsoft.com/isapi/msdnlib.idc?theURL=/library/psdk/dasdk/mdae2dmg.htm
http://www.microsoft.com/Data/ado/ADOTechInfo/dao2ado_3.htm

Increasing Speed of Your ASP Scripts
http://www.4guysfromrolla.com/webtech/121398-1.shtml

Optimizing Your ASP Scripts
http://www.4guysfromrolla.com/webtech/110898-1.shtml


ASP Quick Lessons written by Charles M. Carroll
http://www.learnasp.com/learn/speedresearch.asp Page 231


ASP Speed from ASP Quick Lessons

Speed Research Resources by Charles Carroll

Speed affects your web consumers very much. It is a big subject that we will cover in-depth in this section but if this advice doesn't help you enough you can join [aspfastcode] to get help.

Undergoing renovation - SUB ListServSignup


ASP Quick Lessons written by Charles M. Carroll
http://www.learnasp.com/learn/speedtables.asp Page 232


ASP Speed from ASP Quick Lessons

Speed/Optimization Example: A Table Display

Speeding up your scripts involves many big and small script changes. We have prepared this "before" and "after" example to illustrate the point. This example assumes you truly have to display this many records (for example, a corporate report).  Alternatively:

Side note: If anyone you know believes Access queries are done asynchronously, running a couple of these scripts will prove them wrong. Access queries execute one web user at a time sequentially.

After Optimization

Here is a very fast table display going against an identical huge SQL Server Table:

   <%response.buffer=true%>
   <HEAD><TITLE>dbtablefast.asp</TITLE></HEAD>
   <HTML><body bgcolor="#FFFFFF">
   <%
   myDSN = "DSN=student;UID=student;pwd=magic"
   
   mySQL="select * from authors order by author"
   call query2table(mySQL,myDSN)
   %>

10   <!--#include virtual="/learn/test/lib_dbtablefast.asp"-->
11   </BODY></HTML>
12   
13   

Here is the optimized library lib_dbtablefast.asp which achieves this speed:

   <%
   sub query2table(inputquery, inputDSN)
      dim conntemp, rstemp
      set conntemp=server.createobject("adodb.connection")
      ' 0 seconds means wait forever, default is 15
      conntemp.connectiontimeout=0
      conntemp.open inputDSN
      set rstemp=conntemp.execute(inputquery)
      howmanyfields=rstemp.fields.count -1
10      tablestart="<table border=1 cols=3><col width='15%'><col width='70%'><col width='15%'><tr>"
11      response.write tablestart
12      for i=0 to howmanyfields %>

13                <td><b><%=rstemp(i).name%></B></TD>
14      <% next %>
15      </tr>
16      <% ' Now lets grab all the records
17      DO UNTIL rstemp.eof
18         counter=counter+1
19         response.write "<tr>"
20         for i = 0 to howmanyfields
21            thisvalue=rstemp(i)
22            If isnull(thisvalue) then
23               thisvalue="&nbsp;"
24            end if
25         response.write "<td valign=top>" & thisvalue & "</td>" & vbcrlf
26         next
27         response.write "</tr>"
28         rstemp.movenext
29         IF counter mod 50=0 THEN
30            If response.isclientconnected()=false THEN
31               EXIT DO
32            END IF
33            response.write "</table>" & TableStart
34            response.flush         
35         END IF
36   
37      loop%>

38      </table>
39      <%
40      rstemp.close
41      set rstemp=nothing
42      conntemp.close
43      set conntemp=nothing
44   end sub%>

45   

Before Optimization

Here is the original slow script which basically demonstrates techniques that may work if your data and concurrency load is light, but the script above demonstrates the typical changes made to speed up a script when it becomes needed or you just want to wring every ounce of speed from your site. This script will probably timeout before it's completion!

   <HEAD><TITLE>dbtableslow.asp</TITLE></HEAD>
   <HTML><body bgcolor="#FFFFFF">
   <%
   myDSN = "DSN=student;uid=student;pwd=magic"
   
   mySQL= "SELECT * from authors order by Author"
   call query2table(mySQL,myDSN)
   %>

   <!--#include virtual="/learn/test/lib_dbtableslow.asp"-->
10   </BODY></HTML>

Here is the original slow library lib_dbtableslow.asp :

   <%
   sub query2table(inputquery, inputDSN)
      dim conntemp, rstemp
      set conntemp=server.createobject("adodb.connection")
      conntemp.open inputDSN
      set rstemp=conntemp.execute(inputquery)
      howmanyfields=rstemp.fields.count -1%>

      <table border=1><tr>
      <% 'Put Headings On The Table of Field Names
10      for i=0 to howmanyfields %>

11                <td><b><%=rstemp(i).name%></B></TD>
12      <% next %>
13      </tr>
14      <% ' Now lets grab all the records
15      DO UNTIL rstemp.eof and response.isclientconnected()%>

16         <tr>
17         <% for i = 0 to howmanyfields
18            thisvalue=rstemp(i)
19            If isnull(thisvalue) then
20               thisvalue="&nbsp;"
21            end if%>

22                <td valign=top><%=thisvalue%></td>
23         <% next %>
24         </tr>
25         <%rstemp.movenext
26      loop%>

27      </table>
28      <%
29      rstemp.close
30      set rstemp=nothing
31      conntemp.close
32      set conntemp=nothing
33   end sub%>


ASP Quick Lessons written by Charles M. Carroll
http://www.learnasp.com/learn/speedtablesall.asp Page 233


ASP Speed from ASP Quick Lessons

Speed/Optimization: All Variations

Fetching records in an optimized way actually has many variations. We will list most of them here, provide code sample and typical timings for fetching and displaying records. These timings reveal an interesting behavior. Even if a script reports it ran in say, 7 seconds, that refers to the time that script received from the CPU. So that if 7 scripts take 8 seconds each there may be hundreds or thousands of scripts running on the server that are sharing the CPU. User #1 may see a 7 second result in 21 seconds, so their 7 second report reflects the time spent on the server/CPU for the script and the fact that 14 seconds of other stuff was executed round-robin with the rest of the scripts, not the time since the script started.

Method: LOOP, .movenext, periodic response.flush

Query took 6 seconds.
Query processed 10835 records.
Speed =1805.83333333333 records per second

Method: LOOP, .movenext and periodic response.flush commands. String is assembled with & operator and writen periodically.

Query took 52 seconds.
Query processed 10835 records.
Speed =208.365384615385 records per second.

Observation: The & operator is VERY expensive! Unbelievably so.

Method: Single GetString command

Query took 4 seconds
Query processed 10837 records.
Speed =2709.25 records per second.

Method: GetRows command with no LOOP + movenext but loop through the array with periodic response flushes.

Query took 3 seconds.
Query processed 10834 records.
Speed =3611.33333333333 records per second.

Note: Getstring often wins in many tests but it depends on many factors. I have seen a straight loop take 18 secs where GetRows takes 9 seconds and getstring take 4 secs.

Method: GetRows command of a fixed row count (say 500 record clusters for example) with a reponse.flush after each array is read!

Query took 3 seconds.
Query processed 10782 records.
Speed =3594 records per second.

Method: Displaying a portion of the data (say the first 500 records) only.

Query took 7 seconds.
Query processed 500 records.
Speed =71.4285714285714 records per second.

Note: This was recorded as 7 seconds but actually was much faster actually due to speed the browser reported the results.

Now here is the code that was used to gather all the data.

Here is a table display with a simple LOOP:

   <%response.buffer=true%>
   <HEAD><TITLE>dbtableLoopAll.asp</TITLE></HEAD>
   <HTML><body bgcolor="#FFFFFF">
   <!--#include virtual="/adovbs.inc"-->
   <!--#include virtual="/learn/test/lib_dbtablefastv2.asp"-->
   <%
   server.scripttimeout=240
   optimize=optimize_LoopAll
   
10   myDSN = "DSN=student;UID=student;pwd=magic"
11   'mySQL="select * from authors order by author "
12   mySQL="select * from authors order by author "
13   
14   Call TimerStart
15   call query2table(mySQL,myDSN,optimize,howmany)
16   Call TimerEnd
17   %>

18   </BODY></HTML>

Here is a table display with a simple LOOP assembling a string:

   <%response.buffer=true%>
   <HEAD><TITLE>dbtableLoopAllstring.asp</TITLE></HEAD>
   <HTML><body bgcolor="#FFFFFF">
   <!--#include virtual="/adovbs.inc"-->
   <!--#include virtual="/learn/test/lib_dbtablefastv2.asp"-->
   <%
   server.scripttimeout=240
   optimize=optimize_LoopAll_string
   
10   myDSN = "DSN=student;UID=student;pwd=magic"
11   mySQL="select * from authors order by author "
12   
13   Call TimerStart
14   call query2table(mySQL,myDSN,optimize,howmany)
15   Call TimerEnd
16   %>

17   </BODY></HTML>
18   

Here is a table display with a GetString call and no LOOP:

   <%response.buffer=true%>
   <HEAD><TITLE>dbtablegetstringall.asp</TITLE></HEAD>
   <HTML><body bgcolor="#FFFFFF">
   <!--#include virtual="/adovbs.inc"-->
   <!--#include virtual="/learn/test/lib_dbtablefastv2.asp"-->
   <%
   server.scripttimeout=240
   optimize=optimize_GetStringAll
   myDSN = "DSN=student;UID=student;pwd=magic"
10   mySQL="select * from authors order by author"
11   
12   Call TimerStart
13   call query2table(mySQL,myDSN,optimize,howmany)
14   response.write OptimizationName(optimize) & "<br>"
15   Call TimerEnd
16   %>

17   </BODY></HTML>

Here is a table display with a GetString call (buffered):

   <%response.buffer=true%>
   <HEAD><TITLE>dbtablegetstringbuffered.asp</TITLE></HEAD>
   <HTML><body bgcolor="#FFFFFF">
   <!--#include virtual="/adovbs.inc"-->
   <!--#include virtual="/learn/test/lib_dbtablefastv2.asp"-->
   <%
   server.scripttimeout=240
   optimize=optimize_GetStringBuffered
   myDSN = "DSN=student;UID=student;pwd=magic"
10   mySQL="select * from authors order by author"
11   
12   Call TimerStart
13   call query2table(mySQL,myDSN,optimize,howmany)
14   response.write OptimizationName(optimize) & "<br>"
15   Call TimerEnd
16   %>

17   </BODY></HTML>

Here is a table display with a GetRows call and no LOOP:

   <%response.buffer=true%>
   <HEAD><TITLE>dbtablegetrowsall.asp</TITLE></HEAD>
   <HTML><body bgcolor="#FFFFFF">
   <!--#include virtual="/adovbs.inc"-->
   <!--#include virtual="/learn/test/lib_dbtablefastv2.asp"-->
   <%
   server.scripttimeout=240
   optimize=optimize_getrowsall
   response.write OptimizationName(optimize) & "<p>"
10   
11   myDSN = "DSN=student;UID=student;pwd=magic"
12   mySQL="select * from authors order by author "
13   
14   
15   call TimerStart
16   call query2table(mySQL,myDSN,optimize,howmany)
17   call TimerEnd
18   
19   %>

20   </BODY></HTML>

Here is a table display with a GetRows (buffered):

   <%response.buffer=true%>
   <HEAD><TITLE>dbtableGetRowsBuffered.asp</TITLE></HEAD>
   <HTML><body bgcolor="#FFFFFF">
   <!--#include virtual="/adovbs.inc"-->
   <!--#include virtual="/learn/test/lib_dbtablefastv2.asp"-->
   <%
   server.scripttimeout=240
   optimize=optimize_GetRowsBuffered
   
10   myDSN = "DSN=student;UID=student;pwd=magic"
11   'mySQL="select * from authors order by author "
12   mySQL="select * from authors order by author "
13   
14   Call TimerStart
15   call query2table(mySQL,myDSN,optimize,howmany)
16   Call TimerEnd
17   %>

18   </BODY></HTML>

Here is a table display of a portion of the records:

   <%response.buffer=true%>
   <HEAD><TITLE>dbtablelimitrows.asp</TITLE></HEAD>
   <HTML><body bgcolor="#FFFFFF">
   <!--#include virtual="/adovbs.inc"-->
   <!--#include virtual="/learn/test/lib_dbtablefastv2.asp"-->
   <%
   server.scripttimeout=240
   optimize=optimize_LimitRows
   myDSN = "DSN=student;UID=student;pwd=magic"
10   mySQL="select * from authors order by author"
11   
12   Call TimerStart
13   call query2table(mySQL,myDSN,optimize,howmany)
14   response.write OptimizationName(optimize) & "<br>"
15   Call TimerEnd
16   %>

17   </BODY></HTML>

Here is the optimized library lib_dbtablefastv2.asp which achieves this speed:

   <%
   Const optimize_LoopAll = 1
   Const optimize_GetstringAll = 2
   Const optimize_GetrowsAll = 3
   Const optimize_GetrowsBuffered = 4
   Const optimize_GetStringBuffered = 5
   Const optimize_LimitRows = 6
   Const optimize_LoopAll_String = 7
   
10   dim optimize_buffersize
11   dim optimize_started
12   dim optimize_ended
13   dim optimize_SQL
14   dim optimize_DSN
15   dim optimize_howmany
16   dim optimize_cursorlocation
17   dim optimize_maxrecs
18   dim optimize_disconnectRS
19   
20   optimize_started=0
21   
22   ' performance stuff
23   optimize_buffersize=200
24   'optimize_cursorlocation=aduseclient
25   optimize_maxrecs=500
26   optimize_cursorlocation=aduseserver
27   optimize_disconnectRS=false
28   optimize_stringwrite=false
29   
30   SUB TimerStart()
31      optimize_started=now()
32   END SUB
33   
34   SUB TimerEnd()
35      optimize_ended=now()
36      elapsed=DateDiff("s", optimize_started, optimize_ended)
37      response.write "SQL=<b>" & optimize_SQL & "</b><br>"
38      response.write "DSN=<b>" & optimize_DSN & "</b><br>"
39      response.write "Query took <b>" & elapsed & " seconds.</b><br>"
40      IF optimize_howmany=-1 THEN
41         optimize_howmany=querycount(optimize_DSN,optimize_SQL)
42      END IF
43      response.write "Query processed <b>" & optimize_howmany & " records.</b><br>"
44      response.write "Speed =<b>" & optimize_howmany/elapsed & " records per second.</b><br>"
45      response.write "Notes:<br>"
46      pad="&nbsp;&nbsp;&nbsp;&nbsp;"
47      response.write pad & "buffersize=<b>" & optimize_buffersize & "</b><br>"
48      IF optimize_cursorlocation=adUseClient THEN
49         response.write pad & "cursorlocation=<b>adUseClient</b><br>"
50      END IF
51      IF optimize_cursorlocation=adUseServer THEN
52         response.write pad & "cursorlocation=<b>adUseServer</b><br>"
53      END IF
54   END SUB
55   
56   sub query2table(parmQuery, parmDSN,parmMethod,parmcount)
57      ' method 1 = standard
58      ' method 2 = getrows
59      ' method 3 = getstring
60      dim howmany
61      SELECT CASE parmMethod
62         CASE 1
63            Call loopStandard(parmQuery,parmDSN,howmany)
64         CASE 2
65            Call loopGetString(parmQuery,parmDSN,howmany)
66         CASE 3
67            Call loopGetRows(parmQuery,parmDSN,howmany)
68         CASE 4
69            Call loopGetRowsBuffered(parmQuery,parmDSN,howmany)
70         CASE 5
71            Call loopGetStringBuffered(parmQuery,parmDSN,howmany)
72         CASE 6
73            Call LimitRows(parmQuery,parmDSN,howmany)
74         CASE 7
75            Call loopStandardStringWrite(parmQuery,parmDSN,howmany)
76         CASE ELSE
77            response.write "1, 2 or 3 are only valid speedmethods"
78      END SELECT
79      parmcount=howmany
80      If optimize_started<>0 THEN
81         optimize_DSN=parmDSN
82         optimize_SQL=parmquery
83         optimize_howmany=parmcount
84      END IF
85   END SUB
86   
87   FUNCTION querycount(parmDSN,parmQuery)
88      set rstemp=Server.CreateObject("adodb.Recordset")
89      rstemp.open parmQuery, parmDSN, adopenstatic
90      querycount=rstemp.recordcount
91      rstemp.close
92      set rstemp=nothing
93   END FUNCTION
94   
95   
96   SUB loopstandard(inputquery, inputDSN,inputcount)
97      dim conntemp, rstemp
98      set conntemp=server.createobject("adodb.connection")
99      ' 0 seconds means wait forever, default is 15
100      conntemp.connectiontimeout=0
101      conntemp.cursorlocation=optimize_cursorlocation
102      conntemp.open inputDSN
103      set rstemp=conntemp.execute(inputquery)
104      IF optimize_disconnectRS=true THEN
105         conntemp.close
106      END IF
107      howmanyfields=rstemp.fields.count -1
108      tablestart="<table border=1 cols=3><col width='15%'><col width='70%'><col width='15%'><tr>"
109      response.write tablestart
110      for i=0 to howmanyfields %>

111                <td><b><%=rstemp(i).name%></B></TD>
112      <% next %>
113      </tr>
114      <% ' Now lets grab all the records
115      DO UNTIL rstemp.eof
116         counter=counter+1
117         response.write "<tr>"
118         for i = 0 to howmanyfields
119            thisvalue=rstemp(i)
120            If isnull(thisvalue) then
121               thisvalue="&nbsp;"
122            end if
123         response.write "<td valign=top>" & thisvalue & "</td>" & vbcrlf
124         next
125         response.write "</tr>"
126         rstemp.movenext
127         IF counter mod 50=0 THEN
128            If response.isclientconnected()=false THEN
129               EXIT DO
130            END IF
131            response.write "</table>" & TableStart
132         END IF
133   
134      loop%>

135      </table>
136      <%
137      inputcount=counter
138      rstemp.close
139      set rstemp=nothing
140      conntemp.close
141      set conntemp=nothing
142   END SUB%>

143   
144   <%SUB loopstandardStringWrite(inputquery, inputDSN,inputcount)
145      dim conntemp, rstemp
146      set conntemp=server.createobject("adodb.connection")
147      ' 0 seconds means wait forever, default is 15
148      conntemp.connectiontimeout=0
149      conntemp.cursorlocation=optimize_cursorlocation
150      conntemp.open inputDSN
151      set rstemp=conntemp.execute(inputquery)
152      IF optimize_disconnectRS=true THEN
153         conntemp.close
154      END IF
155      howmanyfields=rstemp.fields.count -1
156      tablestart="<table border=1 cols=3><col width='15%'><col width='70%'><col width='15%'><tr>"
157      response.write tablestart
158      for i=0 to howmanyfields %>

159                <td><b><%=rstemp(i).name%></B></TD>
160      <% next %>
161      </tr>
162      <% ' Now lets grab all the records
163      tempSTR=""
164      DO UNTIL rstemp.eof
165         counter=counter+1
166         tempSTR=tempSTR & "<tr>"
167         for i = 0 to howmanyfields
168            thisvalue=rstemp(i)
169            If isnull(thisvalue) then
170               thisvalue="&nbsp;"
171            end if
172         tempSTR=tempSTR & "<td valign=top>" & thisvalue & "</td>" & vbcrlf
173         next
174         tempSTR=tempSTR & "</tr>"
175         rstemp.movenext
176         IF counter mod 50=0 THEN
177            If response.isclientconnected()=false THEN
178               EXIT DO
179            END IF
180            tempSTR=tempSTR & "</table>" & TableStart
181            response.write tempSTR
182            response.flush
183            tempSTR=""
184         END IF
185      loop%>

186      </table>
187      <%
188      inputcount=counter
189      rstemp.close
190      set rstemp=nothing
191      conntemp.close
192      set conntemp=nothing
193   END SUB%>

194   
195   <%SUB loopGetstring(inputquery, inputDSN,inputcount)
196      dim conntemp, rstemp
197      set conntemp=server.createobject("adodb.connection")
198      ' 0 seconds means wait forever, default is 15
199      conntemp.connectiontimeout=0
200      conntemp.open inputDSN
201      set rstemp=conntemp.execute(inputquery)
202      howmanyfields=rstemp.fields.count -1
203      tablestart="<table border=1 cols=3><col width='15%'><col width='70%'><col width='15%'><tr>"
204      response.write tablestart
205      for i=0 to howmanyfields %>

206                <td><b><%=rstemp(i).name%></B></TD>
207      <% next %>
208      </tr>
209      <%
210      ' Now lets grab all the records
211      tempSTR=rstemp.getstring(,, "</td><td>", "</td></tr><TR><TD>", "&nbsp;")
212      response.write tempSTR
213      response.write "</table>"
214      inputcount=-1
215      rstemp.close
216      set rstemp=nothing
217      conntemp.close
218      set conntemp=nothing
219   END SUB%>

220   
221   
222   <%SUB loopGetstringbuffered(inputquery, inputDSN,inputcount)
223      dim conntemp, rstemp
224      set conntemp=server.createobject("adodb.connection")
225      ' 0 seconds means wait forever, default is 15
226      conntemp.connectiontimeout=0
227      conntemp.open inputDSN
228      set rstemp=conntemp.execute(inputquery)
229      howmanyfields=rstemp.fields.count -1
230      tablestart="<table border=1 cols=3><col width='15%'><col width='70%'><col width='15%'><tr>"
231      response.write tablestart
232      for i=0 to howmanyfields %>

233                <td><b><%=rstemp(i).name%></B></TD>
234      <% next %>
235      </tr>
236      <%
237      ' Now lets grab all the records
238      DO
239         tempSTR=rstemp.getstring(,optimize_buffersize, "</td><td>", "</td></tr><TR><TD>", "&nbsp;")
240         response.write tempSTR
241         If response.isclientconnected()=false THEN
242               EXIT SUB
243         END IF
244         response.write "</table>" & TableStart
245      LOOP UNTIL rstemp.eof
246      response.write "</table>"
247      inputcount=-1
248      rstemp.close
249      set rstemp=nothing
250      conntemp.close
251      set conntemp=nothing
252   END SUB
253   
254   SUB loopGetRows(inputquery, inputDSN,inputcount)
255      dim conntemp, rstemp
256      set conntemp=server.createobject("adodb.connection")
257      ' 0 seconds means wait forever, default is 15
258      conntemp.connectiontimeout=0
259      conntemp.open inputDSN
260      set rstemp=conntemp.execute(inputquery)
261      howmanyfields=rstemp.fields.count -1
262      tablestart="<table border=1 cols=3><col width='15%'><col width='70%'><col width='15%'><tr>"
263      response.write tablestart
264      for i=0 to howmanyfields %>

265                <td><b><%=rstemp(i).name%></B></TD>
266      <% next %>
267      </tr>
268      <%
269      ' Now lets grab all the records
270      alldata=rstemp.getrows
271      numcols=ubound(alldata,1)
272      numrows=ubound(alldata,2)
273      
274      FOR rowcounter= 0 TO numrows
275         FOR colcounter=0 to numcols
276            response.write "<td valign=top>"
277            response.write alldata(colcounter,rowcounter)
278            response.write "</td>"
279         NEXT
280         response.write "</tr>" & vbcrlf
281         IF rowcounter mod 50=0 THEN
282            If response.isclientconnected()=false THEN
283                  EXIT FOR
284               END IF
285            response.write "</table>" & TableStart
286         END IF
287      NEXT
288      response.write "</table>"
289      inputcount=numrows
290      rstemp.close
291      set rstemp=nothing
292      conntemp.close
293      set conntemp=nothing
294   END SUB
295   
296   SUB loopGetRowsBuffered(inputquery, inputDSN,inputcount)
297      dim conntemp, rstemp
298      set conntemp=server.createobject("adodb.connection")
299      ' 0 seconds means wait forever, default is 15
300      conntemp.connectiontimeout=0
301      conntemp.open inputDSN
302      set rstemp=conntemp.execute(inputquery)
303      howmanyfields=rstemp.fields.count -1
304      tablestart="<table border=1 cols=3><col width='15%'><col width='70%'><col width='15%'><tr>"
305      response.write tablestart
306      for i=0 to howmanyfields %>

307                <td><b><%=rstemp(i).name%></B></TD>
308      <% next %>
309      </tr>
310      <%
311      ' Now lets grab all the records
312      DO
313         alldata=rstemp.getrows(optimize_buffersize)
314         numcols=ubound(alldata,1)
315         numrows=ubound(alldata,2)
316      
317         FOR rowcounter= 0 TO numrows
318            FOR colcounter=0 to numcols
319               response.write "<td valign=top>"
320               response.write alldata(colcounter,rowcounter)
321               response.write "</td>"
322            NEXT
323            response.write "</tr>" & vbcrlf
324         NEXT
325         howmany=howmany+numrows
326         If response.isclientconnected()=false THEN
327               EXIT SUB
328         END IF
329         response.write "</table>" & TableStart
330      LOOP UNTIL rstemp.eof
331      response.write "</table>"
332      inputcount=howmany
333      rstemp.close
334      set rstemp=nothing
335      conntemp.close
336      set conntemp=nothing
337   END SUB
338   
339   SUB LimitRows(inputquery, inputDSN,inputcount)
340      set rstemp=Server.CreateObject("adodb.Recordset")
341      rstemp.maxrecords=optimize_maxrecs
342      'rstemp.open inputquery, inputDSN, adopenforwardonly, adlockReadOnly
343      rstemp.open inputquery, inputDSN,adopenstatic
344      
345      howmanyfields=rstemp.fields.count -1
346      tablestart="<table border=1 cols=3><col width='15%'><col width='70%'><col width='15%'><tr>"
347      response.write tablestart
348      for i=0 to howmanyfields %>

349             <td><b><%=rstemp(i).name%></B></TD>
350      <% next %>
351      </tr>
352      <%
353      response.flush
354      tempSTR=rstemp.getstring(,, "</td><td>", "</td></tr><TR><TD>", "&nbsp;")
355      response.write tempSTR
356      response.write "</td></tr></table>"
357      
358      inputcount=optimize_maxrecs
359      rstemp.close
360      set rstemp=nothing
361   END SUB
362   
363   FUNCTION optimizationName(parmNum)
364      SELECT CASE parmnum
365      CASE optimize_LoopAll
366         optimizationName="LoopAll"
367      CASE optimize_GetstringAll
368         optimizationName="GetstringAll"
369      CASE optimize_GetrowsAll
370         optimizationName="GetrowsAll"
371      CASE optimize_GetrowsBuffered
372         optimizationName="GetrowsBuffered"
373      CASE optimize_GetStringBuffered
374         optimizationName="GetStringBuffered"
375      CASE optimize_LimitRows
376         optimizationName="LimitRows"
377      CASE ELSE
378         optimizationName="undefined"
379      END SELECT
380   END FUNCTION
381   %>

382   


ASP Quick Lessons written by Charles M. Carroll
http://www.learnasp.com/learn/speedtablesdrivers.asp Page 234


ASP Speed from ASP Quick Lessons

Speed/Optimization: What about the Driver?

Fetching records in an optimized way may have many variations but before you get to the database you interact with a driver. Here we time the difference between arbitrary drivers. We will benchmark with the simplest method: Fetching and displaying all records with a LOOP, .movenext and periodic response.flush commands.

Here is a table display against a SQL server with a OLEDB driver.

   <%response.buffer=true%>
   <HEAD><TITLE>dbtableSQLoledb.asp</TITLE></HEAD>
   <HTML><body bgcolor="#FFFFFF">
   <!--#include virtual="/adovbs.inc"-->
   <!--#include virtual="/learn/test/lib_dbtablefastv2.asp"-->
   <%
   server.scripttimeout=240
   optimize=optimize_LoopAll
   mySQL="select * from authors where au_id<2000 order by author "
10   
11   myDSN="PROVIDER=SQLOLEDB;DATA SOURCE=sql2.datareturn.com;"
12   myDSN=myDSN & "USER ID=student;PASSWORD=magic;"
13   
14   Call TimerStart
15   call query2table(mySQL,myDSN,optimize,howmany)
16   Call TimerEnd
17   
18   %>

19   </BODY></HTML>

Here is a table display against a SQL server with a ODBC driver:

   <%response.buffer=true%>
   <HEAD><TITLE>dbtableSQLODBC.asp</TITLE></HEAD>
   <HTML><body bgcolor="#FFFFFF">
   <!--#include virtual="/adovbs.inc"-->
   <!--#include virtual="/learn/test/lib_dbtablefastv2.asp"-->
   <%
   server.scripttimeout=240
   
   mySQL="select * from authors where au_id<2000 order by author "
10   optimize=optimize_LoopAll
11   myDSN="PROVIDER=MSDASQL;DRIVER={SQL Server};"
12   myDSN=myDSN & "SERVER=sql2.datareturn.com;UID=student;PWD=magic;"
13   
14   Call TimerStart
15   call query2table(mySQL,myDSN,optimize,howmany)
16   Call TimerEnd
17   %>

18   </BODY></HTML>

Here is the optimized library lib_dbtablefastv2.asp which achieves this speed:

   <%
   Const optimize_LoopAll = 1
   Const optimize_GetstringAll = 2
   Const optimize_GetrowsAll = 3
   Const optimize_GetrowsBuffered = 4
   Const optimize_GetStringBuffered = 5
   Const optimize_LimitRows = 6
   Const optimize_LoopAll_String = 7
   
10   dim optimize_buffersize
11   dim optimize_started
12   dim optimize_ended
13   dim optimize_SQL
14   dim optimize_DSN
15   dim optimize_howmany
16   dim optimize_cursorlocation
17   dim optimize_maxrecs
18   dim optimize_disconnectRS
19   
20   optimize_started=0
21   
22   ' performance stuff
23   optimize_buffersize=200
24   'optimize_cursorlocation=aduseclient
25   optimize_maxrecs=500
26   optimize_cursorlocation=aduseserver
27   optimize_disconnectRS=false
28   optimize_stringwrite=false
29   
30   SUB TimerStart()
31      optimize_started=now()
32   END SUB
33   
34   SUB TimerEnd()
35      optimize_ended=now()
36      elapsed=DateDiff("s", optimize_started, optimize_ended)
37      response.write "SQL=<b>" & optimize_SQL & "</b><br>"
38      response.write "DSN=<b>" & optimize_DSN & "</b><br>"
39      response.write "Query took <b>" & elapsed & " seconds.</b><br>"
40      IF optimize_howmany=-1 THEN
41         optimize_howmany=querycount(optimize_DSN,optimize_SQL)
42      END IF
43      response.write "Query processed <b>" & optimize_howmany & " records.</b><br>"
44      response.write "Speed =<b>" & optimize_howmany/elapsed & " records per second.</b><br>"
45      response.write "Notes:<br>"
46      pad="&nbsp;&nbsp;&nbsp;&nbsp;"
47      response.write pad & "buffersize=<b>" & optimize_buffersize & "</b><br>"
48      IF optimize_cursorlocation=adUseClient THEN
49         response.write pad & "cursorlocation=<b>adUseClient</b><br>"
50      END IF
51      IF optimize_cursorlocation=adUseServer THEN
52         response.write pad & "cursorlocation=<b>adUseServer</b><br>"
53      END IF
54   END SUB
55   
56   sub query2table(parmQuery, parmDSN,parmMethod,parmcount)
57      ' method 1 = standard
58      ' method 2 = getrows
59      ' method 3 = getstring
60      dim howmany
61      SELECT CASE parmMethod
62         CASE 1
63            Call loopStandard(parmQuery,parmDSN,howmany)
64         CASE 2
65            Call loopGetString(parmQuery,parmDSN,howmany)
66         CASE 3
67            Call loopGetRows(parmQuery,parmDSN,howmany)
68         CASE 4
69            Call loopGetRowsBuffered(parmQuery,parmDSN,howmany)
70         CASE 5
71            Call loopGetStringBuffered(parmQuery,parmDSN,howmany)
72         CASE 6
73            Call LimitRows(parmQuery,parmDSN,howmany)
74         CASE 7
75            Call loopStandardStringWrite(parmQuery,parmDSN,howmany)
76         CASE ELSE
77            response.write "1, 2 or 3 are only valid speedmethods"
78      END SELECT
79      parmcount=howmany
80      If optimize_started<>0 THEN
81         optimize_DSN=parmDSN
82         optimize_SQL=parmquery
83         optimize_howmany=parmcount
84      END IF
85   END SUB
86   
87   FUNCTION querycount(parmDSN,parmQuery)
88      set rstemp=Server.CreateObject("adodb.Recordset")
89      rstemp.open parmQuery, parmDSN, adopenstatic
90      querycount=rstemp.recordcount
91      rstemp.close
92      set rstemp=nothing
93   END FUNCTION
94   
95   
96   SUB loopstandard(inputquery, inputDSN,inputcount)
97      dim conntemp, rstemp
98      set conntemp=server.createobject("adodb.connection")
99      ' 0 seconds means wait forever, default is 15
100      conntemp.connectiontimeout=0
101      conntemp.cursorlocation=optimize_cursorlocation
102      conntemp.open inputDSN
103      set rstemp=conntemp.execute(inputquery)
104      IF optimize_disconnectRS=true THEN
105         conntemp.close
106      END IF
107      howmanyfields=rstemp.fields.count -1
108      tablestart="<table border=1 cols=3><col width='15%'><col width='70%'><col width='15%'><tr>"
109      response.write tablestart
110      for i=0 to howmanyfields %>

111                <td><b><%=rstemp(i).name%></B></TD>
112      <% next %>
113      </tr>
114      <% ' Now lets grab all the records
115      DO UNTIL rstemp.eof
116         counter=counter+1
117         response.write "<tr>"
118         for i = 0 to howmanyfields
119            thisvalue=rstemp(i)
120            If isnull(thisvalue) then
121               thisvalue="&nbsp;"
122            end if
123         response.write "<td valign=top>" & thisvalue & "</td>" & vbcrlf
124         next
125         response.write "</tr>"
126         rstemp.movenext
127         IF counter mod 50=0 THEN
128            If response.isclientconnected()=false THEN
129               EXIT DO
130            END IF
131            response.write "</table>" & TableStart
132         END IF
133   
134      loop%>

135      </table>
136      <%
137      inputcount=counter
138      rstemp.close
139      set rstemp=nothing
140      conntemp.close
141      set conntemp=nothing
142   END SUB%>

143   
144   <%SUB loopstandardStringWrite(inputquery, inputDSN,inputcount)
145      dim conntemp, rstemp
146      set conntemp=server.createobject("adodb.connection")
147      ' 0 seconds means wait forever, default is 15
148      conntemp.connectiontimeout=0
149      conntemp.cursorlocation=optimize_cursorlocation
150      conntemp.open inputDSN
151      set rstemp=conntemp.execute(inputquery)
152      IF optimize_disconnectRS=true THEN
153         conntemp.close
154      END IF
155      howmanyfields=rstemp.fields.count -1
156      tablestart="<table border=1 cols=3><col width='15%'><col width='70%'><col width='15%'><tr>"
157      response.write tablestart
158      for i=0 to howmanyfields %>

159                <td><b><%=rstemp(i).name%></B></TD>
160      <% next %>
161      </tr>
162      <% ' Now lets grab all the records
163      tempSTR=""
164      DO UNTIL rstemp.eof
165         counter=counter+1
166         tempSTR=tempSTR & "<tr>"
167         for i = 0 to howmanyfields
168            thisvalue=rstemp(i)
169            If isnull(thisvalue) then
170               thisvalue="&nbsp;"
171            end if
172         tempSTR=tempSTR & "<td valign=top>" & thisvalue & "</td>" & vbcrlf
173         next
174         tempSTR=tempSTR & "</tr>"
175         rstemp.movenext
176         IF counter mod 50=0 THEN
177            If response.isclientconnected()=false THEN
178               EXIT DO
179            END IF
180            tempSTR=tempSTR & "</table>" & TableStart
181            response.write tempSTR
182            response.flush
183            tempSTR=""
184         END IF
185      loop%>

186      </table>
187      <%
188      inputcount=counter
189      rstemp.close
190      set rstemp=nothing
191      conntemp.close
192      set conntemp=nothing
193   END SUB%>

194   
195   <%SUB loopGetstring(inputquery, inputDSN,inputcount)
196      dim conntemp, rstemp
197      set conntemp=server.createobject("adodb.connection")
198      ' 0 seconds means wait forever, default is 15
199      conntemp.connectiontimeout=0
200      conntemp.open inputDSN
201      set rstemp=conntemp.execute(inputquery)
202      howmanyfields=rstemp.fields.count -1
203      tablestart="<table border=1 cols=3><col width='15%'><col width='70%'><col width='15%'><tr>"
204      response.write tablestart
205      for i=0 to howmanyfields %>

206                <td><b><%=rstemp(i).name%></B></TD>
207      <% next %>
208      </tr>
209      <%
210      ' Now lets grab all the records
211      tempSTR=rstemp.getstring(,, "</td><td>", "</td></tr><TR><TD>", "&nbsp;")
212      response.write tempSTR
213      response.write "</table>"
214      inputcount=-1
215      rstemp.close
216      set rstemp=nothing
217      conntemp.close
218      set conntemp=nothing
219   END SUB%>

220   
221   
222   <%SUB loopGetstringbuffered(inputquery, inputDSN,inputcount)
223      dim conntemp, rstemp
224      set conntemp=server.createobject("adodb.connection")
225      ' 0 seconds means wait forever, default is 15
226      conntemp.connectiontimeout=0
227      conntemp.open inputDSN
228      set rstemp=conntemp.execute(inputquery)
229      howmanyfields=rstemp.fields.count -1
230      tablestart="<table border=1 cols=3><col width='15%'><col width='70%'><col width='15%'><tr>"
231      response.write tablestart
232      for i=0 to howmanyfields %>

233                <td><b><%=rstemp(i).name%></B></TD>
234      <% next %>
235      </tr>
236      <%
237      ' Now lets grab all the records
238      DO
239         tempSTR=rstemp.getstring(,optimize_buffersize, "</td><td>", "</td></tr><TR><TD>", "&nbsp;")
240         response.write tempSTR
241         If response.isclientconnected()=false THEN
242               EXIT SUB
243         END IF
244         response.write "</table>" & TableStart
245      LOOP UNTIL rstemp.eof
246      response.write "</table>"
247      inputcount=-1
248      rstemp.close
249      set rstemp=nothing
250      conntemp.close
251      set conntemp=nothing
252   END SUB
253   
254   SUB loopGetRows(inputquery, inputDSN,inputcount)
255      dim conntemp, rstemp
256      set conntemp=server.createobject("adodb.connection")
257      ' 0 seconds means wait forever, default is 15
258      conntemp.connectiontimeout=0
259      conntemp.open inputDSN
260      set rstemp=conntemp.execute(inputquery)
261      howmanyfields=rstemp.fields.count -1
262      tablestart="<table border=1 cols=3><col width='15%'><col width='70%'><col width='15%'><tr>"
263      response.write tablestart
264      for i=0 to howmanyfields %>

265                <td><b><%=rstemp(i).name%></B></TD>
266      <% next %>
267      </tr>
268      <%
269      ' Now lets grab all the records
270      alldata=rstemp.getrows
271      numcols=ubound(alldata,1)
272      numrows=ubound(alldata,2)
273      
274      FOR rowcounter= 0 TO numrows
275         FOR colcounter=0 to numcols
276            response.write "<td valign=top>"
277            response.write alldata(colcounter,rowcounter)
278            response.write "</td>"
279         NEXT
280         response.write "</tr>" & vbcrlf
281         IF rowcounter mod 50=0 THEN
282            If response.isclientconnected()=false THEN
283                  EXIT FOR
284               END IF
285            response.write "</table>" & TableStart
286         END IF
287      NEXT
288      response.write "</table>"
289      inputcount=numrows
290      rstemp.close
291      set rstemp=nothing
292      conntemp.close
293      set conntemp=nothing
294   END SUB
295   
296   SUB loopGetRowsBuffered(inputquery, inputDSN,inputcount)
297      dim conntemp, rstemp
298      set conntemp=server.createobject("adodb.connection")
299      ' 0 seconds means wait forever, default is 15
300      conntemp.connectiontimeout=0
301      conntemp.open inputDSN
302      set rstemp=conntemp.execute(inputquery)
303      howmanyfields=rstemp.fields.count -1
304      tablestart="<table border=1 cols=3><col width='15%'><col width='70%'><col width='15%'><tr>"
305      response.write tablestart
306      for i=0 to howmanyfields %>

307                <td><b><%=rstemp(i).name%></B></TD>
308      <% next %>
309      </tr>
310      <%
311      ' Now lets grab all the records
312      DO
313         alldata=rstemp.getrows(optimize_buffersize)
314         numcols=ubound(alldata,1)
315         numrows=ubound(alldata,2)
316      
317         FOR rowcounter= 0 TO numrows
318            FOR colcounter=0 to numcols
319               response.write "<td valign=top>"
320               response.write alldata(colcounter,rowcounter)
321               response.write "</td>"
322            NEXT
323            response.write "</tr>" & vbcrlf
324         NEXT
325         howmany=howmany+numrows
326         If response.isclientconnected()=false THEN
327               EXIT SUB
328         END IF
329         response.write "</table>" & TableStart
330      LOOP UNTIL rstemp.eof
331      response.write "</table>"
332      inputcount=howmany
333      rstemp.close
334      set rstemp=nothing
335      conntemp.close
336      set conntemp=nothing
337   END SUB
338   
339   SUB LimitRows(inputquery, inputDSN,inputcount)
340      set rstemp=Server.CreateObject("adodb.Recordset")
341      rstemp.maxrecords=optimize_maxrecs
342      'rstemp.open inputquery, inputDSN, adopenforwardonly, adlockReadOnly
343      rstemp.open inputquery, inputDSN,adopenstatic
344      
345      howmanyfields=rstemp.fields.count -1
346      tablestart="<table border=1 cols=3><col width='15%'><col width='70%'><col width='15%'><tr>"
347      response.write tablestart
348      for i=0 to howmanyfields %>

349             <td><b><%=rstemp(i).name%></B></TD>
350      <% next %>
351      </tr>
352      <%
353      response.flush
354      tempSTR=rstemp.getstring(,, "</td><td>", "</td></tr><TR><TD>", "&nbsp;")
355      response.write tempSTR
356      response.write "</td></tr></table>"
357      
358      inputcount=optimize_maxrecs
359      rstemp.close
360      set rstemp=nothing
361   END SUB
362   
363   FUNCTION optimizationName(parmNum)
364      SELECT CASE parmnum
365      CASE optimize_LoopAll
366         optimizationName="LoopAll"
367      CASE optimize_GetstringAll
368         optimizationName="GetstringAll"
369      CASE optimize_GetrowsAll
370         optimizationName="GetrowsAll"
371      CASE optimize_GetrowsBuffered
372         optimizationName="GetrowsBuffered"
373      CASE optimize_GetStringBuffered
374         optimizationName="GetStringBuffered"
375      CASE optimize_LimitRows
376         optimizationName="LimitRows"
377      CASE ELSE
378         optimizationName="undefined"
379      END SELECT
380   END FUNCTION
381   %>

382   


ASP Quick Lessons written by Charles M. Carroll
http://www.learnasp.com/learn/isclientconnected.asp Page 235


IsClientConnected from ASP Quick Lessons

IsClientConnected -- eliminating stray tasks by Charles Carroll

Unbeknownst to most users if their script begins execution it continues invisibly in the background even if the user hits the stop button or moves to a different page on your site or the web. A database loop could tie up the CPU for quite a while, even though the user hit the "stop" button --  the task would still be "spinning/executing" on the server even though the user was long gone. This is particularly true in database tasks.

response.IsClientConnected()
is available beginning with IIS4 (if you want to see if you have it, see /learn/versioncheck.asp) and can be used within a page to determine if the user is still fetching that page, i.e.

Here is some code that will loop until the script times out.  If the user hits stop, then the script will still continue invisibly even if they are executing a different page.

   <%server.scripttimeout=20
   ' this times out the script in 20 seconds whether done or not%>

   <TITLE>infiniteloop.asp</TITLE>
   <body bgcolor="#FFFFFF">
   <%
   DO
      x=x+1
      response.write x & "<br>"
   LOOP
10   %>

11   </body></html>
12   

Here is the fixed code that will loop until the script times out AND WILL STOP IF THE USER HITS "STOP" OR ACCESSES A DIFFERENT PAGE. Notice the mod test to ensure the echeck is only made when x is a multiple of 1000 (1000, 2000, 3000, 4000, etc.) to reduce how many times the client connection is checked.

   <%server.scripttimeout=20
   ' this times out the script in 20 seconds whether done or
   ' the user hit the STOP button
   %>

   <TITLE>infiniteloopfixed.asp</TITLE>
   <body bgcolor="#FFFFFF">
   <%
   DO
      x=x+1
10      response.write x & "<br>"
11      IF x MOD 1000=0 AND response.isclientconnected=false THEN
12         EXIT DO
13      END IF
14   LOOP
15   %>

16   </body></html>
17   

this code above will stop when user hits the stop button.

I recommend that all loops through database recordsets incorporate this so that they don't execute invisibly wasting CPU and database server resources. So here is a database table script that incorporates this functionality and quits reading the database when the user hits stop button or accesses a different page:

   <%response.buffer=true%>
   <TITLE>dbtableisclientconnected.asp</TITLE>
   <body bgcolor="#FFFFFF">
   <%
   ' ASP program that displays a database in table form
   myDSN="DSN=Student;uid=student;pwd=magic"
   mySQL="select * from publishers"
   
   set conntemp=server.createobject("adodb.connection")
10   conntemp.open myDSN
11   set rstemp=conntemp.execute(mySQL)
12   howmanyfields=rstemp.fields.count -1
13   %>

14   <table border=1><tr>
15   <% 'Put Headings On The Table of Field Names
16   for i=0 to howmanyfields %>

17          <td><b><%=rstemp(i).name %></B></TD>
18   <% next %>
19   </tr>
20   <% ' Now lets grab all the records
21   howoften=200 ' how many records to check client connection
22   DO  UNTIL rstemp.eof
23      counter=counter+1
24      response.write "<tr>" & vbcrlf
25      for i = 0 to howmanyfields
26         fieldval=rstemp(i)
27         If isnull(fieldval) THEN
28            fieldval="-null-"
29         END IF
30         If trim(fieldval)="" THEN
31            fieldval="&nbsp;"
32         END IF
33               response.write "<td valign=top>" & fieldval & "</td>" & vbcrlf
34      next
35      response.write "</tr>" & vbcrlf
36      IF counter mod howoften = 0 THEN
37         IF response.isclientconnected=false THEN
38            EXIT DO
39         ELSE
40            response.write "</table>" & vbcrlf & "<table border=1><tr>"
41            response.flush
42         END IF
43      END IF
44      rstemp.movenext
45   LOOP
46   response.write "</table>"
47   rstemp.close
48   set rstemp=nothing
49   conntemp.close
50   set conntemp=nothing
51   %>

52   </body></html>
53   
54   
55   
56   
57   
58   
59   
60   
61   
62   


ASP Quick Lessons written by Charles M. Carroll
http://www.learnasp.com/learn/nothing.asp Page 236


Nothing Controversy from ASP Quick Lessons

The controversy over Nothing by Charles Carroll

Rule #1: All objects created with SET whatever=server.createobject("whatever")
need to be destroyed on that page, i.e.
set whatever=nothing

Rule #2: All objects created with
SET whatever=server.createobject("whatever")
should never be put in a session variable.

These two statements are the source of much controversy. I would like to address the veracity of these statements and address the real truth of this matter and why this truth is important to building high traffic websites. 

The session is issue is dealt with in:
http://www.learnasp.com/learn/sessionoverview.asp
http://www.learnasp.com/learn/globalproblems.asp
http://www.activeserverpages.com/learn/buildvbthreads.asp
http://www.learnasp.com/learn/nosessionobjects.asp

Scenario #1:

set x=server.createobject("whatever.whatever")
....
set x=nothing

Scenario #2

set x=server.createobject("whatever.whatever")
....

In Scenario #1, I can guarantee

In Scenario #2, I cannot guarantee:

I will also state that large ISPs (Innerhost, DataReturn) will guarantee your webserver will come down several times a day or week with scenario #2 (depending on how many objects are created throughout the day). With Scenario #1 the webserver stays up without incident. This evidence indicates the IIS garbage collection screws up.


ASP Quick Lessons written by Charles M. Carroll
http://www.learnasp.com/learn/dbpooling.asp Page 237


dbtable

Database Connection Pooling by Charles Carroll

Connection pooling takes care of re-using connections.

Lets say Scripta.asp

and 1,000 users do this simultaneously. It is not quite simultaneous, let us say that what happens when eight users access a script and create, close and destroy eight connections.

User Open conn. time Process Start time Close time
#1 1:00am .001 1:00am .002 1:00am .012
#2 1:00am .002 1:00am .003 1:00am .013
#3 1:00am .003 1:00am .004 1:00am .009
#4 1:00am .003 1:00am .004 1:00am .015
#5 1:00am .007 1:00am .008 1:00am .014
#6 1:00am .009 1:00am .010 1:00am .021
#7 1:00am .016 1:00am .017 1:00am .028
#8 1:00am .017 1:00am .018 1:00am .026
Time - open conns Open conns Pool to be reused Being Re-used
1:00am .001 - 1 #1 0
1:00am .002 - 2 #1, #2 0
1:00am .010 - 4 #1, #2, #4, #5, #6 #3
1:00am .013 - 4 #2, #4, #5, #6 #1 #6 using #3
1:00am .014 - 3 #4, #5, #6 #1, #2
1:00am .016 - 2 #6, #7 #2, #4 #7 using #1
1:00am .022 - #7, #8 #1, #3, #4, #5 #8 using #2
1:00am .027 - #7 #1, #3, #4, #5
1:00am .029 - #1, #3, #4, #5 waiting

Because of connection pooling they will use MUCH less than 1,000 brand new connections as conn.open statements will be provided with already existing connections invisibly PROVIDING they were closed and thus guaranteed available for re-use.

The pool connections can only be re-used if they are closed. They expire in sixty seconds by default. This is all explained in the following articles:


ASP Quick Lessons written by Charles M. Carroll
http://www.learnasp.com/learn/threads.asp Page 238


VB Component Building Guidelines from ASP Quick Lessons

Threading and ASP/IIS by Charles Carroll

Threads - Worker Bees of the Web Site

All the work done by a webserver is handled by threads. 

Threads are the worker bees of the web server.
Like any employees you want them working hard!

Any ASP script running on the webserver runs on a given thread. If for example, 100 scripts are requested an IIS has 4 threads to service them typically each thread will process 25 scripts.

Think of threads as cashiers at McDonalds or at the supermarket. 4 cashiers could handle 4 customers simultaneously.

In IIS4, the default is 4 threads (which is simply a registry setting) in initial install but extensive real-world testing on Microsoft.com and hig volume sites indicated 20 per CPU would be ideal. 

example:
100 scripts arrive at a web-server with 4 threads. 4 scripts run simultaneously, round-robin style ala:
http://www.learnasp.com/advice/roundrobin.asp
and eventually the 4 threads would probably handle 25 requests each.

100 scripts arrive at a web-server with 20 threads. 20 scripts run simultaneously, round-robin style ala:
http://www.learnasp.com/advice/roundrobin.asp
and eventually the 20 threads would probably handle 5 requests each.

In IIS5 / Win2000 that registry setting is irrelevant. IIS5 dynamically changes the number of threads processing ASP scripts as needed to optimize performance.

IIS4 / NT4 TIP: 
Increase threads from 4 to 20 for each CPU!

thanks to Smiling Jack for this one:
http://www.aspmagazine.com/aspmagazine/issue10kb.asp

see
http://support.microsoft.com/support/kb/articles/q196/0/16.asp
for more details.

Thread Affinity - Enemy of Scalability

Since a request can normally be serviced by any available thread it is like "hopping lines" at cashiers to get to the shortest line. Usually that is true. If a thread finishes its request it just grabs the next waiting script UNLESS the request has thread affinity (which Ted Pattison famed VB author calls a monagomous thread) in which case no matter how many threads are idle the request must wait for the specific thread it has affinity too. Don't make your requests have thread affinity (more on how they can be screwed up this way @
http://www.learnasp.com/advice/dbsessionapp.asp)

Read Up on Threads! Have an Aspirin Ready!

Threads can affect ASP in several ways


ASP Quick Lessons written by Charles M. Carroll
http://www.learnasp.com/learn/threadsafe.asp Page 239


VB Component Building Guidelines from ASP Quick Lessons

Thread Safety Issues by Charles Carroll
  with some help from George Reilly

All the work done by a webserver is handled by threads. They are the worker bees of the webserver. Any process running on the webserver runs on a given thread. Threads can affect ASP in several ways, see:

We will focus on Thread Safety issues here. 

What is Thread Safety?

If a program gets called very fast it can crash or burn out it's motor like a car driven at a high speed UNLESS the designer built in some pretty aggressive code to deal with speed and tested it (kind of like the cars that get run into a wall with crash dummies) Thread safety and high scalability is usually only accomplished by EXTREMELY experienced programmers or commercial components. Thread safety means that the insides were built for speed and then actually tested by creating intense loads (the equivalent of crashing cars into walls) with tools like the Stress Tool at http://homer.rte.microsoft.com/. Better they do this and find out before someone hits a wall and dies the insides need re-inforcement.  

A component that is not thread-safe

Test for Thread Safety with WAST - Not People

Thread Safety testing on home-grown components can be done with tools like the Web Application Stress Tool see:
http://www.asplists.com/asplists/aspwast.asp
Thread Safety issues are more likely to be discovered on multiprocessor machines and that it's vital to stress test components on MP machines to ensure thread safety.

WinInet: Not Thread Safe

The WinInet control is a popular way Visual Basic programmers use to scrape web sites. It however was not tested for server use and had some serious flaws that caused it to create many runtime disasters.

http://support.microsoft.com/support/kb/articles/Q188/9/55.ASP
explains how it could be used in ASP with light load.

http://support.microsoft.com/support/kb/articles/Q183/1/10.ASP
http://support.microsoft.com/support/kb/articles/Q238/4/25.ASP
explains about Thread-Safe issues.

Other articles can be found by searching for
kbWinInet (kbASP can be added to qualify it)

http://support.microsoft.com/support/kb/articles/q237/9/06.asp

Thread Safe WinInet Alternatives

Three alternatives to WinInet exist. 

Microsoft finally created a server side HTTP component in MSXML3.0:
http://msdn.microsoft.com/xml/general/xmlparser.asp

ASPHTTP from www.Serverobjects.com is an example of a very safe implementation. 

ASPTear from http://www.alphasierrapapa.com/ComponentCenter/ is built on WinInet but the designer Christophe Wille has assured me it wrapped it in thread safe C code to skirt the thread safety problems.

Dictionaries - Threading Problems in App or Session Vars

The scripting dictionary is useful but if used at session or application scope can be slow and prohibit scalability in terms of serialization and resource issues.

A FREE replacement interface compatible component can be found at:
http://www.caprockconsulting.com/comsoftware.asp 

http://msdn.microsoft.com/workshop/management/planning/msdnchronicles2.asp
explains how Microsoft had difficulty with scalability at session scope on their site.

http://msdn.microsoft.com/library/techart/d4cache.htm
demonstrates a useful page caching technique.

http://support.microsoft.com/support/kb/articles/Q194/8/03.ASP
discusses using it as application scope object.

A WinNT Option Pack 4 Dictionary Glitch

This is only a problem with the original Windows Option Pack. It's fixed in later service packs and Win2K and it's fixed in everything that installs more recent script engines.

Also an important note for people who have installed WinNT Option Pack 4 to run ASP*: /iishelp/iis/htm/core/iisread.htm

The Scripting.Dictionary object is erroneously marked as Both-threaded. It should be marked as Apartment-threaded. To change this, use the Registry Editor to open the following registry key:
HKEY_CLASSES_ROOT\
  CLSID
   \{EE09B103-97E0-11CF-978F-00A02463E06F}
    \InprocServer32

Change the named value for ThreadingModel to Apartment. If you use the Dictionary object at Application scope without making this change, corruption of data may occur.


ASP Quick Lessons written by Charles M. Carroll
http://www.learnasp.com/learn/roundrobin.asp Page 240


dbtable

Round-Robin Code Execution by Charles Carroll

A common expression you will hear when shifting paradigms (Flat Earth to Round Earth, Cold-Blooded to Warm Blooded Dinosaurs, Traditional Applications to Web Apps) is that everything you know is wrong. Great.... My next question is "What is the right answer in this environment?". Often they have only learned to get rid of the wrong tactics, but are not so fluent in the new tactics. Here we will explain one of the correct things to do when coding an ASP page.

Scripts on a webserver run round-robin. If a script say x.asp is run by 100 people and 50 people are running y.asp then the server may be running:

Person1 x.asp lines 1-3
Person2 x.asp lines 1-3
Person1 x.asp lines 4-20
Person3 x.asp lines 1-3
Person4 x.asp lines 1-3
Person2 x.asp lines 4-10
Person1 y.asp lines 1-5
Person3 x.asp lines 4-6
etc.

If your code does something for example 3 lines later you may think it is inconsequential... 
Only 3 lines after all...
But the webserver may execute thousands of lines in other scripts before returning to your code. 
Hence if the task could be done on line 1 INSTEAD of line 3 that may conserve a resource for thousands of lines of code.

What most people do without thinking:

So if your process opens recordsets a couple of lines before manipulating them this could lead to more open recordsets for the total webserver than you think.

<%
rs1.open
rs2.open
rs3.open
rs4.open
...
process rs1
...
process rs2
...
process rs3
...
process rs4
rs1.close
rs2.close
rs3.close
rs4.close
%>

What they should do:

It is certainly more wasteful than

...
rs1.open
process rs1
rs1.close
...
rs2.open
...
process rs2
rs2.close

rs3.open
...
process rs3
rs4.close

rs4.open
..
process rs4
rs4.close

mostly because of the round-robin effect.

GetString, GetRows conserve resources

This is one of the many reason Getrows and GetString, can be so durn fast ala:
http://www.learnasp.com/learn/dbtablegetrows.asp
http://www.learnasp.com/learn/dbtablegetstring.asp
that code closes recordsets and connections as early as possible.

This is also why disconnected recordets can help an application perform better see:
http://www.learnasp.com/learn/dbtabledisconnected.asp


ASP Quick Lessons written by Charles M. Carroll
http://www.learnasp.com/learn/aspscalability.asp Page 241


Listserrver Join aspscalabilityListserver for more info @

http://www.asplists.com/asplists/aspscalability.asp

Related Links:

 
Transaction Processing Performance Council @
   http://www.tpc.org/
ArrowPoint Mother Nature Profile @
   http://www.arrowpoint.com/solutions/profiles/mother_nature.html
Enterprise Scaling Benchmarks @
   http://www.devx.com/upload/free/features/entdev/1999/08aug99/cs0899/cs0899.asp
Developmentor Load Balancing @
   http://www.develop.com/hp/ewald/lb/loadbalancing.htm
Scalability Resource Kit @
   http://www.microsoft.com/siteserver/commerce/DeployAdmin/ResKit.asp
Cisco's Distributed Director, multiple data centers @
   http://www.cisco.com/warp/public/cc/cisco/mkt/scale/distr/
Microsoft Enterprise White Paper @
   http://www.microsoft.com/NTServer/ntserverenterprise/techdetails/overview/NTSEE.asp
Cisco's Local Director @
   http://www.cisco.com/warp/public/cc/cisco/mkt/scale/locald/
-no name- @
   http://www.level3.com
Fitch & Mathers Intro @
   http://www.fmcorp.com/
Radware - Excellent Cluster @
   http://www.radware.com
Faster SSL Acceleration, deals with AOL too @
   http://www.ipivot.com/products/products-cd8000.html
Pure SSL acceleration @
   http://www.ipivot.com/products/products-ca1000.html
Commerce Accelerator 1000, claims 50X faster SSL @
   http://www.ipivot.com
RSW Load Balance Analyzer @
   http://www.rswsoftware.com/products/eload.html
Endurance 400 @
   http://www.marathontechnologies.com/productinfo/index.htm
L5: A Self Learning Layer-5 Switch @
   http://www.research.ibm.com/people/d/debanjan/papers/l5.pdf
8 App Web Servers That Actually Deliver @
   http://www.zdnet.com/pcweek/stories/news/0,4153,409380,00.html
-no name- @
   http://www.timesten.com
BIG IP by F5 @
   http://www.bigIP.com
Interview with Mother Nature Lead Engineer @
   http://www.internetwk.com/story/INW19990416S0005
Web switches open e-comm doors at Nettaxi @
   http://www.nwfusion.com/archive/1999/82163_12-06-1999.html
Performance Of TCP Splcing For URL-Aware Redirection (requires membership) @
   http://www.usenix.org/events/usits99/cohen.html
Server Farms, Port Density, Load-Balancing Switch @
   http://www.techweb.com/se/directlink.cgi?INW19991018S0017

Recommended Books:

Related Lists:

Mobile lists by Asplists @
   http://www.asplists.com/asplists/mobile.asp
Mobile lists by WROX @
   http://p2p.wrox.com/mobile/

Rules:

Mailing List Manners (suggested by Bob Filipiak) @
   http://db.tidbits.com/getbits.acgi?tbser=1141
Ken Shaffer's Advice on Asking For Help... @
   http://www.adopenstatic.com/personal/help.asp


ASP Quick Lessons written by Charles M. Carroll
http://www.learnasp.com/learn/buildcomponents.asp Page 242


Section Contents

ASP Components Building
        C++/ATL: Component Building (buildc.asp) - Page 243
        Java ASP Components Building (buildjava.asp) - Page 244
        VB: Simple Component (buildvbsimple.asp) - Page 245
        VB: Registering Component (buildregister.asp) - Page 246
        VB: DLL overwrite problems (FAQvbDLLoverwrite.asp) - Page 247
        VB: ADO, Run It! (buildvbado.asp) - Page 248
        VB: ADO, Build It! (buildvbado2.asp) - Page 249
        VB: Warnings/Guidelines (buildvbguidelines.asp) - Page 250
        VB: General Building Guidelines (buildvb.asp) - Page 251
        VB: Installation Requirements (buildvb2.asp) - Page 252
        VB: Threading Models (buildvbthreads.asp) - Page 253


ASP Quick Lessons written by Charles M. Carroll
http://www.learnasp.com/learn/buildc.asp Page 243


Component Building with C, ATL from ASP Quick Lessons

C, C++, ATL ASP Component Building

Building ASP components with C and/or C plus ATL is possible as well. The following links will explain the process and provide some valuable information on debugging, etc:

Developing ASP Components with ATL by George Reilly:
http://www.microsoft.com/workshop/server/asp/comp.asp
This article is superb and concise.

Active Server Components with VS 5.0:
http://www.15seconds.com/issue/970422.htm

Developer's Sample at:
http://www.microsoft.com/windows/downloads/contents/AdminTools/IISDeveloperSample/default.asp?custarea=bus&site=nts&openmenu=&highlighteditem=  

If you have trouble building or running ASP components written in C/C++, we run a listserv/newgroup called [low-levelcomponents] where that is the only topic allowed you can join to get help.

Undergoing renovation - SUB ListServSignup


ASP Quick Lessons written by Charles M. Carroll
http://www.learnasp.com/learn/buildjava.asp Page 244


Listserrver Join javacomponentsListserver for more info @

http://www.asplists.com/asplists/javacomponents.asp

Related Links:

 
Using Java Servlets on IIS 4.0 @
   http://support.microsoft.com/support/kb/articles/Q240/8/42.ASP
Frank Leahy's Tutorial @
   http://www.hotwired.com/webmonkey/99/29/index2a.html?tw=programming
ASP Component Building w/Java Book @
   Http://www.learnasp.com/books/components.asp
Java COM discussion list @
   http://discuss.microsoft.com/archives/java-com.html
home for MS Java @
   http://www.microsoft.com/java/default.htm
Robert Zembowicz White Papers @
   http://www.robertz.com/Papers/
Newsgroups @
   http://developer.java.sun.com/developer/community/

Recommended Books:

        

Related Lists:

Mobile lists by Asplists @
   http://www.asplists.com/asplists/mobile.asp
Mobile lists by WROX @
   http://p2p.wrox.com/mobile/

Rules:

Mailing List Manners (suggested by Bob Filipiak) @
   http://db.tidbits.com/getbits.acgi?tbser=1141
Ken Shaffer's Advice on Asking For Help... @
   http://www.adopenstatic.com/personal/help.asp


ASP Quick Lessons written by Charles M. Carroll
http://www.learnasp.com/learn/buildvbsimple.asp Page 245


Simple VB Component from ASP Quick Lessons

Simple VB Component by Charles Carroll

This is a very simple component written in Visual Basic. You can create it by

Here is the Visual Basic source code for the component:
14   ' projectname =charlescarroll
15   ' classname =simplecomponent
16   Private ASPresponse As response
17   Public Sub onstartpage(sc As ScriptingContext)
18          Set ASPresponse = sc.response()
19   End Sub
20   Public Sub hello()
21          ASPresponse.Write "Hello"
22   End Sub
23   Public Sub goodbye()
24          ASPresponse.Write "Goodbye"
25   End Sub
26   

Now it is invoked on an ASP page with the following code:
   <html><head>
   <title>simplevb.asp</title>&
   <body bgcolor="#FFFFFF">
   <%
   set parrot=server.createobject("charlescarroll.simplecomponent")
   parrot.hello
   response.write "<br>"
   parrot.goodbye
   %>

10   </body></html>


ASP Quick Lessons written by Charles M. Carroll
http://www.learnasp.com/learn/buildregister.asp Page 246


register component from ASP Quick Lessons

Registering A Component

The minimum recommended steps to register your C++/Visual Basic ASP component are:

If you are updating a component (i.e. registering a component that replaces another component) instead:


ASP Quick Lessons written by Charles M. Carroll
http://www.learnasp.com/learn/FAQvbDLLoverwrite.asp Page 247


ASPVBComponents from www.asplists.com

[aspVBComponents] listserv

FAQ #1:I cannot overwrite a DLL I want to update....
writeup thanks to Michiel van Otegem <michiel@itcomposer.nl>

This happens when the DLL is loaded in memory because it is in use or has been used by an application. The DLL needs to be unloaded before it can be overwritten. The solution depends on the version of Internet Information Server (IIS) and if Microsoft Transaction Server (MTX) is being used or not.

IIS version 3 (no MTX)
In order to unload the DLL, you need to stop the webservice. This can be done through Control Panel->Services or with the Internet Service Manager. After the webservice has stopped, the DLL can be overwritten. When the webservice restarts the new DLL is in place and will be used for subsequent calls.

IIS version 4
If the DLL is not registered as an MTX package and the website(s) using the DLL do not run in a separate memory space (check this with the Internet Service Manager), the same course of action as with IIS 3 is to be taken. Because of the complexity of the webservice in IIS 4, the easiest way to shutdown the webservice is through Control Panel->Services.

If the DLL is not registered as an MTX package and the website(s) using the DLL all run in a separate memory space, stopping those websites will suffice. The DLL can then be overwritten en the sites can be restarted.

If the DLL is registered as an MTX package, the DLL will be unloaded after the amount of minutes set with the Transaction Server Explorer for that package, after which you can overwrite the DLL. If the DLL hasn’t been unloaded yet, you can force it to unload with the Transaction Server Explorer by choosing Shutdown (right click on a package). After the new DLL is in place choose Refresh All Components (right click on the computer with the DLL).

There’s a catch however… the new DLL needs to be compiled with binary compatibility with the old DLL. If you don’t do this, you have to unregister and remove the old DLL, place the new DLL, register it and import it into the right package again.


ASP Quick Lessons written by Charles M. Carroll
http://www.learnasp.com/learn/buildvbado.asp Page 248


buildvbdblistaspcall

VB Component: DBHelper from Web Page

Here is a call to a VB custom component we created:

   <html><head>
   <title>dbhelper.asp</title>&
   <body>
   <%
   set mycomponent=server.createobject("charlescarroll.dbhelperver001")
   mycomponent.connect ="DSN=student;uid=student;pwd=magic"
   mycomponent.query = "select * from publishers"
   mycomponent.maketable
   set mycomponent=nothing
10   %>

11   </body></html>


ASP Quick Lessons written by Charles M. Carroll
http://www.learnasp.com/learn/buildvbado2.asp Page 249


buildvbdblist

VB Component: DBHelper by Charles Carroll

This page has the source code to the component. We have specified:
     project name=charlescarroll
     class name=dbhelperver001
Remember these are the names set in the property window, not neccesarily the filenames.

This example will not compile unless you go to the "Project; References" menu and check/turn on the following libraries:

14   ' projectname =charlescarroll
15   ' classname =dbhelperver001
16   Private ASPresponse As Response
17   Private ASPserver As Server
18   Private htmlstart, htmlend, rowstart, rowend
19   Private fieldstart, fieldend, namestart, nameend
20   Public Sub onstartpage(sc As ScriptingContext)
21          Set ASPresponse = sc.Response()
22          Set ASPserver = sc.Server()
23   End Sub
24   Public Property Let connect(temp As Variant)
25          myconnect = temp
26   End Property
27   Public Property Get connect() As Variant
28          connectme = myconnect
29   End Property
30   Public Property Get fieldnames() As Variant
31          fieldnames = myfieldnames
32   End Property
33   
34   Public Property Let fieldnames(temp As Variant)
35          myfieldnames = temp
36   End Property
37   
38   Public Property Let query(temp As Variant)
39          myquery = temp
40   End Property
41   Public Property Get query() As Variant
42          query = myquery
43   End Property
44   
45   Public Property Let selectdefault(temp As Variant)
46          myselectdefault = temp
47   End Property
48   Public Property Get selectdefault() As Variant
49          selectdefault = myselectdefault
50   End Property
51   Public Property Let selectname(temp As Variant)
52          myselectname = temp
53   End Property
54   Public Property Get selectname() As Variant
55          selectname = myselectname
56   End Property
57   
58   Public Sub query2list()
59         htmlstart = "<select name='" & selectname & "'>"
60         htmlend = "</select>"
61         rowstart = "<option>"
62         rowend = "</option>"
63         fieldstart = ""
64         fieldend = ""
65         Call query2html
66   End Sub
67   
68   Public Sub query2table()
69         htmlstart = "<table border=1>"
70         htmlend = "</table>"
71         rowstart = "<tr>"
72         rowend = "</tr>"
73         fieldstart = "<td valign=top>"
74         fieldend = "</td>"
75         Call query2html
76   End Sub
77   
78   Public Sub query2form()
79         htmlstart = ""
80         htmlend = ""
81         rowstart = ""
82         rowend = "<hr>"
83         fieldstart = ""
84         fieldend = "<br>"
85         fieldnames = True
86         namestart = ""
87         nameend = "&nbsp;=&nbsp;"
88         Call query2html
89   End Sub
90   
91   Public Sub query2entryform()
92         htmlstart = ""
93         htmlend = ""
94         rowstart = ""
95         rowend = ""
96         fieldstart = "%name%&nbsp;=&nbsp;<input type='text name='%name%' value='"
97         fieldend = "' size='%size%'><br>"
98         fieldnames = False
99         namestart = ""
100         nameend = "&nbsp;&nbsp;="
101         Call query2html
102   End Sub
103   
104   Public Sub CustomDisplay(PARMhtmlstart, PARMhtmlend, PARMrowstart, PARMrowend, _
105          PARMfieldstart, PARMfieldend, PARMfieldnames, _
106          PARMnamestart, PARMnameend)
107         htmlstart = PARMhtmlstart
108         htmlend = PARMhtmlend
109         rowstart = PARMrowstart
110         rowend = PARMrowend
111         fieldstart = PARMfieldstart
112         fieldend = PARMfieldend
113         fieldnames = PARMfieldnames
114         namestart = PARMnamestart
115         nameend = PARMnameend
116         Call query2html
117   End Sub
118   
119   
120   Private Sub query2html()
121          On Error GoTo Badnews
122          attempt = "creating connection"
123          Set conntemp = ASPserver.CreateObject("adodb.connection")
124         
125          attempt = "opening connection"
126          conntemp.Open myconnect
127         
128          attempt = "making recordset"
129          Set rstemp = conntemp.Execute(myquery)
130          howmanyfields = rstemp.Fields.Count - 1
131          ReDim fsa(howmanyfields)
132          ReDim fea(howmanyfields)
133          For i = 0 To howmanyfields
134          tempstart = Replace(fieldstart, "%name%", rstemp(i).Name)
135          tempend = Replace(fieldend, "%name%", rstemp(i).Name)
136          tempstart = Replace(tempstart, "%size%", rstemp(i).ActualSize)
137          tempend = Replace(tempend, "%size%", rstemp(i).ActualSize)
138          fsa(i) = myfieldstart
139          fea(i) = myfieldend
140          Next
141          ASPresponse.Write htmlstart & vbCrLf
142          Counter = 0
143          Do While Not rstemp.EOF
144          ASPresponse.Write rowstart & vbCrLf
145          For i = 0 To howmanyfields
146          If fieldnames = True Then
147          ASPresponse.Write namestart & rstemp(i).Name & nameend
148          End If
149          ASPresponse.Write fsa(i) & rstemp(i) & fea(i) & vbCrLf
150          Next
151          ASPresponse.Write rowend & vbCrLf
152          Counter = Counter + 1
153          rstemp.MoveNext
154          Loop
155          rstemp.Close
156          Set rstemp = Nothing
157          conntemp.Close
158          Set conntemp = Nothing
159          ASPresponse.Write htmlend
160          Exit Sub
161   Badnews:
162          temp = "Error: " & attempt & "<br>"
163          temp = temp & Err.Description & "<br>"
164          temp = temp & Err.Number
165          ASPresponse.Write temp
166   End Sub
167   


ASP Quick Lessons written by Charles M. Carroll
http://www.learnasp.com/learn/buildvbguidelines.asp Page 250


VB Component Building Guidelines from ASP Quick Lessons

VB ASP Component Building Guidelines by Charles Carroll

Component written in Visual Basic can be written using programming techniques that will cause them to be unstable in a web server environment. Commands, Functions and Objects that are fine in most standalone or client/server VB programs may not be appropriate in a web server component. We offer the following major guidelines:


ASP Quick Lessons written by Charles M. Carroll
http://www.learnasp.com/learn/buildvb.asp Page 251


VB Component Building Steps from ASP Quick Lessons

Generic VB Component Building Steps

Making a VB ASP component is easy:

Public Function onstartpage(sc As Object)
   'Set ... = sc.response()

   'set ... = sc.server()
   'set ... = sc.Request()
   'set ... = sc.application()
   'set ... = sc.session()
End Function

Public Function onendpage(sc As Object)
End Function


ASP Quick Lessons written by Charles M. Carroll
http://www.learnasp.com/learn/buildvb2.asp Page 252


VB Components: What You Need...

VB Components: what you need...

To make a VB ASP component you need the following on your machine:

People having trouble building components can sign up for our listserv:

Undergoing renovation - SUB ListServSignup


ASP Quick Lessons written by Charles M. Carroll
http://www.learnasp.com/learn/buildvbthreads.asp Page 253


VB Component Building Guidelines from ASP Quick Lessons

VB Component Threading Details
by Charles Carroll
special thanks to Jon Flanders, Stephen Martin and Juan Llibre

Component written in Visual Basic are affected by some complex threading isses we will discuss here. The "bible" for all this is:
Programming Distributed Applications with COM and Microsoft Visual Basic 6.0
by Ted Pattison, Published by Microsoft Press.

Objects created and destroyed at the page level scale very well. Once a session level object is created it is attached to a specific, discrete thread. That thread can never be destroyed until all users assigned to that thread either <%session.abandon%> or their session times out. This is the internal workings of the ASP execution environment. Don Box wrote this fascinating detail up a couple of MSJs ago.   Objects created with a session scope, i.e.

set session("whatever")=server.creatobject("whatever.id")

do not scale well and are affected by the threading issues in the following way:

So imagine - you have a four processor machine running IIS/ASP - forty people come into your site, now each of those requests is now tied to a specific thread, now two requests stop (are not currently making requests) - one more comes in and gets dispatched to one of these two threads that are free, and one of the two that stopped comes back - but another Session is using that thread - there are now free threads that cannot be used - they are just sitting there doing nothing - while a user is waiting for its thread to be freed. This is just one example of what can go wrong (not to mention the additional work ASP must do to make sure this all works correctly). Overall placing object marked Apartment into the SessionObject is a very bad thing. You are way better off instantiating on every page.  You are correct - that you cannot place an Apartment threaded object into the ApplicationObject - which is probably what they should have done with the SessionObject as well.

All calls that involve objects conversing must be proxied. The proxy referring to is what the COM runtime creates in an Apartment when that Apartment receives an interface to a COM object which lives in another Apartment.

For example - if you use a COM object which is marked "Free" in the registry - ASP will create that object and it will live in the Multi-Threaded Apartment (MTA), the page which is executing in a Single-Threaded Apartment (STA) will not get direct access to the object - but will talk to the object through what is called a proxy. The proxy looks just like the interface to the Page (has the same methods etc), but when the page calls a method, the proxy forwards the method call (parameters, name etc) to a COM provided channel. This channel calls what is refered to as a stub - which again looks just like the object - but lives in the same Apartment as the Object (in this case the MTA). Then finally the object gets called and then returns throught the same method. This is 1000xs slower that if the object lived in the same Apartment as the page (because of a thread switch - so switching threads you can see is very expensive). This is just how COM works.

When a COM object is redesigned to be stateless and run under MTX, objects in the same package are not crossing process boundaries. Different packages are!

Run the scenarios:

Scenario 1: So if for example,
+ 100 people hit your site for a couple of pages and leave
+ 100 new people arrive in a couple of minutes
+ 200 people arrive after that and then
+ 50 people
=====
450 sessions/objects in memory with 50 !!! people on your site. And dozens or hundred of threads that can't be reclaimed for a while

Scenario 2:
+ 100 people hit your site for a couple of pages and leave
+ 100 new people arrive in a couple of minutes
+ 200 people arrive after that and then
+   50 people
=====
50 objects in memory because you destroyed all objects at the page level. No threads tied up.

If it isn't Apartment Neutral (i.e. aggregates the Free-Threaded Marshaller) - you will tie the session down to that thread - so you have to ask yourself - is tying my sessions down to a specific thread a major performance hit - and that really depends on how many users are hitting your site and how often. In general I think it is a bad thing and should be avoided - unless there is no other way to accomplish what you want - and there almost always is a way - that isn't too much work and doesn't have any negative side-effects

This is why I have <%@enablesessionstate=false%> and a blank global.asa. If I need an object, I create and destroy it at the page level. for almost every page on my site and with 10,000 sessions a day and 90,000 page views we still serve pages fast and don't get locked up very often.


ASP Quick Lessons written by Charles M. Carroll
http://www.learnasp.com/learn/buildmtx.asp Page 254


Section Contents

MTS - Microsoft Transaction Server
        MTS: Overview (buildmtxoverview.asp) - Page 255
        MTS: Essentials (buildmtx2.asp) - Page 256
        MTS: Transactional ASP pages (buildmtxasp.asp) - Page 257
        MTS: Book (booksmtx.asp) - Page 258
        MTS: Book (booksmtx2.asp) - Page 259
        MTS: Registering Components (buildmtxregister.asp) - Page 260


ASP Quick Lessons written by Charles M. Carroll
http://www.learnasp.com/learn/buildmtxoverview.asp Page 255


buildmtx Components and MTX

MTX and Components

Microsoft Transaction Server (MTX) is a tool included with IIS4 NT Option Pack.  It is an essential long term ingredient to scalable, maintainable, reliable websites. It is necessary for commerce or mission critical websites, though it helps improve performance on all websites as well.

Without involving MTX, every request to create an instance of a component (ala server.createobject) and destroy the instance of that component (ala set object=nothing) is sent directly to the component. IIS tends to cache objects so that when you destroy an instance, IIS probably will not remove it from memory so that the next creation attempt will be instant since it is already in memory. This is a direct violation of the DCOM rule that when there are  zero instances of a component in memory, the component is automatically removed from memory.

Any MTX aware component is now managed by MTX and the following benefits are available:

The typical segments of code that would be unique to components managed by MTX would look like this:

Concept Code
Capture Context shared by all MTX managed components private mycntxt as ObjectContext
set mycntxt= GetObjectContext()
Tell MTX your component has completed it's task sucessfully mycntxt.SetComplete
Tell MTX your component has not completed it's task sucessfully mycntxt.SetAbort
Tell MTX to create an instance of your component (don't use new, createobject, or server.createobject) mycntxt.CreateInstance("... objectname ..")


ASP Quick Lessons written by Charles M. Carroll
http://www.learnasp.com/learn/buildmtx2.asp Page 256


buildmtx2 Transaction Essentials from ASP Quick Lessons

MTX: Transaction Essentials

Transaction Server is based on established client server paradigms of reliable transaction processing. The concepts are consistent regardless of the transaction engine involved.

The traditional wisdom is that a robust transaction must pass the ACID test or the transaction procesing has flaws:

Atomic: The transaction must execute completely or not at all.

Consistent: The transaction must never leave any participant in an inconsistent state.

Isolated: The effect of all individual transactions must have exactly the same effect whether run serially (in an ordered sequence) or parallel.

Durable: All transactions must store their results on a permanent or durable device before reporting success.


ASP Quick Lessons written by Charles M. Carroll
http://www.learnasp.com/learn/buildmtxasp.asp Page 257


build MTX ASP Pages from ASP Quick Lessons

MTX with ASP pages instead of Components

ASP pages that need to take advantages of transactions can without being forced to move the ASP script into a component. First one of the following directives must be placed on the page:

<%@ Transaction = Required %>
<%@ Transaction = Requires_New %>
<%@ Transaction = Supported %>
<%@ Transaction = Not_Supported %>

Of course the ASP page must include code to address both committing and aborting the transaction:

<%
SUB OnTransactionCommit()
   ...
END SUB

SUB OnTransactionAbort()
   ...
END SUB
%>


ASP Quick Lessons written by Charles M. Carroll
http://www.learnasp.com/learn/booksmtx.asp Page 258


Books from ActiveServerPages.com

/font>

Database Workshop with Microsoft Transaction Server 2.0
written by Roger Jennings, Steven D. Grey, Rick A. Lievano
published by Sams Publishing

No writeup yet.

Coming soon.

BUY http://www.amazon.com/exec/obidos/ISBN=0672311305/learnasp


ASP Quick Lessons written by Charles M. Carroll
http://www.learnasp.com/learn/booksmtx2.asp Page 259


Books from ActiveServerPages.com

/font>

Not Ready Yet. Coming Soon!


ASP Quick Lessons written by Charles M. Carroll
http://www.learnasp.com/learn/buildmtxregister.asp Page 260


buildmtxregister

Register Components with MTX

Registering a Component with MTX requires that you specify how the component participates (or doesn't participate) in a transaction. The possibilties are:

 


ASP Quick Lessons written by Charles M. Carroll
http://www.learnasp.com/learn/advice.asp Page 261


Section Contents

Advice For Better Coding!
        Database in Session or App. Say NO! (dbsessionapp.asp) - Page 262
        advice: Cache No More by Phil Paxton (cachenomore.asp) - Page 263
        advice:Option Explicit (explicit.asp) - Page 264
        advice: Encode with Redirects (encode.asp) - Page 265
        advice: Write Your SQL (sqlwrite.asp) - Page 266
        advice: Named constants for ADO are better (namedconstants.asp) - Page 267
        advice: Clean Up Your Room, I mean Objects (cleanup.asp) - Page 268
        advice: Server.MapPath is Good (pathmap.asp) - Page 269
        advice: Just Say No to Session COM objects (nosessionobjects.asp) - Page 270
        advice: Don't Read COM Properties Twice (propertyexpense.asp) - Page 271
        advice: Secure Code and Data (securecode.asp) - Page 272
        advice: Encaspulate Code! (encapsulate.asp) - Page 273
        advice: CASE reads better than IF (caseisbetter.asp) - Page 274
        advice: Error Trapping Strategies (errorstrategies.asp) - Page 275
        advice: Error Trapping Secrets (errorsecrets.asp) - Page 276
        advice: You Should... (shoulds.asp) - Page 277


ASP Quick Lessons written by Charles M. Carroll
http://www.learnasp.com/learn/dbsessionapp.asp Page 262


VB Component Building Guidelines from ASP Quick Lessons

Databases and Sessions.... Just Say No!
by Charles Carroll

Many new ASP programmers and some who even call themselves experienced aspire or accomplish placing recordsets and/or applications in session and/or application variables. They do it to speed things up but actually ensure that the site will perform slower as it gets busier. 

Putting a recordset or application into application or session scope leads to:

What works for few users will not for many

Imagine how fast and convenient a Porsche is when driving to Las Vegas with your significant other. Must be the best way to get there... Right? Now imagine a bunch of seniors want to go. 200 seniors x 100 trips in the porsche. Ouch! The tour bus or an airplane scales. The porsche does not. Developers should always design for scaling not minimal users.

Application Level Connections

Mechanically, creating one Application level variables with a database connection is simple.

SUB application_onstart
   set application("theCONN")=server.createobject("adodb.connection")
END SUB

Then any code that wants to use that connection might look like this:
<%
mySQL="select * from publishers where state='NY'
set rstemp=application("theconn").execute(mySQL)
%>

However this code will not scale well. The code is mechanically easy, but the scripts using this code will suffer from Thread-Affinity and Serialization.

An application variable lives until a web server shuts down. It also lives on a specific thread; we would say the object has thread affinity. Any script utilizing that object must live on same thread, as that object or make an expensive marshalled call to talk to that object.

Thread Affinity

Thread affinity is bad. If a request comes in it would be fast if any thread could perform the task. Thread affinity guarantees only 1 thread can service the request and if that thread is busy the task waits in line for that thread, despite other threads who may be able to service the request.

http://www.learnasp.com/advice/threads.asp
explains threading fundamentals.

Serialization is an enemy of Scalability

If multiple tasks all have affinity to the same thread they become serialized, that is to say they all run in sequence. As a real-world analogy for serialization imagine you wanted to buy a meal at a fast-food cashier and the person in front of you ordered 150 sandwiches for their swim-team. You don't get your 1 sandwich until they finish their order. 6 request for 150 records from a database means the fourth request for 1 record comes after those 900 are retrieved. Without thread affinity the requests could be divided among available threads.

Conclusion: All recordsets and database access would have some level of thread affinity if one connection only is made in global.asa. The side-effect would be recordsets that were forced to specific threads and serialized requests effectively slowing a site's overall performance and for specific scripts.

Recordsets stored at Sessions Level...

Mechanically, this is easy to accomplish:

SUB session_onstart
   set session("rstemp")=server.createobject("adodb.recordset")
END SUB

Then any code that wants to use that connection might look like this:
<%
    ...
    mySQL="select * from publishers where state='NY'
    set session("rstemp")=conntemp.execute(mySQL)
%>

However this code will not scale well. The code is mechanically easy, but the scripts using this code will suffer from Thread-Affinity, Serialization, and there will always be more recordsets than users accessing a site. In fact a more aggregious version of Thread Affinity occurs which I will nickname Thread-Locking.

Thread Affinity Part #2

In IIS3 and IIS4 once a user is assigned a session object (recordset or VB5/VB6 component) with thread affinity every script run in that session is forced onto the thread the first script is assigned. It effectively handcuffs every user's script to the thread their first script was assigned. This occurs because recordsets and VB5 and VB6 need to store their data on a specific thread and until destroyed (unlike C++ components which specifically aggregate the Free Thread marshaller) the objects may never be moved to a different thread which hurts performance.

More Recordsets than Users??? Please explain...

If for example a mere 20 users who access 1 page each and no others at tour site, their session objects (in this case recordsets) persist for the default session timeout (20 minutes unless the registry is modified or a page explicitly sets it using the session.timeout command. If then 50 users access several scripts and 20 of them go lunch or go home for the day, the recordsets will waste memory until their session times out. In this example there would be 90 recordsets and 30 active users within minutes. How can any scenario where significantly more resources are allocated than are being used be efficient?

http://www.learnasp.com/learn/globalproblems.asp
explains a typical scenario.

Create and Destroy on Every Page

Even though every page creates and destroys connections, the newly created ones can execute on any thread. Also because of round-robin execution resources are used sparingly and connections are never open too long.

Make Sure Connection Pooling is in Effect

Connection Pooling can speed up sites. ADO invisibly can co-ordinate that any destroyed connections are not instantly destroyed, instead they are left ready to be grabbed by the next page who requests creating a connection. That page's code has a create request that gets intercepted at a low-level and given an already created connection ready to do database access. The programmers code then is not being executed literally; their create requests often get serviced by already created connections.

http://www.learnasp.com/learn/dbpooling.asp
has more information and details.

What is the fastest way then (if I want fast, scalable database displays)?

"The Worlds Fastest Listbox"
http://www.learnasp.com/learn/speedappdata.asp
shows a lightning fast way to display databases.

GetString to speed up Data Transfer
http://www.learnasp.com/learn/dbtablegetstring.asp

GetRows to speed up Data Transfer
http://www.learnasp.com/learn/dbtablegetrows.asp

All we discuss is fast code over at:
http://www.asplists.com/asplists/aspfastcode.asp

What If I am willing to pay the price?

Make sure you test the load using tools like the Web Stress Tool @
http://homer.rte.microsoft.com

Much more information on scalability can be found on
http://www.asplists.com/asplists/aspscalability.asp
which has links  and a signup for an excellent 2 way listserver.


ASP Quick Lessons written by Charles M. Carroll
http://www.learnasp.com/learn/cachenomore.asp Page 263


CacheNoMore from ASP Quick Lessons

Cache No More by Phil Paxton (juggler@iquest.com)

Essentials

Here are the the commands to place at the top of your ASP scripts to ensure that the page is not cached:

<%
Response.Expires = 60
Response.Expiresabsolute = Now() - 1
Response.AddHeader "pragma","no-cache"
Response.AddHeader "cache-control","private"
Response.CacheControl = "no-cache"
%>

Response.Expires = 60
is said to expire at 60 seconds, not 0. Also, Khin Zaw (from http://www.asplists.com/asplists/aspadvanced.asp) has posted research from time spent with some IIS internals experts revealing this can be a very touchy parameter to rely upon and usually requires a rather "large" negative number or pedantically, that would be a very small number).

Response.Expiresabsolute=Now()-2
(my own creation) says "expire this page 48 hours ago", allowing for time differences, rather than specify a static date. If your page is being viewed by a browser in a very different time-zone it 

Response.AddHeader "pragma","no-cache"
Response.AddHeader "cache-control","private"
Response.CacheControl = "no-cache"
their use originates rom an MS KB article. The code is correct but there are some incorrect statements in the article itself.

Some related KB articles include:
http://support.microsoft.com/support/kb/articles/q189/4/09.asp?FR=0
http://support.microsoft.com/support/kb/articles/q172/8/96.asp?FR=0
http://support.microsoft.com/support/kb/articles/q165/1/50.asp?FR=0

If the above techniques do not work in every instance, a "cache-buster" can be employed.

<a href=whatever.asp?Nocache=<%=rnd()%>>
or
<a href=whatever.asp?Nocache=<%=server.URLencode(now())%>>

Another thing to remember: Netscape will continue to cache, even if you turn all caching off. This behavior persisted through 4.5 PR1, PR2, and now in the released version of 4.5.

If you fear you might have to deal with caching later, you might want to build contingencies into your app as you go. Retrofitting #5 throughout even a medium-sized app would take a rather sizeable effort. You could retrofit #1-#4 (inclusive) rather quickly with a single pass through the application, but #5 takes a lot of extra effort. And to that end, I don't ever Response.Redirect anywhere in my code except sample code I post to the lists (then again, the only time I use Response.Write is to the list because I rely on my Utilities-Form.inc library for Display() and HTML()). Everything is Redirect(NewURL) where the Redirect function looks like this:

   Function Redirect( NewURL )
      '
      If Not IsEmpty( NewURL & "" ) Then
         Dim QuestionMark
         '
         QuestionMark = Instr( NewURL, "?" )
         '
         If QuestionMark = 0 Then
            Response.Redirect NewURL & "?" & NoCacheURL()
            Response.End
         Else
            Response.Redirect NEWURL & "&" & NoCacheURL()
            Response.End
         End If
      End If
      '
   End Function

and NoCacheURL looks like this:

   Function NoCacheURL()
      '
      On Error Resume Next
      '
      Randomize
      ' Randomize not needed if you use Now()
      '
      NoCacheURL = "NoCache=" & Server.URLEncode(rnd)
      '
      ' or NoCacheURL = "NoCache=" & Server.URLEncode(Now())
      ' per Bill
      '
   End Function

I've learned that I approach things a little differently (sometimes better, sometimes worse, but overall, just differently) and have gotten used to a bunch of tiny little routines scattered throughout my app with a bunch of #include statements. Some of this might seem like overkill, but you have to understand just how pervasive and frustrating caching can be in a scripted app environment. Caching is great for pure HTML because it reduces server overhead. But if you do much scripting against databases, or time-based functions, it's not unusual to see rather bizarre things happen. Shopping cart applications will suddenly "lose" items already purchased; they'll "regain" items previously deleted. Starting a new order with an assigned "OrderID" (to use as a temporary confirmation number for the sake of the user) will suddenly show items from a previous order. It can be maddening the first time you have to deal with it. And if you don't deal with it head-on in your code, your users may be dealing with it for you -- you can turn caching off for your application in IIS [itself], but what if you are behind a firewall or proxy server which does caching for you? Or, if the user has caching turned on in their browser or they could be behind one or more layers of firewalls or proxy servers, all of which have been sold under the premise of delivering better performance through caching? Unless and until you can control every layer of access to your app, telling your server not to cache isn't a solution because requests may not be making it back to said server.

End-user magazines continue to extol the benefits of caching, demonstrating they are still thinking of an HTML-only world. Scripting and caching are rarely synergistic and are almost always like oil & water: both have a purpose, but rarely together.

You're almost always better off to just turn all caching off and take the performance hit than to try & retrofit all of this into an app which "mysteriously" begins misbehaving.

Should: Ought to, but not necessarily will.


ASP Quick Lessons written by Charles M. Carroll
http://www.learnasp.com/learn/explicit.asp Page 264


ASP Commandments by Phil Paxton from ASP Quick Lessons

ASP Commandment #1: Use Option Explicit

use Option Explicit when writing VBScript.
<% option explicit%>
goes at the top of the script!


ASP Quick Lessons written by Charles M. Carroll
http://www.learnasp.com/learn/encode.asp Page 265


ASP Commandments by Phil Paxton from ASP Quick Lessons

ASP Commandment #2: Encode!

When dynamically building a URL with your code, the URL may work fine in IE but Netscape presents this ERROR message:

HTTP Error 400