My thoughts…

A mix of many topics.

Using a Primary Key with ASP.NET Data Controls

Posted by Rebecca Chernoff on April 27, 2008

It is common in ASP.NET to be working with data.  Using data on the page immediately brings up several concerns to be aware of.  One issue many people are aware of is how to have access to the data that you, as the developer, need – without letting the user have access to the data.  The main example of this is the primary key of your data.  If there is a GridView displaying a list of users for a community site, the users should not be able to see the primary key for anyone.  However, if a row is edited, having the primary key of that user is vital.  Having access to the primary key is extremely important in this scenario.  There are a couple different ways to have access to fields in code-behind that are not visible to the user.  These methods are the topic for this article.

Let’s just get straight to the code now, shall we?  If you want to follow along, create a new website in Visual Studio 2008.  Then, added an xml file to the App_Data folder called Holidays.xml.  This xml contains all the federal holidays that the U.S. Government recognizes for the year 2009.

<?xml version="1.0" encoding="utf-8" ?>
<holidays>
	<holiday>
		<id>1</id>
		<name>New Year's Day</name>
		<date>01/01/2009</date>
	</holiday>
	<holiday>
		<id>2</id>
		<name>Martin Luther King, Jr. Day</name>
		<date>01/19/2009</date>
	</holiday>
	<holiday>
		<id>3</id>
		<name>Washington's Birthday</name>
		<date>02/16/2009</date>
	</holiday>
	<holiday>
		<id>4</id>
		<name>Good Friday</name>
		<date>04/20/2009</date>
	</holiday>
	<holiday>
		<id>5</id>
		<name>Memorial Day</name>
		<date>05/25/2009</date>
	</holiday>
	<holiday>
		<id>6</id>
		<name>Independance Day (observed)</name>
		<date>07/03/2009</date>
	</holiday>
	<holiday>
		<id>7</id>
		<name>Labor Day</name>
		<date>09/07/2009</date>
	</holiday>
	<holiday>
		<id>8</id>
		<name>Thanksgiving Day</name>
		<date>11/26/2009</date>
	</holiday>
	<holiday>
		<id>9</id>
		<name>Christmas</name>
		<date>12/25/2009</date>
	</holiday>
</holidays>

In order to display the holidays, I am using a very basic GridView. I am not using a DataSource control, rather I’ve chosen to bind the GridView to a collection in code-behind.  I’ve also set up a label to display information about the currently selected row.

<asp:Label runat="server" ID="lblSelected"
    Text="Please select a holiday." />

<asp:GridView runat="server" ID="gvHolidays"
    AutoGenerateColumns="False"
    AutoGenerateSelectButton="True"
    OnSelectedIndexChanging="gvHolidays_SelectedIndexChanging">
    <Columns>
        <asp:BoundField HeaderText="Name"
            DataField="Name" SortExpression="Name" />
        <asp:BoundField HeaderText="Day"
            DataField="Day" SortExpression="Day" />
        <asp:BoundField DataField="Date" HeaderText="Date"
            SortExpression="Date" />
    </Columns>
</asp:GridView>

In the code-behind, I pull the holidays out of the xml file and stuff them into the GridView.  I am using a couple of new features in .net 3.5.  If you don’t understand the syntax, don’t worry.  Trust me that the holidays from my xml file are being bound to the grid.  You can bind the grid however you want.

One important piece here is that my holidays object does include the Id field.  There is no column for the Id field in the GridView, because as the topic of this article dictates, the user cannot have access to the primary key data. For now though, this is just the setup. The good stuff comes in a minute.

protected void Page_Load(object sender, EventArgs e) {
    gvHolidays.SelectedIndexChanging += new GridViewSelectEventHandler(gvHolidays_SelectedIndexChanging);
    if (!IsPostBack) {
        XDocument xDoc = XDocument.Load(HttpContext.Current.Server.MapPath("~/App_Data/Holidays.xml"));
        var holidays = from h in xDoc.Descendants("holiday")
                       orderby h.Element("date").Value
                       select new { Id = Int32.Parse(h.Element("id").Value), Name = h.Element("name").Value, Day = h.Element("day").Value, Date = DateTime.Parse(h.Element("date").Value) };
        gvHolidays.DataSource = holidays;
        gvHolidays.DataBind();
    }
}

void gvHolidays_SelectedIndexChanging(object sender, GridViewSelectEventArgs e) {
    int rowIndex = e.NewSelectedIndex;
    lblSelected.Text = "You selected RowIndex " + rowIndex;
}

At this point, we have a GridView that looks like the following:  When a row is selected, the GridViewSelectEventArgs provides us with the index of the row that was selected in the NewSelectedIndex property.

Basic GridView

This is all fine and dandy, but now that the border of the puzzle is put together, it is time to get to the mess that is the rest of the puzzle.  My DataSource includes the Id field, but this isn’t something that the user should have access to.  This field needs to be available server-side, but should not be readable on the client-side.  We have 3 options for accomplishing this.

Try #1:  BoundField with Visible=”False”

This option might be what you try first.  Don’t!  It won’t work.  When a BoundField is not going to be rendered (i.e., when Visible=”False”), the value does not make a round-trip between the client and the server.  This makes it impossible to get the value of our primary key from the server when we react to a Selecting, Updating, or Deleting event.

Try #2:  TemplateField with Visible=”False”

After hearing that a BoundField will not work, it might seem that a TemplateField won’t work either.  In fact, it will work.  A TemplateField is really just the controls you put inside the template.  This means that the controls themselves will handle the Visible property.  If a Label s put iinside a TemplateField, then it will provide the primary key.  There is one caveat I should mention for this method.  If you are adding multiple TemplateFields, while it won’t increase the size of your html markup, it will increase the size of your ViewState.

<asp:TemplateField Visible="false">
    <ItemTemplate>
        <asp:Label runat="server" ID="lblId"
            Text='<%# Eval("Id") %>' />
    </ItemTemplate>
</asp:TemplateField>

Once the TemplateField is in the GridView, pulling out the primary key is a trivial matter.

protected void gvHolidays_SelectedIndexChanging(object sender, GridViewSelectEventArgs e) {
    int rowIndex = e.NewSelectedIndex;
    int primaryKey = Int32.Parse(((Label)gvHolidays.Rows[rowIndex].FindControl("lblId")).Text);
    lblSelected.Text = "You selected RowIndex " + rowIndex + " which has a primary key of " + primaryKey;
}

Doing it this way gets a little messy because the return object from FindControl must be cast into a Label. Then, the Text of the Label must be parsed into an int. Not what I would call clean. There is an easier way…

Try #3:  Using DataKeyNames and DataKeys properties

I’d like to offer the final method, which is the one that I recommend.  The data controls in ASP.NET 2.0+ have a DataKeyNames property.  When this property is used, a DataKeys collection will be created that contains the values specified as a DataKeyName. Let’s update our GridView to use the DataKeyNames property.

<asp:GridView runat="server" ID="gvHolidays"
    AutoGenerateColumns="False"
    AutoGenerateSelectButton="True"
    OnSelectedIndexChanging="gvHolidays_SelectedIndexChanging"
    DataKeyNames="Id"
    <Columns>
        <asp:BoundField HeaderText="Name"
            DataField="Name" SortExpression="Name" />
        <asp:BoundField DataField="Date" HeaderText="Date"
            SortExpression="Date"
            DataFormatString="{0:D}" />
    </Columns>
</asp:GridView>

Notice that I have set DataKeyNames=”Id”. In my code-behind, the DataKeys collection will now exist.

protected void gvHolidays_SelectedIndexChanging(object sender, GridViewSelectEventArgs e) {
    int rowIndex = e.NewSelectedIndex;
    int primaryKey = (int)gvHolidays.DataKeys[rowIndex].Values["Id"];
    lblSelected.Text = "You selected RowIndex " + rowIndex + " which has a primary key of " + primaryKey;
}

Simple, right?! Since the DataKeyNames property only contains one field, it is ok to use gvHolidays.DataKeys[rowIndex].Value. It is good practice to not use this shortcut because if the code is changed later to put another field into the DataKeys collection, the existing code needs to be changed. Yes, multiple fields can be put into the DataKeyNames property – comma separate them. A caveat though: don’t put too many fields into the DataKeys collection because it will increase the weight of the page.

It is extremely important to recognize that both of these methods have issues you must be aware of if you are using Updating and Deleting in your GridView. Read this article!!! Really these issues only come into play if you have ViewState turned off. Even if you are not currently doing this, read this article. Maybe down the road when you are, you will remember this article. 😛

16 Responses to “Using a Primary Key with ASP.NET Data Controls”

  1. d03boy said

    I love you.

  2. frenky said

    tsMOLy http://gdjI3b7VaWpU1m0dGpvjRrcu9Fk.com

  3. Hqbfpysm said

    Wonderfull great site lolita magazines nude girls uhwr

  4. Apqopggm said

    It’s a bad line nude underage pussie zabd

  5. Diorneht said

    I’m self-employed legal underage nudity
    cis

  6. Esnftpdq said

    Good crew it’s cool 🙂 underage incest stories
    541

  7. Zxrtomqo said

    Three years toplist early bbs
    54406

  8. Hkmrpcir said

    My battery’s about to run out cp rail
    :((

  9. Kirkhrvb said

    What part of do you come from? russian models nn
    8[[[

  10. Wuduaftv said

    I was born in Australia but grew up in England Pthc P2p dlxr

  11. Byzgfeun said

    It’s a bad line Pthc Bbs
    tlyqra

  12. Dstvflga said

    We’d like to offer you the job

  13. natural nusantara…

    […]Using a Primary Key with ASP.NET Data Controls « My thoughts…[…]…

  14. Jmvvsggq said

    I’d like some euros http://lebodudelusoj.de.tl allis chalmers model i love Cytherea she sweet little tities and nice soft white butt i love seeing her squiting and rubing that tight litte boby of hers

  15. Ygzuwurw said

    I’m only getting an answering machine http://yfycalokytij.de.tl skinny model thumbs Lovely girl, lovely tits and body…I am usually not a big fan of masturbation video but this one is good!

  16. I am looking to buy this sexy Shorty Lace Bra and Panty Set from http://chautmet.com! Would you recommend them?

Leave a reply to Zxrtomqo Cancel reply