Blog homepage

Content from old blog

www.marcustucker.com

Bookmark this page



previous month  OCTOBER 2014  next month
s m t w t f s
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26
27 28 29 30 31


BLOG ARCHIVE
 
RSS ATOM  Full archive
 
current month



CATEGORIES
 
alert [ 1 ]  RSS ATOM
blog [ 8 ]  RSS ATOM
development [ 9 ]  RSS ATOM
    ASP / scripting  [ 13RSS ATOM
        snippets  [ 1RSS ATOM
    database [ 0 ] RSS ATOM
    web standards  [ 1RSS ATOM
    XML [ 0 ] RSS ATOM
general [ 24 ]  RSS ATOM
    humour [ 0 ] RSS ATOM
personal [ 6 ]  RSS ATOM
photography [ 1 ]  RSS ATOM
politics [ 1 ]  RSS ATOM
rant [ 8 ]  RSS ATOM
reading [ 18 ]  RSS ATOM


SEARCH
 


BLOGROLL
 
 


ARTICLES
 
Access Stored Queries

VBScript String Concatenation
 


23 Feb 2005
IE's "friendly" error messages
While hacking URLs at www.sonyericsson.com to make it possible to be automatically informed when a new firmware is released for my P900 by using the excellent free service WatchThatPage to monitor the URL that I had hacked together (no thanks to the abominally unfriendly URL scheme used by their CMS), I came across the following message hidden in a comment in a redirector page:
Unfortunately, Microsoft has added a clever new "feature" to Internet Explorer. If the text in an error's message is "too small", specifically less than 512 bytes, Internet Explorer returns its own error message. Yes, you can turn that off, but *surprise* it's pretty tricky to find buried as a switch called "smart error messages" That means, of course, that many of Resin's error messages are censored by default. And, of course, you'll be shocked to learn that IIS always returns error messages that are long enough to make Internet Explorer happy. The workaround is pretty simple: pad the error message with a big comment to push it over the five hundred and twelve byte minimum. Of course, that's exactly what you're reading right now.
NOTE: "Resin" is presumably the name of their CMS "Resin" is a JSP/servlet load balancing system... (thanks Rick, should have Google'd!)

So, it would appear that 512 is the magic number of bytes required to force IE to display your error message instead of your own. Personally I think it's is damn stupid of IE to attempt to intercept an error and display its own error message instead of the server's, and such a feature certainly shouldn't be on by default. It's impossible to fathom the total loss of productivity that this single implementation "feature" has caused to puzzled developers across the world, but here's proof (if proof be needed) that it is a recurrent problem.

It's a matter of habit that I always switch off "Show friendly HTTP error messages" (the correct name for the switch mentioned in the above text), and "Show friendly URLs" in the preferences section of Internet Explorer, since I find them irritating and they often interfere with debugging web apps during development. But clearly one should take precautions (as described in the quoted text above) to ensure that IE doesn't interfere with error messages displayed to end users.

Another thumbs-down to MS for that not-so-bright idea. [:(]

Incidentally, I also switch on "Display a notification about every script error", which is one of the main reasons why there's so much bad JavaScript floating around - developers who don't switch this on aren't told about errors in their code. Naturally, this also causes huge headaches during development for those who aren't aware of this.
 
development , rant
posted by  Marcus at  12:28 | permalink | comments [3] | trackbacks [71]



15 Feb 2005
Reading Roundup 15/02/2005
I seem to be failing miserably in my aim of blogging original content more frequently... but at least here are a selection of interesting links to keep your brain ticking over:

Photographer Seeks Resolution
You think your 4 megapixel camera takes good photos? Check out what this guy's 4 *gigapixel* ultra-high resolution digital camera produces!

The cranky user: Performance anxiety (Where does all the processing speed go?)
Despite incredible advancements in hardware technology - most of us now have a 2GHz+ computer on our desks (or perhaps even on our lap) with number-crunching capabilities which were only available from supercomputers 10 years ago - Windows and Office are still dog slow! Why hasn't our day-to-day PC experience improved?

Using SQL Server's XML Support
An thorough guide to SQL Server's XML features, nothing new, just well-written and all in one place!

The Dollars and Sense of Building to Standards
A look at the real-world (i.e. economic and practical) advantages of building to web standards. As an aside, I did notice the use of user-agent stats of questionably reliability - see my post in the comments.

CodeCon 2005 has been and gone, bringing some very interesting projects to light:
- Incoherence, a realtime stereo imaging visualisation tool (available as a plugin for Winamp, iTunes, Media Player, etc)
- Mappr and PhotoSpace, two projects which attempt to correlate photos to geographic locations, and leverage existing mapping (and other) services to this end.

And finally...
Marijuana makes blood rush to the head
Interesting new research... and a possible world record? 50 joints a day?! Crazy (man)![;)]
 
development , general , reading
posted by  Marcus at  16:35 | permalink | comments [0] | trackbacks [107]



2 Feb 2005
Code Snippets (I)
A few simple but handy snippets of code for you...

Kill
Firstly, since I use it in almost every function which uses objects, I thought I'd better repost Kill(), which tidies up objects and arrays, with special handling for ADO and Dictionary objects.

NOTE: All code posted on this blog from now on will assume that this function is part of your includes

Function Kill(byref Obj)
Select Case True
Case IsObject(Obj)
Select Case LCase(TypeName(Obj))
Case "recordset", "command", "stream", "connection"
'ADO objects
If Obj.State <> 0 then
Obj.Close
End If

case "dictionary"
'remove all the pairs
Obj.RemoveAll

Case else
'something else so don't
'do anything special

End Select

Set Obj = Nothing

Case IsArray(Obj)
'clear the array
Erase Obj

Case Else
'do nothing at all

End Select

'Now revert it to an unitialized state
Obj = Empty
End Function



IsBlank
This is another of my most frequently used snippets, which acts as a catch-all checker for variables, meaning that you no longer have to worry about the variable type when you want to use a If MyVar="" Then statement. It will automatically test the variable using all the appropriate checks - see the code for exactly what it does and how. Simple, but remarkably handy! Give it a go next time you write a complicated script or entire app!

NOTE: All code posted on this blog from now on will assume that this function is part of your includes

Function IsBlank(ByRef Var)
IsBlank = False

Select Case True
Case IsObject(Var)
If var Is Nothing Then
IsBlank = True
End If

Case IsEmpty(Var), IsNull(Var)
IsBlank = True

Case IsArray(Var)
If UBound(Var) = 0 Then
IsBlank = True
End If

Case IsNumeric(Var)
If (Var = 0) Then
IsBlank = True
End If

Case Else
If Trim(Var) = "" Then
IsBlank = True
End If
End Select
End Function



ToggleVariable
Invaluable for all sorts of situations where variable needs to flip-flop between two values - one example being alternating colours for table rows.

'Toggles a variable between two values, and will initalise
'the variable to the "on" state if it doesn't have either value
Function ToggleVariable(Byref Variable, ByVal StateOn, ByVal StateOff)
If (Variable = StateOn) Then
Variable = StateOff
Else
Variable = StateOn
End If

ToggleVariable = Variable
End Function
For example:
For N = 1 To 10
Response.Write "<" & "tr bgcolor=""" & ToggleVariable(C, "#ffaaaa", "#aaffaa") & """>"
Response.Write "<" & "td>" & N & "<" & "/td>"
Response.Write "<" & "/tr>"
Next
(tags are broken up to circumvent posting problems in this blog)

Note that although it's a function which returns the new value, it does directly modify the variable (because it's passed ByRef) and therefore can be called as a sub too:
For N = 1 To 10
Call ToggleVariable(OddRowIndicator, True, False)
If (OddRowIndicator = True) Then
'do something here
End If
Next



GetCurrentURL
Sometimes it's handy to know what the current URL is within your script, but strangely enough ASP doesn't expose this information directly, instead it must be assembled from various server variables. Here's a little function which does it for you:
Function GetCurrentURL()
'Select the protocol
If request.servervariables("HTTPS") = "on" Then
GetCurrentURL = "https://"
Else
GetCurrentURL = "http://"
End If

GetCurrentURL = GetCurrentURL & Request.ServerVariables("SERVER_NAME")

If (Request.ServerVariables("SERVER_PORT") <> 80) Then
GetCurrentURL = GetCurrentURL & ":" & Request.ServerVariables("SERVER_PORT")
End If

GetCurrentURL = GetCurrentURL & Request.ServerVariables("URL")

If (Request.QueryString <> "") Then
GetCurrentURL = GetCurrentURL & "?" & Request.QueryString
End If
End Function



IIf
And last but not least here's, a handy VBScript version of a VB statement which is also commonly used as a macro in C/C++. This snippet lets you condense a simple "If...Then...Else...End If" block into a single line.

'Immediate If
Function IIf(Condition, ValueIfTrue, ValueIfFalse)
If Condition Then
IIf = ValueIfTrue
Else
IIf = ValueIfFalse
End if
End Function


For example, you could turn this:
If IsNull(Price) Then
Response.Write "(n/a)"
Else
Response.Write Price
End If

Into this:
Response.Write IIF(IsNull(Price), "(n/a)", Price)
However, let me just make you aware of a slight caveat that presents itself when using this shorthand form...

Let's say that we wanted to format the price as a number with 2 decimal places - one might naturally use FormatNumber(Price, 2) to do this and insert it into the code like so:
Response.Write IIF(IsNull(Price), "(n/a)", FormatNumber(Price, 2))
Unfortunately, this won't work. When you call a function or sub, all parameters are passed either ByRef or ByVal, but regardless it is either a variable (which may contain an object, array, or value) or a value which is passed. Therefore, all three parameters to the IIF function are evaluated before the function is called, and the resulting values are passed.

The consequence of this is that if the variable Price is ever Null, the script will throw an error, because FormatNumber() chokes on Nulls. Therefore, be careful about how you use this and remember that is not quite a 1:1 replacement for the full statement block.


That's all for now, if you have any questions please post a comment and I'll be sure to answer it.
 
ASP / scripting , development , snippets
posted by  Marcus at  13:55 | permalink | comments [3] | trackbacks [34]



2 Feb 2005
Reading Roundup 02/02/2005
Another mixed bag of interesting reads for you...


  • x86-64: The Golden Handcuffs

  • A well-rounded coverage of the history of the latest and greatest processor architecture to hit the consumer PC market, pitched just right so that readers of all levels of experience can get something out of it.


  • Flash of Unstyled Content (FOUC)

  • Notes on an annoying CSS rendering phenomenon, and how to work around it.


  • It Pays to Trust Your Gut

  • Why we might be deceiving ourselves if we think that rational logic is always the best approach.


  • Benford's Law

  • That's a Big Transistor

  • Microsoft guru Eric Lippert never fails to come up with fascinating blog posts, quite how he gets any work done is beyond me!


  • ASP.Net: 10 Tips for Writing High-Performance Web Applications

  • Although this is an ASP.Net article, I thought it would be worth pointing out that tips 1 thru 3 are just as applicable to ASP classic, so if improved performance is your goal, take a look. This article also neatly demonstrates a few killer features of the ASP.Net platform - its sophisticated data and page caching facilities being must-haves in themselves.


  • Controlling Stored Procedure Caching with ... Dynamic SQL?!?

  • An excellent article by Adam on how SQL's execution plan caching works, and how you can ensure that you get the best performance out of dynamic SQL


  • Sequential Numbering/Counting of Records with SQL Server

  • Numbering of rows in a query result set is a pain in SQL 2000, but it's possible and the article above shows you how. Thank goodness the new ROW_NUMBER() function in SQL Server 2005 will let us do this in the future with a minimum of fuss.


  • An Overview of SQL Server 2005 for the Database Developer

  • What's New in FOR XML in Microsoft SQL Server 2005

  • XML Support in Microsoft SQL Server 2005

  • ADO.NET 2.0 Feature Matrix

  • Various noteworthy SQL2005 and .Net 2.0 articles that I've been perusing recently


  • IE content-type logic

  • IE's content-type sniffing has been the subject of much debate over the years and a headache for many a developer, so it's nice to find out why things are the way they are. And why it's too late for Microsoft to change it.
     
    development , general , reading
    posted by  Marcus at  13:40 | permalink | comments [3] | trackbacks [43]



    19 Jan 2005
    New demo of new trick of old dog
    A couple of posts back I shared my GetFolderAsRecordset() function, but I forgot to post a related snippet of code - here's a function which returns the last modified date/time of the most recent file in a given folder, something which is pretty longwinded to do with the FSO, but with GetFolderAsRecordset() in place it only takes a couple of lines (you could compress it into 4 if you used the code inline):
    Function GetMostRecentFileDate(FolderPath)
    Dim FolderRS
    Set FolderRS = GetFolderAsRecordset(FolderPath)
    If Not FolderRS.EOF Then
    FolderRS.Sort = "Modified DESC"
    GetMostRecentFileDate = FolderRS("Modified")
    Else
    GetMostRecentFileDate = Null
    End If
    Kill FolderRS
    End Function
    This function comes in very handy for some data import systems that I wrote at work (each daily import file is a complete data set, not a delta, so I only need to select the most recent one to import - there may be many queued there under various circumstances). I'm sure that you can think of plenty of ways that you could use and adapt this for your own applications...
     
    ASP / scripting , development
    posted by  Marcus at  13:19 | permalink | comments [4] | trackbacks [92]



    30 Dec 2004
    Festive Merriment
    Just a quick post to wish you all a (belated) merry xmas and a happy new year! I hope you have a great time on friday night, and you'll be pleased to know that one of my new year's resolutions will be to post here more often.

    In the past calendar year the amount of hands-on coding that I've been doing has dropped dramatically (to virtually none at all), and I also left the forums at SitePoint.com and Codingforums.com because I felt that I'd devoted enough of my free time to helping others over the years and I thought that it was about time I spend more of my time doing other things. Well, I've certainly been busy in the evenings, and I've been having a great time, perhaps too much fun - I've been neglecting this blog and haven't done any ASP coding for myself (i.e. on my site) for a loooong time!

    However, in the coming months there's a few ASP projects that I'll be getting stuck into (both at work and at home), and so it's only natural that I'll start to post more frequently here. I'll share code where I can, and if there are any particular topics that you'd like me to cover, such as particularly complex techniques (multi-record form data processing, for example) then drop me a line and I'll see what I can do.

    See you in 2005!
     
    ASP / scripting , development , general , personal
    posted by  Marcus at  11:50 | permalink | comments [1] | trackbacks [22]



    9 Dec 2004
    Old dog... new tricks?
    Most ASP developers seem to have jumped on the ASP.Net bandwagon already, but I thought I'd spread a little love among the remaining ASP classic developers by sharing some of the handy functions & subs that I've developed over the years. I've been meaning to do this for a while, but I simply haven't got round to it until now... my apologies!

    I posted quite a few snippets of code on my old blog, so have a look at see if there's anything of interest to you there.

    One thing I mentioned there (and provided code for) was the concept of disconnected recordsets, but I didn't really go into what they can be used for, so here's one great use for them - directory listings.

    It is often desirable to manipulate a number of files (or subfolders) within a folder, but unfortunately doing so with the FSO is rather longwinded, particularly if you're only processing a subset of the files - all files in "c:\Gallery\" ending in ".jpg" which are less than 1MB in size. Wouldn't it be great if you could retrieve these as a list which could be iterated through?

    Well now you can - behold GetFolderAsRecordset(), a function I whipped up a while ago (and recently enhanced) which returns the contents of the specified folder as a disconnect recordset, with each file and folder represented as a record. The name, extension, size, created date, and last modified date of each item are represented as fields, there's a fields to indicate whether the item is a file or folder, and finally there's a field which indicates whether the item can be accessed (it may not if the process under which the script runs has insufficient rights to access the file/folder).

    By representing the folder in this way, a number of options are opened up. Firstly, the selection of certain files via particular criteria becomes simple, thanks to the .Filter property. For example, to turn the hypothetical mentioned earlier into reality, all you need to do is this:

    Set FolderContents = GetFolderAsRecordset("c:\Gallery\")
    FolderContents.Filter = "Type='File' AND Extension='jpg' AND Size<" & 1024^2

    While Not FolderContents.EOF
    'Do something here

    FolderContents.MoveNext
    Wend
    NOTE: The Type='File' criterion is needed because folders can have extensions too... I can't remember EVER giving a folder an extension, but it's been possible since MSDOS v1, so assume nothing!

    Secondly, by default the function groups the folder contents by type (folders and files) and then sorts alphabetically. However you can easily change this by setting the .Sort property (e.g. FolderContents.Sort='Size DESC')

    Then, there's persistence and XML - by calling the recordset's native sub .Save() you can turn the recordset into XML, save it to disk, and then retrieve it another time. Alternatively, by specifying an ADO Stream object as the output rather than a file and then transforming the XML with some XSLT, you can generate a cleaner output (XML or otherwise) which could be used for all sorts of things (the response to software auto-update request, perhaps)

    Most people use recordsets for the retrieval and manipulation of tabular data, and this is no exception - it's childsplay to dump the recordset contents to an HTML table, and enabling sortable columns would take only a couple of lines of code! It could even form the part of one of those "file manager" web apps.. as if there aren't enough of those around already!

    I've recently used it as the core for an image batch processing script at work, and it's also very easily to modify the above snippet to generate a quick'n'dirty list of files which meet certain criteria (perhaps for pasting into an email) something which should be part of Windows Explorer, but sadly isn't (although I am aware that numerous directory listing shell extension utils have sprung up to fill this niche). Anyway, I hope you find it useful - it has certainly saved me hours of coding on numerous occasions!

    And now the moment you've all been waiting for - the code! As well as the function discussed above, there are also a few handy wrapper functions for creating folders, moving files, copying files, deleting files, renaming files, etc. Nothing special, but it's nice to be able to call them as a one-liner!

    It would be nice to get some feedback, so if you find it useful or have problems/suggestions, please post a comment! If this goes down well I may be inclined to release more code in the near future... [;)]


    NOTE: I have intentionally instantiated all objects in the code with a call to CreateObject() because the code is equally useful in Windows shell scripts, and by using the generic CreateObject() form, the code can be used for either without requiring changes. And in case you're wondering why you need to use the host-specific form at all (i.e. Server.CreateObject() or WScript.CreateObject()), you're not the only one! However, all-knowing scripting guru Eric Lippert was kind enough to provide some answers when I asked him a while ago, so read up (comments too)!
     
    ASP / scripting , development
    posted by  Marcus at  17:46 | permalink | comments [7] | trackbacks [42]



    23 Sep 2004
    New Article
    I've been away in Ibiza for a week (yes, I'll be posting photos soon) and I've just got back to find that the kind folks at ASP 101 have published my new article about VBScript String Concatenation (And Why It Should Be Avoided Like The Plague).

    Let me know what you think!

    [:)]
     
    ASP / scripting , development
    posted by  Marcus at  15:25 | permalink | comments [1] | trackbacks [14]



    17 Aug 2004
    Change Control in a Content Management System
    In the past I've written a couple of web apps which were essentially content management systems (I'll refer to them as CMSes from now on), and in each case the entered content went live straight away, without passing through an approval stage - these were small-scale systems with the content being maintained by an individual (me, in the case of my web site).

    In many other systems, particularly those with many authors (such as news/dating/auction/job sites, corporate intranets, etc), this approval stage is in place so that all content is vetted before being published, and can be edited/rejected/etc as appropriate. Of course as well it being sensible for any publically accessible content to go through an editorial process, this also helps to protect sites from legal repercussions by putting an obstacle in the path of anybody wishing to publish offensive or defamatory content, and this can only become more and more important as the legal framework for web-related copyright, slander, and other issues becomes more clearly defined (and rigorously enforced).

    While the bulk of the content passing through most such systems would probably be new content, a sizeable proportion is likely to be amended content, perhaps with broken hyperlinks fixed, typos correct, footnotes and updates added, etc. Amending content after initial publication is quite common in the blogging world, and is a regular occurence on corporate intranets.

    Quite why I was thinking about this particular type of application I'm not altogether sure, but the thought struck me that it would be very handy for the content approvers if rather than seeing the entire body of content that needs to be approved, they instead saw only the parts that had changed, just like many developers do with code thanks to file comparison/difference tools (Araxis Merge being the one I use, for example).

    So my ponderance is: "is there an equivalent for content management systems?"

    Such a feature/tool, targeted specifically towards XHTML markup and perhaps implemented as a reusable component on a range of server-side platforms (ASP/ASP.Net/PHP/JSP/CF) would be pretty damn useful for people editing/managing content across the web and very lucrative for the developer. The idea could even be extended to providing a full web document versioning system, similar to how VSS and CVS operate in the desktop world. Or do some CMSes already integrate with VSS/CVS?

    Does such a component or suite of classes exist? If not, why not? If so, what's it called? Post a comment and let me know your thoughts...
     
    development
    posted by  Marcus at  19:48 | permalink | comments [1] | trackbacks [32]