How to run the SQL code and loop/display the results on the same aspx page?

Viewed 97

I'm trying to create a homepage for my asp .net project, which should display all the products available from the database. The code below is my aspx code, and I've labelled the code I'm trying to loop and display all the results from the database with --> and <--.

<%@ Page Title="" Language="C#" MasterPageFile="~/Site1.Master" AutoEventWireup="true" CodeBehind="home.aspx.cs" Inherits="Try.WebForm1" %>
<asp:Content ID="Content1" ContentPlaceHolderID="head" runat="server">

</asp:Content>
<asp:Content ID="Content2" ContentPlaceHolderID="ContentPlaceHolder1" runat="server">
<section class="py-5">      
            <div class="container px-4 px-lg-5 mt-5">
                <div class="row gx-4 gx-lg-5 row-cols-2 row-cols-md-3 row-cols-xl-4 justify-content-center">
                  
                    <div class="col mb-5">
                        <div class="card h-100">
                       -->  <!-- Product image-->
                            <img class="card-img-top" width="205.99px" height="205.99px" src="data:image/jpg;base64,<%= @Convert.ToBase64String(*product image*) %>" alt="..." />
                            <!-- Product details-->
                            <div class="card-body p-4">
                                <div class="text-center">
                                    
                                    <!-- Product name-->
                                    <h5 class="fw-bolder">*product name*</h5>
                                    <!-- Product price-->
                                    *product price*<br/>
                                    *product description*
                                </div>
                            </div> <--
                            
                            <!-- Product actions-->
                            <div class="card-footer p-4 pt-0 border-top-0 bg-transparent">
                            <div class="text-center"><a class="btn btn-outline-dark mt-auto" href="productDetails.aspx">Details</a></div><br />
                            <div class="text-center"><a class="btn btn-outline-dark mt-auto" href="home.aspx">Add to cart</a></div> 

                            </div>
                        </div>
                    </div>

                </div>
            </div>
        </section>
</asp:Content>

And the code below are the code which I currently left at the aspx.cs page to run the SQL and retrieve the result. I wish to put it somewhere within the aspx page with <% %> but there are errors.

using System;
using System.Collections.Generic;
using System.Configuration;
using System.Data.SqlClient;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;

namespace Try
{
    public partial class WebForm1 : System.Web.UI.Page
    {
        protected void Page_Load(object sender, EventArgs e)
        {
            string strCon = ConfigurationManager.ConnectionStrings["WebConfigConString"].ConnectionString;
            SqlConnection con = new SqlConnection(strCon);
            con.Open();

            string strHome = "SELECT * FROM PRODUCT";
            SqlCommand cmdHome = new SqlCommand(strHome, con);

            SqlDataReader dtrHome = cmdHome.ExecuteReader();

            while (dtrHome.Read())
            {
                //display the result from database on the aspx page
            }

        }
    }
}
1 Answers

Well, the most common way to "display" repeating data?

Is to use one of the built in controls that displays repeating data. Then you can "feed" the control the data source, and asp.net does the work for you!

So, say I drop in a GridView (often a great choice).

So, now our markup is this:

        <asp:GridView ID="GridView1" runat="server" Width="70%">

        </asp:GridView>

And our code on page load is now this:

    protected void Page_Load(object sender, EventArgs e)
    {
        if (!IsPostBack)
            LoadData();

    }

    void LoadData()
    {

        using (SqlConnection conn = new SqlConnection(Properties.Settings.Default.TEST4))
        {
            string strSQL = 
                @"SELECT ID, Fighter, Engine, Thrust, Description FROM Fighters";
            using (SqlCommand cmdSQL = new SqlCommand(strSQL, conn))
            {
                conn.Open();
                DataTable rstData = new DataTable();
                rstData.Load(cmdSQL.ExecuteReader());

                GridView1.DataSource = rstData;
                GridView1.DataBind();
            }
        }
    }

And our results are now this:

enter image description here

So, in effect we can layout "one thing", and then have it repeated.

Now, my Fighters table has a column that links to picture.

So, I can use the wizard to create the GV, and then delete the sql data source on the page, and say with this markup:

        <asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="False" 
        DataKeyNames="ID" CssClass="table"  >
        <Columns>
            <asp:BoundField DataField="Fighter" HeaderText="Fighter"  />
            <asp:BoundField DataField="Engine" HeaderText="Engine"  />
            <asp:BoundField DataField="Thrust" HeaderText="Thrust"  />
            <asp:BoundField DataField="Description" HeaderText="Description" />

            <asp:TemplateField HeaderText="View">
                <ItemTemplate>
                    <asp:ImageButton ID="cmdView" runat="server" Width="150px"
                        ImageUrl = '<%# Eval("ImagePath") %>'
                        OnClick="cmdView_Click" />
                </ItemTemplate>
            </asp:TemplateField>
        </Columns>
    </asp:GridView>

And now I get this:

enter image description here

But, maybe I don't want a grid, but a card like view?

Ok, then we can use a "repeater".

Again, the idea is we layout ONE thing, and then feed it data, and it "repeats" for us.

So, lets now use repeater.

Inside the repeater, we create "one" thing we want to display.

So, say this markup:

<asp:Repeater ID="Repeater1" runat="server" >
    <ItemTemplate>                   
        <div style="border-style:solid;color:black;width:320px;height:450px;float:left;margin-right:10px;margin-bottom:10px">
            <div style="text-align:center;padding:2px 10px 2px 10px">
                <h3><%# Eval("Fighter") %></h3>
                <asp:Image ID="Image2" runat="server" 
                    ImageUrl = '<%# Eval("ImagePath") %>' Width="170" />
                <h4>Engine</h4>
                <asp:Label ID="EngineLabel2" runat="server" Text='<%# Eval("Engine") %>' />
                <h4>Description</h4>
                <asp:Label ID="DescLabel" runat="server" Text='<%# Eval("Description") %>' />
            </div>
        </div>
    </ItemTemplate>
</asp:Repeater>

Code to load - idential (just send that rstData (our table) to the repeater.

We now get this:

enter image description here

And because each "repeated" thing is a simple div (floated left),

Then if I re-size my browser, then I see this (for a big wide screen browser and monitor).

enter image description here

As you can see, you get a LOT of nice repeating data, and for VERY little efforts on your part.

Since you wanting to display products? Then use a GridView, or often better a ListView. You can even let the wizard generate that grid or listview for you. Then you can clean it up a bit, or leave as is.

Edit#2: How to get the row in question with a button click?

Ok, the next logical issue and question? We VERY much will have a button click for each of the rows of data.

With a GridView, it is far better, since the gridview has what we call "datakeys". This allows a easy row click, and code behind can then get with great ease the row you just clicked on. And VERY nice is gridview/listview (and a few more data repeating controls has this data keys option. This option is VERY important, since then we NEVER have to show, expose or even have the database PK value show in the browser side markup and code. Even if we "hide" the field and value in the browser - it STILL not a great idea to EVER expose, or EVEN allow database key id's in the browser side).

However, unfortatnly, the "repeater" is NOT one of those controls that has the datakeys option!!!

So, there are two solutions. One is to use somthing other then the repeater.

but, it not the end of the world, and lets just go with a plane jane button, and include with that button the current database row pk id. (as noted, not a huge deal, but my coding standards do not have nor expose or use or allow users to see the database pk in the browser side markup. It really comes down to how high secuirty you want and need here. So, we can just include the database pk id here, and it not the end of the world.

As noted, if using gridview or listview (and a few others), then data keys and the PK row ID can be had with great ease - no special markup or expose of the PK row id is required. But, lets just use the repeater.

So, in our above card like view (and if you are NOT using a card like view, but repeating rows of data, then I do suggest listview, or datalistview, since datlist view works VERY much like the repeater - but has more features. In fact the big problem here is so many controls to choose from!!! (I tend to learn just a few of them, and use that control. But, for the most part all of these data repating type of controls work VERY much the same. So, once you learn one, then you can use that knowledge with all of them.

So, lets drop in a plain jane button into the repeater. Say at the top and to the right (I choosing top, since if I put button on the bottom, then the location of the button will vary/change, and that's not great for the user as they can "learn" what spot to click on over and over - easy for user).

So, we drop in a plane jane button, add the click event, and we have this:

                <asp:Button ID="cmdMyView" runat="server" Text="View" 
                    CssClass="btn-info" style="float:right"
                    OnClick="cmdMyView_Click"
                    CommandArgument = '<%# Eval("ID") %>'
                    />
                <br />

And now we see/get this:

enter image description here

And our button code can be this:

    protected void cmdMyView_Click(object sender, EventArgs e)
    {
        Button btn = (Button)sender;
        RepeaterItem rRow = (RepeaterItem)btn.NamingContainer;
        int MyRowIndex = rRow.ItemIndex;
        int MyPK = Convert.ToInt32(btn.CommandArgument);

        Debug.Print("Row index click = " + MyRowIndex);
        Debug.Print("Pk data base = " + MyPK);

        // get say the engine from the row click
        Label lblEngine = (Label)rRow.FindControl("EngineLabel2");
        Debug.Print("engine = " + lblEngine.Text);            
    }

Output: enter image description here

Related