volume one
volume one

Reputation: 7573

How to display <cfreturn> output from a CFC being called from a form

I have a web form which uses the action attribute to call a CFC like this:

<form action="mycfc.cfc?method=registeruser">

The CFC processes the data in the form and then I want it to return a variable telling the user if their form submission has been successful or not.

So within my CFC, I put this:

<cffunction name="registeruser" access="remote" hint="registers a new user" returnformat="JSON">
... PROCESSES FORM HERE THEN...    
<cfset Msg = 'Success'>
<cfreturn Msg>
<cflocation url = "/registrationpage.cfm">
</cffunction>

How do I display the Msg variable in the registrationpage.cfm page? My output is set to JSON so I guess I have to DeSerialize but I have no idea how to actually reference/access this output from the method.

Upvotes: 1

Views: 2557

Answers (2)

plalx
plalx

Reputation: 43728

My whole answer is for educationnal purposes only and I strongly advise you to use an existing framework rather than reinventing the Wheels. Have a look at Picking a ColdFusion MVC Framework

You can store the value in the session scope. A lot of frameworks does it using a flash memory concept, which is a temporary memory (implemented as a struct) that destroys members when accessed.

Have a look at http://cfwheels.org/docs/1-1/chapter/using-the-flash it's quite straight forward to implement an API that does this.

Client code could look like (depending on your implementation):

<cfset session.flash.set('importantMsg', 'some important msg')>
<cflocation ...>

Then from the other page:

<cfif session.flash.has('importantMsg')>
    <!--- The following line should also destroy the 'importantMsg' key --->
    #session.flash.get('importantMsg')#
</cfif>

Here's an implementation example (not that the implementation is not thread-safe):

FlashMemory.cfc

<cfcomponent>
    <cffunction name="init" returntype="FlashMemory">
        <cfset variables.instance = {flash = {}}>
    </cffunction>

    <cffunction name="set" returntype="void">
        <cfargument name="key" type="string" required="true">
        <cfargument name="value" type="any" required="true">

        <cfset variables.instance.flash[arguments.key] = arguments.value>
    </cffunction>

    <cffunction name="get" returntype="any">
        <cfargument name="key" type="string" required="true">
        <cfset var v = variables.instance.flash[arguments.key]>
        <cfset structDelete(variables.instance.flash, arguments.key)>
        <cfreturn v>
    </cffunction>

    <cffunction name="has" returntype="boolean">
        <cfargument name="key" type="string" required="true">
        <cfreturn structKeyExists(variables.instance.flash, arguments.key)>
    </cffunction>
</cfcomponent>

onSessionStart

<cfset session.flash = new FlashMemory()>

Also please note that in your case, your remote CFC methods shouldn't return anything. You will use the flash memory to pass data around instead. That means when the method has finished it's work you can simply redirect the client.

You probably shouldn't use remote CFC methods in this particular case:

I have never really used remote CFC methods as stateful web services. The various advantages of remote CFC methods like their ability to spit out data in multiple data-interchange formats (JSON, WDDX...) is lost with your implementation.

You could simply do something like:

registration.cfm

<cfset errors = session.flash.get('registrationErrors')>

<cfif arrayLen(errors)>
    <!--- Display errors --->
</cfif>

<form method="post" action="register.cfm">
...
</form>

register.cfm

<cfset registration = new Registration(argumentcollection = form)>
<cfset validator = new RegistrationValidator(registration)>

<cfif validator.validate()>
    <cfset application.userService.register(registration)>

    <!--- You can also redirect to a page that represents the correct state --->
    <cflocation url="registered.cfm" addtoken="no">
<cfelse>
    <!--- Store the errors collection in the flash memory --->
    <cfset session.flash.set('registrationErrors', validator.errors())>

    <!--- Redirect to the page the user came from --->
    <cflocation url="#cgi.http_referer#" addtoken="no">
</cfif>

Upvotes: 3

Dan Bracuk
Dan Bracuk

Reputation: 20804

Take the cflocation tag out of your function. It will not execute anyway because it's after the cfreturn tag.

Also, post your form to a .cfm page, not the .cfc. From that .cfm page, do this:

<cfset MyObject = CreateObject(stuff for your cfc goes here)>
<cfset MessageFromFunction = MyObject.registeruser()>
<cfoutput>#MessageFromFunction</cfoutput.

Upvotes: 2

Related Questions