Blog Stats
  • Posts - 171
  • Articles - 1
  • Comments - 197
  • Trackbacks - 5

 

ObjectDataSource: invocare il metodo Select nella pagina

In ASP.NET 2.0 l'uso dei DataSourceControl risparmia tempo e codice in quanto questi controlli si occupano di gestire autonomamente le operazioni più comuni di data binding.

Per esempio nella pagina non è più necessario dover invocare il metodo DataBind sul controllo che lo usa.

L'ObjectDataSource ci permette di effettuare il data binding utilizzando metodi invece che sintassi SQL.
Questo ci permette di continuare a lavorare con il nostro strato di business o di accesso ai dati e di avere allo stesso tempo il vantaggio d'uso di un controllo simile.

Detto questo, non è tutto oro quello che luccica.

Sappiamo che l'ObjectDataSource utilizza reflection per invocare i metodi sul tipo specificato.
Quindi quando per esempio la GridView avrà bisogno di effettuare "data bind", passerà la chiamata all' ObjectDataSource associato il quale istanzierà il tipo contenente il metodo di Select, invocandolo a sua volta.

Se siamo curiosi, con Reflector è possibile andare a vedere come funziona il tutto.

Nei casi meno "demo-oriented" è utile poter decidere che il metodo di Select e SelectCount stiano direttamente all'interno della pagina aspx che ospita i controlli.
Questo dal momento che potrei aver bisogno di effettuare ordinamenti o filtri che non posso incapsulare come parametri del metodo di Select.

Possiamo configurare l'ObjectDataSource in modo che il metodo di Select specificato stia nella pagina.Ma se ci mettiamo a debug nel metodo stesso, possiamo notare che quando viene invocato il contesto "this" è si la pagina stessa, ma completamente vuota.

Questo perchè, come spiegato prima, l'ObjectDataSource crea l'istanza e poi invoca il metodo.Quindi è più che corretto trovarsi l'istanza vuota.

Per risolvere il problema allora possiamo utilizzare un nostro custom ObjectDataSource, che qui ho chiamato SmartObjectDatasource.

Questo non fa nient'altro che intercenttare l'evento di creazione dell'istanza e modificare l'istanza stessa:

public class SmartObjectDataSource : ObjectDataSource
{

    
protected override void OnInit(EventArgs e)
    {
        
base.OnInit(e);

        
this.ObjectCreated += new ObjectDataSourceObjectEventHandler(SmartObjectDataSource_ObjectCreated);
    }
   
    
void SmartObjectDataSource_ObjectCreatedobject sender, ObjectDataSourceEventArgs e)
    {
        
if (e.ObjectInstance is System.Web.UI.Page)
        {
            ((System.Web.UI.Page)e.ObjectInstance) = this.Page;

        }            
    }

}

Cosi facendo quando il metodo di Select sarà invocato, noi saremo sicuri che "this" corrisponderà alla pagina vera e propria, con tutti i dati caricati(session, form, viewstate, controlli, etc...).

 

Per chi usa ATLAS per incapsulare all'interno di un UpdatePanel il controllo che usa lo SmartObjectDataSource ci sono alcuni problemi.
Infatti in questo caso la pagina non riesce più ad eseguire il rendering parziale e ci troviamo di fronte al classico postback, nonostante tutto(lato ATLAS) sia configurato per bene.

Il problema è dovuto a questa riga

((System.Web.UI.Page)e.ObjectInstance) = this.Page;

Per ovviare al problema è sufficiente modificare il codice dello SmartObjectDataSource in questo modo:

public class SmartObjectDataSource : ObjectDataSource
{

    
protected override void OnInit(EventArgs e)
    {
        
base.OnInit(e);

        
this.ObjectCreated += new ObjectDataSourceObjectEventHandler(SmartObjectDataSource_ObjectCreated);
    }
   
    
void SmartObjectDataSource_ObjectCreated object sender, ObjectDataSourceEventArgs e)
    {
        
if (e.ObjectInstance is System.Web.UI.Page)
        {
            ((System.Web.UI.Page)e.ObjectInstance).Items.Add("PageInstance", 
this.Page);
        }            
    }

}

Nel metodo di Select nella pagina al posto di riferirsi a "this" per avere la pagina, sarà sufficiente ricavarla in questo modo :

MyPageAspx page = (MyPageAspx)this.Items["PageInstance"];

Comments have been closed on this topic.
 

 

Copyright © Luca Mauri