You are viewing documentation for v1.1.x. Change

Beginner Tutorial: Hello World

In this tutorial, we'll be writing a simple application to make sure we have Wheels installed properly and that everything is working as it should. Along the way, you'll get to know some basics about how applications built on top of Wheels work.

Testing Your Install

Let's make sure we're all on the same page. I'm going to assume that you've already downloaded the latest version of Wheels and have it installed on your system. If you haven't done that, stop and read the Installation chapter and get everything setup. It's okay, this web page will wait for you.

Okay, so you have Wheels installed and can see the Wheels "Congratulations!" page as shown in Figure 1 below. That wasn't that hard now, was it?

Welcome to wheels
Figure 1: Wheels congratulations screen.

Hello World: Your First Wheels App

Okay, let's get to some example code. We know that you've been dying to get your hands on some code!

To continue with Programming Tutorial Tradition, we'll create the ubiquitous Hello World! application. But to keep things interesting, let's add a little Wheels magic along the way.

Setting up the Controller

Let's create a controller from scratch to illustrate how easy it is to set up a controller and plug it into the Wheels framework.

First, create a file called Say.cfc in the controllers directory and add the code below to the file.

<cfcomponent extends="Controller">


Congratulations, you just created your first Wheels controller! What does this controller do, you might ask? Well, to be honest, not much. It has no functions defined so it doesn't add any new functionality to our Wheels application. But because it extends the base Controller component, it inherits quite a bit of powerful functionality and is now tied into our Wheels application.

So what happens if we try to call our new controller right now? Lets take a look! Open your browser and point your browser to the new controller. Because my server is installed on port 80, my URL is http://cfwheels.1.0/index.cfm/say. You may need to enter a different URL, depending on how your web server is configured. In my case, I will be using the host name cfwheels.1.0, so my URL will look like:


If you did everything right, you will get the Wheels error shown below in Figure 2. (Ironic that getting an error is doing something right, huh? Don't get used to it, buddy!)

No action error
Figure 2: Wheels error after setting up your blank say controller.

The error says "Could not find the view page for the 'index' action in the 'say' controller." Where did "index" come from? The URL we typed in only specified a controller name but no action. When an action is not specified in the URL, Wheels assumes that we want the default action. Out of the box, the default action in Wheels is set to index. So in our example, Wheels tried to find the index action within the say controller, and it threw an error because it couldn't find its view page.

Setting up an Action

But let's jump ahead. Now that we have the controller created, let's add an action to it called hello. Change your say controller so it looks like the code block below:

<cfcomponent extends="Controller">

<cffunction name="hello"></cffunction>


As you can see, we created an empty method named hello.

Now let's call our new action in the browser and see what we get. To call the hello action we simply add /hello to the end of the previous URL that we used to call our say controller:


Once again, we get a ColdFusion error. Although we have created the controller and added the hello action to it, we haven't created the view.

Setting up the View

By default, when an action is called, Wheels will look for a view file with the same name as the action. It then hands off the processing to the view to display the user interface. In our case, Wheels tried to find a view file for our say/hello action and couldn't find one.

Let's remedy the situation and create a view file. View files are simple CFML pages that handle the output of our application. In most cases, views will return HTML code to the brower. By default, the view files will have the same name as our controller actions and will be grouped into a directory under the view directory. This new directory will have the same name as our controller.

Find the views directory in the root of your Wheels installation. There will be a few directories in there already. For now, we need to create a new directory in the views directory called say. This is the same name as the controller that we created above.

Now inside the say directory, create a file called hello.cfm. In the hello.cfm file, add the following line of code:

<h1>Hello World!</h1>

Save your hello.cfm file, and let's call our say/hello action once again. You have your first working Wheels page if your browser looks like Figure 3 below.

Working hello
Figure 3: Your first working Wheels action.

You have just created your first functional Wheels page, albeit it is a very simple one. Pat yourself on the back, go grab a snack, and when you're ready, let's go on and extend the functionality of our Hello World! application a little more.

Adding Dynamic Content to Your View

We will add some simple dynamic content to our hello action and add a second action to the application. We'll then use some Wheels code to tie the 2 actions together. Let's get get to it!

The Dynamic Content

The first thing we are going to do is to add some dynamic content to our say/hello action. Modify your say controller so it looks like the code block below:

<cfcomponent extends="Controller">

<cffunction name="hello">
<cfset time = Now()>


All we are doing here is creating a variable called time and setting its value to the current server time using the basic ColdFusion Now() function. When we do this, the variable becomes immediately available to our view code.

Why not just set up this value directly in the view? If you think about it, maybe the logic behind the value of time may eventually change. What if eventually we want to display its value based on the user's time zone? What if later we decide to pull it from a web service instead? Remember, the controller is supposed to coordinate all of the data and business logic, not the view.

Displaying the Dynamic Content

Next, we will modify our say/hello.cfm view file so that it looks like the code block bellow. When we do this, the value will be displayed in the browser.

<h1>Hello World!</h1>
<p>Current time: <cfoutput>#time#</cfoutput></p>

Now call your say/hello action again in your browser. Your browser should look like Figure 4 below.

Hello with time
Figure 4: Hello World with the current date and time.

This simple example showed that any dynamic content created in a controller action is available to the corresponding view file. In our application, we created a time variable in the say/hello controller action and display that variable in our say/hello.cfm view file.

Adding a Second Action: Goodbye

Now we will expand the functionality of our application once again by adding a second action to our say controller. If you feel adventurous, go ahead and add a goodbye action to the say controller on your own, then create a goodbye.cfm view file that displays a "Goodbye" message to the user. If you're not feeling that adventurous, we'll quickly go step by step.

First, modify the the say controller file so that it looks like the code block below.

<cfcomponent extends="Controller">

<cffunction name="hello">
<cfset time = Now()>

<cffunction name="goodbye"></cffunction>


Now go to the view/say directory and create a goodbye.cfm page.

Add the following code to the goodbye.cfm page and save it.

<h1>Goodbye World!</h1>

If we did everything right, we should be able to call the new say/goodbye action using the following URL:


Your browser should look like Figure 5 below:

Working goodbye
Figure 3: Your new goodbye action.

Linking to Other Actions

Now let's link our two actions together. We will do this by adding a link to the bottom of each page so that it calls the other page.

Linking Hello to Goodbye

Open the say/hello.cfm view file. We are going to add a line of code to the end of this file so our say/hello.cfm view file looks like the code block below:

<h1>Hello World!</h1>
<p>Current time: <cfoutput>#time#</cfoutput></p>
<p>Time to say <cfoutput>#linkTo(text="goodbye", action="goodbye")#?</cfoutput></p>

The linkTo() function is a built-in Wheels function. In this case, we are passing 2 named parameters to it. The first parameter, text, is the text that will be displayed in the hyperlink. The second parameter, action, defines the action to point the link to. By using this built-in function, your application's main URL may change, and even controllers and actions may get shifted around, but you won't suffer from the dreaded dead link. Wheels will always create a valid link for you as long as you configure it correctly when you make infrastructure changes to your application.

Once you have added the additional line of code to the end of the say/hello.cfm view file, save your file and call the say/hello action from your browser. Your browser should look like Figure 6 below.

Hello with goodbye link
Figure 6: Your say/hello action with a link to the goodbye action.

You can see that Wheels created a link for us and added an appropriate URL for the say/goodbye action to the link.

Linking Goodbye to Hello

Let's complete our little app and add a corresponding link to the bottom of our say/goodbye.cfm view page.

Open your say/goodbye.cfm view page and modify it so it looks like the code block below.

<h1>Goodbye World!</h1>
<p>Time to say <cfoutput>#linkTo(text="hello", action="hello")#?</cfoutput></p>

If you now call the say/goodbye action in your browser, your browser should look like Figure 7 below.

Goodbye with hello link
Figure 7: Your say/goodbye action with a link to the hello action.

Much More to Learn

You now know enough to be dangerous with ColdFusion on Wheels. Look out! But there are many more powerful features to cover. You may have noticed that we haven't even talked about the M in MVC.

No worries. We will get there. And we think you will enjoy it.

^ Top
Table of Contents


Read and submit questions, clarifications, and corrections about this chapter.

[Add Comment]

  1. Sameer Gupta's Gravatar Sameer Gupta says:

    Thanks for wonderful write up.

    The link to video of this chapter is broken.

  2. Chris Peters's Gravatar Chris Peters says:


    Thanks for letting us know! I fixed the link.

  3. mugafuga's Gravatar mugafuga says:

    I would love to see an mov that shows how to use ORM and the Model side of wheels. Great stuff!

  4. Ben Margolis's Gravatar Ben Margolis says:

    I haven't written this app myself yet, but in your code you don't have the word "World!" You just have "Hello!" or "Goodbye!" The output images say "Hello World!" and "Goodbye World!"

  5. Baz's Gravatar Baz says:

    This is not a big deal but may confuse some people learning... The word "World" is missing from all the examples. The code shows "Hello!" but the results shows "Hello World!" same for "Goodbye".

  6. Martin's Gravatar Martin says:

    lol thats true, ahhahaha the developer was druged :P

    btw this tutorial rocks!!

  7. When running CF9 with the built-in CF server (port 8500) you'll have to use: http://localhost:8500/<optional-subdir(s)>/index.cfm?controller=say&action=hello

    Also see

  8. Chris Peters's Gravatar Chris Peters says:

    Got the screenshot/code discrepency fixed. Cocaine's a hell of a drug! :)

  9. Rick Troiani's Gravatar Rick Troiani says:

    Excellent tutorial.  Much better than Fusebox, Model Glue, Coldspring, etc.  Love the examples!

  10. walt's Gravatar walt says:

    THANK you. That's a VERY big piece of info to know.

  11. walt's Gravatar walt says:

    ok, it's just flat easier to use Apache instead of finagling CF to work with Windows 7.

  12. Andy's Gravatar Andy says:

    When creating the hello.cfm file, the tutorial indicates that it should be created in a folder named "say" in the "view" folder of the cfwheels root.  There is a directory named "views" in the root and one named "view" in the /wheels subfolder... Could be confusing.

    From just going through the tutorial, it appears that the tutorial should say to create the "say" folder in the "views" folder of cfwheels root, right?

  13. David's Gravatar David says:

    I followed the tutorial using Railo express.  I found that URL rewriting worked auto-magically when using the resin version of Railo express.  

  14. Darren's Gravatar Darren says:

    When you click the links in the tutorial the url isn't rewritten but instead shows the querystring, is this correct? shouldn't it conform to the rewritten url?

  15. Darren's Gravatar Darren says:

    Found the issue, the .htaccess file isn't included in the wheels 1.0 zip file, I had to create it myself by copying the file from svn

  16. Chris Peters's Gravatar Chris Peters says:

    Darren, if you're using an OS like Mac, it'll hide files like .htaccess in your file system view.

  17. Coming from RoR.

    I'm testing on Railo Express (railo_3.1.2.001_resin_3.1.9_express_win), cfwheels.1.0.4, WinXP SP3.
    Looks that variables are *not* passed from the Controller Action to the View.
    Getting error:
    variable [TIME] doesn't exist

    Defining variables directly in the view does work, but makes no sense if I want to use MVC . . .

    What is configured wrong, and where?

  18. Chris Peters's Gravatar Chris Peters says:


    Welcome from RoR. :)

    It sounds like Wheels isn't running the controller. Did you name it Say.cfc with a capital S? Is it extending Controller with a captial C?

    I'm not sure that it matters because you're in Windows, but I want to make sure that you're naming things in the correct manner.

  19. I went back to cfwheels.1.0.3 that solved the issue.

    At the beginning I indeed wrote "say.cfm", after it wasn't working changed it to "Say.cfm";
    Restarting Railo and cleaning Browser Cache didn't work.

    I will redo it from scratch in 1.0.4, see what will happen.

  20. [issue solved]
    I meant Say.cfc not Say.cfm ... sorry for the typo.

    I retested it with 1.0.4; Its also working now.
    Maybe I had a typo, really named it *.cfm, not *.cfc

    The revert to 1.0.3 forced me to recreate all files from scratch, that definitely fixed the issue RoR;

    Thanks for your fast Reply :)

  21. Chris Peters's Gravatar Chris Peters says:


    Glad you got it working, even if it meant redoing everything. ;)

  22. Greg Ostravich's Gravatar Greg Ostravich says:

    I ran into problems (will include the stack trace below) and the problem was I had enabled too much stuff on my CFIDE.  Be aware that when you change the custom settings you may end up flagging things that wouldn't really be an error within the framework.

    Here's that stack trace...

    The web site you are accessing has experienced an unexpected error.
    Please contact the website administrator.

    The following information is meant for the website developer for debugging purposes.
    Error Occurred While Processing Request
    The request has exceeded the allowable time limit Tag: cfoutput

    The error occurred in /Applications/ColdFusion9/wwwroot/wheels_site/wheels/global/cfml.cfm: line 101
    Called from /Applications/ColdFusion9/wwwroot/wheels_site/wheels/events/onerror.cfm: line 45
    Called from /Applications/ColdFusion9/wwwroot/wheels_site/wheels/global/cfml.cfm: line 43
    Called from /Applications/ColdFusion9/wwwroot/wheels_site/wheels/events/onerror.cfm: line 6
    99 : </cfif>;
    100 : <!--- we prefix returnValue with "wheels" here to make sure the variable does not get overwritten in the included template --->
    101 : <cfsavecontent variable="loc.wheelsReturnValue"><cfoutput><cfinclude template="../../#LCase(arguments.$template)#"></cfoutput></cfsavecontent>;
    102 : <cfreturn loc.wheelsReturnValue>
    103 : </cffunction>;

  23. vishal's Gravatar vishal says:

    How will an action link to actions in other controllers in linkto helper function?

  24. Vishal,

    Check out the documentation link here:

    You are able to specify the controller.


  25. ds's Gravatar ds says:

    Can we use cfscript in the controller for this example?

  26. ds's Gravatar ds says:

    Never mind, got just stick hello in variables scope.  

    component extends="Controller"
    varibles.time = "";
    public function hello(){
    varibles.time = time = now();
    return varibles.time;

  27. Hi,

    I've been coding CF for 10+ years and believe it or not, CFWheels is my first attempt at using an MVC framework. Nice job with the tutorials!

    One question, I successfully set up IIS 7 and web.config to enable URL rewriting so my hello world page comes up at, however the linkTo function links to that page from my goodbye page as Having the same page up at two different URLs is obviously an unmitigated disaster from an SEO standpoint, as well as confusing for users. Shouldn't the linkTo function be linking directly to say/hello and not rewrite.cfm/say/hello?

    Thanks for any help!

  28. Basil's Gravatar Basil says:

    I'm on Ubuntu 10.04 using Railo 3.23. I have cf wheels extracted to the root. It is not allowing for url rewriting. How do I enable this?

  29. Shailesh's Gravatar Shailesh says:

    URLs like these - http://mywheels.local/Say/hello aren't working
    these urls are working - http://mywheels.local/index.cfm?controller=say&action=hello

    Tested it with Railo, IIS7, Cfwheels 1.1.5, URL Rewrite enabled

  30. My issue above fixed itself, I think I only restarted IIS but not CF and I'm guessing a later server reboot did the trick.

    Also it would be cool if when I'm logged in to this site, the name, email, website etc. fields were pre-filled with no CAPTCHA.


  31. Stevie's Gravatar Stevie says:

    Hi,  I followed the example and got everything to work except for the outputting the time variable from the Say.cfc.  Time variable is declared in the hello function just like the example and I am keep on getting Variable Time is not defined.  As if Say.cfc is not being invoked at all.

    How do I go about of troubleshooting this?

  32. Chris Peters's Gravatar Chris Peters says:


    The view page will be invoked whether or a controller action is found or not. The best way to debug is to put this in the controller action:

    <cfabort showerror="Hello">

    ...and see if it's executed.

    If not, it's because you have not named the controller CFC or action to the conventions that Wheels is looking for. In the root controllers folder, you should have Say.cfc with a capital S. The action should be a public method called hello with a lowercase h.

  33. Stevie's Gravatar Stevie says:

    I don't know what I did wrong but everything is working after I reinstall the Wheels framework.  Thanks.

  34. Kirby's Gravatar Kirby says:

    The cfabbort doesn't show.  I even coppied everything into a new function and .cfm named index, but still getting the 'time' doesn't exist error.  I have a capital S for Say.cfc and capital C for Controller.  running CF8 on win7, using built in CF server.  erased wheels root folder and recreated from .zip, but same error.  using wheels 1.1.5, tried all alternate urls in comments too, same errors.

  35. joven's Gravatar joven says:

    this start my excitement to thsi framework :D

  36. Bill Ryder's Gravatar Bill Ryder says:

    @Marc de Ruijter, huge help!  I just installed the current Railo and wanted to drop cfwheels into a subdirectory on an existing website.  The installation tutorial info was not working and had me pulling my hair out.  Here's the URL I needed:


    ...obviously the cfwheels directory being where I dropped cfwheels on my website.

  37. Bill Ryder's Gravatar Bill Ryder says:

    Working on Rewrite.

    This works: http://localhost/cf/cfwheels/index.cfm?controller=say&action=hello
    This does not: http://localhost/cf/cfwheels/say/hello

    This is with Railo 3.3.1 and Tomcat 6.0.24 that came with it, on Lion osx.  Tried uncommenting the appropriate lines in .htaccess within the cfwheels directory, restarting Tomcat and Railo.  No dice.  Anyone have experience or advice to pass along with this configuration?

  38. sathish's Gravatar sathish says:


    I am new to CFWheels. I am trying to understand if i can do nested controller invocations in CFWheels and if so, how it is to be done. In fusebox, i can have a fuseaction called "action1" in circuit "c1" and inside it, i can invoke/include fuseactions from the same circuit or other circuits. i.e C1.action1 internally invokes C2.action1, C1.action3, C3.action1 etc and this is possible. Earlier we had to do this using CFMODULE tag by invoking the specific fuseaction as a customtag call. But since FB5.0 this can be done by using the FB's XML tags and it does  not work as a customtag invocation but rather as a include action improving performance and also enabling the variables created in the current context to be used in the invoked fuseaction.

    How can i do the same in wheels. In your example you have mentioned that if we have a Hello() and Welcome() actions defined in a Say controller, we can further create another method / action called HellowWelcome() that could internally invoke Hello() and Welcome(). This is udnerstandable and is as per the CFC functionalities. But how can i invoke an action in another controller. For example Shop.ShowBaset() inside Hello()?

  39. Bigscreentv's Gravatar Bigscreentv says:


    I am having issues with viewing figure two.

    I have created Say.cfc in the controllers folder, however I am not sure what my url should be. I've tried:


    I get either a Google Chrome "can't find" error, or my browser thinks I'm doing a Google search.

    I am very new to CF so any help would be appreciated.



  40. calle's Gravatar calle says:

    it's http://localhost/wheels_site/index.cfm/say/hello
    (otherwise you're using the default 'index' action index.cfm/say/index)

  41. Donna French's Gravatar Donna French says:

    I'm running MAMP & Railo 4.0 and cannot get this to work. I've tried putting it in the root folder as well as it's own & keep getting a 404 error. Any suggestions?

Add Comment