Results 1 to 3 of 3

Thread: Object reference not set to an instance of an object

  1. #1

    Thread Starter
    Fanatic Member
    Join Date
    Jul 2001
    Location
    London UK
    Posts
    671

    Object reference not set to an instance of an object

    I am trying to write a simple user control to hold a cached HTML "Select" Box

    This works fine if I drag the control onto the page directly (in which case I can't work out how to access the control's properties) but errors if I try and programmatically load it into a placeholder


    A cut down version of how I am trying to do this is below...

    Code:
    using ShoppingCart_Net.Controls;
    
    namespace ShoppingCart_Net.productdb
    {
    	public class browser_home : System.Web.UI.Page
    	{
    		protected CachedListBox clbTypes = new CachedListBox();
    	
    		private void Page_Load(object sender, System.EventArgs e)
    		{
    			string ConnectionString = ConfigurationSettings.AppSettings["ConnectionString"].ToString();
    			phTypes.Controls.Add(clbTypes);
    			clbTypes.Query = "Select ProductTypes.ProductTypeID,ProductTypes.ProductTypeDescription From ProductTypes Order By ProductTypes.ProductTypeDescription";
    			clbTypes.TextField = "ProductTypeDescription";
    			clbTypes.ValueField = "ProductTypeID";
    			clbTypes.ConnectionString = ConnectionString;
    		}
    
    
    	}
    }

    The CachedListBox.ascx page just contains one line (apart from the directives) as below.

    <aspropDownList id="lbCached" runat="server"></aspropDownList>


    The (cut down) code behind for the user control is...

    Code:
    namespace ShoppingCart_Net.Controls
    {
    	using System.Data.OleDb;
    
    	public class CachedListBox : System.Web.UI.UserControl
    	{
    		protected System.Web.UI.WebControls.DropDownList lbCached;
    		private string mQuery, mConnectionString, mTextField, mValueField;
    
    		private void Page_Load(object sender, System.EventArgs e)
    		{
    			if (! this.IsPostBack) 
    			{
    				OleDbConnection objConn = new OleDbConnection(mConnectionString);
    				OleDbCommand objComm = new OleDbCommand(mQuery, objConn);
    				objConn.Open();
    				try
    				{
    					lbCached.DataTextField = mTextField;
    					lbCached.DataValueField = mValueField;
    					lbCached.DataSource = objComm.ExecuteReader();
    					lbCached.DataBind();
    				}
    				finally
    				{
    					objConn.Close();
    				}
    			}
    		} 
    
    
    
    
    		
    		public string Query
    		{
    			get
    			{
    				return mQuery;
    			}
    			set
    			{
    				mQuery = value;
    			}
    		}
    
    		
    //Other Properties omitted for conciseness
    	}
    }
    The Error occurs at the first use of lbCached in the Page_Load event above and is as follows...

    "Exception Details: System.NullReferenceException: Object reference not set to an instance of an object."

    Can anyone see what I am doing wrong?

    Cheers!

    Martin

  2. #2
    Hyperactive Member
    Join Date
    Aug 2002
    Location
    Fort Collins, CO
    Posts
    366
    Well the main problem is that, programmatically you have to load usercontrols(using Page.LoadControl), you can't just create a new instance. Cached list box is a cool idea, but why not really have a listbox Cached? The way you have it is good, but it's really only "caching" your listbox in ViewState, you get that for free anyway. The next user that hits that page would need to go get the data again. My general rule of thumb is if the html output is very simple, say a single control or two, I use custom server controls; if the html output is more complex, like tables, containing serveral controls, or a complex layout, i use user controls(just my .02). Check this out:
    PHP Code:
    using System;
    using System.Data;
    using System.Data.SqlClient;
    using System.Web;
    using System.Web.UI;
    using System.Web.UI.WebControls;

    namespace 
    CSharpWeb.Components
    {
        public class 
    CachedListBox DropDownList
        
    {
            private 
    string _query "";
            private 
    string _connString "";
            private 
    string _textField "";
            private 
    string _valueField "";
            public 
    string Query
            
    {
                
    get
                
    {
                    return 
    _query;
                }
                
    set
                
    {
                    
    _query value;
                }
            }
            public 
    string ConnString
            
    {
                
    get
                
    {
                    return 
    _connString;
                }
                
    set
                
    {
                    
    _connString value;
                }
            }
            public 
    string TextField
            
    {
                
    get
                
    {
                    return 
    _textField;
                }
                
    set
                
    {
                    
    _textField value;
                }
            }
            public 
    string ValueField
            
    {
                
    get
                
    {
                    return 
    _valueField;
                }
                
    set
                
    {
                    
    _valueField value;
                }
            }
            public 
    override void DataBind()
            {
                
    base.DataSource getData();
                
    base.DataTextField this.TextField;
                
    base.DataValueField this.ValueField;
                
    base.DataBind();
            }
            private 
    DataSet getData()
            {
                
    DataSet ds null;
                if (
    HttpContext.Current.Cache[this.ID] != null)
                    
    ds = (DataSet)HttpContext.Current.Cache[this.ID];
                else
                {
                    
    using(SqlConnection cn = new SqlConnection(this.ConnString))
                    {
                        
    using (SqlCommand cmd = new SqlCommand(this.Querycn))
                        {
                            
    using (SqlDataAdapter da = new SqlDataAdapter(cmd))
                            {
                                
    ds = new DataSet();
                                
    da.Fill(ds);
                                
    HttpContext.Current.Cache[this.ID] = ds;
                            }
                        }
                    }
                }
                return 
    ds;
            }
            public 
    void Refresh()
            {
                
    HttpContext.Current.Cache.Remove(this.ID);
                
    this.DataBind();
            }
        }

    This basically caches the data needed for the control for any user who hits that page. It's saving it under the key name defined by it's ID, so any other controls named the same but on different pages would screw up the cache, just need some unique naming convention.
    Then the aspx page would look something like this(fyi, my web project is named CSharpWeb, which will be the assembly reference in the following):
    Code:
    <%@ Page language="c#" Codebehind="CachedListBoxTest.aspx.cs" AutoEventWireup="false" Inherits="CSharpWeb.Components.CachedListBoxTest" %>
    <%@ Register TagPrefix="PVB" Assembly="CSharpWeb" Namespace="CSharpWeb.Components" %>
    <html>
    	<body>
    		<form runat="server">
    			<PVB:CachedListBox ID="myCachedListBox" Runat="server"/>
    			<asp:Button ID="btnSubmit" Runat="server" Text="Submit" OnClick="btnSubmit_Click"/>
    		</form>
    	</body>
    </html>
    and the code behind like this:
    PHP Code:
    namespace CSharpWeb.Components
    {
        public class 
    CachedListBoxTest System.Web.UI.Page
        
    {
            protected 
    CachedListBox myCachedListBox;
            protected 
    Button btnSubmit;
            protected 
    void btnSubmit_Click(object senderEventArgs e)
            {
                
    //do nothing
            
    }
            protected 
    override void OnInit(EventArgs e)
            {
                if (!
    Page.IsPostBack)
                {
                    
                    
    myCachedListBox.ConnString "user id=sa;password=sa;server=DeathAngel;database=scratch;";
                    
    myCachedListBox.TextField "StateName";
                    
    myCachedListBox.ValueField "StateCode";
                    
    myCachedListBox.Query "Select StateName, StateCode From State";
                    
    myCachedListBox.DataBind();
                }
                
    base.OnInit (e);
            }

        }

    And if the control would be used in multiple places, i'll create a specialized control(in this case a StateDropDownList) that has the data methods built into the control. That way if you're gonna reuse the code you don't have to keep setting the query, connectionstring, textfield, etc. - you'd just create the control and voila, it's a select box with a list of states in it. Anyway, good luck.

  3. #3

    Thread Starter
    Fanatic Member
    Join Date
    Jul 2001
    Location
    London UK
    Posts
    671
    Thanks pvb, I misunderstood user control caching - it is a lot clearer now!

    cheers for the code - very cool!

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width