Learn About Doug!
View Doug Boude's online resume
updated 4/22/2009

View Doug Boude's profile on LinkedIn
Link to me!

Follow Doug Boude on Twitter
Follow me!

Be Doug's friend on Facebook
Befriend me!
(I promise not to follow you home)
Contact Doug!
OO Lexicon
Chat with Doug!
Recent Entries
You may also be interested in...
Florida web site design



Czech your Page Rank!
Check Page Rank of any web site pages instantly:
This free page rank checking tool is powered by Page Rank Checker service
Surf's Up!
Visit Egosurf.org and massage YOUR web ego!
My Score: 9,001
Doug's Books

Read (and recommend)

  • Men are from Mars, Women are from Venus
  • The Wisdom of Crowds: Why the Many Are Smarter Than the Few and How Collective Wisdom Shapes Business, Economies, Societies and Nations
  • Blink: The Power of Thinking Without Thinking
  • Head First Design Patterns
  • Transact-SQL Programming
  • What's So Amazing About Grace?
  • Just So Stories (Rudyard Kipling collection)

Reading

  • Prayer: Does it Make Any Difference?
  • Data Mining (Practical Machine Learning Tools and Techniques)
<< July, 2008 >>
SMTWTFS
12345
6789101112
13141516171819
20212223242526
2728293031
Search Blog

Recent Comments
Re: Equivalent of SQL "TOP X" in Oracle (by Azzedo at 7/01 4:39 PM)
Re: Small But Seriously Irritating Export to Excel Issue (by dougboude at 6/30 2:47 PM)
Re: Small But Seriously Irritating Export to Excel Issue (by Shannon Hicks at 6/30 1:41 PM)
Re: Disappearing IE Popup Window During Save/Open Dialog (by James Moberg at 6/26 7:17 PM)
Re: Buying a New Home in San Antonio (by ike at 6/26 2:58 PM)
Re: SQL Forward Engineering with Visio 2003 Professional (by Matthew at 6/17 2:33 PM)
Re: Special Character/Unicode Issue in Ajax Data Retrieval (by matt at 6/15 3:34 AM)
Re: My Twelve Steps to a Coldbox App (by Dutch Rapley at 6/12 1:34 PM)
Re: My Twelve Steps to a Coldbox App (by dougboude at 6/12 12:09 PM)
Re: My Twelve Steps to a Coldbox App (by Dutch Rapley at 6/12 11:52 AM)
Categories
Archives
Photo Albums
Funnies (5)
Family (3)
RSS

Powered by
BlogCFM v1.11

29 July 2008
How to Think about Controller objects and Model objects
with Coldspring in the mix!

Even though MVC has been "all the rage" now for a good long time and several frameworks have been lovingly and painstakingly developed and shared by the CF community to help facilitate the migration to a more standardized OO approach to development, I do believe that there will always be a need to regularly return to the foundational principles of our craft. For some, an affirmation or further perfecting of their core thought processes; for others, the first exposure to a new way of thinking about and viewing the tools they wield as a problem solver and programmer. After having immersed oneself so deeply in MVC and OO for a substantial length of time and embracing those concepts so completely, these foundational principles can become so much a part of us that we hardly even recognize them as such, and tend rather to simply see them as a part of who we are and how we think. Sometimes, though, the privileged occasion arises when we get to once again see them as the wondrous, shiny ideas that they are, when a person who has had the tenaciousness and fortitude to embark upon that OO journey asks us to share our own insight in order to facilitate the evolution of their own assimilation of these concepts.

Alright, perhaps a bit too poetic a prelude, but I was recently asked to share my own understanding of the relationship between controller objects and model objects and the mechanics there. I couldn't help but get a little excited as I took the time to examine my own understanding of the subject and attempt to relate it to this person and realized just how much a part of my thinking it has become. Of course, it goes without saying that I know for a fact I still have a lot of room for growth in this area, but I do feel at least a sense of satisfaction that the couple of years I've invested so far in this has grown me more technically than I believe I had in the five years prior doing procedural coding.

 Okay, enough with the nostalgia already! Here's the question I was asked:

[10:09 PM]  hey Doug-
[10:10 PM]  thanks so much for all the tutorials and learning materials, can't thank you enough
[10:11 PM]  i've got a basic model glue site up and running with one exception, total MVC with not much in the model, totally bloated controllers. Still trying to get my head around calling and using the code from my model via the controller, any blog entries or anecodotal stories to suggest that would guide me?

My Response:

Hey, you're welcome for the tutorials and such. I definitely don't do it for the fame, but rather because I KNOW how painful it can be to traverse a new learning curve, espcially when it comes to frameworks, OO, and the like. If I can spare someone even ten minutes of hair pulling then I've accomplished what I set out to do! :)
 
Using your model code in your controllers (which is exactly what a person should be doing :) )...this is nothing more or less than giving your controller cfc an instance of your model cfc so it can manipulate it, call its methods, etc. For instance, imagine for a moment that we are attempting to log a person in to our app (framework doesn't matter, all we know is it's one that supports MVC). The user has just filled in their username and password and clicked the submit button, and those two pieces of info are now handed off to our controller via whatever mechanism the framework we're using has provided us. We have created for ourselves a Security.cfc that has a method called "Login".

 
<cfcomponent displayname="Security">
   <cffunction name="login">
       <cfargument name="username" />
       <cfargument name="password" />
    ...
   </cffunction>
</cfcomponent>


 
Now, Security is our controller, so by virtue of that fact the general rule of thumb is that the controller's job is to be nothing more than a liaison between the View (our forms and results page) and our model (where the real work gets done!), our controller cfc should have very little code in it and in fact should be using our model object to get the real work done. In order for it to do that, it needs an instance of it's Model security counterpart. In our scenario, we have a CFC living in the Model directory also called Security which performs the actual act of attempting authentication. Here's what our Model/Security.cfc might look like:
 

<cfcomponent displayname="Security">
   <cffunction name="login">
       <cfargument name="username" />
       <cfargument name="password" />
       <cfset var results = false /><!--- set the value of our return variable. by default we're going to return a result of false, meaning the authentication failed --->
       <cfquery name="qryLogin">
          select username from user_table where username = <cfqueryparam value="#arguments.username#" cfsqltype="cf_sql_varchar" /> and password = <cfqueryparam value="#arguments.password#" cfsqltype="cf_sql_varchar" />
       </cfquery>
       <cfif qryLogin.recordcount eq 1><!--- we authenticated! --->
            <cfset results = true />
       </cfif>
       <cfreturn results />
   </cffunction>
</cfcomponent>

 
Makes sense to you, I'm sure...same kind of code we've been using for decades to authenticate a person, right? Okay, so now we need for our controller to actually make the login call. Let's give our Security controller access to this functionality. Here's our controller Security CFC again...
 

<cfcomponent displayname="Security">
   <cffunction name="login">
       <cfargument name="username" />
       <cfargument name="password" />
       <cfset var objSecurity = createobject("component","Model.Security") />
       <cfset var results = false />
       <cfset results = objSecurity.login(username=arguments.username,password=arguments.password) />
       <cfreturn results />
   </cffunction>
</cfcomponent>

 
So, within our controller, we have created an instance of our Model security CFC and called its login method. I know this is a very simplified example, but it is precisely the way to think about the relationship between your model and your controller objects! We can get a little fancier if we like and put our object into the variables scope within our CFC so that we only create one instance of it and then let every method in the controller access it as needed, like this:
 

<cfcomponent displayname="Security">
 <cffunction name="init">
  <cfset variables._objSecurity = createobject("component","Model.security") />
 </cffunction>
 <cffunction name="getSecurity">
  <cfreturn variables._objSecurity />
 </cffunction>
 <cffunction name="login">
    <cfargument name="username" />
    <cfargument name="password" />
    <cfset var results = false />
    <cfset results = getSecurity().login(username=arguments.username,password=arguments.password) />
    <cfreturn results />
 </cffunction>
</cfcomponent>


 
Now any method in my controller that needs to use the model security object need only do a "getSecurity()" call! This is assuming that your Init method is getting called when your controller is instantiated by your framework; it would need to in order for the security object to be present and available.
 
Now, for many reasons, it is not the best idea to be hard coding object instantiation into your controllers. I mean, what if you did that and then somewhere down the road you had to make a change to your Model/security.cfc that now required the init method to be called upon instantiation? You would have to hunt down every place in your app where the security object was being instantiated and change the createobject line to include the init method call. In this scenario probably not a huge deal to do so; but potentially this could create a LOT of extra maintenance. This specific thing is why I have come to love Coldspring so much. It allows me to "inject" an instance of my model/security.cfc into my controller/security.cfc in one handy place so that I need never (probably) touch my controller when a change is made to my model as I described. Here is my controller when I inject the model/security object using Coldspring:
 

<cfcomponent displayname="Security">
 <!--- Coldspring Autowire methods --->
 <cffunction name="setSecurity" access="public" returntype="void" output="false">
  <cfargument name="Security" required="true" type="any" />
  <cfset variables._Security = arguments.Security />
 </cffunction>
 <cffunction name="getSecurity" access="private" returntype="any" output="false">
  <cfreturn variables._Security />
 </cffunction>
 
 <cffunction name="login">
    <cfargument name="username" />
    <cfargument name="password" />
    <cfset var results = false />
    <cfset results = getSecurity().login(username=arguments.username,password=arguments.password) />
    <cfreturn results />
 </cffunction>
</cfcomponent>

 
By adding Coldspring to the mix, when it instantiates your controllers and finds corresponding SET and GET methods like that, it will look to see if it has a definition for the object the set and get references (in this case, the set and get are for 'Security'...getSECURITY, setSECURITY...so it will be looking for a bean definition named SECURITY). If it does, it will go ahead and create that object and inject it into the controller for you so that it is "present and accounted for" from that moment on. So, I could theoretically define a whole bunch of different objects (aka 'beans') for Coldspring, and then when I need one of those objects in my controller, all i gotta do is create a SET and GET method that matches the object name. Let's say our Security controller ALSO needs to be able to send emails, and our app has an Emailservice CFC in the model. Well heck, let's just inject that bad boy and use it! :
 

<cfcomponent displayname="Security">
 <!--- Coldspring Autowire methods --->
 <cffunction name="setSecurity" access="public" returntype="void" output="false">
  <cfargument name="Security" required="true" type="any" />
  <cfset variables._Security = arguments.Security />
 </cffunction>
 <cffunction name="getSecurity" access="private" returntype="any" output="false">
  <cfreturn variables._Security />
 </cffunction>
 
 <cffunction name="setEmailService" access="public" returntype="void" output="false">
  <cfargument name="EmailService" required="true" type="any" />
  <cfset variables._EmailService = arguments.EmailService />
 </cffunction>
 <cffunction name="getEmailService" access="private" returntype="any" output="false">
  <cfreturn variables._EmailService />
 </cffunction>
 
 <cffunction name="login">
    <cfargument name="username" />
    <cfargument name="password" />
    <cfset var results = false />
    <cfset results = getSecurity().login(username=arguments.username,password=arguments.password) />
    <cfif not results>
      <cfset getEmailService().sendAdminEmail(subject="failed login") />
    </cfif>
    <cfreturn results />
 </cffunction>
</cfcomponent>

 
Coldspring just makes object injection SO simple, don't you think? Setters and getters are one way of injecting objects using Coldspring; it also can do it another way, which I won't get into right now (no need to muddy the waters at this juncture). Now, you should also know that there are times when individual Model objects ALSO need to use instances of other model objects (you may have encountered this already at some point). For instance, the example of an Emailservice object...by virtue of the very defnition of a service object (which I do have a blog post about), it is likely manipulating the methods of two or more OTHER objects. Just like our controller, for our model object to use another object, it has to have an instance injected into it somehow. Either we created that instance manually using a Createobject statement, OR we leveraged Coldspring to auto-inject those instances for us. The manner in which it is done is exactly the same as it is for controllers, no significant differences at all.
 
Okay, I know I've kinda gone on and on about this, but (if you can't tell) I do tend to have a passion for Coldspring and the beauty it brings to an OO application! But you know, even if you opt not to leverage Coldspring to perform the object injection and choose rather to do it manually (which I, for one, would not frown upon you for doing :) ), the concept is exactly the same: If one object needs to manipulate another object,  you must create an instance of the needed object(s) within the controlling object, whether that happens to live in the model or controller. Having said that, there are a few hard and fast rules of thumb when writing these apps that I always follow and which you may want to consider for yourself.
 
1. A controller's job is to be liaison between view and model, only. Keep controller methods as light as possible, doing as little work as possible.
2. A controller should NEVER talk to the database
3. A controller is the ONLY one who has the privilege of talking to Session or Application scopes (unless you have yourself a session facade object, which I personally have never seen the need for. If you DO have a session facade object, then IT is the only object in the app who has the privilege of talking to session. in that case, the session facade will have a corresponding controller and model object).
4. Model objects should be doing as much of the app's work as possible. In a nutshell, build your model objects as if tomorrow you would be told that you had to change frameworks and your model was the only thing you could take with you.
5. NEVER even consider injecting a controller object into a model object. BLAH! YUK! PTOOEY! In fact, never allow yourself the sacrelige of injecting one CONTROLLER into another. If you're seeing the possibility of a need to do that, then probably you need to refactor some logic and move some code around.
 
That's about it. Have I helped fill in any gaps? Have I opened any more? Did I address what it is you were needing? Let me know, I don't mind taking the time to share (and learn)!
 
Doug  :0)

 

 

 

Posted by dougboude at 9:31 AM | PRINT THIS POST! | Link | 2 comments



24 July 2008
Using Special Characters within Coldspring.XML

Just because a person uses Model Glue and has learned enough about XML to know how to create basic settings doesn't necessarily mean that they have a strong command of XML, right? Well, I needed to put a funky, "special character filled" value into my global config object for use later, and through some experimentation found that using XML's 'CDATA' allowed me to do this so I thought I'd share it since I hadn't seen it used in Coldspring.xml before. Allow the picture to speak volumes:

  <bean id="GlobalConfig" class="ModelGlue.Bean.CommonBeans.SimpleConfig">
    <property name="Config">
      <map>
        <entry key="DNS"><value>myDNS</value></entry>
  <entry key="FusionMapDir"><value>/FusionMaps</value></entry>
  <entry key="FusionJS"><value>/js/FusionMaps.js</value></entry>
  <entry key="FusionChartDir"><value>/FusionCharts</value></entry>
  <entry key="FusionChartJS"><value>/js/FusionCharts.js</value></entry>
  <entry key="PDFRoot"><value>/images/PDFMaps</value></entry>
  <entry key="adminEvents"><value>page.admin,page.datamgmt,page.entityadmin,page.dataadmin</value></entry>
       <entry key="chartSubCaption"><value><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Asia Matters for America\nwww.asiamattersforamerica.org\n]]></value></entry>
   </map>     
    </property>
  </bean>

I am using a third party Flash-based charting tool and needed to apply a global sub caption to all charts produced, so decided to store it in my Coldspring.xml as part of my global config bean.

Now, I will say that I first attempted to pass in that subcaption value within my modelglue.xml file as an argument, like so:

 

 <event-handler name="getChart">
   <broadcasts>
    <message name="getChartData">
     <argument name="qryName" value="qryChartData" />
     <argument name="entityTypeID" value="3" />
    </message>
    <message name="getChartXML">
     <argument name="subcaption" value="&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Asia Matters for America\nwww.asiamattersforamerica.org\n" />
    </message>
   </broadcasts>
   <results />
   <views>
    <include name="returnChart" template="dspBigChart.cfm" />
   </views>
  </event-handler>

Of course, that turned my xml invalid. So I tried doing it like this:

 

  <event-handler name="getChart">
   <broadcasts>
    <message name="getChartData">
     <argument name="qryName" value="qryChartData" />
     <argument name="entityTypeID" value="3" />
    </message>
    <message name="getChartXML">
     <argument name="subcaption" value="<![CDATA[&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Asia Matters for America\nwww.asiamattersforamerica.org\n]]>" />
    </message>
   </broadcasts>
   <results />
   <views>
    <include name="returnChart" template="dspBigChart.cfm" />
   </views>
  </event-handler>

Still invalid, so i just gave up and went with the coldspring.xml approach for time's sake. Does anybody know the correct way (if there is one) to utilize CDATA within an XML attribute value like I tried to do? I probably won't stray from the way I'm doing it now in my global config, but I am curious.

Posted by dougboude at 12:09 AM | PRINT THIS POST! | Link | 0 comments
05 July 2008
Helpful Hint for Retrieving CFGRID via Ajax

Here's the scenario...

You're building a Model-Glue application and you're using some Ajax calls to retrieve some data displayed within a CFGRID. When you navigate directly TO the event that performs the Ajax action (index.cfm?event=ajax.getDataSetforEdit&dataSetID=2 , for instance) the page loads just fine and renders the grid without a hitch. When you attempt to retrieve and display it by updating the innerHTML of a target DIV tag, however(something like:

new Ajax.Updater('datatarget','index.cfm?event=ajax.getDataSetforEdit&dataSetID=2',{method:'post',evalScripts: true});

 

)    your browser complains (see the error messages below) and the grid doesn't display!

 

 

 

              Symptom as seen in IE7                                                        Symptom as seen in Firefox's Firebug window

The first thing you need to do is to make SURE that you have a proper server mapping to the CFIDE directory. Not a COLDFUSION mapping, but a WEBSERVER mapping. In IIS you create a virtual directory pointing to CFIDE; in Apache you edit the http.conf file and add an Alias (see my buddy Jim Pickering's post for details on how to do this in Apache). After ensuring that I indeed DID have a proper mapping, I was STILL getting the error...dig dig some more. I finally came across a single, obscure tidbit that turned out to be the answer to the challenge:

 When retrieving and displaying data in a CFGRID via Ajax, your parent page must import the CFGRID library by adding the line: 

<cfajaximport tags="cfgrid" />

 

Typically you don't have to worry about importing any libraries, but in the case of utilizing Ajax to render the grid, you do. In my situation, I'm using Prototype to perform my Ajax calls, so I'm certain this scenario doesn't just apply to those using CF's built in Ajax functionality (and in fact, may not apply at all in that case! I don't know that for sure though).

Anyway, just wanted to post this in case it saves anybody else some time (and so I can reference it next time I run into this and have completely forgotten what the underlying cause is).

Doug out.

Posted by dougboude at 2:59 AM | PRINT THIS POST! | Link | 0 comments
03 July 2008
Basic Security in Fusebox 5.5.x (sans XML)
I have recently begun a project using the latest version of Fusebox (5.5.1). This is my second forray into Fusebox 5x, but the first one wasn't much more than a hello world for my own benefit. This time, I'm taking the "sans XML" approach and using FB in its MVC arrangement to build an application that is primarily a data management tool utilizing Java proxies exclusively as its means to communicate with a backend Oracle database. So, as I learn things along the way, I'm going to be sharing them as blog posts in order to possibly give others some stepping stones as they traverse their own FB "sans XML" J-curve.

I should also say that I am coming to Fusebox 5.5 after having exclusively used Model-Glue v2 for the past year and a half or so. Since one's natural approach is to try and equate what you already know from your current framework of choice to the one you are now learning, that is what I will be doing as well, so you may often see me reference things in Model-Glue terminology to help bridge the knowledge gap. In fact, one of the first things I did was to rename my fuseaction to "event", just to make me feel a little more at home. :)

Okay, so one of the first things I needed to create for this app was some basic security; if the user is not logged on, they don't get past the first page, period. Though there are always many solutions to the same challenge, following is my own approach to the matter.

Step 1 is find the best place within the Fusebox event lifecycle (which I STILL don't fully know, nor could I find any clear documentation on) in which to "intercept and potentially redirect" our call. Basically, before our user arrives at their destination page, we want to see if it is a secured page (which all of mine are except for the login) AND if the user has already successfully authenticated, then redirect them to the login page if needed.

In order to maintain the user's state (keep track of whether or not they logged in, store their personal info in a handy, globally available package), I created a User.cfc that I make sure has been instantiated with an initial 'loggedin' setting of false (this is built into the CFC's init method), and placed into the session scope. In Fusebox 5.5.1, the most appropriate place to do this that I found is in the Application.CFC's "onRequestStart" method. Mine looks like this:

<cffunction access="public" name="onRequestStart" output="false" returntype="void" hint="I am the code to execute at the beginning of a request. ">
    <cfargument name="targetPage" />
    <cfset super.onRequestStart(arguments.targetPage) />
    <!--- formerly in fusebox.init.cfm --->
    <cfset self = myFusebox.getSelf() />
    <cfset myself = myFusebox.getMyself() />

    <cfif not structkeyexists(session,"user")>
        <cfset session.user = createObject( 'component','model.user').init()/>
    </cfif>
   
    <!--- making our user object available in the event bean. Event is created by Fusebox and is available to us at this point. --->
    <cfset event.setValue("user",session.user) />
</cffunction>


Notice that we are doing a call to "super.onRequeststart". This is because our Application.cfc is extending (<cfcomponent extends="fusebox5.Application" output="false">) Fusebox's Application.cfc, so we need to make sure the framework gets to execute its onRequestStart as well. If we didn't make the 'super' call, our method would override FB's method and things just wouldn't go well at all.

Okay, so now with every request, I ensure that I have at LEAST an empty user object in session. The remainder of the onRequestStart method places my user object into a handly little bucket Fusebox provides us called (thankfully) 'Event'. This works very well for me, as in Model-Glue it's ALL ABOUT the event, my brutha from anotha mutha. By putting user into 'event', i can access it from anywhere else in my application WITHOUT having to talk directly to session ( a big OO No No, for the most part).

Now, the request still has not yet arrived at its destination page, and Fusebox has another file yet to process before it renders any content: Fusebox.init.cfm.

Though I tried madly to do all of my intercept and redirect within application.cfc, alas I could not make it work. Feedback from Mr. Corfield affirmed that indeed application.cfc was not the best place to do what I was trying to do, anyway, and directed me to fusebox.init.cfm as the most proper location to perform any needed manipulation of the target fuseaction. Here is the content of my fusebox.init.cfm file:

<!--- ************ SECURITY CHECK! ***************** --->
<!--- if we're not authenticated and our current fuseaction is NOT our default fuseaction (in order to avoid a dreaded infinite loop), make it so --->
<cfif (not structkeyexists(session,"user") OR not session.user.getLoggedin()) AND attributes.fuseaction IS NOT myFusebox.getApplication().defaultfuseaction>
    <!--- if user is not logged in, replace the current fuseaction/event name with our default --->
    <cfset myFusebox.relocate(url=myFusebox.getApplication().myself & myFusebox.getApplication().defaultfuseaction) />
</cfif>



As you can see, i'm doing a simple check of the user object and the target fuseaction. If the user isn't logged in (or user object doesn't exist for whatever reason) AND our target fuseaction is something OTHER than our default fuseaction (login), then we're leveraging the fusebox 'Relocate' method to force the user to our login page.

That's it, it's that simple. If I had to do fuseaction level security, or individual page security, I think I'd probably STILL perform those actions at these exact same locations, only I'd be adding in additional checks for the user's roles and the fuseaction's security level.

Feedback on my approach solicited. :)

Doug out

 

UPDATE TO PREVIOUS POST (7/9/08)

Based on the comments I received, I made a little time to pursue the route I had proposed for implementing role/fuseaction based security and found that I could do it easily without having to add any more controllers or fuseactions. Building on all of the code above, I simply added to my user object a 'Roles' variable that contains a list of the authenticated user's roles. I then added to my global configuration bean an item 'publicFuseActions' that contains a list of the fuseactions I am NOT securing (since those are far fewer than the ones I AM securing...I could've easily reversed the contents of this list to contain FAs that ARE secured). Lastly, I made a modification to the security check in my fusebox.init.cfm to evaluate the following:

(

the user is NOT logged in

OR

user IS logged in AND the requested fuseaction IS a secure one AND the authenticated user does NOT have the appropriate role

)

AND

our requested fuseaction is NOT our default fuseaction

If the entire statement above evaluates to true, then our user needs to be redirected to the login page.

Here is my fusebox.init.cfm that accomplishes the above logic:

 

<cfif ((not structkeyexists(session,"user") OR not session.user.getLoggedin()) OR (listfindnocase(application.globals.config.getConfigSetting("publicFAs"),attributes.fuseaction) eq 0 AND listfindnocase("Admin",session.user.getRoles()) eq 0)) AND attributes.fuseaction IS NOT myFusebox.getApplication().defaultfuseaction>
 <cfset myFusebox.relocate(url=myFusebox.getApplication().myself & myFusebox.getApplication().defaultfuseaction) />
</cfif>

 

Again, I have to ask what would be the motivation/need to create additional controllers and fuseactions to perform security/role based fuseaction routing when the single IF statement above, strategically placed, accomplishes it just fine? Am I over-simplifying things? (or is it really just that simple?  ) . If I wanted to get even more elaborate, such as routing based on role, or a diversity of messages to match the situation, I would probably add a message dictionary to my global config bean and replace my growing IF statement with a call to a global security object that would perform appropriate evaluations and return the needed responses for me to execute an appropriate redirect and message. One more object in my model that I create as a singleton and have available to my fusebox.init.cfm...why complicate it any more than that? Again, input solicited.

Doug out. again.

 

Posted by dougboude at 1:51 PM | PRINT THIS POST! | Link | 5 comments