Visualforceのビューステートおよび画面間情報維持について

#1.ビューステートについて
簡単に言うと、ビューステートはクライアント側とサーバ側の間にメンテナンスしたい情報の格納場所です。

  - formタグ必要
  - Base64で暗号化
  - クライアント側保存
  
　　```<input type=“hidden” id=“com.salesforce.visualforce.ViewState” name=“com.salesforce.visualforce.ViewState” value=“Base64で暗号化された内容”/>```

ビューステートを理解するには、post backリクエストを理解する必要があります。
post backリクエストとは、Visualforceページにおいてformタグから情報を送信した際に、情報送信後の次の遷移ページが送信前と同一ページである場合のポストリクエストのことを指します。
#2.ビューステートサイズの確認方法
**開発者コンソール**
![image.png](https://qiita-image-store.s3.amazonaws.com/0/332907/d4916d8a-5c84-1144-f0f6-72fde81da209.png)
**Visualforce実行画面**
![image.png](https://qiita-image-store.s3.amazonaws.com/0/332907/62b335ff-7e2c-d07c-ee57-dda87ca19396.png)
#3.画面間情報維持について
##各Visualforce 画面は一つのControllerで画面間遷移情報維持

**画面の遷移図**
![image.png](https://qiita-image-store.s3.amazonaws.com/0/332907/113b2a37-e574-2e57-00b8-03228efef867.png)
**ViewStateの格納状況**
![image.png](https://qiita-image-store.s3.amazonaws.com/0/332907/0ce3e735-b7b4-ec10-401b-5ac874a5ad1a.png)
#4.実装例
```java:AccountSearchController.cls
public with sharing class AccountSearchController {
    public String name {get;set;}
    public List<Account> results { get; set; }
    public AccountSearchController() {
        this.name = '';
        this.results = new List<Account>();
    }
    public PageReference doSearch() {
        try {
            String strSoqlQuery = 'select Name, Phone, Website from Account';
            String strName;
            If (String.IsNotBlank(this.name)) {
                strName = '%' + this.name + '%';
                strSoqlQuery = strSoqlQuery + ' where Name like :strName';
            }
            this.results = database.query(strSoqlQuery);
        } catch (Exception e){
             ApexPages.addMessage(new ApexPages.Message(ApexPages.Severity.ERROR, e.getMessage()));
             return null;
        } 
        
        return Page.AccountSearchResultPage;
    }
    
    public PageReference doPrevious(){
        return Page.AccountSearchPage;
    }
}
```
```html:AccountSearchPage.page
<apex:page controller="AccountSearchController">
    <apex:form id="TheForm">
        <apex:pageBlock title="検索条件">
            <apex:pageblockSection id="conditionSection" title="検索" columns="1">
                <apex:pageBlockSectionItem >
                    <apex:outputLabel value="取引先名" />
                    <apex:inputText value="{!name}" />
                </apex:pageBlockSectionItem>
            </apex:pageblockSection>
            <apex:pageBlockButtons id="buttonSection" location="bottom">
                <apex:commandButton value="検索" action="{!doSearch}" style="font-size:12pt;width:100px;height:30px;"/>
            </apex:pageBlockButtons>
        </apex:pageBlock>
    </apex:form>
</apex:page>
```
```html:AccountSearchResultPage.page
<apex:page controller="AccountSearchController">
    <apex:form id="theForm">
        <apex:outputpanel id="searchresult">
            <apex:commandButton value="戻る" action="{!doPrevious}" style="font-size:12pt;width:100px;height:30px;"/>
            
            <apex:pageBlock title="検索結果：" rendered="{!(results.size == 0)}">検索条件に該当するデータがありません</apex:pageBlock>
            <apex:pageBlock id="resultBlock" title="取引先一覧" rendered="{!(results.size > 0)}">
                <apex:outputtext style="width:110px" value="結果 : {!results.size}件" />
                <apex:pageblockTable id="resultTable" value="{!results}" var="o"
                    frame="box">
                    <apex:column style="width:80px">
                        <apex:facet name="header">取引先名</apex:facet>
                        <apex:outputlink value="/{!o.Id}">
                            <apex:outputField style="width:80px" value="{!o.Name}" />
                        </apex:outputlink>
                    </apex:column>
                    <apex:column style="width:160px">
                        <apex:facet name="header">電話</apex:facet>
                        <apex:outputField style="width:150px" value="{!o.Phone}" />
                    </apex:column>
                    <apex:column style="width:160px">
                        <apex:facet name="header">  Web サイト</apex:facet>
                        <apex:outputField style="width:150px"
                            value="{!o.Website}" />
                    </apex:column>
                </apex:pageblockTable>
            </apex:pageBlock>
        </apex:outputpanel>
    </apex:form>
</apex:page>
```
#5.検証
**画面**
![image.png](https://qiita-image-store.s3.amazonaws.com/0/332907/cbb8079a-e08e-6044-7047-446e2e7b0f7c.png)
**view state**
![image.png](https://qiita-image-store.s3.amazonaws.com/0/332907/f43583ca-d19e-4b71-aab3-2a7cb34450ab.png)
#6.注意事項
- **各Visualforce pageにController(extensions含む)の定義は一致する必要があります。**
- Spring ‘19 リリースからビューステートサイズの上限が 135KB から 170KB に増加しました。