Advertisement
If you have a new account but are having problems posting or verifying your account, please email us on hello@boards.ie for help. Thanks :)
Hello all! Please ensure that you are posting a new thread or question in the appropriate forum. The Feedback forum is overwhelmed with questions that are having to be moved elsewhere. If you need help to verify your account contact hello@boards.ie
Hi all! We have been experiencing an issue on site where threads have been missing the latest postings. The platform host Vanilla are working on this issue. A workaround that has been used by some is to navigate back from 1 to 10+ pages to re-sync the thread and this will then show the latest posts. Thanks, Mike.
Hi there,
There is an issue with role permissions that is being worked on at the moment.
If you are having trouble with access or permissions on regional forums please post here to get access: https://www.boards.ie/discussion/2058365403/you-do-not-have-permission-for-that#latest

C# shopping basket, trying to remove an item...

1356

Comments

  • Closed Accounts Posts: 7,097 ✭✭✭Darragh29


    Just one question here... Do I have to create the actual DB on my remote server??? I see the SQL script to create tables, etc, but do I need to create the actual DB first??? If I do, what do I need to call it???


  • Registered Users, Registered Users 2 Posts: 2,931 ✭✭✭Ginger


    The sample relies on the database to get the product info

    So if you are running this on your desktop and have an SQL 2005/2008 server installed (any edition), just use the scripts to create the database and then modify the connection string to suit the changes eg change the name of the database andor/usernames and passwords

    You may need to create your own user for this database and give them execute rights on the database you created

    The script also creates the 2 stored procedures that the return the data

    Now if you are doing this on the remote server, just use whatever tools they suggest in their Help/FAQ


  • Registered Users, Registered Users 2 Posts: 2,931 ✭✭✭Ginger


    You call the database whatever you like, just change the name in the the connection string

    In the web.config you will see

    <connectionStrings>
    <add name="default" connectionString="Data Source=localhost;Initial Catalog=ShoppingCartDemo;User Id=ShoppingCartDemoUser;Password=password;"/>
    </connectionStrings>

    Change the Data Source to the name or IP of the server or whatever the hosting company says it should be

    Change Initial Catalog to the name of your database

    Change the User Id to the name of your user that will have access to the database and similarly the password


  • Closed Accounts Posts: 7,097 ✭✭✭Darragh29


    Right, its all hooked up and working now! I'm just trying to get my head around what is going on behind the scenes, and especially what happens between the Shopping Cart Demo folder and the other three folders: Common, Business and DataAccess... I've never seen a project working as it was meant to structured and approached as this one has been, although I read a small bit about Data Access Layers and Business Logic Layers and that stuff although I'lll have to read up on it all again...

    Before I go pulling the solution apart, I want to just look at what is happening and see if I can get a broad understanding as to how it all hooks up together...


  • Registered Users, Registered Users 2 Posts: 2,931 ✭✭✭Ginger


    Righty then

    I will go through the Catalog.aspx file for you and show it all works

    Firstly you need to look at the project called common. It contains 2 classes. Product and CartItem
        public class Product
        {
            public int Id { get; set; }
            public string Name { get; set; }
            public string Description { get; set; }
            public int Cost { get; set; }
        }
    
       public class CartItem : Product
        {
            public int Amount { get; set; }
        }
    
    

    The product class represents strangely enough the product with a Name, Description and Cost etc. CartItem inherits (gets the same) these properties from Product and add its own property called Amount. This allows us to have a number of the same products in the cart and just to hold an amount value for them.

    These classes are common to all the projects in the solution (hence the project name common).

    Now in Catalog.aspx, it has just a couple of things on it. One is a repeater which shows the data the way I want it.

    So if you look at the repeater in the source code of the aspx fille you see
    <asp:Repeater ID="_Catalog" runat="server">
        <HeaderTemplate>
        <table>
        <tr>
        <td>Name</td>
        <td>Description</td>
        <td>Cost</td>
        <td>&nbsp;</td>
        </tr>
        </HeaderTemplate>
        <ItemTemplate>
        <tr>
        <td><%# ((Product)Container.DataItem).Name %></td>
        <td><%# ((Product)Container.DataItem).Description %></td>
        <td><%# ((Product)Container.DataItem).Cost.ToString(CultureInfo.InvariantCulture) %></td>
        <td><asp:Button ID="_AddToCart" CommandArgument="<%# ((Product)Container.DataItem).Id.ToString() %>" CommandName="AddToCart" runat="server" Text="Buy this" /> </td>
        </tr>
        </ItemTemplate>
        <FooterTemplate>
        </FooterTemplate>
        </asp:Repeater>
    

    What a repeater does, is it takes a datasource, in our case a list of products and outputs them in the way that we define it in the <ItemTemplate> part of the repeater.

    You will see that I have a HTML table row (tr) and a couple of cells in which I put the different values using the Container.DataItem function... except I tell to make it into a Product class so I can access the properties easier
    <%# ((Product)Container.DataItem).Name %>
    

    Now the final trick is the button.
    
    <asp:Button ID="_AddToCart" CommandArgument="<%# ((Product)Container.DataItem).Id.ToString() %>" CommandName="AddToCart" runat="server" Text="Buy this" />
    

    What this does is the following. I tell it to send the Id of the product back using the CommandArgument part of the code and I tell it that I want the command it sends back to be AddToCart. I could change this to any value I want.

    So every product in the list outputs a Name, Description and Cost and a button with its Id as the command argument in a seperate table row.

    Now into the code behind of Catalog.aspx

    The first thing that happens when you enter the page is that I assign a handler to catch the events from the repeater.
    protected override void OnInit(EventArgs e)
            {
                //Add an event handler to handle our button events in the repeater
                _Catalog.ItemCommand += CatalogItemCommand;
    
                base.OnInit(e);
            }
    

    This catches when the button is clicked.

    Next thing is that the Page_Load event fires.
          protected void Page_Load(object sender, EventArgs e)
            {
                //Only bind the first time
                if (Page.IsPostBack) return;
                _Catalog.DataSource = ProductBl.GetAllProducts();
                _Catalog.DataBind();
    
                _CartSize.Text = Session["Cart"] != null ? ((List<CartItem>) Session["Cart"]).Count.ToString() : "0";
            }
    

    I check to see if the page is a postback because I dont want to rebind the data everytime, only the first time.

    My DataSource for the repeater is a function in the ProductBL (Business Layer). It returns a generic list of products.
    public static List<Product> GetAllProducts()
            {
                ProductDal productDal = new ProductDal();
                return productDal.GetAllProducts();
            }
    

    The function GetAllProducts in the ProductBl is basically a pass through to the DataAccess project. Because I have minimal business logic in this solution I dont really need a Business layer but I put it in just to show how its done.

    The GetAllProducts function in the DataAccess project (ProductDal.cs) does the following.
    public List<Product> GetAllProducts()
            {
                DbHelper dbHelper = new DbHelper();
    
                DataSet dataSet = dbHelper.RunProcDs("usp_select_allProducts");
    
                return Common.CreateList<Product>(dataSet);
            }
    

    Firstly it creates a DbHelper object which manages all my connections and interactions with the database. By using something like this helper object I dont need to do all the same open db stuff every time.

    I create a dataset and tell it that its to be filled from the RunProcDs command in the helper. I tell it run the stored procedure usp_select_allProducts.

    This stored proc is simply the following SQL
    SELECT Id,[Name],Description,Cost FROM Product
    

    I then use another one of my helper classes. This one takes a dataset and creates a list of objects from that data. This function is located in Common.cs file.

    It does this using a trick called Reflection. In .NET you can find out all the property names of an object. So get all the names of the properties of the object I want to create, in this case Product, which is Id,Name,Description and Cost. See the names of the properties in the class are the same as the names of the columns in the database.

    So I tell it to loop through all the properties in the class and put the value of the column with the same name into the property. Eg

    Product.Id = datarow["Id"]

    And because the data type of the property and the one in the database are the same it works happily.
            internal static T CreateObject<T>(DataRow row) where T : new()
            {
                PropertyInfo[] propertyInfos = typeof (T).GetProperties();
    
                T obj = new T();
    
                foreach (var info in propertyInfos)
                {
                    info.SetValue(obj, row[info.Name], null);
                }
    
                return obj;
            }
    
            internal static List<T> CreateList<T>(DataSet dataSet) where T : new()
            {
                List<T> list = new List<T>();
    
                foreach (DataRow dataRow in dataSet.Tables[0].Rows)
                {
                    list.Add(CreateObject<T>(dataRow));
                }
    
                return list;
            }
    

    How do I tell it what object to create. Using a technique known as Generics, I can tell the program to expect some type of object and to work with that.

    So in the function CreateObject for example, I tell it that it will be an object of type T (ie I dont know), and that I will let it know at runtime.

    The reason for using Generics means I dont need to create a function for each object, which if you are using a lot of objects that would be a lot of repeated code.

    At this stage the DataAccess project has a list of products and returns that to the Business project which in turn returns it to Catalog.aspx. This looks like a long trip but because everything is designed to just get the job done its very quick.

    The repeater binds to this list and the stuff in ItemTemplate tells it how to show it.

    With me so far??

    Right then, on to the all important button that adds stuff to the cart.

    When you click the button, the page does a postback, and because I have an event handler to handle anything that happens in the repeater, it goes in there. (It doesnt rebind because we check for that)

    So the code for the function is
    private void CatalogItemCommand(object source, RepeaterCommandEventArgs e)
            {
                if (!Equals(e.CommandName, "AddToCart")) return;
    
                //Check if the session is null and assign the correct list
                List<CartItem> cartItems = Session["Cart"] != null ? (List<CartItem>) Session["Cart"] : new List<CartItem>();
    
                //Get the item I want from the database.
                CartItem cartItem = ProductBl.GetItem<CartItem>(Convert.ToInt32(e.CommandArgument));
    
                // This section can be used if you wanted to see if there was an item matching.
                CartItem hasitem = cartItems.Find((delegate(CartItem ci) { return ci.Id == cartItem.Id; }));
    
                //If the item exists, get its current amount and add 1. Then remove it
                if (hasitem != null)
                {
                    cartItem.Amount = hasitem.Amount + 1;
                    cartItems.Remove(hasitem);
                }
                else
                {
                    cartItem.Amount = 1;
                }
    
                //add our item to the cart with its correct amount
                cartItems.Add(cartItem);
    
                //put the cart back into the session state
                Session["Cart"] = cartItems;
    
                //This displays the size of the list which is the number of items but not the quantity
                _CartSize.Text = cartItems.Count.ToString();
            }
    

    What I do first is check what type of command I am getting, ie AddToCart. If you have a couple of different buttons or linkbuttons or whatever you could use that check to find what code to run.
    List<CartItem> cartItems = Session["Cart"] != null ? (List<CartItem>) Session["Cart"] : new List<CartItem>();
    

    Now the next line creates a new list of cartitem and assigns the value either to a new list or the list in my session. The syntax that it uses is just shorthand.

    So now I have a list of cartitem.
    CartItem cartItem = ProductBl.GetItem<CartItem>(Convert.ToInt32(e.CommandArgument));
    

    I create a new cartitem by using the function caaled GetItem and pass in the id of the product I want. This Id is the CommandArgument that i set in my button. The getting the details works the exact same as getting the list as described above.

    Now the next bit is a bit funky.

    I want to see if the person already put the same product in the cart and if they did, I want to increase the quantity by 1.

    So I create a new cartitem and try to find it in my list. If its there, it will come back as the same object otherwise it will be null.

    So I check to see if my hasitem is null and if its not, I add 1 to the amount and then I remove it from my list so that I only add the object once. You will see why in a minute.

    If the hasitem is null, I just use my new cartitem above and set amount to 1.

    After all that, I have a cartitem that has the correct amount and add that to the list.

    I then put the list back into the session (or for the first time it doesnt matter) and then I set the label to the count size of the list, which isnt the actual number of items but just the number of items in the list eg if you have 2 products with amounts of 2, it wont show 4, it will only show that you have 2 items because its using the count on the list.

    So that is the catalog page explained.

    I will do ShoppingCart in the next post!


  • Registered Users, Registered Users 2 Posts: 2,931 ✭✭✭Ginger


    Now for ShoppingCart.aspx

    Again we are using a repeater in much the same way as we are using it in catalog. In this case I have 2 buttons, one is Update and the other Remove.

    They are different in a respect to the add method in Catalog.aspx because they dont contain a CommandArgument because it is not needed.

    The reason for this, is because we are using our own maintained list. ie we know where everything is.

    The update button doesnt do anything but is just there to show you can have more than 1 button.

    So the Repeater definition looks like this
      <asp:Repeater ID="_Cart" runat="server">
        <HeaderTemplate>
        <table>
        <tr>
        <td>Name</td>
        <td>Description</td>
        <td>Cost</td>
        <td>Amount</td>
        <td>&nbsp;</td>
        <td>&nbsp;</td>
        </tr>
        </HeaderTemplate>
        <ItemTemplate>
        <tr>
        <td><%# ((CartItem)Container.DataItem).Name %></td>
        <td><%# ((CartItem)Container.DataItem).Description %></td>
        <td><%# ((CartItem)Container.DataItem).Cost.ToString(CultureInfo.InvariantCulture) %></td>
        <td><%# ((CartItem)Container.DataItem).Amount.ToString(CultureInfo.InvariantCulture) %></td>
        <td><asp:Button ID="_Update" CommandName="Update" runat="server" Text="Update (no function)" /> </td>
        <td><asp:Button ID="_Remove" CommandName="Remove" runat="server" Text="Remove This" /> </td>
        
        </tr>
        </ItemTemplate>
        <FooterTemplate>
        </FooterTemplate>
        </asp:Repeater>
    

    In our page load, we bind the repeater to the List we have held in session. I check to see if the cart is there, in case of session timeout :)

    The reason I have a function called BindCart, is that I need to bind it again once I have deleted information so to save a couple of lines, I use the same function.

    Right the user clicks the update button, the CartItemCommand is run. Since I dont handle the Update command nothing happens.

    Click on delete and here is what happens
    void CartItemCommand(object source, RepeaterCommandEventArgs e)
            {
                //Check what button was pressed and do stuff
                if(e.CommandName=="Remove" && Session["Cart"]!=null)
                {
                    List<CartItem> cartItems = (List<CartItem>) Session["Cart"];
                    //since the session is a controlled list, just remove at the index
                    cartItems.RemoveAt(e.Item.ItemIndex);
                    //Assign back to session
                    Session["Cart"] = cartItems;
                    BindCart();
                }
            }
    

    I check to see if the Command is remove and that the cart is still in Session. Have to check each time otherwise you could get some dodgy errors.

    I create a list and copy the cart from the session to this list.

    I tell it to remove the item at a particular index, ie the index that it was in the repeater.

    Now this the bit. Both use 0 indexes lists ie the lists start counting from 0. When you click the button, it sends the eventhandler some data included is the position in the index you clicked.

    So say you had 10 items in your cart, you would have a list from 0-9. If you clicked on the last item (index 9), it would send that data back to the eventhandler. Since the repeater and cart are synced you need to just delete at index 9 to remove the last one. Ok?

    So we just delete at the position that we need to do and copy the cart back into session and rebind the repeater. thats it.

    This technique wouldnt work if we were using sorting because the lists would be out of sync. In the case of adding sorting you need to add the command argument with the id and then find the object with that ID in the list.

    That is how simple it is.


  • Closed Accounts Posts: 7,097 ✭✭✭Darragh29


    Just sent ya an e-mail there Ginger...


  • Registered Users, Registered Users 2 Posts: 2,931 ✭✭✭Ginger


    Hi

    Going to reply to the message on the forum. Just easier for people to see

    Ok

    To use your dropdown selection with the Catalog.aspx file you will need a new method in DataAccess eg
    public List<Product> GetAllProducts(string catName)
            {
                SqlParameter[] sqlParameters = {
                                                   DbHelper.MakeInParam("CatName", SqlDbType.Varchar, 50, catName)
                                               };
                DataSet dataSet = new DbHelper().RunProcDs("usp_select_AllProductsByCat", sqlParameters);
                return Common.CreateList<Product>(dataSet);
            }
    

    This will return a list of products by Category. Modify it so that you can pass in how ever many arguments you need to get your data back.

    Now you see how the page for Shopping cart is done at the moment in that project.

    You can copy the repeater from that page into your MainText.aspx and replace where you currently show the shopping cart.

    You will need to modify the code behind to add a repeater event handler (the part in the OnInit).

    Now when you click purchase, you can use the exact same logic I am using to add to the list, but after that, you need to bind the ShoppingCart repeater to the Session and you will then have a delete button for each item. If you want to change it to a link button that is fine too the same logic still applies here.

    Now you might need to change the Product class in Common to match your database structure, which quickly looking at what you show in the catalog is

    Retail_Price, Product_Description and Component_Manufacturer and hopefully(!!!) some ID field..

    You will only need to change 1 class, and add some stored procs, and change the repeater to use the new property names to make this work.

    So in a nutshell

    On MainTest.aspx

    Once you get the value of DropDownList3 (the Engine dropdown), pass that value to the function to get your list of products that match (in your case, I see you pass all 3 vars in)

    Eg if you were to use a repeater for this part, you would do something like this
    
    function that handles DropDownList3 SelectedItemChanged
    
    CatalogRepeater.DataSource = Business.GetAllPoducts(DropDownList3.SelectedValue); //change to use all 3
    CatalogRepeater.DataBind();
    
    

    Replace all the code that currently show the Product catalog with a repeater, designed the same way that it is use in the Catalog.aspx page.

    This would display the list of Products for that engine in this case. Each would have a purchase button with the ID of the product and you would be able to use the same logic as in Catalog.aspx. Just change the names you use in the class eg Description now becomes Product_Description, Cost becomes Retail_Price and Name can be changed to the Component_Manufacturer

    Now in the function CatalogItemCommand

    You would add a new new bit after you add the List of Cartitems into Session to bind the ShoppingCartRepeater to that.

    Now to make this all easier to understand, I just recreated Catalog.aspx with the changes like this

    Its just both pages combined and the only change is that when you add an item to the cart, I bind the shopping cart.


  • Closed Accounts Posts: 7,097 ✭✭✭Darragh29


    I'm gonna give this a shot, there's a river near my house and I can see myself jumping into it before this day is up! :D:D:D


  • Closed Accounts Posts: 7,097 ✭✭✭Darragh29


    Is the approach with this meant to be that I continue to post in my 3 values from my dropdown list into my DB? Then when they are in there is it that I bind my application to the DB values posted after my Button1_Click event???


  • Advertisement
  • Registered Users, Registered Users 2 Posts: 2,931 ✭✭✭Ginger


    Button 1 is the purchase button isnt it

    Ok the way that I would do this, is the following

    You will notice there are 2 repeaters on the new Catalog.aspx page.

    I am going to be very blunt and tell you to use a repeater and scrap your previous methods as its not good, confusing the crap out of you and its easier to see what is happening with this code (a lot less spaghetti!) I dont normally tell people to do this :)

    Where you normally outputted your car part and session info, remove it. Remove your purchase button as well, basically I want all the stuff including what is in the DropdownList3 SelectedIndex changed removed. Keep Ddl1 and 2 as is they are ok for the moment.

    Use the repeater sample I gave you and edit the item template to output the information how you want.

    In the database create a new stored procedure that gets back the list of products eg From your code

    SELECT * FROM Vehicle_Data WHERE Vehicle_Make = '" + DropDownList1.SelectedItem.Value + "' AND Vehicle_Model = '" + DropDownList2.SelectedItem.Value + "' AND Engine_Type = '" + DropDownList3.SelectedItem.Value + "'

    CREATE PROCEDURE dbo.usp_select_product
    (
    @Make VARCHAR(200),
    @Model VARCHAR(200),
    @Engine VARCHAR(200)
    )
    SELECT etc etc

    Now create a method in DataAccess that takes 3 string params and executes that proc and returns a list of information (similar to GetAllProducts is written)

    In Business create a method that takes 3 string params and returns a List<Product>, same as GetAllProducts

    Finally in your SelectedIndexChanged in DropDownList3 (assuming the repeater is called _Catalog)

    _Catalog.DataSource = Business.YourMethodName(string1,string2,string3);
    _Catalog.DataBind();

    This will output the data in the way you want, and give you a purchase button for each item.

    Now you can use the exact same code as in Catalog.aspx to put the items in the cart and show them in the Cart repeater.

    What I am trying to do here is simplify the whole process for you, so you can just databind and forget :)

    I am working on the idea that you are using the solution I provided as a base at this point.. If you are'nt it would be handy to know...


  • Registered Users, Registered Users 2 Posts: 2,931 ✭✭✭Ginger


    Additionally, if you want to supply the database, I can do a bit on this, and probably show how this works ...


  • Closed Accounts Posts: 7,097 ✭✭✭Darragh29


    Ginger wrote: »
    Button 1 is the purchase button isnt it

    Yip, the three Dropdown Lists are linked, so the idea being that by using the 3 Dropdown Lists, I can get make, model & engine type from a user. When I have that, I've posted these three pieces of info into my DB on Button1_Click.
    Ginger wrote: »
    I am going to be very blunt and tell you to use a repeater and scrap your previous methods as its not good, confusing the crap out of you and its easier to see what is happening with this code (a lot less spaghetti!) I dont normally tell people to do this :)

    I'm trying to keep with how you are approaching this so I can pick up the proper approach you've used, but I have to admit a lot of it is going over my head because I've been doing in my own half arsed way up until now!

    Where you normally outputted your car part and session info, remove it. Remove your purchase button as well, basically I want all the stuff including what is in the DropdownList3 SelectedIndex changed removed. Keep Ddl1 and 2 as is they are ok for the moment.

    Use the repeater sample I gave you and edit the item template to output the information how you want.

    In the database create a new stored procedure that gets back the list of products eg From your code

    SELECT * FROM Vehicle_Data WHERE Vehicle_Make = '" + DropDownList1.SelectedItem.Value + "' AND Vehicle_Model = '" + DropDownList2.SelectedItem.Value + "' AND Engine_Type = '" + DropDownList3.SelectedItem.Value + "'

    CREATE PROCEDURE dbo.usp_select_product
    (
    @Make VARCHAR(200),
    @Model VARCHAR(200),
    @Engine VARCHAR(200)
    )
    SELECT etc etc

    Now create a method in DataAccess that takes 3 string params and executes that proc and returns a list of information (similar to GetAllProducts is written)

    In Business create a method that takes 3 string params and returns a List<Product>, same as GetAllProducts

    Finally in your SelectedIndexChanged in DropDownList3 (assuming the repeater is called _Catalog)

    _Catalog.DataSource = Business.YourMethodName(string1,string2,string3);
    _Catalog.DataBind();

    This will output the data in the way you want, and give you a purchase button for each item.

    Now you can use the exact same code as in Catalog.aspx to put the items in the cart and show them in the Cart repeater.

    What I am trying to do here is simplify the whole process for you, so you can just databind and forget :)

    I am working on the idea that you are using the solution I provided as a base at this point.. If you are'nt it would be handy to know...[/QUOTE]

    I am using the solution you provided but I'm going to be honest and say that a lot/most of it is going over my head! I'm just not fluent enough with asp.net and C# to get my head around what is happening. Some of the stuff I'm seeing here for the first time, repeaters, stored procedures, data access laters, business layers, etc... I was already on shaky ground with functions, arguments, and methods! :D:D:D


  • Registered Users, Registered Users 2 Posts: 2,931 ✭✭✭Ginger


    Alrighty,

    Understood :)

    Send me on the table structure of you Vehicle_Data table and I can probably recreate the classes for this...

    Additionally its better with the dropdowns have the values as numbers rather than text values.

    Currently I am doing a refactoring project with another company and teaching them the same tricks :)


  • Closed Accounts Posts: 7,097 ✭✭✭Darragh29


    Ginger wrote: »
    Alrighty,

    Understood :)

    Send me on the table structure of you Vehicle_Data table and I can probably recreate the classes for this...

    Additionally its better with the dropdowns have the values as numbers rather than text values.

    Currently I am doing a refactoring project with another company and teaching them the same tricks :)

    As rattled as I am with the new "proper" approach you're showing me, I'll eventually be able to make sense of it when I get my head around what bits of the solution are interacting with what other bits and it all starts sinking in...


  • Registered Users, Registered Users 2 Posts: 2,931 ✭✭✭Ginger


    No worries, the main thing is to look at it a bit like this.

    You are creating a load of pieces that work together much in the same was an engine :) its looks complex to the untrained eye, but in reality its just a simple explosion provides energy eventually to move the wheels!

    And not to say you are untrained, you just need to learn how all the parts fit together!


  • Closed Accounts Posts: 7,097 ✭✭✭Darragh29


    I'm spending tonight reading up on Classes, Methods & Objects, and tomorrow I'm going to read the whole thread again... I think this is where my problem is with this, when you say I need to write a class, I don't know really what a class does 'cos I never used on before in C#, I did years ago in C but that was just to do an exam, I never really understood what was going on!


  • Closed Accounts Posts: 7,097 ✭✭✭Darragh29


    What I did tonight was refreshed my C# basics and also tried to bring over my old MainTest.aspx file and codebehind page into the solution that Ginger did for me. I had loads and loads of compilation errors mainly due to code missing from my web.config file, but I've got the page to compile now, except that I've a load of schema warnings (26 of em) and for some weird reason, all my labels and controls in my cs page are coming up as "Does not exist in the current context", although when I go to use intellisense, they are all there no problem and all the controls exist in my aspx page which I thought meant I could work on them anywhere in my cs page....

    :confused::confused::confused:

    What I'm trying to do here is now that I have my Dropdown Ajax 3 layer menu in the same project as Ginger's solution, I can start trying to tie the whole thing up together and see if I can get this working as I want to...

    Right, bed time...


  • Registered Users, Registered Users 2 Posts: 2,931 ✭✭✭Ginger


    Ok

    Might I suggest something

    Go slowly

    Dont bring in old code in such a large chuck, it just adds to the problem..

    WHat you should do is create the dropdowns again and get them working so that they bring back the correct cascade sequence.

    Then start looking at binding the correct data to the repeater.

    Once you have done that you can skin the page and its nearly finished for you


  • Advertisement
  • Registered Users, Registered Users 2 Posts: 2,931 ✭✭✭Ginger


    As for the errors, did you add the Test.aspx, the code behind file and the designer file when you added them to the solution


  • Closed Accounts Posts: 7,097 ✭✭✭Darragh29


    Ok, I've gone back to the start of the task here again. I've just taken your solution and have taken out all my Ajax menu and will try to start from scratch again and take smaller steps...


  • Registered Users, Registered Users 2 Posts: 2,931 ✭✭✭Ginger


    The smaller the step the easier to debug... :)


  • Closed Accounts Posts: 7,097 ✭✭✭Darragh29


    Here's the latest problem...

    Let's just forget about my own code for for a minute, the AJAX Drop down solution I've been using is available as a "boil in the bag/ready to go" solution from www.asp.net. So I went back there and just downloaded the solution from the site as it was before I fiddled around with it. All I'm trying to do is get this dropdown solution into the wider solution you gave me and even that can't be done using .net without a headache!

    I've been trying to do this using MS developer 2008 with your solution open in that environment and I've been getting stupid errors all week, all relating to the Ajax/dropdown part of the solution.

    Then I open the same AJAX solution using MS Developer 2005 and no problem whatsoever!

    Then I try to open your solution in MS Developer 2005 and I get another error that I've been getting there previously, that forced me to work on your solution using MS Developer 2008. Now that I've been using MS Developer 2008, I can't open my AJAX solution that is key to filtering the data I need to work...

    No matter what I try to do when using this framework, I feel like I'm standing on my head and p*ssing down upon myself!


  • Registered Users, Registered Users 2 Posts: 2,791 ✭✭✭John_Mc


    Darragh29 wrote: »
    Here's the latest problem...

    Let's just forget about my own code for for a minute, the AJAX Drop down solution I've been using is available as a "boil in the bag/ready to go" solution from www.asp.net. So I went back there and just downloaded the solution from the site as it was before I fiddled around with it. All I'm trying to do is get this dropdown solution into the wider solution you gave me and even that can't be done using .net without a headache!

    I've been trying to do this using MS developer 2008 with your solution open in that environment and I've been getting stupid errors all week, all relating to the Ajax/dropdown part of the solution.

    Then I open the same AJAX solution using MS Developer 2005 and no problem whatsoever!

    Then I try to open your solution in MS Developer 2005 and I get another error that I've been getting there previously, that forced me to work on your solution using MS Developer 2008. Now that I've been using MS Developer 2008, I can't open my AJAX solution that is key to filtering the data I need to work...

    No matter what I try to do when using this framework, I feel like I'm standing on my head and p*ssing down upon myself!

    It's amusing the way you blame .net for everything, and not your lack of knowledge on how the framework works :)

    Post some error messages there and we should be able to help out


  • Closed Accounts Posts: 7,097 ✭✭✭Darragh29


    John_Mc wrote: »
    It's amusing the way you blame .net for everything, and not your lack of knowledge on how the framework works :)

    Post some error messages there and we should be able to help out

    Ah I know it's my lack of knowledge that is the problem here, I'm under no illusions about that, but I think if I'm trying to open a solution when I'm using Developer 2008 running on the 2.0 framework and I try to do the same thing with MS Developer 2005 runnning on the 2.0 framework, I didn't expect to have a problem!

    I'm sure you remember back when you started this, by virtue of the fact that you were inexperienced, you always think by default that the problem is something you've done in respect of a line of code or a statement or something, but not some stupid little issue that stops you successfully running a solution on two different development programs running on the same framework... Some of the errors I'm googling, others seem to be having the same issues and they are down to bugs in the application.


  • Advertisement
  • Closed Accounts Posts: 7,097 ✭✭✭Darragh29


    John_Mc wrote: »

    Post some error messages there and we should be able to help out

    Right, here we go. I'm back using MS Developer 2005 and my AJAX Dropdown menu is working fine, so no issues there...

    I've tried to copy Gingers solution into this project and I'm getting one error that is a show stopper. I've done two screen shots to show the problem. This same problem last week led me to ditch MS Dev 2005 and jump to MS Dev 2008 and that got rid of this particular problem. Now I'm finding that my AJAX solution does work on MS Dev 2005 but not on MS Dev 2008. So I'm stuck with two development environments with one half of what I hope is a full solution working on each environment!


  • Registered Users, Registered Users 2 Posts: 2,791 ✭✭✭John_Mc


    Darragh29 wrote: »
    Right, here we go. I'm back using MS Developer 2005 and my AJAX Dropdown menu is working fine, so no issues there...

    I've tried to copy Gingers solution into this project and I'm getting one error that is a show stopper. I've done two screen shots to show the problem. This same problem last week led me to ditch MS Dev 2005 and jump to MS Dev 2008 and that got rid of this particular problem. Now I'm finding that my AJAX solution does work on MS Dev 2005 but not on MS Dev 2008. So I'm stuck with two development environments with one half of what I hope is a full solution working on each environment!

    Google returned plenty of results for this. Check out this and see if it helps.


  • Registered Users, Registered Users 2 Posts: 2,931 ✭✭✭Ginger


    Alrighty same error

    What is the folder path to the solution??? Full path

    Are you running this in the Inetpub\wwwroot directory if so, we need to make a virtual folder and make it into an application

    Additionally if you are running this in a folder that has many levels, check and see if there is a web.config in the folders above it


  • Closed Accounts Posts: 7,097 ✭✭✭Darragh29


    Right, that other error (ISS Virtual Folder), error has disappeared and now I have 4 different errors that I haven't seen before...


  • Registered Users, Registered Users 2 Posts: 2,931 ✭✭✭Ginger


    I see your issue now and why you are getting your problems

    you have 2 web projects there..

    The structure of that solution is incorrect

    You probably created a new website project and then added the projects that i made is that right??? You see how you have 2 app_code and app_data folders

    If you look at the solution in 2008 you will see that the Business, DataAccess and Common are all projects rather than folders which is the case in yours.

    To make this work with existing solution, I suggest that you use 2008 only.

    Add a reference in the ShoppingCartDemo project (the one that is highlighted in the picture)

    You can add the existing ASMX file to this solution (there could be an issue with namespaces) and you can also add the existing ajax.aspx file too.


  • Advertisement
  • Closed Accounts Posts: 7,097 ✭✭✭Darragh29


    I think I need to pick one development program and stick to it, so here we go, it's MS Dev 2008. The other version is now in the bin...


  • Registered Users, Registered Users 2 Posts: 2,931 ✭✭✭Ginger


    Easiest thing being honest


  • Closed Accounts Posts: 7,097 ✭✭✭Darragh29


    What I've done is I've taken the code from my Ajax.aspx and codebehind page and placed it into the empty Default.aspx page in Ginger's solution.

    I'm getting the following 4 errors when I do this. I haven't modifed the config.web file yet because when I did that before, I ended up generating a load of errors. I can't add an assembly reference into the project for System.Web.UI, when I click on "Add Reference", the above library isn't there when I try to add it, I'm wondering would this be the problem?


  • Registered Users, Registered Users 2 Posts: 2,791 ✭✭✭John_Mc


    Darragh29 wrote: »
    What I've done is I've taken the code from my Ajax.aspx and codebehind page and placed it into the empty Default.aspx page in Ginger's solution.

    I'm getting the following 4 errors when I do this. I haven't modifed the config.web file yet because when I did that before, I ended up generating a load of errors. I can't add an assembly reference into the project for System.Web.UI, when I click on "Add Reference", the above library isn't there when I try to add it, I'm wondering would this be the problem?

    Think you need to add references to System.Web.UI and System.Web.UI.Extensions.

    You should be able to browse to it if its not listed


  • Closed Accounts Posts: 7,097 ✭✭✭Darragh29


    Ginger wrote: »
    Easiest thing being honest

    Buy a solution I think!


  • Closed Accounts Posts: 7,097 ✭✭✭Darragh29


    John_Mc wrote: »
    Think you need to add references to System.Web.UI and System.Web.UI.Extensions.

    You should be able to browse to it if its not listed

    That's cleared those 4 errors but generated another 8. I'm obviously missing a reference somewhere that exists in MSD 2005 but not in MSD 2008. I'm starting to get my head around the problem...


  • Closed Accounts Posts: 7,097 ✭✭✭Darragh29


    I'll just have to pick my way through the solution in both environments and see what is in 2005 that is missing in 2008 in terms of assembly references...


  • Registered Users, Registered Users 2 Posts: 2,931 ✭✭✭Ginger


    Can you post the code in default.aspx.cs (ie the codebehind file) so I can see whats happening


  • Registered Users, Registered Users 2 Posts: 2,931 ✭✭✭Ginger


    Also you need to add your Cars.asmx as a web reference for your web project


  • Closed Accounts Posts: 7,097 ✭✭✭Darragh29


    Ginger wrote: »
    Also you need to add your Cars.asmx as a web reference for your web project

    I'd say this is my problem. I have 8 errors but the last one below I think is the cause of all the others... here's my codebehind page:


    using System;
    using System.Web.UI;
    using System.Data;
    using System.Configuration;
    using System.Collections;
    using System.Web;
    using System.Web.Security;
    using System.Web.UI.WebControls;
    using System.Web.UI.WebControls.WebParts;
    using System.Web.UI.HtmlControls;
    using System.Web.Services;
    using System.Collections.Specialized;
    using AjaxControlToolkit;

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

    protected void DropDownList3_SelectedIndexChanged(object sender, EventArgs e)
    {
    // Get selected values
    string make = DropDownList1.SelectedItem.Text;
    string model = DropDownList2.SelectedItem.Text;
    string color = DropDownList3.SelectedItem.Text;

    // Output result string based on which values are specified
    if (string.IsNullOrEmpty(make))
    {
    Label1.Text = "Please select a make.";
    }
    else if (string.IsNullOrEmpty(model))
    {
    Label1.Text = "Please select a model.";
    }
    else if (string.IsNullOrEmpty(color))
    {
    Label1.Text = "Please select a color.";
    }
    else
    {
    Label1.Text = string.Format("You have chosen a {0} {1} {2}. Nice car!", color, make, model);
    }
    }

    [WebMethod]
    [System.Web.Script.Services.ScriptMethod]
    public static CascadingDropDownNameValue[] GetDropDownContentsPageMethod(string knownCategoryValues, string category)
    {
    return new CarsService().GetDropDownContents(knownCategoryValues, category);
    }


    }


  • Advertisement
  • Registered Users, Registered Users 2 Posts: 2,931 ✭✭✭Ginger


    First off

    Right click on the ShoppingCartDemo project (the fourth one in the solution) and click add web reference and add Cars.asmx (that will remove part of the issue) and then add it with a using command

    Second bit, you are missing a namespace so

    using System;
    using System.Web.UI;
    using System.Data;
    using System.Configuration;
    using System.Collections;
    using System.Web;
    using System.Web.Security;
    using System.Web.UI.WebControls;
    using System.Web.UI.WebControls.WebParts;
    using System.Web.UI.HtmlControls;
    using System.Web.Services;
    using System.Collections.Specialized;
    using AjaxControlToolkit;

    namespace ShoppingCartDemo
    {


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

    protected void DropDownList3_SelectedIndexChanged(object sender, EventArgs e)
    {
    // Get selected values
    string make = DropDownList1.SelectedItem.Text;
    string model = DropDownList2.SelectedItem.Text;
    string color = DropDownList3.SelectedItem.Text;

    // Output result string based on which values are specified
    if (string.IsNullOrEmpty(make))
    {
    Label1.Text = "Please select a make.";
    }
    else if (string.IsNullOrEmpty(model))
    {
    Label1.Text = "Please select a model.";
    }
    else if (string.IsNullOrEmpty(color))
    {
    Label1.Text = "Please select a color.";
    }
    else
    {
    Label1.Text = string.Format("You have chosen a {0} {1} {2}. Nice car!", color, make, model);
    }
    }

    [WebMethod]
    [System.Web.Script.Services.ScriptMethod]
    public static CascadingDropDownNameValue[] GetDropDownContentsPageMethod(string knownCategoryValues, string category)
    {
    return new CarsService().GetDropDownContents(knownCategoryValues, category);
    }


    }
    }


  • Closed Accounts Posts: 7,097 ✭✭✭Darragh29


    After I changed the namespace line, 7/8 of the errors disappeared so there's only 1 left...

    The type or namespace name 'CarsService' could not be found (are you missing a using directive or an assembly reference?)

    You can see my Web reference on the screenshot below. Do I just call it up with:

    using CarsService;

    ???

    I've done this but still have the 1 remaining error so I'm wondering am I calling it up correctly with using CarsService; ???


  • Registered Users, Registered Users 2 Posts: 2,931 ✭✭✭Ginger


    Ok, the second error is usually that the application hasnt being compiled...

    The first one, you need to change it to using localhost; because that is the name of the reference


  • Closed Accounts Posts: 7,097 ✭✭✭Darragh29


    I've changed the name of the web reference to CService and changed the line in the codebehind page to:

    using CServce;

    But still have the 1 error....

    There is an option to help binding the CarsService and it has changed the using CService; to using ShoppingCartDemo.CService;


  • Closed Accounts Posts: 7,097 ✭✭✭Darragh29


    This was the problem here:

    public static CascadingDropDownNameValue[] GetDropDownContentsPageMethod(string knownCategoryValues, string category)


    I had to change it to...

    public static ShoppingCartDemo.CService.CascadingDropDownNameValue[] GetDropDownContentsPageMethod(string knownCategoryValues, string category)


  • Registered Users, Registered Users 2 Posts: 2,931 ✭✭✭Ginger


    You can probably remove the ShoppingCartDemo.Cservice and replace it with a using ShoppingCartDemo.CService


  • Closed Accounts Posts: 7,097 ✭✭✭Darragh29


    Ginger wrote: »
    You can probably remove the ShoppingCartDemo.Cservice and replace it with a using ShoppingCartDemo.CService

    I tried that and it came back with an error saying there was an ambigious reference between two methods so I tried adding in the ShoppingCartDemo. and all is working grand now...

    I had to add enableEventValidation="false" Into the first line in my aspx page because I was getting this error, but when I changed enableEventValidation="false" to enableEventValidation="true", the solution worked grand...

    So now I have the two parts I need in my solution, here comes the hard part!!! :D:D:D


  • Closed Accounts Posts: 7,097 ✭✭✭Darragh29


    Just wondering should I be trying to get these two solutions into the same aspx file before trying to do any further with this???


  • Closed Accounts Posts: 7,097 ✭✭✭Darragh29


    Am nearly there with this. Ginger you'll never have to buy a pint in Dublin again if this works for me! :D;):D


  • Advertisement
  • Registered Users, Registered Users 2 Posts: 2,931 ✭✭✭Ginger


    Good to hear, Dublin is wickedly cheaper than here anyways... is it coming along ok?


Advertisement