[SalesForce] Viewstate Issue: Unable to clear attachments if there are any failures in the transaction

I have a simple page with an inputText, inputFIle and a command button component. InputText capture a decimal value. Clicking on save, I am clearing the attachment object but lets say something else fails in the transaction then the attachment is not nullified and I get a view state error.

Lets say I enter an invalid decimal 4,000 in the input, upload a 1 MB file and click on save, I get Maximum view state size limit (135KB) exceeded. Actual view state size for this page was 1,043.156KB. Can anyone please explain why the attachment object is transmitting back to the page even when I am clearly nullifying it immediately on click on save?

public class ViewStateClass{
    public decimal amount{get;set;}
    public attachment attach{get;set;}
    public transient list<attachment> attachmentList{get;set;}

    public ViewStateClass(){
        attach = new Attachment();
        iniAttachList();
    }

    public void iniAttachList(){
        attachmentList= new List<Attachment>();
        attachmentList.add(new attachment());
        attachmentList.add(new attachment());
        attachmentList.add(new attachment());

    }

    public pagereference save(){
        attach = null;
        try{
            decimal calculatedValue = calc();
            attach = null;
        }catch(exception e){
            attach = null;
        }

        return null;
    }

    public decimal calc(){
        if(amount>0){
        //do something.
           amount++;
           return amount;
        }else{
            return 0;
        }
    }

}

Page:

<apex:page controller="ViewStateClass" docType="html-5.0">
    <apex:form >
        <apex:pageMessages />
        <apex:pageBlock >
            <apex:inputtext value="{!amount}"/>
            <apex:inputFile value="{!attach.body}"/>
            <apex:commandButton action="{!save}" value="save"/>
            <apex:pageBlockTable value="{!attachmentList}" var="att">
                <apex:column headerValue="upload files">
                    <apex:inputFile value="{!att.body}"/>
                </apex:column>
            </apex:pageBlockTable>
        </apex:pageBlock>
    </apex:form>
</apex:page>

Making the attach object transient doesn't throw any view state error, but in real scenario I have a list which I am passing to the page, initially adding only 3 dummy attachment objects to it. But when I submit the page and something fails the list is not reinitialized causing the table to be blank when the page reloads. Any idea how to reinitialize the list?

Update:

Updated the code, Now if we add '4,000' and upload the file in any of the inputfile from the table and hit on save the page refreshes with the error message but the table itself is not available and since the list is transient, we can initialize it. Let me know if there's a way to it?

Best Answer

The validation of the amount field is done before the save action is executed. If you add some debugging to the save action you will see that it never gets executed. The view state is being used to recreate the page with the error "Value '4,000' cannot be converted from Text to Number" but because the view state is so large you are getting the view state error.

If you make the attach variable Transient it will not be added to the view state and will stop your problem from happening:

public transient Attachment attach {get; set;}

An Introduction to Visualforce View State is a good overview of what the view state is for.

Related Topic