My musings about .NET and what not

How to Validate User Input With Values From a Database

Okay, nothing profound or earth-shattering, but I see this question asked so often in the forums that I figured I'd create a blog post about it. That way, the next time someone asks this question I can simply point them here. ;-)

I'm sure you're all familiar with the various ASP.NET validation controls. These allow you to validate user input for required entries (RequiredFieldValidator), against known values or data types (CompareValidator), against patterns (RegularExpressionValidator) and so on. But what if you need to validate using values stored in a database, where validation succeeds or fails based on the existence or (non-existence) of the entered value?

Here, we'll create a very simple page with only a textbox, a button, a label, a couple of validation controls, and a data source. (I'm using a SqlDataSource for simplicity; obviously, you can use any data source you have, such as ObjectDataSource, DataSets, or whatever.) This will be part of a softball league signup site. The user must enter a unique name for his or her team. If that name is already used by another team, the user is warned and asked to pick another name. If the name is unique, the application accepts it.

For this example, we're going to be using a real simple database -- only one table, containing the names of the existing teams. (Please excuse the extreme lameness of the team names I came up with.)

Here is the ASPX code for the page shown above:

<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" %>
 
DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
   <title>Pick a Name for Your Teamtitle>
head>
<body>
   <form id="form1" runat="server">
      <div>
         <h2>
            Pick a Name for Your Teamh2>
         Name:
         <asp:TextBox ID="txtTeam" runat="server" />
         <asp:Button ID="btnValidate" runat="server" Text="Go" />
         <br />
         <asp:RequiredFieldValidator ID="reqval_txtTeam" runat="server" 
            ErrorMessage="You must enter a team name."
            ControlToValidate="txtTeam" Display="Dynamic" />
         <asp:CustomValidator ID="custval_txtTeam" runat="server" 
            ErrorMessage="That name is already taken. Please pick another."
            ControlToValidate="txtTeam" Display="Dynamic" 
            OnServerValidate="custval_txtTeam_ServerValidate" />
         <asp:Label ID="lblResult" runat="server" EnableViewState="False" />
         <asp:SqlDataSource ID="SqlDataSourceTeams" runat="server" 
            ConnectionString="<%$ ConnectionStrings:ConnectionString %>"
            SelectCommand="SELECT [TeamName] FROM [Teams]">asp:SqlDataSource>
      div>
   form>
body>
html>

You'll notice there are two validation controls used to validate the textbox. One of them is a RequiredFieldValidator. We need this because we obviously can't test against non-existent input. The other is a CustomValidator. The CustomValidator lets us define our own server side validation logic, which is wired with the OnServerValidate event handler. In the server side validation function, we're going to search the database for the entered value. If it's there, validation will fail and the CustomValidator's ErrorMessage will be displayed. If it's a unique name, validation passes and the user is notified to that effect.

protected void custval_txtTeam_ServerValidate(object source, ServerValidateEventArgs args)
{
   args.IsValid = true;
   foreach (DataRowView drv in SqlDataSourceTeams.Select(DataSourceSelectArguments.Empty))
   {
      if (drv["TeamName"].ToString() == args.Value)
      {
         args.IsValid = false;
         break;
      }            
   }
 
   if (args.IsValid)
      lblResult.Text = "Congratulations! That name is not taken.";
}

The actual logic is pretty simple. The ServerValidateEventArgs object has a boolean property IsValid which gets or sets whether the validation passes. We set args.IsValid = true at the beginning. We then loop through the collection of data rows returned by the SqlDataSource. For each row, we check the value of the TeamName column. If the value from the row matches the entered value we are validating (specified by args.Value), then args.IsValid is set to false and the loop is terminated. In this case, validation fails. If no matches are found, the validation passes.

Obviously, you aren't limited to simple equality checks using this technique. You can use inequality operators, regular expressions, and so on to do complex validation against one or more database columns, or even across multiple tables.

Subscribe to this blog for more cool content like this!

kick it on DotNetKicks.com

shout it on DotNetShoutOut.com

vote it on WebDevVote.com

Bookmark / Share

    » Similar Posts

    1. Master / Detail Editing With a ListView and DetailsView
    2. Nested ListViews and More - Working with Databound Controls Inside the ListView
    3. Defensive Programming, or Why Exception Handling Is Like Car Insurance

    » Trackbacks & Pingbacks

    No trackbacks yet.
    Trackback link for this post:
    http://leedumond.com/trackback.ashx?id=37

    » Comments

    1. TechBandit avatar

      Cool Article.Dont think lot of people use it.

      It solved my problem.Thanks.

      TechBandit — January 17, 2009 6:53 AM
    2. TUT avatar

      hi, thanks to your solution which helped me in my problem. but now i have another problem, how do you remember the user status with sessionID?

      TUT — February 7, 2010 3:38 AM
    3. Lee Dumond avatar

      TUT - not sure how your question relates to this blog post. But anyway, you can stuff anything you like into the session by using a key/value pair: Session["Thing'] = myThing

      Lee Dumond — February 7, 2010 3:52 AM
    4. TUT avatar

      i have a login.aspx.cs, after the user login i have the following code

      Session["StatusID"] = LoggedIN.Status;

      in another .aspx.cs i have the following coding to retrieve it but it cant work

      lblStatus.Text = Session.SessionID;

      it displays a random number and alphabet like this

      "zutugx5523mb2eao4p1h1qvz"

      can you help me with this? thanks!

      TUT — February 8, 2010 3:41 AM
    5. Lee Dumond avatar

      Tut, you can try:

      lblStatus.Text = Session["StatusID"].ToString()

      or better yet, try using a LoginStatus control for this:

      msdn.microsoft.com/.../system.web.ui.w

      Lee Dumond — February 8, 2010 7:37 AM
    6. Dan avatar

      This is great but how would I add extra columbs to validate.

      I am creating a booking system, I need to check if theres a date, time and instructorID already in the database when the user is entering a booking, if all three of these columbs contain the same value which has been entered in the booking form then I need an error saying "this booking has already been taken". I only want to get the error message if all three of the values being enterd are the same as in the database, as I have multiple time slots and instructors, hope this all makes sense.

      Thanks

      Dan — March 19, 2010 8:28 AM
    7. Lee Dumond avatar

      Checking multiple columns is really no different than checking a single column. In the OnServerValidate event, you simply need to loop through each row in the records, and check the values in each row against the 3 entered values. Obviously, if your 3 columns are not in the same table, you're going to have to do some joins in your SQL to get them all into the same DataView or DataTable.

      Lee Dumond — March 19, 2010 8:48 AM
    8. Dan avatar

      Thank you, I understand what your saying, but how would I add in the extra columns to validate, what would the code be to add in the extra columns? would I have to enter in the same code 3 times and change it to validate each control or is there a way of just simply adding in the other 2 columns? Also if I add in the extra columns will it only show the error if all three of the columns find a match in the booking form?

      Thanks..

      Dan — March 19, 2010 10:04 AM
    9. Lee Dumond avatar

      No, you need to write a custom SQL query that combines the three columns and returns them as a set of records, then you loop through the set. This is easy if all the columns are in the same table. Otherwise, you'll have to use JOINs to gather the columns based on how they are related.

      Lee Dumond — March 19, 2010 10:20 AM
    10. Dan avatar

      Ok thank you for your help, I understand what you mean I just dont have the knowlege to do it. Do u know any good examples of this or any good tutorials which could help me finish my booking system?

      Dan — March 19, 2010 10:59 AM
    11. kostas avatar

      I'm new in asp.net. Is there any vb code to use for this case?

      I double-clicked the CustomValidator (named "ExistNameValidator") in Visual Studio 2008 and i got:

      "Protected Sub ExistNameValidator_ServerValidate(ByVal source As Object, ByVal args As System.Web.UI.WebControls.ServerValidateEventArgs) Handles ExistNameValidator.ServerValidate"

      but after that i don't know what to write in vb.

      Can you please help me?

      Many thanks in advance.

      kostas — April 16, 2010 4:28 AM
    12. taina avatar

      hey i tried the code above to a registration page, but i had some doubts.Now if there is no conflict of names with the database i want all the registration details to be entered into the database with an alert saying "you have registered successfully". How do i do that? Can u please help me?..

      ps:. i already had the insertion query mentioned in my code along with the msg "record inserted" after submitting but im not understanding how to incorporate the code above along with the code i already have.

      taina — April 19, 2010 3:01 PM
    13. taina avatar

      in my databse i chose the customer id as my primary key too.. although while entering an already entered customer id an error occurred saying dat conflicting ids cannot be entered but i dont know how to write the code for the part which says that "this id already exists please try again"...this is wat i did now i need to incorporate what u showed in my code

      protected void Button1_Click(object sender, EventArgs e)

      {

      String q = "insert into CustomerTab values('" + TextBox1.Text + "','" + TextBox2.Text + "','" + TextBox3.Text + "','" + DL2.SelectedValue + "','" + TextBox4.Text + "','" + TextBox5.Text + "','" + TextBox6.Text + "','" + TextBox7.Text + "','" + TextBox8.Text + "','" + TextBox9.Text + "','" + DL1.SelectedValue + "')";

      con.Open();

      cmd=new SqlCommand(q,con);

      cmd.ExecuteNonQuery();

      con.Close();

      //Response.Write("Record Inserted");

      Response.Write("");

      }

      here my TextBox1 is my customer id which i entered as my primary key

      taina — April 19, 2010 3:06 PM
    14. taina avatar

      never mind... i got it :) thanq

      taina — April 22, 2010 1:29 PM
    15. How about using objectdatasource?

      i can't figure out how to change the codes for the CustomValidator.

      melody — December 30, 2010 7:27 AM
    16. Kelvin avatar

      Hi, great article that wrote. It has been very useful for me.

      I just have a question, if you want compare between numbers, how do you modify your code? My operator is also less than or equal to (<=). So the amount in textbox should less than or equal to the amount in database.

      Kelvin — December 30, 2010 2:29 PM
    17. Roger avatar

      Good tutorial. Do you have the code in vb instead of c#?

      Thanks

      Roger — January 4, 2011 10:57 AM
    18. Chad avatar

      Hi, I'm getting this error when running your example: CS0246: The type or namespace name 'DataRowView' could not be found (are you missing a using directive or an assembly reference?)

      Do you have any suggestions on how to resolve?

      Chad — February 5, 2011 11:05 PM

    » Leave a Comment