ASP.NET satur ļoti noderīgu kolekcijas klasi System.Web.UI.StateManagedCollection (MSDN dokumentācija). Galvenā tās priekšrocība pār parastajām kolekcijām ir tās spēja saglabāt visas izmaiņas ViewState, lai, lapai apstrādājot vairākus secīgus pieprasījumus, veiktās izmaiņas tiktu automātiski saglabātas.
Piemēram, ObjectDataSource parametru kolekcijas izmanto šo kolekciju, lai gadījumos, kad parametri tiek mainīti (tiek pievienoti parametri vai mainītas to vērtības), šīs izmaiņas saglabātos ViewState tāpat kā ievades lauku vērtības.
Diemžēl šī kolekcija satur diezgan brangu kļūdu – tā nesaglabā ViewState datos izmaiņas situācijās, kad visa kolekcija tiek iztukšota. Piemēram, ja izmanto asp:Menu vadīklu un kāda pieprasījuma laikā iztīra kāda zara visus ierakstus. Pēc nākamā pieprasījuma šīe ieraksti atkal būs savās vietās it kā nekad nekas nebūtu noticis.
Šo kļūdu pieteicu Microsoft, lai gan cerība, ka tā tiks salabota, ir diezgan minimāla. Visdrīzāk tiks pateikts, ka, jā, kļūda ir, bet tā netiks labota, lai nenograutu eksistējošas sistēmas, kas uz šo kļūdu paļaujas (apzināti vai neapzināti).
Bet katrā ziņā, vismaz nosacīts apkārtceļs eksistē (izmantojams tikai savās atvasinātajās klasēs, tas nevar salabot esošās .NET klases).
#region [ Workaround for the bug when the original StateManagedCollection does not persist Clear() call ]
/*
* Workaround for the bug described here: https://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=486953
*
* If Clear() was called StateManagedCollection saves all of the items in the ViewState. Unfortunately,
* if the collection remains empty when the state is saved, StateManagedCollection saves just a "null".
* When LoadViewState is called, _saveAll private field is not set as it should be.
*/
private static Func<StateManagedCollection, bool> _SaveAll;
private static object _SaveAllLock = new object();
private bool SaveAll
{
get
{
if (_SaveAll == null)
{
lock (_SaveAllLock)
{
if (_SaveAll == null)
{
var p = System.Linq.Expressions.Expression.Parameter(typeof(StateManagedCollection), "col");
var f = System.Linq.Expressions.Expression.Field(p, "_saveAll");
_SaveAll = System.Linq.Expressions.Expression.Lambda<Func<StateManagedCollection, bool>>(f, p).Compile();
}
}
}
return _SaveAll(this);
}
}
private static Func<StateManagedCollection, object> _BaseSaveViewState;
private static object _BaseSaveViewStateLock = new object();
object IStateManager.SaveViewState()
{
if (this.Count == 0 && this.SaveAll)
return new Pair(new object[0], new int[0]);
if (_BaseSaveViewState == null)
{
lock (_BaseSaveViewStateLock)
{
if (_BaseSaveViewState == null)
{
var p = System.Linq.Expressions.Expression.Parameter(typeof(StateManagedCollection), "col");
var f = System.Linq.Expressions.Expression.Call(p, "System.Web.UI.IStateManager.SaveViewState", Type.EmptyTypes);
_BaseSaveViewState = System.Linq.Expressions.Expression.Lambda<Func<StateManagedCollection, object>>(f, p).Compile();
}
}
}
return _BaseSaveViewState(this);
}
#endregion
6d5c7775-f3ca-4337-9547-9ec73b1dca9a|0|.0|015880aa-1e7c-4e05-a104-8c054d966a2e