title: Data Persistence across ASP.NET postbacks
body: <p><strong>Context:</strong>  </p>
  
  <p>I've often been in situations where our ASP.NET pages would have to show data to the user on a GridView, let him change it as he pleases (Textbox on cells) and only save it to the database when he actually hits the "Save Button". This data is usually a virtual state of the information on the page, meaning that the user can change everything without really saving it until he hits the "Save Button".
  In those cases, there's always list of data that needs to be persisted across ASP.NET Postbacks. This data could be an instance of a <code>DataTable</code> or just some <code>List&lt;Someclass&gt;</code>. </p>
  
  <p>I often see people implementing this and persisting the data on <code>Session</code>. On that cases i also usually see problems when it comes to some user navigating with multiple tabs open, some times on the same page. Where the data of two different tabs would get merged and cause problems of information being scrambled.</p>
  
  <p>Example of how Session is often used:</p>
  
  <pre><code>private List&lt;SomeClass&gt; DataList
  {
      get
      {
          return Session["SomeKey"] as List&lt;SomeClass&gt;;
      }
      set 
      {
          Session["SomeKey"] = value;
      }
  }
  </code></pre>
  
  <p>People often tries to solve it by doing something like this:</p>
  
  <pre><code>protected void Page_Load(object sender, EventArgs e)
  {
      if (!IsPostBack)
      {
          DataList = null
      }
      else
      {
          FillGridView(DataList);
      }
  }
  </code></pre>
  
  <p>But what about when two tabs are already loaded and the user is changing the GridView values and for some weird reason he tries to save the data by hitting the Save button on the other page? I personally dislike this option.</p>
  
  <p>Other ways to do this would be to put the data on <code>ViewState</code>. However, when it comes to persisting substantially big lists, it could impact the page heavily when it's stored on the page (<code>HiddenField</code>).</p>
  
  <p>But, what's the best way to make that work? Once, i thought in using <code>Session</code> together with <code>ViewState</code> where the <code>ViewState</code> would hold an unique identifier which would index the <code>Session</code> saved data. That would prevent sharing the data between tabs on the browser:</p>
  
  <pre><code>private List&lt;SomeClass&gt; DataList
  {
      get
      {
          if (ViewState["SomeKey"] == null)
          {
              ViewState["SomeKey"] = Guid.NewGuid().ToString();
          }
  
          return Session[ViewState["SomeKey"].ToString()] as List&lt;SomeClass&gt;;
      }
      set {
  
          if (ViewState["SomeKey"] == null)
          {
              ViewState["SomeKey"] = Guid.NewGuid().ToString();
          }
  
          Session[ViewState["SomeKey"].ToString()] = value;
      }
  }
  </code></pre>
  
  <p>On the other hand it would store a new list of data to the Session every time the user enters the page. Which would impact the server memory. Maybe they could be erased in some way.</p>
  
  <p><strong>Question:</strong> </p>
  
  <p>What would be the best way of persisting that kind of data across Postbacks, considering the contexts of multiple tabs on the browser, with the less cost to the server and to the maintenance coding team?</p>
  
  <p><strong>Update:</strong></p>
  
  <p>As @nunespascal nicely posted, one option would be to store the <code>ViewState</code> in the <code>Session</code> using the <code>SessionPageStatePersister</code>. But unfortunately that's not an option on my case. And yet it is not very different from my last example, saving the data on the Session indexed by an UniqueId stored on the ViewState.</p>
  
  <p>Would there be any other options?</p>