[Looking for Charlie's main web site?]

Working around an issue with CF and IIS 7 (related to .NET)

Note: This blog post is from 2008. Some content may be outdated--though not necessarily. Same with links and subsequent comments from myself or others. Corrections are welcome, in the comments. And I may revise the content as necessary.
Here's a tip about an error others may hit when configuring CF with IIS on Vista. I'll clarify that I'm on CF8, Vista SP1, and may possibly have installed some .NET 2.0-based apps or products, all of which could have contributed to this issue. YMMV.

UPDATE: I have an update on this: the reason I had the issue was not related to SP1. And it wasn't that I'd "installed a .NET 2.0 app" since I installed Vista. Rather, it turns out that it was because I'd restored from backup some files into my IIS docroot that included a web.config that DID have .NET 2.0 config entries. Even so, this could happen to others, or to others who DO install .NET 2.0 apps, so I leave it for others to consider.

I'd been running Vista for a while on my development machine, and though I'd installed CF8 on it without problem, I chose at first to use the built-in web server to start (both with the standalone and multiserver deployments of the CF8 Developer edition.)

Today I decided to hook it to IIS. Since I'd not made the choice to use IIS on install of CF 8, I of course used the web server configuration tool (start>programs>adobe>coldfusion 8>web server configuration tool). Though I'm on Vista Ultimate and could define more than one web site (a nice bonus of the Ultimate and Business editions all Vista editions, without needing to buy a Server edition of Windows), I had not defined any beyond the default web site. (Update: I spoke today with Bill Staples, one of the folks in charge of IIS 7, about this whole issue, which is when I realized it came about from me doing the restore. Anyway, he said that the support of multiple sites is something in all editions of Vista. Nice.)

(One interesting thing that happened was I got a popup telling me that CF would need a few minutes to configure itself with IIS 7. I took a screenshot of the window that popped up but lost it from the clipboard. Perhaps someone else will see it and can comment here what it says, to help those doing searches later. But as it said, after a couple of minutes it did take.)

Error on first CFM page request

But when I requested my first CFM page, I got a big ugly IIS 7 error page (an HTML page), the crux of which reported:

ASP.NET applications require migration when specifying configuration in <httpModules> or <httpHandlers>.

Yikes. It went on to provide various details on the problem as well as some workarounds. The gist was that the system.web httphandlers entry in the config files had something that was no longer compatible with the new, default "integrated mode" of IIS (defined as the "managed pipeline mode"). What had CF done? How would I best resolve it?

Quick and dirty workaround: Change mode to "classic"

One of the workarounds described changing the "mode" for the "managed pipeline mode" from "integrated" to "classic". This is defined in the site's application pool, which you can modify in the IIS manager (selecting "application pools", then the app pool (by default, the "default web site" uses "DefaultAppPool"). See the screenshot here.

Sure enough, changing it to "classic" made the problem go away, but that may not be the best solution.

Better Solution: Migrating the .NET settings in a single, simple step

I did some digging and found one blog entry with a good bit of info, and he seems to assert that this is just a breaking change in IIS 7 for ASP.NET 2.0 apps.

He also made the case for not using the workaround above (changing the mode to "classic"), as it could cause loss of many of the nifty features that IIS 7 adds. Instead, he proposed that one should instead seriously consider the option to upgrade the .NET 2.0 app config entries to work properly in integrated mode. Turns out this is just a simple command line command:

%SystemRoot%\system32\inetsrv\appcmd migrate config "Default Web Site/"

I had set the mode back to "integrated" to confirm that the error came back (it did), so I then dropped to the command line (using start>run and entering "cmd") and pasted that line verbatim (right-click and paste, not ctrl-v) onto the command line (again, since I'm using the "default web site"). It came back with 2 lines in response:

Successfully migrated section "system.web/httpHandlers".
Successfully migrated section "system.web/httpHandlers".

I then re-requested my CFM page, and it worked, so that seems the solution.

Since I knew I didn't have any custom-written .NET 2.0 apps on my machine, I knew there was no great risk to me doing this. (I had not myself built any .NET 2.0 apps of my own, but I may well have downloaded and installed some app that's built on it. So it's possible that if you have not, that you will not ever get this issue. I'm offering it for those who may, so they can find it on a web search.) (See my update at the top of this entry.)

The blog entry also implies that this may be an issue for SP1, so perhaps others who are not yet on SP1 won't have seen this problem yet. If anyone reads this who is not on SP1 and it solves things for you, do let us know in the comments. (Bill Staples also confirmed that this was not an issue new to SP1.)

Hope this has been helpful for someone.

PS Please, I'm not interested in any snide comments about the wisdom/folly of using Vista. Like others, I have my reasons for doing so, and I've been very satisfied with it so far. I share the above for others in the Vista boat, whether by their choice or others'.

No CF Meetup this week: Thurs Mar 27

Note: This blog post is from 2008. Some content may be outdated--though not necessarily. Same with links and subsequent comments from myself or others. Corrections are welcome, in the comments. And I may revise the content as necessary.
There will be no CF meetup meeting this week.

Besides not having any speakers who've proposed to speak, I'm out of town traveling in the great (rainy, chilly) northwest (where I was invited to an intimate Microsoft tech summit). I just don't know if my schedule will permit me to speak myself if I wanted to, so it's best not to set any expectations. Ray, also, is already committed, so we'll pick things up next week.

I'm always looking for speakers. I also have some interesting new ideas I'll be trying in coming weeks.

Stopping multiple form submissions with CF 7/8 and "submitonce" validation

Note: This blog post is from 2008. Some content may be outdated--though not necessarily. Same with links and subsequent comments from myself or others. Corrections are welcome, in the comments. And I may revise the content as necessary.
What happens in your app if a user hits the submit button more than once before the form is processed, such as when the form didn't come back quickly enough, so the user submitted the form again? Would you be interested to know that CF has a feature to prevent them doing that? It's an often-missed hidden gem of CF7.

Have you ever considered this prospect of multiple form submissions? What could happen? It could cause multiple inserts to a database, or multiple charges to a card, or unexpected increases in some session variable counter, etc., which could be real trouble for you or your users.

It's a subject that comes up often in developer circles (even outside of CF). The good news is that there's a very simple solution in the available validate="submitonce" option of CFINPUT, which as of CF7 can be used for submit buttons. You'd use CFINPUT TYPE="submit" VALIDATE="submitonce" NAME="somename", as demonstrated in a complete code example below.

In this entry, I offer more info on the feature. I've not found too many other resources discussing it, so I hope this will help folks. There are some interesting challenges you should understand as well.

Problem already solved for you in Firefox--but do all your users use it?

For instance, if you've read about the feature and tried it on Firefox, you may have been surprised that you couldn't see what it did differently than a normal submit button. That's because it turns out Firefox already solves the problem itself, by preventing double-submission of a given form. It doesn't hurt to use the CF-based feature on FF. It just isn't needed. But you certainly still need the CF-based feature, though, if you may have users visiting your site with other browsers. (I can confirm that even IE 7 does not prevent double form submissions. Haven't tested Safari yet. Any takers want to report in the comments?)

Demonstrating the problem of multiple form submissions

It's not too difficult to demonstrate the problem of multiple form submissions. All you need is a means to track how many times the server-side form processing takes place for a given form's submission(s). In your real application, again, this may lead to multiple inserts in a database or multiple charges to a customer's credit card. To keep things simple, I'll demonstrate it using a session variable that's incremented on each form submission.

But then more important (to demonstrate the effect), we need the form processing to simulate "taking too long" so that a series of rapid submissions of a form will be able to be sent before the processing of the page "completes". We can do that in CF6+ by calling the Java thread sleep method, or in CF8 we can use the new sleep built-in function.

The example code is offered at the bottom here. Before you take a look at that, or try it out, note a few things.

Applies to form, not submit button

Besides the point above about Firefox being immune automatically to the multiple form submission problem, note that this multiple submission protection is enabled on the form itself, not on the submit button, so it does apply just as readily to forms submitted by pressing enter (when permitted by the browser) as by forms submitted by pressing the submit button.

The fact that it's enabled for the entire form (when the CFINPUT above is used) means also that you can't test this by having a "regular" submit button and a "protected" one in the same form. Again, it's not the submit button that gets the protection, but the form in which the CFINPUT type="submit" appears. You'll notice, therefore, that my demo code above uses 2 forms. (It's not at all important whether I use or don't use CFFORM in the "unprotected" form example. It just makes no difference.)

Does require use of CFFORM And Javascript

That makes a point though: the CFINPUT tag does indeed need to be used within a CFFORM tag, as shown in the second form. And further the feature is indeed relying on Javascript (generated by CF) to perform the multiple submit prevention. Neither should be a showstopper for most. You don't need to convert any other HTML tags within a form to their CFML CFFORM equivalents (like CFSELECT or CFTEXTAREA) just to enable the CFINPUT for form submission.

Some may want to point out that you don't need to use this particular approach to solve the problem: there are other Javascript-based approaches, as well as some that assert to work without JS. I'll leave it to commenters to mention them here, if interested.

My goal was to demonstrate the submitonce functionality, since it's not been discussed much. Do let me know if this was interesting to you.

Some final observations about my code example

I've provided comments in my code example code, about things that aren't related to the multiple submissions feature, but which may raise questions for some.

First, note that because I'm using sessions to demonstrate the feature, I've just gone ahead and put the CFAPPLICATION tag right into this template, so it doesn't matter where you put the code (won't be helped or hurt by an existing application.cfm or application.cfc, with respect to the session var created.)

As for the forms, note that I'm using self-posting forms. It doesn't matter if you do or don't for this multiple submission prevention feature to work.

And note that I don't use any means to force a filename into the form ACTION attribute, to make it post back to itself. If you leave the action empty, that makes the form self-posting. This is a legitimate HTML-specified use, if not widely known. No need to force the current file into it using #cgi.script_name# or the like.

And I determine if the form is submitted using a test for cgi.request_method being "post", which it will be on a form submission (versus it being a "get" when the page is first loaded). I don't use a test for whether the submit button is defined (a technique that is taught by some but will fail when the page is run on IE, if the user presses enter rather than the submit button, at least when there's only a single input field). Again, these choices have NO effect on the validity of the tests.

Finally, while I don't *need* to specify the empty action or post method on a CFFORM (since they're the default), I do it to avoid any confusion from those looking at the code and not familiar with that

The example code

You should be able to drop this code, verbatim, into any CFML page in any CF7 or 8 server to see the effect.

<cfapplication sessionmanagement="Yes" name="submitoncedemo">
<cfparam name="session.submitted" default="0">
<cfset interval=2>

<h4>Demonstration of New submitonce validation in CF7+</h4>

Try clicking each of the submit buttons below multiple times, in rapid succession, before the page returns from its #interval# second delay. Wait for that delay before noticing the count indicated after the 2nd form.
Notice how the "uncontrolled submit" will cause execution of multiple submissions (as tracked by a session variable). (The problem is not apparent in Firefox 1.5 and above, as it includes its own feature to prevent multiple form submissions. Try it on IE, though, even IE 7.)

<form name="test" action="" method="post">
<input type="Submit" value="Uncontrolled Submit">
<input type="button" onclick="location.href='<cfoutput>#cgi.script_name#</cfoutput>'" value="Reset Counter">
<!--- the use of no value for ACTION, to do a self-post of the form to itself, is legitimate HTML-specified functionality, if not widely known. No need to force the current file into it using #cgi.script_name# or the like. --->

The "controlled submit" will not. Regardless of how many times you press it, it will only register a single increment in the session count, demonstrating that CF prevented the form processing from being executed more than once until the form processing page was completed.

<!--- This needs to be in a separate form from above, because the submitonce validation applies to the form, not the button. And while I don't *need* to specify the empty action or post method on a CFFORM (since they're the default), I do it to avoid any confusion from those looking at the code and not familair with that. --->
<cfform name="test2" action="" method="POST">
<cfinput type="Submit" validate="submitonce" name="submit" value="Controlled Submit">
<input type="button" onclick="location.href='<cfoutput>#cgi.script_name#</cfoutput>'" value="Reset Counter">

<cfif cgi.request_method is "get">
   <!--- if the form is requested the first time, or via the HREF below, reset the session variable. --->
   <cfset session.submitted=0>
<cfelseif cgi.request_method is "post">
   <!--- if the form is submitted, process it. (There are other ways to test form submissions, but this is a very good one for many reasons.) --->
   <!--- put thread to sleep for the number of seconds indicated above, to simulate a wait while form submission is being processed --->
   <cfset thread = createObject("java", "java.lang.Thread")>
   <cfset thread.sleep(javaCast("long", 1000*interval))>
   <!--- in CF8, could use sleep function:    <cfset sleep(interval)> --->

   <!--- yes, perhaps we should lock the sesion variable below, but it's not critical to help or hurt this demo--->
   <cfset session.submitted=session.submitted+1>

Submitted: #session.submitted# times.

<hr size="3" color="##000000">

The form above has 2 submit buttons to demonstrate the new SubmitOnce validation in CF7+.
The first button, "Uncontrolled Submit", is a normal submit button (<input type="submit">).
The second button, "Controlled Submit", uses (<cfinput type="submit" validate="submitonce" name="somename">) which causes CF to prevent it being clicked twice to cause submission of a single form.
To demonstrate the effect, the action processing of this form is set to wait #interval# seconds before completing. It also outputs (using a session variable) how many times the button led to submission of a request to the form processing portion of the page.
Note that clicking the uncontrolled submit multiple times in rapid succession (on other than Firefox--haven't tested on Safari) will lead to multiple submissions. Even though you don't see the output of each submission (because each new submission starts a new request to the server), the increase in the session variable at a rate higher than just one per the #interval# second interval it takes for the form to complete. This demonstrates that multiple submissions are being caused.
Do the same with the "controlled submit" button, and that doesn't happen. It only ever increases by one per 3 second period.

Look ma, I'm on the radio again (my CFWeekly interview is now up)

Note: This blog post is from 2008. Some content may be outdated--though not necessarily. Same with links and subsequent comments from myself or others. Corrections are welcome, in the comments. And I may revise the content as necessary.
I had the distinct pleasure of being interviewed for the second time on the ColdFusion weekly podcast (last time in Oct '06). Some may know that Matt and Peter are starting to do interviews of speakers presenting at the upcoming cf.Objective() conference, and I happened to be the first in the lineup. The interview is up as this week's podcast.

In the 45 minute talk, we discuss both talks I'll be doing at the conference, first "Hidden Gems in the CF8 Monitor" and then "Step Debugging in CF 6/7/8". The first is a condensation of my 4-part series of articles in the Adobe DevCenter, where I highlight the most compelling tips, tricks, and traps I found. I think many will be surprised by them, and in the interview I share several from the talk.

Matt also asked me about how it compares to FusionReactor and SeeFusion, and I shared my thoughts for why there's a place for all, and along those lines (of how competing things fit together), he also asked me my thoughts on the open sourcing of BD/J2EE.

Of course, one of the things I clarified was that I left New Atlanta nearly 2 years ago (next week). Many seem not to have gotten that memo! But I explain more, including why I'm not so sure it will light the world on fire as a "free CFML engine" though it may well help a lot of people, so check out the discussion if you're interested in that topic.

I also shared some news that I've never blogged about nor spoken much about: the fact that when the roles of CF Product Manager (when Tim stepped down 2 years ago) and CF Evangelist (when Ben knew a few months ago that he was moving up to lead all the Evangelists in Adobe) first became available, I had the distinct honor of having been asked first (so I was told) if I wanted those roles. It's hard for that not to sound self-aggrandizing, which is why I've not mentioned it publicly, but I mentioned it in the interview to make the point to listeners that I really am all about CF now, and that plenty of folks at Adobe did realize I was still very much a CF community guy all along.

Anyway, I explained that I didn't take the roles simply because in the first case, the product manager role, it would have involved relocation to Boston (love Atlanta's weather too much, plus I was enrolled in an Atlanta-based seminary at the time). In the second case, Ben's role, it would have been awesome, but we all know it involves a LOT of travel. My wife and I just didn't want to be apart so much and so often (and again there are those seminary studies). It was tough to say no, but as I mentioned in the interview, of course Adobe got great folks for the roles ultimately, in Jason and Adam, respectively.

The interview concluded with my discussion of the Step Debugging talk I'll give at cf.o. I explained how it will cover both the CF8 Debugger (useful only on CF8) and FusionDebug (which can run on 6, 7, and 8). I explained (as I have many times) how though they're both based on Eclipse, that needn't be a show-stopper.

I explained how FusionDebug even offers an installer that bundles Eclipse, CFEclipse, and FusionDebug all at once, which is a great help for those challenged to install it (though it's also available as an add-in). I noted that the CF8 debugger is available only as an add-in, which can be a challenge to some, but I pointed out (as I have previously) that my 25-page chapter on the CF8 debugger, in the CFWACK, is available online. That should really help those who've been challenged to get started with the CF8 debugger. Anyway, I'll explain a lot more about using the debugger, and when/why/how one should, in the talk at the conference.

So, though I didn't plan it, I guess this interview was as much a show about how I'm not any one company's guy. :-) Whether it's supporting the CF8 monitor or FusionReactor/SeeFusion, the CF8 debugger or FusionDebug, CF or the other CFML engines, or even the consulting I do (done mostly on my own, but also some for Intergral and for Universal Mind, as I mentioned), I'm out here just trying to help where I can, whoever I can, however I can. :-) I just want to share info or tools and let folks make their own decisions. (In that regard, be sure also to check out my list of 400+ tools/resources for CFers and the CF Meetup that I run.)

Anyway, it took only a few minutes for you to read this entry. I think you'll enjoy the full 45 minute version in the podcast, which you can just click here to listen to the MP3 (no need to have an Ipod!).

8 Adobe AIR Apps that DON'T Suck

Note: This blog post is from 2008. Some content may be outdated--though not necessarily. Same with links and subsequent comments from myself or others. Corrections are welcome, in the comments. And I may revise the content as necessary.
Looking for some demonstrations of effective use of AIR? Check out 8 Adobe AIR Apps that DON'T Suck. Sure, it's got the oft-mentioned Ebay one, but lots more, including ones for Google Analytics, Pownce, Twitter, and Digg, that you may have missed.

Of course, many of those same examples (and more, though not all) are offered at the Adobe AIR showcase page. Still, the showcase is just a handful of highlighted examples and some, such as the WebKut page clipping tool and the XDrive app aren't listed. You can instead find those and dozens more at the AIR Marketplace. Curiously, a few of the makeuseof linked examples aren't even listed in the the Marketplace site, including the Google Analytics (still in beta), Pownce, Twhirl, or Digg ones, to name a few. (That may be old news to avid AIR fans, but I thought I'd point it out for those on the periphery.)

Given that, and for those who don't look at the Showcase or Marketplace pages regularly anyway, I thought this blog entry worth highlighting. In any case, It's nice to see outsiders picking up the baton in the AIR race.

BTW, I'm a huge fan of the site it's posted at, makeuseof.com, as they offer really valuable resource links on a wide range of tech topics every day.

Copyright ©2020 Charlie Arehart
Carehart Logo
BlogCFC was created by Raymond Camden. This blog is running version 5.005.
(Want to validate the html in this page?)

Managed Hosting Services provided by
Managed Dedicated Hosting