Wednesday, May 14, 2008

Dynamic GridView with paging throws 'Object reference not set to an instance of an object.'

Well, someone asked me today about why his dynamically generated GridView throws a 'Object reference not set to an instance of an object.' exception at DataBind when he sets AllowPaging to true. I replicated the error and looked at the stack trace, it looked like this:
   at System.Web.UI.WebControls.GridView.BuildCallbackArgument(Int32 pageIndex)
at System.Web.UI.WebControls.GridView.CreateNumericPager(TableRow row, PagedDataSource pagedDataSource, Boolean addFirstLastPageButtons)
at System.Web.UI.WebControls.GridView.InitializePager(GridViewRow row, Int32 columnSpan, PagedDataSource pagedDataSource)
at System.Web.UI.WebControls.GridView.CreateRow(Int32 rowIndex, Int32 dataSourceIndex, DataControlRowType rowType, DataControlRowState rowState, Boolean dataBind, Object dataItem, DataControlField[] fields, TableRowCollection rows, PagedDataSource pagedDataSource)
at System.Web.UI.WebControls.GridView.CreateChildControls(IEnumerable dataSource, Boolean dataBinding)
at System.Web.UI.WebControls.CompositeDataBoundControl.PerformDataBinding(IEnumerable data)
at System.Web.UI.WebControls.GridView.PerformDataBinding(IEnumerable data)
at System.Web.UI.WebControls.DataBoundControl.OnDataSourceViewSelectCallback(IEnumerable data)
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 System.Web.UI.WebControls.GridView.DataBind()
at Malaka.Page_Load(Object sender, EventArgs e) in c:\Inetpub\wwwroot\ScrollableFixedHeaderGrid\Malaka.aspx.cs:line 14
at System.Web.Util.CalliHelper.EventArgFunctionCaller(IntPtr fp, Object o, Object t, EventArgs e)
at System.Web.Util.CalliEventHandlerDelegateProxy.Callback(Object sender, EventArgs e)
at System.Web.UI.Control.OnLoad(EventArgs e)
at System.Web.UI.Control.LoadRecursive()
at System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint)

So, the error occurs at the BuildCallbackArgument method in the GridView object. I used Lutz Roeder's Reflector to see the source of the GridView object and I got to this piece of code:
        private string BuildCallbackArgument(int pageIndex)
if (string.IsNullOrEmpty(this._sortExpressionSerialized))
this._sortExpressionSerialized = this.StateFormatter.Serialize(this.SortExpression);
return string.Concat(new object[] { "\"", pageIndex, "|", (int) this.SortDirection, "|", this._sortExpressionSerialized, "|\"" });

The error appears to be thrown by the StateFormatter property returning null. It's source is:
        private IStateFormatter StateFormatter
if (this._stateFormatter == null)
this._stateFormatter = this.Page.CreateStateFormatter();
return this._stateFormatter;

Got it? It assumes you already added the GridView to a Page. Well, this is the usual issue with the GridView.

Solution: Add the GridView to your Page (or to a fictive Page) and then DataBind it.


Mark Kenney said...

I'm seeing this now... but it is code that worked fine in ASP.NET 2.0 but throws the error now in 3.5. We have the gridview added to an updatepanel, which is in turn wrapped in a webpart. Sure enough, StateFormatter is null now. Puzzling!

Siderite said...

Interesting enough. Could it be because that piece of code was added in some service pack to 2.0 which you didn't have installed?

Anonymous said...

Thanks a lot for this article, one small change of adding the gridview to the page and then databinding did solve my problem. I was working on this from past 2 days and could not figure out what went wrong.

Martin said...

THANK YOU!! (Been trying to get to the bottom of this all morning)

Siderite said...

You're welcome :)

Oddin said...

Solved my problem... Thanks a lot...

Anonymous said...

Perfect !!
It helped a lot. Thanks for your effort

Anonymous said...

Thanks a lot!