So: we've been glorifying the wonders of dynamically generated
WAP content, especially within ColdFusion. Is it perfect? Of course
not. There are several traps, as well as a few more tricks, that
you should know about before setting off to code CF/WML.
When CFCONTENT is Unavailable
First and foremost, you may find that the all-important
<CFCONTENT> tag is rejected as an invalid CF tag. There are
two situations in which this could occur. First, if you're using
the free version of ColdFusion (CF Express), the tag is simply not
supported. Perhaps that will change in the future, but for now it
does mean that you can't create WML content within CF Express.
The other situation where <CFCONTENT> is unavailable is
when the CF administrator has disabled the tag for security
reasons. The security risks have nothing to do with the way we're
using <CFCONTENT>, but rather with ways it can be used for
other purposes (via its FILE attribute). Sadly, this too is a
showstopper until Allaire provides a means to restrict the use of
the FILE attribute, while permitting our more generic use of the
tag. (In my CF/WML chapter in Professional WAP Programming,
Wrox Press, I offer a possible workaround.)
Studio Traps (and Tricks)
Another problem for some is that Studio support for creating WML
pages and elements is all based on the Phone.com specification for
WML, rather than the more generic WAP Forum standard. As such, it
is possible to create WML code that will not work in all browsers
(specifically, those that do not support the Phone.com
specification).
I also recommended earlier that you should place the
<CFCONTENT> tag on the same first line as the XML
declaration. Unfortunately, Studio's new page Wizard for creating a
CF/WML skeleton page does not follow that recommendation.
Both of the above problems can be solved by modifying the file
that Studio uses to create that skeletal page - it's simply a
file in the directory ProgramFiles\
Allaire\ColdFusionStudio4.5\Wizards\WML, on the drive where Studio
is installed. The file is called (literally) Dynamic(usingCF).cfm.
Modify it to suit your tastes, and the next time you use the File |
New | WML | Dynamic feature, the new untitled page shown will
reflect your changes.
A subtler problem in Studio is that there is an option that
causes all tags created by features like Tag Insight and Tag Editor
to be in uppercase. Since WML requires lowercase tags, this feature
should be turned off. (See Options | Settings | HTML | Lowercase
all inserted tags.)
CF's HTML Heritage
A more pernicious problem is one based on CF's heritage as a
tool for creating HTML pages. While we've simply coded WML and
there's been no problem, there are features in CF that create
output for us, and those features tend to create output in HTML.
Specifically, CF error messages and debugging information include
HTML tags. Sadly, a WML browser will generate an error if HTML code
is sent to it. But again, there are a couple of workarounds for
this.
CF provides for a special file called application.cfm to be
executed before any other CF page. My recommendation is to place
such a file in the same directory as your WML code (preferably in a
directory that has only CF templates that create WML code), so it
can execute several CF tags that solve some of these problems. The
details of this approach are explained in Professional WAP
Programming, but here's the listing for those who just want
working code without explanation:
<CFSETTING ENABLECFOUTPUTONLY="Yes">
<!- the line above prevents this file from sending any code
to
the browser until the end. I've placed the
comment after it to prevent
even a needless carriage return being sent to
the browser ->
<!- Setup to test the version of CF server currently running.
->
<CFSET
version=listgetat(Server.ColdFusion.ProductVersion,1,", ")
& "." &
listgetat(Server.ColdFusion.ProductVersion,2,", ")>
<!- Turn on use of the wml_error.cfm with new CFERROR
TYPE="exception"
Before 4.5, the CFERROR TYPE="exception"
option was not allowed.
The tags and attribute existed, but the
options did not. We can't
even list the option if before 4.5, as the
compiler will generate
an error. But we can play a trick to get it
to work if ge 4.5,
while still allowing this code to compile
successfully in a 4.0 server ->
<CFIF version ge 4.5>
<CFSET type="exception">
<CFERROR TYPE="#type#"
template="wml_error.cfm">
</CFIF>
<!- Use CFSETTING to turn off CF server-side debugging, if
turned
on, since it, too, is HTML that will choke a
WML browser.
Before 4.0, the CFSETTING SHOWDEBUGOUTPUT
attribute was not
allowed, but there's no way to trick the
server with this one,
since you can't use variables for either tags
or their
attributes. If you're running a release older
than 4.0, simply
remove the following line ->
<CFSETTING showdebugoutput="no">
<!- Restore the setting that prevented this file sending any
text
to the browser. Must be done or subsequent
pages will send no
output to the browser unless it's enclosed in
CFOUTPUT - generally
not desirable ->
<CFSETTING ENABLECFOUTPUTONLY="no">
You can't run application.cfm directly. Instead, you place it in
the directory where it is to affect other programs, and whenever
one of those other programs is executed, the application.cfm is run
first.
The application.cfm file above refers to another .cfm file
called wml_error.cfm, which offers an alternative means of
formatting the output of CF errors when they occur. Here is that
code:
<CFCONTENT TYPE="text/vnd.wap.wml"><?xml
version="1.0"?>
<!DOCTYPE wml PUBLIC "-//PHONE.COM//DTD WML 1.1//EN"
"http://www.phone.com/dtd/wml11.dtd">
<wml>
<card>
<CFOUTPUT>
<p><b>An error has occurred in this application.
Please
share this
diagnostic information with the system
administrator<CFIF cferror.mailto is not ""> at
#cferror.mailto#</CFIF>.</b></p>
<p><b>Error Text:</b>
#htmleditformat(cferror.diagnostics)#</p>
<p><b>DateTime:</b>
#cferror.datetime#</p>
<p><b>Error Template:</b>
<CFIF cferror.Template is "">
(unavailable)<CFELSE>#cferror.Template#</CFIF></p>
<p><b>Referrer:</b>
<CFIF cferror.httpreferer is "">
(unavailable)<CFELSE>#cferror.httpreferer#</CFIF></p>
<p><b>Query String:</b>
<CFIF cferror.querystring is "">
(unavailable)<CFELSE>#cferror.querystring#</CFIF></p>
<p><b>Browser:</b>
<CFIF cferror.browser is "">
(unavailable)<CFELSE>#cferror.browser#</CFIF></p>
</cfoutput>
</card>
</wml>
Another element of CF's HTML heritage is that several CF tags
are designed to generate HTML (and/or JavaScript code) for you
automatically, such as CFFORM (and its child tags CFINPUT,
CFSELECT) and CFTABLE. As useful as these are for HTML-oriented CF
developers, they must not be used when creating WML decks from
within CF, since they do not generate valid WML.