Stamane ho fatto una scoperta che definirei sconcertante. La semplice lettura della proprietà Controls, in alcuni WebControl di ASP.NET causa notevoli malfunzionamenti al ciclo di vita della pagina. In particolare stavo utilizzando il metodo di cui ho parlato in un post precedente, per cercare dei controlli all'interno della gerarchia della pagina. Questa ricerca, se eseguita all'interno dell'OnInit, fa si che alcuni controlli non manifestino più gli eventi tipici. Ad esempio, un LinkButton non notificava più il "Click", e una FormView non era più in grado di gestire il postback correttamente.

Dopo una lunga estenuante ricerca, sono riuscito ad individuare la riga che era origine del problema, e con mio stupore mi sono reso contro che in quel punto non facevo altro che leggere la proprietà Controls per enumerare i controlli figlio. C'è voluta una breve indagine on il Reflector per arrivare ad una possibile spiegazione. La proprietà Controls non legge semplicemente il valore di un field, ma si occupa anche di inizializzare la collection nel caso in cui essa non sia già popolata; ecco il codice estratto da reflector:

public virtual ControlCollection Controls
{
      
get
      
{
            
if ((this._occasionalFields == null) || 
                (
this._occasionalFields.Controls == null))
            {
                  
this.EnsureOccasionalFields();
                  
this._occasionalFields.Controls = 
                      
this.CreateControlCollection();
            }
            
return this._occasionalFields.Controls;
      }
}

Come appare chiaro questo codice si occupa di istanziare una ControlCollection di default qualora essa non sia già presente. A quanto pare questa inizializzazione causa problemi se effettuata esternamente. Suppongo che da qualche parte, all'interno del ciclo di vita di un chiamata, esista una porzione di codice che verifica se tale proprietà è già inizializzata e si comporta di conseguenza in modi del tutto diversi. In effetti, a ben guardare la classe Control espone un metodo che compie questa verifica e che torna utile per aggirare questo malfunzionamento. Si tratta di HasControls(), un metodo che restituisce false se la proprietà non è inizializzata. Evidentemente in Microsoft il problema ho avevano previsto, e quindi hanno fornito un metodo per aggirarlo. Ecco quindi come dovrebbe essere modificato il codice dell'esempio precedente:

public static T FindControlRecursive<T>(Control root, string id)
    where T : Control
{
    
if (root.ID == id && root is T)
        
return root as T;

    
if (root.HasControls())
    {
        
foreach (Control child in root.Controls)
        {
            T foundControl = FindControlRecursive<T>(child, id);
    
            
if (foundControl != null)
                
return foundControl;
        }
    }

    
return default(T);
}

In questo modo non si modificherà lo stato del controllo. Rimane semplicemente da rilevare che si tratta di un comportamento decisamente subdolo, che andrebbe affrontato e corretto. Probabilmente sollevare un'eccezione sarebbe stato preferibile. A me è costato 3 ore di lavoro. Spero che a voi vada meglio.

powered by IMHO 1.3

 


per leggere il post originale o inviare un commento visita il seguente indirizzo: ASP.NET 2.0: Quando leggere una property fa la differenza