Allora, dopo i due post di introduzione della problematica e di descrizione di tutte le possibili implementazioni, ecco la conclusione sull'argomento.
Abbiamo detto che per inserire il contenuto del ViewState al di fuori della pagina aspx abbiamo tre possibilità:

  • utilizzare il filesystem
  • utilizzare la sessione
  • utilizzare la cache della pagina
Ecco, per comodità ho creato una mia soluzione per poter decidere su ogni pagina il tipo di tecnica da utilizzare, potendo quindi scegliere modificando una variabile aggiunta a quelle delle classe Page, classe da cui ereditano tutte le pagine ASP.NET.
Mi sono quindi creato un'enumeration per darmi la possibilità di effettuare la scelta:

namespace Peppe.Web.UI

{
public enum ViewStateLocation
{
///<summary>Leaves the viewstate ones its place.</summary> Default,
///<summary>Sets view state saved on page cache.</summary> Cache,
///<summary>Sets view state saved on session.</summary> Session,
///<summary>Sets view state saved on filesystem.</summary> FileSystem
}
}

e sono andato a creare una nuova classe che erediti dalla classe Page.
A questa classe ho aggiunto la proprietà ViewStateLocation, per settare il tipo di tecnica da utilizzare per salvare il viewstate, e le proprietà ViewStateDirectory e ViewStateFilePath, utili per l'archiviazione del viewstate sul filesystem. Infine ho fatto l'overload dei metodi LoadPageStateFromPersistenceMedium e SavePageStateToPersistenceMedium e ci ho inserito dentro il codice necessario ad implementare tutte le tecniche descritte.

protected override object LoadPageStateFromPersistenceMedium()

{
switch(this.ViewStateLocation)
{
case ViewStateLocation.Cache:
{
LosFormatter formatter = new LosFormatter();
string str = Request.Form["__VIEWSTATE_KEY"];
if (!str.StartsWith("VIEWSTATE_"))
{
throw new Exception("Invalid viewstate key:" + str);
}
object vs = Cache[str];
if(vs != null)
return formatter.Deserialize(vs.ToString());
else
return null;
}
case ViewStateLocation.Session:
{
LosFormatter formatter = new LosFormatter();
object vs = Session["state"];
if (vs!=null)
return formatter.Deserialize(vs.ToString());
else
return null;
}
case ViewStateLocation.FileSystem:
{
string vsString = Request.Form[ViewStateHiddenFieldName];
if (!File.Exists(vsString))
throw new Exception("The Viewstate file " + vsString + " is missing.");
else
{
LosFormatter formatter = new LosFormatter();
StreamReader sr = File.OpenText(vsString);
string viewStateString = sr.ReadToEnd();
sr.Close();
return formatter.Deserialize(viewStateString);
}
}
default:
{
return base.LoadPageStateFromPersistenceMedium();
}
}
}

protected override void SavePageStateToPersistenceMedium(object viewState)
{
switch(this.ViewStateLocation)
{
case ViewStateLocation.Cache:
{
LosFormatter formatter = new LosFormatter();
StringWriter writer = new StringWriter();
string str = "VIEWSTATE_" + Request.UserHostAddress + "_"
+ DateTime.Now.Ticks.ToString();
formatter.Serialize(writer, viewState);
Cache.Add(str, writer.ToString(), null,
DateTime.Now.AddMinutes(Session.Timeout),TimeSpan.Zero,
CacheItemPriority.Default, null);
writer.Close();
RegisterHiddenField("__VIEWSTATE_KEY", str);
break;
}
case ViewStateLocation.Session:
{
StringWriter writer = new StringWriter();
LosFormatter formatter = new LosFormatter();
formatter.Serialize(writer, viewState);
string state = writer.ToString();
writer.Close();
Session["state"] = state;
break;
}
case ViewStateLocation.FileSystem:
{
LosFormatter formatter = new LosFormatter();
StringWriter writer = new StringWriter();
formatter.Serialize(writer, viewState);
StreamWriter sw = File.CreateText(this.ViewStateFilePath);
sw.Write(writer.ToString());
sw.Close();
writer.Close();
Page.RegisterHiddenField(ViewStateHiddenFieldName, ViewStateFilePath);
break;
}
default:
{
base.SavePageStateToPersistenceMedium(viewState);
break;
}
}
}

Fatto questo, non resta altro che ereditare le nostre classi di code-behind delle nostre pagine .aspx, dalla classe che abbiamo appena definito e non dalla classe Page, e assegnare un valore alla variabile ViewStateLocation.

public class myASPXpage : Peppe.Web.UI.Page

{
public void Page_Load(object sender, System.EventArgs e)
{
this.ViewStateLocation = Peppe.Web.UI.ViewStateLocation.Session;
}
}

E con questo post chiudo l'argomento :)