Module 16 was about making an application fast and observable. Module 17 is about making it maintainable as it grows. A single .cfm file mixing a database query, business rules, and HTML in one place works fine for a small page and becomes unworkable once an application has dozens of them. MVC is the standard answer to that problem.
Learning Objectives
After completing this lesson, you'll be able to:
- Explain what each of Model, View, and Controller is actually responsible for.
- Write a basic Model, View, and Controller in vanilla CFML.
- Know a real gap between the MVC pattern itself and what a framework like ColdBox adds on top of it.
- Recognize the major ColdFusion MVC frameworks by name: ColdBox, FW/1, CFWheels, and the legacy ones you'll still see in older codebases.
How a Request Flows Through MVC
Client Request Arrives
a form submission or a URL
Controller Orchestrates
decides what to do about it
Model Handles Data
query, validation, business rules
View Renders the Output
HTML, or a JSON response
The Three Layers
| Layer | Responsible For | Never Does |
|---|---|---|
| Model | Data access, validation, business rules | Know anything about HTML or the browser |
| View | Presentation, formatting data for output | Run a SQL query or decide application logic |
| Controller | Receiving the request, calling the Model, choosing the View | Contain the actual business logic itself |
The Model: Data and Business Logic
component {
public query function getUsers() {
return queryExecute(
"SELECT id, name, email FROM users ORDER BY name",
{},
{ datasource: "myDSN" }
);
}
}The View: Presentation Only
<h1>User List</h1>
<table>
<cfoutput query="users">
<tr>
<td>#encodeForHTML(name)#</td>
<td>#encodeForHTML(email)#</td>
</tr>
</cfoutput>
</table>The View only formats data it's handed, it never queries the database itself. encodeForHTML() here is the same output-encoding function from the XSS Prevention lesson, a View outputting unencoded data is exactly the vulnerability that lesson covered.
The Controller: The Traffic Cop
component {
property name="userModel";
public function list() {
var users = userModel.getUsers();
return view("users/list", { users: users });
}
}A Real Gap: view() Isn't a Native CFML Function
The Controller example above reads cleanly, but that view() call is doing a lot of invisible work: resolving "users/list" to an actual file path, passing variables into that template's scope, and rendering it as the response. None of that exists in vanilla CFML. Plain ColdFusion has no built-in router, no automatic Controller dispatch, and no view() helper, you'd wire all of that yourself with something like a single index.cfm front controller that reads the URL, calls the right CFC method, then cfincludes the matching .cfm template with the Model's data in scope. What ColdBox, FW/1, and CFWheels actually provide isn't the MVC pattern itself (you can write that by hand, as shown above), it's that routing and dispatch wiring, plus dependency injection, logging, and caching built on top of it.
Popular ColdFusion MVC Frameworks
| Framework | Known For |
|---|---|
| ColdBox | The most actively maintained, enterprise-grade option. Built by Ortus Solutions, with dependency injection via WireBox, plus built-in caching, logging, and security tooling |
| FW/1 (Framework One) | Lightweight, convention-over-configuration, minimal setup, maps URLs to folders automatically |
| CFWheels | Inspired by Ruby on Rails, with an Active Record-style approach to database interaction |
| Fusebox, Mach-II, Model-Glue | Older frameworks you're more likely to encounter maintaining an existing codebase than choosing for a new one |
Common Beginner Mistakes
Letting the View run its own database query
The moment a .cfm template runs a cfquery directly, it's no longer just a View, it's back to mixing concerns. The Model fetches data, the View only formats what it's handed.
Putting business logic in the Controller instead of the Model
The Controller should orchestrate (call the Model, pick the View), not contain the actual validation rules or calculations itself. Logic that lives in the Controller is harder to reuse and test than logic that lives in the Model.
Assuming view() or a router is just part of CFML
They're not, vanilla ColdFusion has no built-in MVC dispatch mechanism. That convenience comes from adopting a framework like ColdBox or FW/1, or building the equivalent wiring by hand.
Best Practices
- Keep the Model ignorant of HTML entirely, it should work the same whether its output ends up in a View or a REST API response.
- Keep business logic out of the Controller, it orchestrates, the Model decides.
- Encode output in the View the same way covered in the XSS Prevention lesson, regardless of which layer the data originally came from.
- For a new project, reach for an established framework (ColdBox or FW/1) rather than hand-rolling the routing and dispatch layer from scratch.
Interview Questions
What's the core problem MVC solves compared to a traditional single-file .cfm page?
A single file mixing database queries, business rules, and HTML becomes hard to maintain and test as an application grows. MVC separates those concerns into three layers, each with one responsibility.
What exactly does a framework like ColdBox add on top of the MVC pattern itself?
The MVC pattern (Model, View, Controller as separate layers) can be hand-written in vanilla CFML. A framework adds the routing/dispatch wiring between them (resolving a URL to a Controller action, rendering the matching View), plus extras like dependency injection, caching, and logging.
Why shouldn't the View execute a database query directly, even if it would technically work?
It breaks the separation of concerns MVC exists for. The View would then depend on knowing how to fetch data, making it harder to reuse, test, or swap out independently of the Model.
Summary
In this lesson, you broke an application into Model, View, and Controller layers, wrote a basic version of each in vanilla CFML, saw a real gap between the MVC pattern itself and what a framework adds on top of it, and got an overview of the ColdFusion framework landscape: ColdBox, FW/1, CFWheels, and the legacy names you'll still run into.
What's Next?
The next lesson looks at ColdBox specifically, the most widely used modern ColdFusion MVC framework.