No Persistent Variables After Refresh

16 views
Skip to first unread message

Brian H.

unread,
Jan 24, 2012, 1:48:41 AM1/24/12
to Mach-II for CFML
I've noticed that after a "persist" redirect where I get redirected
to:

http://site/route?persistId=....

My persisted arguments are there, however refreshing the page causes
no persisted argument population, even though the page URL -still-
contains the persistId.

Are persisted variables deleted after their first access? I thought
that they existed for the lifetime of the session.

Running <cfset MACHII_CONFIG_MODE = 0 />

-Brian

Peter J. Farrell

unread,
Jan 24, 2012, 1:49:51 AM1/24/12
to mach-ii-for...@googlegroups.com
Brian H. said the following on 01/24/2012 12:48 AM:

> Are persisted variables deleted after their first access?
Yes.

--
Peter J. Farrell
pe...@mach-ii.com
p...@maestropublishing.com
http://blog.maestropublishing.com
Identi.ca / Twitter: @maestrofjp

Brian H.

unread,
Jan 24, 2012, 12:56:30 PM1/24/12
to Mach-II for CFML
Really. Has this always been the case? Any particularly justification
as to why? This is worrying to me as I build my applications so that
non-action pages (listing screens, managers, etc) can be refreshed
without causing a problem. With these variables deleted after first
request, that is no longer possible.

Normally I've only persisted things such as response codes to show the
user a message, so refreshing would cause the message to disappear,
which wasn't a bit deal. However now I am persisting a special key
through my redirections, and the process would be broken if the user
ever refreshed.

Thoughts?

-Brian


On Jan 24, 1:49 am, "Peter J. Farrell" <pe...@mach-ii.com> wrote:
> Brian H. said the following on 01/24/2012 12:48 AM:> Are persisted variables deleted after their first access?
>
> Yes.
>
> --
> Peter J. Farrell
> pe...@mach-ii.com
> p...@maestropublishing.comhttp://blog.maestropublishing.com
> Identi.ca / Twitter: @maestrofjp

Peter J. Farrell

unread,
Jan 24, 2012, 1:01:32 PM1/24/12
to mach-ii-for...@googlegroups.com
Brian H. said the following on 01/24/2012 11:56 AM:

> Really. Has this always been the case? Any particularly justification
> as to why?
Yes, it has always acted in this way. Redirect persist is basically a
"flash" scope to fix the issue of not being able to do a redirect and
loosing the current request. Basically redirect persist is basically a
"faux" way to make two requests (initial one and the redirect) into
"one" request.

> This is worrying to me as I build my applications so that
> non-action pages (listing screens, managers, etc) can be refreshed
> without causing a problem. With these variables deleted after first
> request, that is no longer possible.
>
> Normally I've only persisted things such as response codes to show the
> user a message, so refreshing would cause the message to disappear,
> which wasn't a bit deal. However now I am persisting a special key
> through my redirections, and the process would be broken if the user
> ever refreshed.

Put that key in the URL. Use the "args" attribute of <redirect> or the
args argument of RedirectEvent() to stick an additional key in the URL.

.pjf

Brian H.

unread,
Jan 24, 2012, 4:49:02 PM1/24/12
to Mach-II for CFML
True, until I have multiple elements that should NOT appear in the URL
(like sensitive keys, status messages, etc) and which were nicely
obfuscated by M2's persistID. I guess it looks like it makes more
sense to use my own persistence system and do as you are saying,
expose that ID in the URL.

-Brian
> p...@maestropublishing.comhttp://blog.maestropublishing.com
> Identi.ca / Twitter: @maestrofjp

Peter J. Farrell

unread,
Jan 24, 2012, 5:05:30 PM1/24/12
to mach-ii-for...@googlegroups.com
Brian H. said the following on 01/24/2012 03:49 PM:

> True, until I have multiple elements that should NOT appear in the URL
> (like sensitive keys, status messages, etc) and which were nicely
> obfuscated by M2's persistID. I guess it looks like it makes more
> sense to use my own persistence system and do as you are saying,
> expose that ID in the URL.
I use a filter that pulls information from the session scope from an
event arg that comes from the URL. Here's a sample:

<!---
Notes:
* Uses the "id" key in the url

Params:
elementProperty = Name of the event-arg to place the data into
redirectEvent = The event to redirect to if there is no active ID element
--->
<cfcomponent
displayname="getElementByIdFilter"
extends="MachII.framework.EventFilter"
depends="sessionFacade,udfs"
output="false"
hint="Gets elements from the session facade by id.">

<!---
PUBLIC FUNCTIONS
--->
<cffunction name="filterEvent" access="public" returntype="boolean"
output="false"
hint="Runs the filter event.">
<cfargument name="event" type="MachII.framework.Event" required="true" />
<cfargument name="eventContext" type="MachII.framework.EventContext"
required="true" />
<cfargument name="paramArgs" type="struct" required="true" />

<cfset var id = arguments.event.getArg("id", "") />

<!--- Get the bean if it is defined --->
<cfif getUdfs().isUUID(id) AND getSessionFacade().isElementByIdDefined(id)>
<cfset arguments.event.setArg(arguments.paramArgs.elementProperty,
getSessionFacade().getElementById(id)) />
<cfreturn TRUE />
<cfelse>
<cfset RedirectEvent(arguments.paramArgs.redirectEvent) />
<cfreturn FALSE />
</cfif>
</cffunction>

</cfcomponent>

Session Facade:

<cffunction name="formatUUID" access="private" returntype="string"
output="false"
hint="Formats a uuid into a safe format to as a variable.">
<cfargument name="id" type="uuid" required="true" />
<cfreturn "_" & Replace(arguments.id, "-", "_", "ALL") />
</cffunction>

<cffunction name="isElementsDefined" access="public"
returntype="boolean" output="false">
<cfreturn IsDefined("session.user.elementsById") />
</cffunction>
<cffunction name="setupElements" access="private" returntype="void"
output="false"
hint="Setups the elements service.">
<cfset session.user.elementsById.lastCleanup = DateConvert("local2UTC",
Now()) />
<cfset session.user.elementsById.data = StructNew() />
<cfset session.user.elementsById.timestamps = StructNew() />
</cffunction>

<cffunction name="cleanupElements" access="private" returntype="void"
output="false"
hint="Cleans up left over elements.">

<cfset var sorted = "" />
<cfset var datetime = DateConvert("local2UTC", Now()) />
<cfset var i = "" />

<!--- Check if cleanup if is required and do double lock --->
<cfif DateDiff("s", getElementLastCleanup(), datetime) GTE 600>
<cflock name="sessionFacade_cleanupElements_#session.cfid#" timeout="1"
throwontimeout="false">
<cfif DateDiff("s", getElementLastCleanup(), DateConvert("local2UTC",
Now())) GTE 600>

<!--- Reset the last cleanup --->
<cfset resetElementLastCleanup() />

<!--- Get sorted list --->
<cfset sorted = StructSort(session.user.elementsById.timestamps, "text",
"ASC") />

<!--- Loop through and delete --->
<cfif ArrayLen(sorted)>
<cfloop from="1" to="#ArrayLen(sorted)#" index="i">
<cfif DateDiff("s", sorted[i], datetime) GTE 1800>
<cfset StructDelete(session.user.elementsById.data,
session.user.elementsById.timestamps[sorted[i]], FALSE) />
<cfset StructDelete(session.user.elementsById.timestamps, sorted[i],
FALSE) />
<cfelse>
<cfbreak />
</cfif>
</cfloop>
</cfif>
</cfif>
</cflock>
</cfif>
</cffunction>

<cffunction name="resetElementLastCleanup" access="private"
returntype="void" output="false">
<cfset session.user.elementsById.lastCleanup = DateConvert("local2UTC",
Now()) />
</cffunction>
<cffunction name="getElementLastCleanup" access="public"
returntype="date" output="false">
<cfreturn session.user.elementsById.lastCleanup />
</cffunction>

<cffunction name="getElementCount" access="public" returntype="numeric"
output="false">
<cfreturn StructCount(session.user.elementsById.data) />
</cffunction>

<cffunction name="makeElementTimestamp" access="private"
returntype="void" output="false"
hint="Makes a timestamp for element. Deletes old keys.">
<cfargument name="id" type="uuid" required="true" />

<cfset var stamps =
StructFindValue(session.user.elementsById.timestamps,
formatUUID(arguments.id), "ALL") />
<cfset var i = "" />

<cfloop from="1" to="#ArrayLen(stamps)#" index="i">
<cfset StructDelete(session.user.elementsById.timestamps, stamps[i].key,
FALSE) />
</cfloop>

<cfset session.user.elementsById.timestamps[DateConvert("local2UTC",
Now())] = formatUUID(arguments.id) />
</cffunction>

Reply all
Reply to author
Forward
0 new messages