Solved

scope in web application - global.asax

Posted on 2007-04-07
15
883 Views
Last Modified: 2008-02-01
I am building a simple shopping cart applicaiton.  A single products page shows items in a row that contains an 'add' button which starts the process in code behind (.aspx.cs)  C# code

I have a global.asax file in which I declare a session object to store the shopping cart items in an encrypted string called ‘cart’.  This object is built in the session_start event of global.asax.   Also in that file is a public class CartItem with a constructor for the details [in each row of the product catalog].  

What I don’t understand is how to call this method CartItem from an aspx.cs file.  In the code behind [.aspx.cs] is the _ItemCommand event where I have this line

      List<int, CartItem> cart = (Session["cart"] as List<int, CartItem>);

 I get an ‘out of context’ error for CartItem.  This looks like a scope issue to me.  I imagine that the global.asax file is in fact global to the application and that its public methods should be visible from other files.  What am I missing?

Thanks for any advice,
0
Comment
Question by:lunarbeach
  • 8
  • 7
15 Comments
 
LVL 14

Expert Comment

by:steveberzins
Comment Utility
use the classname 'Global' remember this is an object just like any other, so you need to access the method through the object, probably best to make it static as well...
0
 
LVL 1

Author Comment

by:lunarbeach
Comment Utility
If I rename the class 'global' and redisignate the constructor method by the same name, my call to it from .aspx.cs does not work.  If I move the class to the .aspx.cs file then the object creation in asax does not see it.  I changed the call to use a dictionary for the cart list.  This is the dictionary line in the _ItemCommand event  

Dictionary <int, CartItem> cart = (Session["cart"] as Dictionary <int, CartItem>);

This is the class

public class CartItem
{
    public readonly int productID;
    public readonly string productName;
    public readonly decimal unitPrice;
    public int quantity = 1;      //  first add qty is one

    public CartItem(int _productID, string _productName, decimal _unitPrice)
    {
        productID = _productID;
        productName = _productName;
        unitPrice = _unitPrice;
    }
}

here is the session object in the global session_start event

     Session ["cart"] = new System.Collections.Generic.Dictionary<int, CartItem>();

The problem I have seems to be where to put the class so both the session and dictionary lines can see it.

??



0
 
LVL 14

Expert Comment

by:steveberzins
Comment Utility
ok, I'm just guessing here, but it may be that you need to add usings for the namespace that CartItem is in to anywhere you use CartItem objects.

if this isn't the issue, may help to provide more code, if possible/reasonable.
0
 
LVL 1

Author Comment

by:lunarbeach
Comment Utility
That seems a valid approach.  Applying a namespace to the .aspx.cs file is not unlike its use in windows forms applications.  Yet I do not know how to apply it to the .asax file.  I receive an error indicating that the content [namespace] is not valid for an application file.  Besides, are not all these files part of the namespace for the web application ?
0
 
LVL 14

Expert Comment

by:steveberzins
Comment Utility
not sure why it would complain...there is an asax.cs file, should be able to add usings there just like any other code behind file, is this what you meant when you said .asax?

and yes, if all the files are in the same (usually app root) directory, they should all have the same namespace, but since you were having problems, again without seeing your project, my supposition was that you probably have either your aspx pages in a subfolder, or the code file that CartItem is in, is in a subfolder, which, when the namespace is generated, would create a new namespace using the default project namespace, and adding .foldername to it.

you can either change the namespaces all to match, or you can add the usings to fix it.

if you are still having issues, I think from here it would make sense to see some code, to help us help you.
0
 
LVL 1

Author Comment

by:lunarbeach
Comment Utility
how would I present the code?  There are a number of files that make up the web application in Visual Studio.

As to your last comment, there is no asax.cs file.  Also there are no subfolders (except for images).

0
 
LVL 14

Expert Comment

by:steveberzins
Comment Utility
dunno if there are better ways, but usually if it is not too much code, just paste it into a comment right here, with filenames, and then the code that goes in it, if you're project is large, it may make sense to create a small project with just enough code to demonstrate your issue, and work it out from there.

I thought I've seen other questions, with links to code files, or zips of projects, but I have never created them, just seen them...if you can find where to do that, it may be a good idea.
0
Free Trending Threat Insights Every Day

Enhance your security with threat intelligence from the web. Get trending threat insights on hackers, exploits, and suspicious IP addresses delivered to your inbox with our free Cyber Daily.

 
LVL 14

Expert Comment

by:steveberzins
Comment Utility
and, forgot to ask, what version of the framework we working with on this?
0
 
LVL 14

Expert Comment

by:steveberzins
Comment Utility
silly question... List<...> should have given me the answer without having to ask :)
0
 
LVL 1

Author Comment

by:lunarbeach
Comment Utility
Here are the two relevant files
global.asax

{ <%@ Application Language="C#" %>

<script runat="server">    
    void Application_Start(object sender, EventArgs e)
    {
        // Code that runs on application startup
    }
   
    void Application_End(object sender, EventArgs e)
    {
        //  Code that runs on application shutdown
    }
       
    void Application_Error(object sender, EventArgs e)
    {
        // Code that runs when an unhandled error occurs
    }

    void Session_Start(object sender, EventArgs e)
    {
        // Code that runs when a new session is started
        // Create a dictionary for <productId, CartItem> object to store selected item details
        // in encrypted session string designated 'cart'
       
          Session ["cart"] = new System.Collections.Generic.Dictionary<int, CartItem>();
    }

    void Session_End(object sender, EventArgs e)
    {
        // Code that runs when a session ends.
        // Note: The Session_End event is raised only when the sessionstate mode
        // is set to InProc in the Web.config file. If session mode is set to StateServer
        // or SQLServer, the event is not raised.
    }
       
</script>
}
~~~~~~~~~~~~~~~~~~~~~~~~
default.aspx.cs

using System;
using System.Windows;
using System.Data;
using System.Configuration;
using System.Collections;
using System.Collections.Generic;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;

    public class CartItem
    {
        public readonly int productID;
        public readonly string productName;
        public readonly decimal unitPrice;
        public int quantity = 1;      //  first add qty is one

        public CartItem(int _productID, string _productName, decimal _unitPrice)
        {
            productID = _productID;
            productName = _productName;
            unitPrice = _unitPrice;
        }
    }

    public partial class Default2 : System.Web.UI.Page
    {

        protected void Page_Load(object sender, EventArgs e)
        {

        }
        protected void rptPlanets_ItemCommand(object source, RepeaterCommandEventArgs e)
        {
            PlanetsTableAdapters.PlanetsTableAdapter buyOne = new   PlanetsTableAdapters.PlanetsTableAdapter();
            int productID = (int.Parse)(e.CommandArgument.ToString());
            buyOne.GetData();

            // find the product name and unit price (era time segments) of selected item

            Label lblName = (e.Item.FindControl("lblname") as Label);
            Label lblUnitPrice = (e.Item.FindControl("lbltime") as Label);
            string productName = lblName.Text;
            int unitPrice = int.Parse(lblUnitPrice.Text.Substring(1));

            //  Session.Add(productID, CartItem(productID, productName, unitPrice));

            // Get cart
            Dictionary<int, CartItem> cart = (Session["cart"] as Dictionary<int, CartItem>);

            //if (cart.ContainsKey(productID))       // chk to for item in cart
            //{
            //    cart[productID].Quantity++;        // Add one to quantity of item already in cart
            //}
            //else
            //{
            //    cart.Add(productID, new CartItem(productID, productName, unitPrice));
            //}

            Response.Redirect("Cart.aspx");
        }
    }
~~~~~~~~~~~~~~~~END~~~~~~~~

0
 
LVL 14

Accepted Solution

by:
steveberzins earned 500 total points
Comment Utility
ok, first, if you can, try to delete the global.asax you have, and use the Poroject -> Add new item, and select Global Application Class, this should add the .asax, and the asax.cs files for you, I'm using a team server edition of visual studio, if you are using a different version of the IDE, this might be slightly different for you, and if there is an option to create a code behind file, make sure it is checked.

if you can't do this, for whatever reason, the manual steps are

1. in the global.asax you have, change the file so the only thing in it is
<%@ Application Codebehind="Global.asax.cs" Inherits="MyApp.Global" Language="C#" %>
replace MyApp. with the correct namespace, or remove it if you don't want to use a namespace.
I'd suggest using a namespace, and keeping them all the same...but it isn't necessary, just a good idea IMHO.

2. create a Global.asax.cs file and have at least this in it.

using System;
using System.Data;
using System.Configuration;
using System.Collections;
using System.Web;
using System.Web.Security;
using System.Web.SessionState;

namespace MyApp
{
    public class Global : System.Web.HttpApplication
    {

        protected void Application_Start(object sender, EventArgs e)
        {

        }

        protected void Application_End(object sender, EventArgs e)
        {

        }

        void Session_Start(object sender, EventArgs e)
        {
            // Code that runs when a new session is started
            // Create a dictionary for <productId, CartItem> object to store selected item details
            // in encrypted session string designated 'cart'

            Session["cart"] = new System.Collections.Generic.Dictionary<int, CartItem>();
        }

    }
}

3. I think it is good practice to keep classes to one class per code file, so put your CartItem in a new class file. putting more than one class per file and not naming the file using the class name makes for confusion if anyone else were to ever need to work on your code.
and specify the namespace or remove it so they're all the same.

using System;
using System.Data;
using System.Configuration;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;

namespace MyApp
{
    public class CartItem
    {
        public readonly int productID;
        public readonly string productName;
        public readonly decimal unitPrice;
        public int quantity = 1;      //  first add qty is one

        public CartItem(int _productID, string _productName, decimal _unitPrice)
        {
            productID = _productID;
            productName = _productName;
            unitPrice = _unitPrice;
        }
    }
}

I put this into a test project, and it all worked except the code with I don't have, like the PlanetsTableAdapter stuff.

this all boils down to namespace, or scope, as you initially said, but could be avoided for the most part, by 1. actually using namespaces, and 1. sane coding practices/standards. :) like putting the CartItem in its own class, with a name space, and then just adding a using to have easy access to it, and the fact you didn't have a .cs file for the global.asax was problematic as well, not sure how that happened, when I add one to my project, it created it with the .asax and asax.cs files and did it all for me so adding a using there was just lilke any other code behind file.

could maybe have just added an <@ Import ...> tag to the global.asax, but I like the codebehind style, and didn't even try it.
0
 
LVL 1

Author Comment

by:lunarbeach
Comment Utility
Thanks steveb
that all looks quite good.
I deleted the global.asax file and created it anew.  The option is greyed out for 'code in separate file'.  I dont' find anything in the documentaion or on the MS website that helps with this yet, though I will continue to search and read on this topic.  I attempted the manual method and got as far as step 2

2. create a Global.asax.cs file

I don't know how to do that.  I find no way to attach a file of any kind to the global.asax file.  I am using VS2005 pro. If there is a setting or switch of some type I have yet to find it.
0
 
LVL 1

Author Comment

by:lunarbeach
Comment Utility
I found how to put the .asax.cs file in the app folder ..... I will let you know how it comes together shortly.  Thanks for your patience and effort
0
 
LVL 1

Author Comment

by:lunarbeach
Comment Utility
Ok!  That worked great.  Everyone can see clearly now.  Thank you for your organizational efforts.  I am closing this question.  You have been very helpful to work thru this.  Thank you
0
 
LVL 1

Author Comment

by:lunarbeach
Comment Utility
Sorry for the delay, I thought I closed this.  {new interface here is unfamiliar yet}
Thanks
0

Featured Post

Enabling OSINT in Activity Based Intelligence

Activity based intelligence (ABI) requires access to all available sources of data. Recorded Future allows analysts to observe structured data on the open, deep, and dark web.

Join & Write a Comment

Introduction A frequently used term in Object-Oriented design is "SOLID" which is a mnemonic acronym that covers five principles of OO design.  These principles do not stand alone; there is interplay among them.  And they are not laws, merely princ…
It was really hard time for me to get the understanding of Delegates in C#. I went through many websites and articles but I found them very clumsy. After going through those sites, I noted down the points in a easy way so here I am sharing that unde…
Use Wufoo, an online form creation tool, to make powerful forms. Learn how to choose which pages of your form are visible to your users based on their inputs. The page rules feature provides you with an opportunity to create if:then statements for y…
Learn how to set-up custom confirmation messages to users who complete your Wufoo form. Include inputs from fields in your form, webpage redirects, and more with Wufoo’s confirmation options.

743 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

9 Experts available now in Live!

Get 1:1 Help Now