Blog Home  Home Feed your aggregator (RSS 2.0)  
Data Source Controls - Under the Hood (Part 1) - Manuel Abadia's ASP.NET stuff
# Thursday, January 12, 2006

The new data source controls and the new data binding infrastructure is a cool feature that can simplify development time (especially for simple scenarios and for people without much knowledge of the framework). However, for hardcore developers, not knowing what exactly the new data binding infrastructure does under the hood is problematic and unfortunately, it isn't very well documented anywhere...  I'll try to explain some of the "magic" involved in this. 


All data bound controls designed to use the new data source controls inherit from the BaseDataBound class. This class has the following public properties:

virtual object DataSource  { get; set; }

virtual string DataSourceId { get; set; }

and the following template methods:


protected abstract void PerformSelect();

protected abstract void ValidateDataSource(object dataSource);

The first one (DataSource) is what we used to bind data in 1.x. The second one (DataSourceId) is what lets a data bound control "play" with a data source control.

If you set the DataSource property, the ValidateDataSource method is called, where a control should check that the data source is of a type that it can work with (usually IListSource, IEnumerable or IDataSource). More about the template methods later.

If you change the DataSourceId after the init stage, the DataBind method will be called on PreRender. If you change it after PreRender, it will call DataBind immediately. Note that if you have the DataSourceId set before PreLoad, DataBind is not called by this class!

 The class takes part in the page's life cycle:
* OnInit: if ViewState is disabled, the control will be bound every time on PreRender.
* OnPreLoad: sets an internal flag that marks the end of the init stage.
* OnPreRender: sets an internal flag that marks the begin of the PreRender stage and calls to DataBind.

The class has one public method:

public override void DataBind();

that calls the template method PerformSelect, that should fetch data from the underlying data source.



DataBoundControl inherits from BaseDataBound and is the base class for all data bound controls that display tabular or list-style information. This class adds a public property:

public virtual string DataMember { get; set; }


that is used to determine the list to use if the data source exposes more than one list of data.

The main task this class accomplishes is to isolate the derived classes from extracting the data from the data source (remember that the control can be bound using the DataSource property or with the DataSourceId property, and it should support both kind of data sources). The data will be presented to the derived classes as an IEnumerable collection in the template method:

protected internal virtual void PerformDataBinding(IEnumerable data);

Fortunately the hard work is done by the method ConnectToDataSourceView that gets a reference to a DataSourceView. This is straight forward if the control is bound using DataSourceId, but it has to use a wrapper class in order to expose the DataSource as a data source control (ReadOnlyDataSource that implements IDataSource, returning a view (ReadOnlyDataSourceView) that only supports the select method).

The class takes part in the page's life cycle:
* OnPreLoad: calls the base OnPreLoad and if is the first time the page is requested, or if view state is enabled but the control hasn't been data bound yet, it sets a flag to try to bind data in the OnPreRender stage.
* OnLoad: tries to get a view of the data source (if it doesn't have it yet) and if for some reason the OnPreLoad didn't try to bind the data and we haven't bound the data yet, sets a flag to try to bind data in the OnPreRender stage.

As you can see this class fills the gap that the base class left in order to automatically bind data when the DataSourceId was set before the PreLoad stage.

If the control is bound using DataSourceId, the control captures the DataSourceViewChanged event from the DataSourceView to rebind the control if the data source changes (more on this when explaining the DataSourceView class).

This class implements the template methods defined in BaseDataBound, ValidateDataSource and PerformSelect. The first one checks if the data source implements IListSource, IEnumerable or IDataSource raising an exception in case it doesn't. The second one (PerformSelect) is called by the DataBind method and does the following:
* if we're binding using DataSource, raises the DataBinding event
* gets a DataSourceView from the data source
* marks the control as data bound
* creates the select parameters and calls the DataSourceView's select method, passing a callback that will be called when the select method completes.

The method that will be called when the select method has completed is PerformDataBinding, where the IEnumerable data is passed as the first parameter.

I'll blog about DataSourceControl and DataSourceView when time permits.

Thursday, January 12, 2006 1:01:34 AM (Romance Standard Time, UTC+01:00)  #    Comments [10]   ASP.NET  |  Tracked by:
"DataSourceControls summary" (Manuel Abadia's ASP.NET stuff) [Trackback],guid,7cef4a16-10ec-44e5-8f3c-36a977b8... [Pingback]
Wednesday, April 5, 2006 7:49:26 AM (Romance Daylight Time, UTC+02:00)
your article is very good and very useful, but it is very difficult to find your blogs (I use google to search your blogs)

I wonder why you DONOT put your article into
If do that, More and More people get benifit from your article
Wednesday, April 5, 2006 12:09:58 PM (Romance Daylight Time, UTC+02:00)
I don't think its difficult to find information if you're on the main page:

I don't know the implications of putting my blog on Is there information about what control do you have?
Friday, April 14, 2006 2:51:16 PM (Romance Daylight Time, UTC+02:00)
I ran into one problem with the CompositeDataBoundControl when it came to design time databinding of a ObjectDataSource representing a dataset of a Sql Table.
I called PerformSelect() method which caused an exception:

Message: Exception has been thrown by the target of an invocation.
StackTrace: at System.RuntimeMethodHandle._InvokeMethodFast(Object target, Object[] arguments, SignatureStruct& sig, MethodAttributes methodAttributes, RuntimeTypeHandle typeOwner)
at System.RuntimeMethodHandle.InvokeMethodFast(Object target, Object[] arguments, Signature sig, MethodAttributes methodAttributes, RuntimeTypeHandle typeOwner)
at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture, Boolean skipVisibilityChecks)
at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
at System.Web.UI.WebControls.ObjectDataSourceView.InvokeMethod(ObjectDataSourceMethod method, Boolean disposeInstance, Object& instance)
at System.Web.UI.WebControls.ObjectDataSourceView.ExecuteSelect(DataSourceSelectArguments arguments)
at System.Web.UI.DataSourceView.Select(DataSourceSelectArguments arguments, DataSourceViewSelectCallback callback)
at System.Web.UI.WebControls.DataBoundControl.PerformSelect()
at System.Web.UI.WebControls.BaseDataBoundControl.DataBind()
at DataBoundTest.DataTest.DataBind() in C:\Documents and Settings\Developer\My Documents\Visual Studio 2005\Projects\Controls\DataBoundTest\DataTest.cs:line 45
Source: mscorlib
InnerException Source: App_Code.c7wsyhkd
InnerException StackTrace: at NameDataSetTableAdapters.NameTableAdapter.InitConnection()
at NameDataSetTableAdapters.NameTableAdapter.get_Connection()
at NameDataSetTableAdapters.NameTableAdapter.InitAdapter()
at NameDataSetTableAdapters.NameTableAdapter.get_Adapter()
at NameDataSetTableAdapters.NameTableAdapter.GetData()
InnerException Message: Object reference not set to an instance of an object.

I then tried the same thing in FormView and it did the same.

My post here:

So far I've had no joy in getting this to work. I'm able to select data with all the other sources accept ObjectDataSource. Theres nothing on the net about this at all.. very blank in this area.

If anyone who reads this blog or maybe the blog owner could give me a hand?
Daniel Vickers
Wednesday, April 19, 2006 7:34:40 PM (Romance Daylight Time, UTC+02:00)
If you send me the code (my email is on the left of the page) I can take a look to it.
Wednesday, June 28, 2006 6:43:30 PM (Romance Daylight Time, UTC+02:00)
I had faced this type of exception and
i have not idea for what reason this will propagate,

Exception #1 Source: mscorlib
Invalid length for a Base-64 char array.
at System.Convert.FromBase64String(String s)
at System.Web.UI.LosFormatter.Deserialize(String input)
at System.Web.UI.Page.LoadPageStateFromPersistenceMedium()

Please, Do reply,
Thanking u,
Tuesday, August 1, 2006 12:48:07 PM (Romance Daylight Time, UTC+02:00)
What if ViewState is disabled and you need to handle postback events from dynamically generated inner control of a databoundcontrol (e.g. LinkButton inside of FormView)? FormView binds data at OnPreRender, so control tree is not built in time of handling postback events (after OnLoad). The target of postback (LinkButton) doesn't exists yet, so the OnClick event doesn't fire. When you force FormView to bind data at OnInit stage by DataBind method, it works; however, it doesn't mark the FormView as data bound, so at OnPreRender the data binding occurs again!
Thursday, February 8, 2007 10:13:14 PM (Romance Standard Time, UTC+01:00)
I am writing a custom gridview control, and I would like the user to toggle the auto data bind feature when the DataSourceID property has been set.

Sometimes I don't want DataBind() is performed when the DataSourceID is set, I would like to have the option to only data bind when the DataBind() method is called explicitely.

Thanks in advance.
Sunday, February 11, 2007 10:10:14 PM (Romance Standard Time, UTC+01:00)

The default implementation of the DataSourceID property is:

if (string.IsNullOrEmpty(value) && !string.IsNullOrEmpty(this.DataSourceID))
this._requiresBindToNull = true;
this.ViewState["DataSourceID"] = value;


I haven't tested this but you can try to override the DataSourceId property and save the value that returns the RequiresDataBinding property before OnDataPropertyChanged is called. Then use the saved value to restore the RequiresDataBinding property if you do not want the auto bind feature.

The only problem is that RequiresDataBinding does the binding if it is set after the PreRender stage. You may also want to override RequiresDataBinding to avoid doing the actual binding if you do not want the auto bind feature.

Hope it helps,
Thursday, June 21, 2007 9:21:04 PM (Romance Daylight Time, UTC+02:00)
Thanks a lot for this. It showed me what I originally broke (viewstate) and why one my fix attempts broke it further (changing data source) so when I fixed the original problem with the latter still in place, it was still broken. Clear layouts of control lifecycles can be hard to come by.
Wednesday, July 16, 2008 2:09:41 PM (Romance Daylight Time, UTC+02:00)
Hi Manuel

If DataSourceId is set in CreateChildControls and databinding is done in a different class, how can you handle exceptions that may be thrown at databind?
I am using this in a SharePoint webpart
Matt Williams
All comments require the approval of the site owner before being displayed.
Home page

Comment (Some html is allowed: a@href@title, strike) where the @ means "attribute." For example, you can use <a href="" title=""> or <blockquote cite="Scott">.  

[Captcha]Enter the code shown (prevents robots):

Live Comment Preview
Copyright © 2020 Manuel Abadia. All rights reserved.
DasBlog 'Portal' theme by Johnny Hughes.