mercoledì 2 marzo 2011

Leaky abstraction: Asp.Net MasterPage

Consideriamo una pagina web in cui, cliccando su un elemento in una lista, vengono visualizzati alcuni controlli, che dipendono dal tipo di elemento cliccato. A design-time non è dato di sapere quali sono questi controlli, i quali, a loro volta, possono provocare postback. Sono necessari dei controlli dinamici.
AFAIK, l'approccio migliore a questo problema è:
  • creazione dello UserControl in un evento della pagina
  • aggiunta del controllo in un PlaceHolder
  • impostazione del path dello UserControl in un HiddenField
  • nell'OnInit della pagina creazione del controllo a partire da Request.Form, per permettere il caricamento del ViewState
ossia una cosa del genere:
protected override void OnInit(EventArgs e) {
  if(IsPostback) {
    var currentView = Request.Form[CurrentViewHiddenControl.UniqueID];
    if (!string.IsNullOrEmpty(currentView)) {
       var control = LoadControl(currentView);
       control.ID = "MyView";
       PlaceHolder1.Controls.Add(control);
    }
  }
}

protected void OnSelected(Item item) {
  PlaceHolder1.Controls.Clear();
  
  var controlPath = GetControlPathByItem( item );
  var control = LoadControl( controlPath );
  control.ID = "MyView";
  PlaceHolder1.Controls.Add(control);

  CurrentViewHiddenControl.Value = controlPath;
}
Ma non funziona se i controlli vengono creati in un UpdatePanel e la pagina ha una MasterPage; quello che succede è che il primo postback non viene gestito correttamente. E non c'è modo di farlo funzionare, se non togliendo la MasterPage. Ora, può anche darsi che esista qualche workaround molto tricky, ma è assurdo che un normale processo, come il ciclo di vita di una pagina, venga stravolto da un dettaglio grafico quindi MasterPage = leaky abstraction.

Nessun commento: