Take the 2-minute tour ×
Salesforce Stack Exchange is a question and answer site for Salesforce administrators, implementation experts, developers and anybody in-between. It's 100% free, no registration required.

The documentation says that using the transient keyword on properties will keep them out of the view state, but my testing seems to show otherwise. How can I exclude this property from the view state?

Example of smallest view state (0.86kb internal):

// ViewStateProblems.cls
public class ViewStateProblems {
}

// ViewStateProblems.page
<apex:page controller="ViewStateProblems">
    <apex:form ></apex:form> <!-- remove the form and view state goes away -->
</apex:page>

Example showing a table of records with no view state (0kb):

// ViewStateProblems.cls
public class ViewStateProblems {
    public List<Case> getCases(){
        return [select CaseNumber, OwnerId, ContactId from Case limit 1000];
    }
}

// ViewStateProblems.page
<apex:page controller="ViewStateProblems">
    <apex:pageBlock >
        <apex:pageBlockTable value="{!cases}" var="c">
            <apex:column value="{!c.CaseNumber}"/>
            <apex:column value="{!c.OwnerId}"/>
            <apex:column value="{!c.ContactId}"/>
        </apex:pageBlockTable>
    </apex:pageBlock>
</apex:page>

Turning on view state by just adding a form to the page. Note, my cases object is not in the form tags (internal view state of 26.02):

// ViewStateProblems.cls
public class ViewStateProblems {
    public List<Case> getCases(){
        return [select CaseNumber, OwnerId, ContactId from Case limit 1000];
    }
}

// ViewStateProblems.page
<apex:page controller="ViewStateProblems">
    <apex:pageBlock >
        <apex:pageBlockTable value="{!cases}" var="c">
            <apex:column value="{!c.CaseNumber}"/>
            <apex:column value="{!c.OwnerId}"/>
            <apex:column value="{!c.ContactId}"/>
        </apex:pageBlockTable>
    </apex:pageBlock>
    <apex:form> maybe create new case here </apex:form>
</apex:page>

Picture of view state (I don't yet sufficient karma to upload photos): http://cl.ly/image/1N183P2C3D3W

Here I make a version using the transient keyword on the cases property but it has no effect on the view state size (internal view state of 26.02):

// ViewStateProblems.cls
public class ViewStateProblems {
    public transient List<Case> cases {get; private set;} {
        cases = [select CaseNumber, OwnerId, ContactId from Case limit 1000]; 
    }
}

// ViewStateProblems.page
<apex:page controller="ViewStateProblems">
    <apex:pageBlock >
        <apex:pageBlockTable value="{!cases}" var="c">
            <apex:column value="{!c.CaseNumber}"/>
            <apex:column value="{!c.OwnerId}"/>
            <apex:column value="{!c.ContactId}"/>
        </apex:pageBlockTable>
    </apex:pageBlock>
    <apex:form> maybe create new case here </apex:form>
</apex:page>

Shouldn't that example using the transient keywork have had the same internal view state size as the first form example of only 0.86kb? If not, how can I stop the cases property from being sent in view state?

share|improve this question
add comment

4 Answers

up vote 3 down vote accepted


The Salesforce documentation states that using transient keyword will reduce the view state, but it also states that it stores some of VF data for housekeeping. To reduce the view state size please try the below code.

<apex:pageBlock >
        <table cellspacing="0" cellpadding="0" border="0" id="searchResults" class="list">
             <thead class="rich-table-thead">
                 <tr class="headerRow">
                     <th>Case Number</th>
                     <th>Case Owner</th>
                     <th>Contact Name</th>
                 </tr>
             </thead>
             <tbody>
                 <apex:repeat value="{!cases}" var="c">
                     <tr onfocus="if (window.hiOn){hiOn(this);}" onblur="if (window.hiOff){hiOff(this);}" onmouseout="if (window.hiOff){hiOff(this);} " onmouseover="if (window.hiOn){hiOn(this);} " class="dataRow even  first">
                         <td class="dataCell">{!c.CaseNumber}</td>
                         <td class="dataCell">{!c.OwnerId}</td>
                         <td class="dataCell">{!c.ContactId}</td>
                     </tr>
                 </apex:repeat>
             </tbody>
         </table>
     </apex:pageBlock> 
   <apex:form > maybe create new case here </apex:form>  

Here we are replacing pageblocktable with a html table. In my observation pageblocktable seems to consume a big part of Internal view state. Using the above code will reduce around 45-48% view state.

share|improve this answer
    
I tested this code, and indeed it reduces the view state by a massive amount. This question was posed because I have a much bigger page with nested tables that is hitting the view state limit with a couple hundred records... and this is getting me the closes to solving this problem. –  James Sullivan Feb 8 '13 at 6:08
    
Please have a look here salesforce.stackexchange.com/questions/4537/…. Nicely Explained!! –  Avidev9 Feb 8 '13 at 6:10
add comment

The viewstate contains all the information that needs to be moved from the controller back to the page. Using transient on a property that is used in your page is of no help as you want that information and so the system sends it down as it should do so you can see it.

If you declare a private member in your controller and initialised it with a huge string you'll see your view state size increase. If you then add transient you'll see it go down again as that string value will not longer be passed back and forth on each request.

I don't know for sure but I suspect that in the setup you've described here, although your value is in the view state so the records can be displayed on the page, I doubt any values are sent back to the system in the next request.

Long story short, values for properties you need on the page will always be in the viewstate. The transient keyword is to indicate to the system which information can be discarded when a request is completed because you won't need it in the next one.

share|improve this answer
    
If I add the readOnly property to the page tag, the view state goes away... which sounds contradictory to the logic about all displayed objects needing to be in view state. –  James Sullivan Feb 8 '13 at 5:46
    
Upon rereading your text, it sounds like your impression of the view state is that it contains all the data displayed in the page and that the page is not rendered at all server-side. Am I interpreting that correctly? –  James Sullivan Feb 8 '13 at 6:02
    
Yes I believe that is the case, though your use of readonly definitely has some interesting insights. If the page is read only no state information will ever need to come back to the server, however in your scenario it would appear that without that prerequisite the server assumes that the data may be needed later down the track even though you're not writing to the property in question. –  LaceySnr Feb 8 '13 at 6:11
add comment

The docs contain a nicely informative summary of the ingredients of the view state:

The data in the view state should be sufficient to recreate the state of the page when the postback is received. To do this, it stores the following data:

All non-transient data members in the associated controller (either standard or custom) and the controller extensions.

Objects that are reachable from a non-transient data member in a controller or controller extension.

The component tree for that page, which represents the page's component structure and the associated state, which are the values applied to those components.

A small amount of data for Visualforce to do housekeeping.

View state data is encrypted and cannot be viewed with tools like Firebug. The view state inspector described below lets you look at the contents of view state.

So due to #3 above, you can't ever prevent values that are applied to components from being sent in view state, because they are required by the design of Visualforce views.

share|improve this answer
    
Where is the cases property being accessed from a non-transient member? Adding the attribute readOnly to the page tag will remove the state, but trying it on other pages it doesn't seem to work on all pages. My main goal is to slim down my state and make the page fast when displaying big tables of records. –  James Sullivan Feb 8 '13 at 5:42
    
Sorry, I was referring to the third bullet point (fourth paragraph) - "The component tree for that page" which includes the values applied to those components. i.e. wherever you bind values to components, they will end up in view state no matter what. –  jkraybill Feb 8 '13 at 5:58
    
That doesn't happen, though, when I use the readOnly attribute in the page tag. They talk about trimming view state by using the transient keyword but your description makes it sound like transient does not have impact on trimming down the view state with regards to the governor limit, but only with regards to the data coming back to the server on post. –  James Sullivan Feb 8 '13 at 6:00
add comment

The following code will remove the setter and thus remove the cases property from the viewstate.

// ViewStateProblems.cls
public class ViewStateProblems {
    public List<Case> getcases() {
        return [select CaseNumber, OwnerId, ContactId from Case limit 1000]; 
    }
}
share|improve this answer
    
That's what I assumed, but that code (my 3rd example) creates a view state. –  James Sullivan Feb 8 '13 at 5:44
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.