+ Start a Discussion
Jason Kuzmak 12Jason Kuzmak 12 

why is my visualforce page view state so much larger for other users?

Hi all,

There are probably steps I can look into to further optimize my visualforce page, but before I start into that, I'm wondering if it's not some sort of browser issue.

 

When I look at my view state size in the developer window it says 79KB. When my field tech tries to open it, it says that the view state has exceeded the limit of 170KB, and is 194KB instead. Why would it be more than 100KB larger when another viewer tries to access it? 

 

Best Answer chosen by Jason Kuzmak 12
Dushyant SonwarDushyant Sonwar
It may be because of sharing rules  , one user has limited access and other user might have full access so the query returning more data and giving you view state error.

Hope this helps.

All Answers

Dushyant SonwarDushyant Sonwar
It may be because of sharing rules  , one user has limited access and other user might have full access so the query returning more data and giving you view state error.

Hope this helps.
This was selected as the best answer
Jason Kuzmak 12Jason Kuzmak 12

@Dushyant Sonwar 

Unfortunately, I'm the admin and would have access to more of the information than the technician who is receiving the error. 

Dushyant SonwarDushyant Sonwar
HI Jason ,

There might be custom data rendering/filtering logic for specific user profile/roles on vf pages or apex class.
It would be helpful if you post your vf and apex code.

Thanks,
 
Jason Kuzmak 12Jason Kuzmak 12

Hi Dushyant,

No problem, and thanks!

For some context, the structure of this custom checklist object is that a guy in our engineering department creates items for the checklist through the template object (Checklist_Template_Item__c), but these items don't get queried until a specific machine is being serviced, since each item applies to several (but not all) machines. In this way he can create a single item, and just tell the system what machines it applies to. They get populated and attached to Salesforce's WorkOrderLineItem records as Checklist_Item__c object records, and are displayed in their respective Checklist_Section__c using <apex:repeat>. 

 

Here is the visualforce code:

<apex:page standardController="Checklist__c" extensions="ChecklistExtension">
    
    <html>
        <style>
        red{
            color: red;
        }
        nowrap{
            white-space: nowrap;
        }
        </style>
    </html>
    
    <apex:pagemessages />
    
    <apex:form >
        <apex:variable var="sectionMap" value="{!sectionItemListMap}"/>
        <apex:variable var="itemMasterList" value="{!myItemList}"/>
        <apex:variable var="checklist" value="{!myChecklist}"/>
        <apex:pageBlock title="{!checklist.Name}">
        
            <apex:pageBlockButtons location="both">
                <apex:commandButton value="Verify" action="{!verify}"/>
                <apex:commandButton value="Save" action="{!saveCust}"/>
                <apex:commandButton value="Quick Save" action="{!quickSaveCust}"/>
                <apex:commandButton value="Cancel" action="{!cancel}"/>
            </apex:pageBlockButtons>
            <apex:pageBlockSection columns="1">
                <strong>Notice:</strong> all fields with a red asterisk (<red> * </red>) will be required to <strong>submit</strong> this record, but will not be required to save it. 
            </apex:pageBlockSection>
            <apex:pageBlockSection columns="2" collapsible="false">
            
                <apex:repeat value="{!sectionList}" var="section">
                    <apex:pageBlock title="{!section.Name}" >
                        <apex:repeat value="{!itemMasterList}" var="item" id="itemRepeat">
                            <apex:variable value="{!section.Name == item.Checklist_Section__r.Name}" var="showIfMatch"/>
                            
                            <apex:outputPanel rendered="{!showIfMatch}">
                                <p style="text-indent:5em">
                                    <apex:outputText title="highlighted objective" rendered="{!item.Highlight__c == true}">
                                        <red><strong>{!item.Objective__c}</strong></red>
                                    </apex:outputText>
                                    <apex:outputText title="standard objective" rendered="{!item.Highlight__c == false}">
                                        {!item.Objective__c}
                                    </apex:outputText>
                                </p>
                                <br/>
                                <apex:dataTable value="{!item}" var="placeHolder" styleClass="tableClass" width="80%" align="center" cellpadding="5px" border="True" >
                                    <apex:column >
                                        <apex:dataTable value="{!item}" var="itemTable">
                                            <apex:column >
                                                <red>* </red>
                                                <apex:outputText value="Checked"/>
                                            </apex:column>
                                            <apex:column >
                                                <apex:inputCheckbox value="{!itemTable.Checked__c}"  disabled="{!item.CheckedAvailable__c == false}" required="true"/>
                                            </apex:column>
                                        </apex:dataTable>
                                    </apex:column>
                                    <apex:column >
                                         <apex:dataTable value="{!item}" var="itemTable">
                                            <apex:column >
                                                <apex:outputText rendered="{!item.Replaced_Required__c}">
                                                    <red>* </red>
                                                </apex:outputText>
                                                <apex:outputText value="Replaced"/>
                                            </apex:column>
                                            <apex:column >
                                                <apex:inputCheckbox value="{!itemTable.Replaced__c}"  disabled="{!item.ReplacedAvailable__c == false}"/>
                                            </apex:column>
                                        </apex:dataTable>
                                    </apex:column>
                                    <apex:column >
                                         <apex:dataTable value="{!item}" var="itemTable">
                                            <apex:column >
                                                <apex:outputText value="Oiled"/>
                                            </apex:column>
                                            <apex:column >
                                                <apex:inputCheckbox value="{!itemTable.Oiled__c}"  disabled="{!item.OiledAvailable__c == false}"/>
                                            </apex:column>
                                        </apex:dataTable>
                                    </apex:column>
                                    <apex:column >
                                         <apex:dataTable value="{!item}" var="itemTable">
                                            <apex:column >
                                                <apex:outputText value="N/A"/>
                                            </apex:column>
                                            <apex:column >
                                                <apex:inputCheckbox value="{!itemTable.N_A__c}"  disabled="{!item.NAavailable__c == false}"/>
                                            </apex:column>
                                        </apex:dataTable>
                                    </apex:column>
                                </apex:dataTable>
                                <br/>
                            </apex:outputPanel>
                        </apex:repeat>
                    </apex:pageBlock>
                </apex:repeat>
            </apex:pageBlockSection>
        </apex:pageBlock>
    </apex:form>
</apex:page>

Here is the controller:
public class ChecklistExtension{
    // This Visualforce page extension will load data from a pre-built checklist record.
    
    
    public Checklist__c myChecklist{get;set;}
    public List<Checklist_Item__c> myItemList{get;set;}
    public List<Checklist_Section__c> sectionList{get;set;}
    public Map<String, List<Checklist_Item__c>> sectionItemListMap{get;set;}
        
    // I need to list the related checklist items that have already been queried and populated for this checklist
    
    public ChecklistExtension(ApexPages.StandardController stdController){
        this.myChecklist = (Checklist__c)stdController.getRecord();
        
        if(myChecklist.id != null){
            myChecklist = [Select Id, Is_Complete__c, Name From Checklist__c Where Id = :myChecklist.Id];
        }
        
        List<Checklist_Item__c> itemList = [Select Id, Checklist__c, Objective__c, Checked__c, CheckedAvailable__c, N_A__c, NAavailable__c, Oiled__c, OiledAvailable__c, Replaced__c, ReplacedAvailable__c,
                                               Sort_Order__c, Checklist_Section__c, Checklist_Section__r.Sort_Order__c, Checklist_Section__r.Name, Name, Replaced_Required__c, Highlight__c
                                          From Checklist_Item__c
                                             Where Checklist__c = :myChecklist.Id];
        
        // map ascending integer values to sections in order
        
        Set<Decimal> sectionSortValueSet = new Set<Decimal>();
        // this maps an ascending integer value to each sort order.
        Map<Integer,Decimal> integerSectionSortMap = new Map<Integer,Decimal>();
        // this maps each sort order with its corresponding section.
        Map<Decimal,Checklist_Section__c> sortSectionMap = new Map<Decimal,Checklist_Section__c>();
        
        
        
        // map items to their respective sections' sort orders
        Map<Decimal,List<Checklist_Item__c>> sectionItemListPrepMap = new Map<Decimal,List<Checklist_Item__c>>();
        Integer itemListSize = itemList.size();
        Integer itemCounter = 0;
        for(Checklist_Item__c ci : itemList){
            // un-highlight everything
            ci.Highlight__c = false;
            
            ++itemCounter;
            // check current item's section sort number against prior values
            if(!sectionSortValueSet.contains(ci.Checklist_Section__r.Sort_Order__c)){
                sectionSortValueSet.add(ci.Checklist_Section__r.Sort_Order__c);
            }
            
            // when we hit the last item in the list, THEN iterate over your section list
            if(itemCounter == itemListSize){
                if(sectionSortValueSet.size() > 0){
                    List<Decimal> sectionSortValueList = new List<Decimal>();
                    sectionSortValueList.addAll(sectionSortValueSet);
                    sectionSortValueList.sort();
                    
                    for(Integer i = 0; i < sectionSortValueList.size(); ++i){
                        integerSectionSortMap.put(i,sectionSortValueList.get(i));
                        System.debug('integerSectionSortMap = '+integerSectionSortMap);
                    }
                    
                }
            }
            // end section sort 
            
            List<Checklist_Item__c> currentSubList = new List<Checklist_Item__c>();
            // if list has already begun being populated, get partial list from map
            if(sectionItemListPrepMap.containsKey(ci.Checklist_Section__r.Sort_Order__c)){
                currentSubList = sectionItemListPrepMap.get(ci.Checklist_Section__r.Sort_Order__c);
            }
            
            currentSubList.add(ci);
            sectionItemListPrepMap.put(ci.Checklist_Section__r.Sort_Order__c,currentSubList);
        }           
        
        List<Checklist_Item__c> prepItemList = new List<Checklist_Item__c>();
        
        // build sections and add them to list based on queried data from Checklist Items
        List<Checklist_Section__c> prepSectionList = new List<Checklist_Section__c>();
        Set<String> hitSections = new Set<String>();
        for(Integer i = 0; i < integerSectionSortMap.size(); ++i){
            // iterate through the checklist sections in order
            Decimal currentSectionNumber = integerSectionSortMap.get(i);
            List<Checklist_Item__c> currentItemList = sectionItemListPrepMap.get(currentSectionNumber);
            
            // sort items into a list based not only on their own order, but their sections' order
            List<Decimal> itemSortOrderList = new List<Decimal>();
            // sort individual items in section's list
            Integer currentListSize = currentItemList.size();
            itemCounter = 0;
            Map<Integer,Decimal> integerSortOrderMap = new Map<Integer,Decimal>();
            Map<Decimal,Checklist_Item__c> sortOrderItemMap = new Map<Decimal,Checklist_Item__c>(); 
            for(Checklist_Item__c ci : currentItemList){
                
                ++itemCounter;
                
                // throw section name into the hit name set
                if(!hitSections.contains(ci.Checklist_Section__r.Name)){
                    hitSections.add(ci.Checklist_Section__r.Name);
                    Checklist_Section__c newSection = new Checklist_Section__c(
                        Name = ci.Checklist_Section__r.Name,
                        Sort_Order__c = ci.Checklist_Section__r.Sort_Order__c,
                        Id = ci.Checklist_Section__c
                    );
                    prepSectionList.add(newSection);
                }
                
                System.debug('itemCounter = '+itemCounter);
                System.debug('putting sort order of '+ci.Sort_Order__c+' into map, along with its item: '+ci);
                sortOrderItemMap.put(ci.Sort_Order__c,ci);
                if(itemCounter == currentListSize){
                    System.debug('itemCounter matched currentListSize of '+currentListSize);
                    itemSortOrderList.addAll(sortOrderItemMap.keySet());
                }
            }
            if(itemSortOrderList.size() > 0){
                itemSortOrderList.sort();
                // apply each order number its own ascending integer value
                for(Integer ii = 0; ii < itemSortOrderList.size(); ++ii){
                    integerSortOrderMap.put(ii,itemSortOrderList.get(ii));
                    System.debug('this sort order was applied to integerSortOrderMap: '+itemSortOrderList.get(ii));
                }
                
                // run through checklist again and apply each item from currentItemList to master item list by getting it, in order, from maps
                
                for(Integer ii = 0; ii < currentListSize; ++ii){
                    Decimal currentSort = integerSortOrderMap.get(ii);
                    System.debug('currentSort = '+currentSort);
                    
                    Checklist_Item__c currentItem = sortOrderItemMap.get(currentSort);
                    // apply to master item list
                    System.debug('currentItem = '+currentItem);
                    prepItemList.add(currentItem);
                }
            }
        }
        
        System.debug('prepSectionList.size() = '+prepSectionList.size());
        System.debug('prepItemList.size() = '+prepItemList.size());
        
        myItemList = prepItemList;
        sectionList = prepSectionList;
        
    }
    
    
    public ApexPages.PageReference saveCust(){
        ApexPages.StandardController thisController = new ApexPages.StandardController(myChecklist);
        System.debug('myItemList.size() = '+myItemList.size());
        Integer completeCounter = 0;
        if(myItemList.size() > 0){
          for(Checklist_Item__c ci : myItemList){
              // 4-2-2019: Per Chris Steiner, every item must at least be "Checked"
              if(ci.Checked__c == true || ci.Replaced__c == true || ci.Oiled__c == true || ci.N_A__c == true){
                  ++completeCounter;
              }
              if(ci.Checked__c == false){
                  --completeCounter;
              }
              if(ci.Replaced_Required__c == true && ci.Replaced__c == false){
                  --completeCounter;
              }
              // un-highlight all items on save
              ci.Highlight__c = false;
          }
          
          Boolean shouldUpdate = false;
          
          // if the number of completed items 
          if(completeCounter == myItemList.size()){
              if(myChecklist.Is_Complete__c == false){
                  myChecklist.Is_Complete__c = true;
                  shouldUpdate = true;
              }
          }
          else{
              if(myChecklist.Is_Complete__c == true){
                  myChecklist.Is_Complete__c = false;
                  shouldUpdate = true;
              }
          }
          
          if(shouldUpdate == true){
              update myChecklist;     
          }
          
          update myItemList;
        }
        
        return thisController.view();
    }
    
    public ApexPages.PageReference quickSaveCust(){
        ApexPages.StandardController thisController = new ApexPages.StandardController(myChecklist);
        System.debug('myItemList.size() = '+myItemList.size());
        Integer completeCounter = 0;
        
        for(Checklist_Item__c ci : myItemList){
            // 4-2-2019: Per Chris Steiner, every item must at least be "Checked"
            if(ci.Checked__c == true || ci.Replaced__c == true || ci.Oiled__c == true || ci.N_A__c == true){
                ++completeCounter;
            }
            if(ci.Checked__c == false){
                --completeCounter;
            }
            if(ci.Replaced_Required__c == true && ci.Replaced__c == false){
                --completeCounter;
            }
        }
        
        Boolean shouldUpdate = false;
        
        // if the number of completed items 
        if(completeCounter == myItemList.size()){
            if(myChecklist.Is_Complete__c == false){
                myChecklist.Is_Complete__c = true;
                shouldUpdate = true;
            }
        }
        else{
            if(myChecklist.Is_Complete__c == true){
                myChecklist.Is_Complete__c = false;
                shouldUpdate = true;
            }
        }
        
        if(shouldUpdate == true){
            update myChecklist;     
        }
        
        update myItemList;
        return null;
    }
    
    public ApexPages.PageReference verify(){
    ApexPages.StandardController thisController = new ApexPages.StandardController(myChecklist);
    System.debug('myItemList.size() = '+myItemList.size());
    for(Checklist_Item__c ci : myItemList){
        if(ci.Checked__c == false || (ci.Replaced_Required__c == true && ci.Replaced__c == false)){
            ci.Highlight__c = true;
        }
        if(ci.Checked__c == true){
            if((ci.Replaced_Required__c == true && ci.Replaced__c == true) || ci.Replaced_Required__c == false){
                ci.Highlight__c = false;
            }
        }
    }
    
    update myItemList;
    return null;
    } 
}

 
Dushyant SonwarDushyant Sonwar
Hi Jason ,

You can reduce the view state , just replacing the apex:datatable with html table. Plus you have nested data so i think that also putting more weight on your vf page.

If still view state is exceeding after datatable replacement , then you need to flat out your data to avoid nesting wherever there is possiblity to reduce nesting of data.

 
Jason Kuzmak 12Jason Kuzmak 12

Hi Dushyant,

Your first suggestion worked!! I had originally started with HTML tables, and was unwilling to try to make that work again X)

Sorry to make you wade through all of my code; I gave my test user permission to the Checklist Section object, and that seems to have done the trick.