Problem with a gridview, paging and "object reference not set" error
I'm stuck with the following problem. I'm trying to implement a basic GridView paged result set, which connects to an Oracle database. By itself, the GridView, and the paged results, work fine. The problem comes when I try to put it in page layout class that we have at work.
We have ClassA, which inherits from Page, and is a corporate standard. Then I have ClassB, which inherits from ClassA and which includes application-specific code. The page that the GridView is on inherits from ClassB. This all seems to work fine in other pages, and I don't think it's the source of the problem, but I thought I'd mention it.
What happens is that the first time the page with the GridView loads, everything looks normal. The query runs and the first 10 records are displayed, with the numbers for paging below. When I click on "2" or any of the other pages, I get the "yellow screen of death" with the following message: "Object reference not set to an instance of an object". The object being referred to in that error line is "Me", the Page object (ASP.pagename_aspx in the debugger). I don't believe that the exact line it fails on is that important, because I've switched the order of a few statements around and it just fails on the earliest one.
I've traced through with the debugger and it looks normal, only that on Page 1 it works fine, and Page 2 it fails.
I have implemented the PageIndexChanging event (again, it works by itself if I remove inheritance from ClassB. Also, if I try inheriting directly from ClassA (bypassing ClassB entirely), I still get the problem.
Any ideas? Thanks.
I ran into a similar situation where the base (ClassA in your example) had variables that were set up to handle all the paging and sorting bits, and the GridView was wired up to events that used those variables. Not setting the proper base class variables in my page caused the exact same sort of error.
When I've had similar problems in the past, it has usually been a databinding problem (not calling DataBind() at the right time so when it tries to look at the next page the DataSource is null).
I agree with @DotNetDaddy in that you need to make sure you set the datasource on post-back, as this is almost certainly the reason for the "fun" yellow screen of death. The below is a very simple example that shows sorting and paging for a GridView in .NET 2.0+
The below is the exact markup required for this gridview to work correctly w/ my vb code
<asp:GridView ID="gridSuppliers" EnableViewState="false" runat="server" OnPageIndexChanging="gridSuppliers_PageIndexChanging" AutoGenerateColumns="false" AllowPaging="true" AllowSorting="true" CssClass="datatable" CellPadding="0" CellSpacing="0" BorderWidth="0" GridLines="None">...</asp:GridView>
Next is the code-behind file w/ the required sorting/paging implementation for a collection based databind
Partial Public Class _Default Inherits System.Web.UI.Page Implements ISupplierView Private presenter As SupplierPresenter Protected Overrides Sub OnInit(ByVal e As System.EventArgs) MyBase.OnInit(e) presenter = New SupplierPresenter(Me) End Sub Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load presenter.OnViewLoad() End Sub Protected Sub gridSuppliers_PageIndexChanging(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.GridViewPageEventArgs) Handles gridSuppliers.PageIndexChanging gridSuppliers.PageIndex = e.NewPageIndex presenter.PopulateSupplierList() End Sub Private Sub gridSuppliers_Sorting(ByVal sender As Object, ByVal e As GridViewSortEventArgs) Handles gridSuppliers.Sorting If DirectCast(ViewState("PreviousSortExpression"), String) = e.SortExpression Then If DirectCast(ViewState("PreviousSortDirection"), String) = "Ascending" Then e.SortDirection = System.Web.UI.WebControls.SortDirection.Descending ViewState("PreviousSortDirection") = "Descending" Else e.SortDirection = System.Web.UI.WebControls.SortDirection.Ascending ViewState("PreviousSortDirection") = "Ascending" End If Else e.SortDirection = System.Web.UI.WebControls.SortDirection.Ascending ViewState("PreviousSortDirection") = "Ascending" End If ViewState("PreviousSortExpression") = e.SortExpression Dim gv As GridView = DirectCast(sender, GridView) If e.SortExpression.Length > 0 Then For Each field As DataControlField In gv.Columns If field.SortExpression = e.SortExpression Then ViewState("PreviousHeaderIndex") = gv.Columns.IndexOf(field) Exit For End If Next End If presenter.PopulateSupplierList() End Sub #Region "ISupplierView Properties" Private ReadOnly Property PageIsPostBack() As Boolean Implements ISupplierView.PageIsPostBack Get Return Page.IsPostBack End Get End Property Private ReadOnly Property SortExpression() As String Implements ISupplierView.SortExpression Get If ViewState("PreviousSortExpression") Is Nothing Then ViewState("PreviousSortExpression") = "CompanyName" End If Return DirectCast(ViewState("PreviousSortExpression"), String) End Get End Property Public ReadOnly Property SortDirection() As String Implements Library.ISupplierView.SortDirection Get If ViewState("PreviousSortDirection") Is Nothing Then ViewState("PreviousSortDirection") = "Ascending" End If Return DirectCast(ViewState("PreviousSortDirection"), String) End Get End Property Public Property Suppliers() As System.Collections.Generic.List(Of Library.Supplier) Implements Library.ISupplierView.Suppliers Get Return DirectCast(gridSuppliers.DataSource(), List(Of Supplier)) End Get Set(ByVal value As System.Collections.Generic.List(Of Library.Supplier)) gridSuppliers.DataSource = value gridSuppliers.DataBind() End Set End Property #End Region End Class
And finally, the presenter class used in the code-behind
Public Class SupplierPresenter Private mView As ISupplierView Private mSupplierService As ISupplierService Public Sub New(ByVal View As ISupplierView) Me.New(View, New SupplierService()) End Sub Public Sub New(ByVal View As ISupplierView, ByVal SupplierService As ISupplierService) mView = View mSupplierService = SupplierService End Sub Public Sub OnViewLoad() If mView.PageIsPostBack = False Then PopulateSupplierList() End If End Sub Public Sub PopulateSupplierList() Try Dim SupplierList As List(Of Supplier) = mSupplierService.GetSuppliers() SupplierList.Sort(New GenericComparer(Of Supplier)(mView.SortExpression, mView.SortDirection)) mView.Suppliers = SupplierList Catch ex As Exception Throw ex End Try End Sub End Class
**the class required to sort a generic collection that is referenced in the presenter
Imports System.Reflection Imports System.Web.UI.WebControls Public Class GenericComparer(Of T) Implements IComparer(Of T) Private mDirection As String Private mExpression As String Public Sub New(ByVal Expression As String, ByVal Direction As String) mExpression = Expression mDirection = Direction End Sub Public Function Compare(ByVal x As T, ByVal y As T) As Integer Implements System.Collections.Generic.IComparer(Of T).Compare Dim propertyInfo As PropertyInfo = GetType(T).GetProperty(mExpression) Dim obj1 As IComparable = DirectCast(propertyInfo.GetValue(x, Nothing), IComparable) Dim obj2 As IComparable = DirectCast(propertyInfo.GetValue(y, Nothing), IComparable) If mDirection = "Ascending" Then Return obj1.CompareTo(obj2) Else Return obj2.CompareTo(obj1) End If End Function End Class
I lost my original unregistered login which I used to post this question.
Anyway, Harper Shelby's answer turned out to be correct. There was an unset variable in that base class (a custom object that is our corporate standard) that caused the problem (and no helpful error message).
If an admin, or someone with the right powers sees this, you could mark Harper's answer as the one, and close this. Thanks to everyone for their help.