Sunday, October 10, 2010

Building contact form and storing the data using LINQ TO SQL

This article is about saving data entered by the user through a form into a database connection by using linq to sql.

First we'll create a table called ContactTbl database contains 8 columns: contactId (int, pk), firstName (nvarchar), lastName (nvarchar), country (nvarchar), city (nvarchar), street (nvarchar), email (nvarchar), comments (nvarchar) and dateArrived (DateTime). The contactTbl should look like that:

contact

The next step is to create LINQ TO SQL DataClass and to drag and drop the contactTbl into it. Now, when the database is configured and ready to receive data, we opened a new aspx page with additional external page coding behind. We use C # so the code behaind page will name default.aspx.cs.

Drag and drop TextBox controllers to the div section from the left toolbox menu using design mode and supply to each TextBox ID property the same name you were used the contactTbl columns.

The contact form design mode view:

coForm

The contact form code view:

<%@ 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></title>
<
style type="text/css">
.style1
{
width: 392px;
height: 265px;
}
.style2
{
}
.style3
{
width: 153px;
}
</style>
</
head>
<
body>
<
form id="form1" runat="server">
<
div>

<
table class="style1" dir="ltr">
<
tr>
<
td class="style3"
style="font-family: Arial, Helvetica, sans-serif; font-size: small">
First name:</td>
<
td>
<
asp:TextBox ID="firstName" runat="server" Width="245px"></asp:TextBox>
</
td>
</
tr>
<
tr>
<
td class="style3"
style="font-family: Arial, Helvetica, sans-serif; font-size: small">
Last name:</td>
<
td>
<
asp:TextBox ID="lastName" runat="server" Width="245px"></asp:TextBox>
</
td>
</
tr>
<
tr>
<
td class="style3"
style="font-family: Arial, Helvetica, sans-serif; font-size: small">
Country:</td>
<
td>
<
asp:TextBox ID="country" runat="server" Width="245px"></asp:TextBox>
</
td>
</
tr>
<
tr>
<
td class="style3"
style="font-family: Arial, Helvetica, sans-serif; font-size: small">
City:</td>
<
td>
<
asp:TextBox ID="city" runat="server" Width="245px"></asp:TextBox>
</
td>
</
tr>
<
tr>
<
td class="style3"
style="font-family: Arial, Helvetica, sans-serif; font-size: small">
Address:</td>
<
td>
<
asp:TextBox ID="address" runat="server" Width="245px"></asp:TextBox>
</
td>
</
tr>
<
tr>
<
td class="style3"
style="font-family: Arial, Helvetica, sans-serif; font-size: small">
Email:</td>
<
td>
<
asp:TextBox ID="email" runat="server" Width="245px"></asp:TextBox>
</
td>
</
tr>
<
tr>
<
td class="style3"
style="font-family: Arial, Helvetica, sans-serif; font-size: small">
Comments:</td>
<
td>
<
asp:TextBox ID="comments" runat="server" Height="91px" TextMode="MultiLine"
Width="245px"></asp:TextBox>
</
td>
</
tr>
<
tr>
<
td align="right" class="style2" colspan="2">
<
asp:Button ID="sendBtn" OnClick="sendBtn_Click" runat="server" Text="Send" Width="86px" />
</
td>
</
tr>
</
table>

</
div>
</
form>
</
body>
</
html>

Don’t forget to configure the buttons’ OnClick event:

<asp:Button ID="sendBtn" OnClick="sendBtn_Click" runat="server" Text="Send" Width="86px" />

All those who like challenges, try to use cascading drop-down list instead of text boxes as we learned in the previous article “Cascading Drop Down List using ASP.NET and C# + LINQ TO SQL”.


You can also verify the information the user enters using validation tool from the toolbox menu. Here are some options for validation testing an empty text box, and a valid email address.

<asp:RequiredFieldValidator ID="RequiredFieldValidator1" runat="server" 
ErrorMessage="first name is required" ControlToValidate="firstName"></asp:RequiredFieldValidator>
<
br />
<
asp:RegularExpressionValidator ID="RegularExpressionValidator1" runat="server"
ErrorMessage="Please provide a valid email address" ControlToValidate="email"
ValidationExpression="\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*"></asp:RegularExpressionValidator>
<
asp:ValidationSummary ID="ValidationSummary1" runat="server" />
By default the ValidationSummary control display the error messages in list but you can choose displaying the errors using message box by changing the ShowSummary value to false and the ShowMessageBox to true.

The only thing left is to write the code handler sending data to the database. First we need to create a function that handle the buttons’ OnClick event:

protected void sendBtn_Click(object sender, EventArgs e)
{
}

The next step is to create a name for the database using DataContext:

DataClassesDataContext db = new DataClassesDataContext();

Then create new instance of the contactTbl DataClass (the “addNewContact” is a unique name iv’e selected, it can be any name you’ll like):

contactTbl addNewContact = new contactTbl();

Then, start define the value for each column in the contactTbl dataclass:

addNewContact.firstName = firstName.Text;
addNewContact.lastName = lastName.Text;
addNewContact.country = country.Text;
addNewContact.city = city.Text;
addNewContact.street = street.Text;
addNewContact.email = email.Text;
addNewContact.comments = comments.Text;
addNewContact.dateArrived = DateTime.Now;
 

Because we’re created DataClass and “Diagramed” the database, The contactTbl know the columns names, so after you’ll click the dot (.) sign right after the “addNewContact” dataclass, you will be able to select which column to deal with. In all cases we are getting the values from a textboxes (firstName.Text) except the dateArrived column which describes the date and time we received the request from the user by using the DateTime.Now method.


Finally we need to insert the new data into our contactTbl table and to update the changes.

db.contactTbls.InsertOnSubmit(addNewContact);
db.SubmitChanges();

At the first line we are calling the database name we’ve created (.) the name of the updating table (.) and then using the InsertOnSubmit method which store all the data we kept in the addNewContact new dataclass. Finally, we submit the changes we’re making on the database.


The Final step is to response the user about the results of the submitting. There is a few ways to modify that by response.redirect to the same page or to a new page - Site administrators often prefer to redirect a user to a new page and thus implement tracking feature requests through Google Analytics, etc. You can also return a message through a Label control and to clear the TextBoxes controls using the String.Empty command.

firstName.Text = String.Empty;

The full aspx.cs code:

public partial class _Default : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{

}
protected void sendBtn_Click(object sender, EventArgs e)
{
DataClassesDataContext db = new DataClassesDataContext();
contactTbl addNewContact = new contactTbl();
addNewContact.firstName = firstName.Text;
addNewContact.lastName = lastName.Text;
addNewContact.country = country.Text;
addNewContact.city = city.Text;
addNewContact.street = street.Text;
addNewContact.email = email.Text;
addNewContact.comments = comments.Text;
addNewContact.dateArrived = DateTime.Now;
db.contactTbls.InsertOnSubmit(addNewContact);
db.SubmitChanges();

Response.Redirect("contactSent.aspx");
}
}

Saturday, October 9, 2010

Cascading Drop Down List using ASP.NET and C# + LINQ TO SQL

This article explains how to build a cascading drop-down list, using the language of ASP.NET and C #. Cascading drop-down list allows you to filter information sent from the database, allowing users to select relevant information according to its previous selection. For example, when we want to allow the user to search our website name of a street, we can present him with a scrolling list of states / countries, and the user to select a state. The next drop-down list will be updated automatically from the database and ask for the relevant towns only.

The first thing we should do is create 3 tables in the database, the first one call “Countries”. This table including 2 columns for countId (int) and countName (nvchar = for the name of the country). The second table is called “Cities” and including 3 columns: cityId (int), countId (int – inherits from the Countries countId), cityName (nvchar) and “Streets” which including streetId (int), cityId (int – inherits from the Cities cityId), streetName (nvchar).

dbCount

At this article we are using LINQ TO SQL, so the next thing we are needing to do is to create Data Class and drag into it the database tables. My data class call “DataClass.dbml”.

Now lets Fill the database tables with data!

countries

at the cities table, don’t forget to fill up the countId!

cities

and finally, the streets table

streets

as you can see, i was filled some values for Miami and New York City only! so later when we will select for other cities, the street drop down list will not fire cause there will be no data to display. Lets begin write some code.

Create Aspx page and check the Place code in separate file. in this case i am not using Master Page. In the design mode, drag and drop 3 drop down list controls (ddl) to the Div section. Give each ddl unique id: countDDL, cityDDL and streetDDL. For the countDDL and cityDDL make sure you are using AutoPost and Enabled the cityDDL + streetDDL to false. next you will need to use the OnSelectedIndexChanged function for the 2 first DDLs.

<form id="form1" runat="server">
<
div>

<
asp:DropDownList ID="countDDL" AutoPostBack="true" runat="server" Height="16px" Width="217px" OnSelectedIndexChanged="countDDL_OnSelectedIndexChanged">
</
asp:DropDownList>
<
br />
<
br />
<
asp:DropDownList ID="cityDDL" AutoPostBack="true" runat="server" Height="16px" Width="217px" Enabled="false" OnSelectedIndexChanged="cityDDL_OnSelectedIndexChanged">
</
asp:DropDownList>
<
br />
<
br />
<
asp:DropDownList ID="streetDDL" runat="server" Height="16px" Width="217px" Enabled="false">
</
asp:DropDownList>

</
div>
</
form>

The next step, is to fill the countDDL with the countries names from the Countries table while the page is load. We need to do that on the Page_load event.

protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
countDDL.AppendDataBoundItems = true;
countDDL.Items.Add(new ListItem("Select country...", ""));
DataClassesDataContext db = new DataClassesDataContext();
var selectCountries = from t in db.Countries
orderby t.countName
select t;
countDDL.DataSource = selectCountries;
countDDL.DataTextField = "countName";
countDDL.DataValueField = "countId";
countDDL.DataBind();

cityDDL.AppendDataBoundItems = true;
cityDDL.Items.Add(new ListItem("Select City...", ""));

streetDDL.AppendDataBoundItems = true;
streetDDL.Items.Add(new ListItem("Select Street...", ""));
}
}
protected void countDDL_OnSelectedIndexChanged(object sender, EventArgs e)
{

}
protected void cityDDL_OnSelectedIndexChanged(object sender, EventArgs e)
{

}

Don’t forget to use the OnSelectedIndexChanged functions for the countDDL and cityDDL so there will be no compile errors.At the Page_Load event we are first using the AppendDataBoundItems to display some content like “Select Country…” that not send from the SQL database. Next we are using Linq to sql select statement to read all the countries names from the Countries table (order by the name of the countries). Then we set the DataTextField to the countName column which hold the county name and the DataValueField that hold the countId integer.  The last action is to put some values in the cityDDL and the streetDDL AppendDataBoundItems property.


The next step is to fire the OnSelectedIndexChanged event for each DDL so when we will select some value from the countDDL the cityDDL will fill up with the relevant content.


The OnSelectedIndexChanged event code is very similar to the Page_Load event with few changes. First of all we need to Clear() the coutDDL so that the data inside the ddl will not duplicate again and again.

protected void countDDL_OnSelectedIndexChanged(object sender, EventArgs e)
{
cityDDL.Items.Clear();
cityDDL.Items.Add(new ListItem("Select City...", ""));
streetDDL.Items.Clear();
streetDDL.Items.Add(new ListItem("Select Street...", ""));

cityDDL.AppendDataBoundItems = true;
DataClassesDataContext db = new DataClassesDataContext();
var selectCities = from t in db.Cities
where t.countId == Convert.ToInt32(countDDL.SelectedItem.Value)
orderby t.cityName
select t;
cityDDL.DataSource = selectCities;
cityDDL.DataTextField = "cityName";
cityDDL.DataValueField = "cityId";
cityDDL.DataBind();

if (cityDDL.Items.Count > 1)
{
cityDDL.Enabled = true;
}
else
{
cityDDL.Enabled = false;
streetDDL.Enabled = false;
}
}

The changes we used in this code is the where statement to filter and match the cities values to the selected country (by using the countId integer) and the if statement that check the return value(s) from the cityDDL so if there is no value the cityDDL will stay enabled false. We need to handle the cityDDL OnSelectedIndexChanged function to fire the streetDDL. We are doing that exactly the same way we’ve thread the cityDDL OnSelectedIndexChanged function.

protected void cityDDL_OnSelectedIndexChanged(object sender, EventArgs e)
{
streetDDL.Items.Clear();
streetDDL.Items.Add(new ListItem("Select Street...", ""));

streetDDL.AppendDataBoundItems = true;
DataClassesDataContext db = new DataClassesDataContext();
var selectStreets = from t in db.Streets
where t.cityId == Convert.ToInt32(cityDDL.SelectedItem.Value)
orderby t.streetName
select t;
streetDDL.DataSource = selectStreets;
streetDDL.DataTextField = "streetName";
streetDDL.DataValueField = "streetId";
streetDDL.DataBind();

if (streetDDL.Items.Count > 1)
{
streetDDL.Enabled = true;
}
else
{
streetDDL.Enabled = false;
}
}

I hope you find this article useful, feel free to comment.


This is the full Default.aspx.cs code

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;

public partial class _Default : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
countDDL.AppendDataBoundItems = true;
countDDL.Items.Add(new ListItem("Select country...", ""));
DataClassesDataContext db = new DataClassesDataContext();
var selectCountries = from t in db.Countries
orderby t.countName
select t;
countDDL.DataSource = selectCountries;
countDDL.DataTextField = "countName";
countDDL.DataValueField = "countId";
countDDL.DataBind();

cityDDL.AppendDataBoundItems = true;
cityDDL.Items.Add(new ListItem("Select City...", ""));

streetDDL.AppendDataBoundItems = true;
streetDDL.Items.Add(new ListItem("Select Street...", ""));
}
}
protected void countDDL_OnSelectedIndexChanged(object sender, EventArgs e)
{
cityDDL.Items.Clear();
cityDDL.Items.Add(new ListItem("Select City...", ""));
streetDDL.Items.Clear();
streetDDL.Items.Add(new ListItem("Select Street...", ""));

cityDDL.AppendDataBoundItems = true;
DataClassesDataContext db = new DataClassesDataContext();
var selectCities = from t in db.Cities
where t.countId == Convert.ToInt32(countDDL.SelectedItem.Value)
orderby t.cityName
select t;
cityDDL.DataSource = selectCities;
cityDDL.DataTextField = "cityName";
cityDDL.DataValueField = "cityId";
cityDDL.DataBind();

if (cityDDL.Items.Count > 1)
{
cityDDL.Enabled = true;
}
else
{
cityDDL.Enabled = false;
streetDDL.Enabled = false;
}
}
protected void cityDDL_OnSelectedIndexChanged(object sender, EventArgs e)
{
streetDDL.Items.Clear();
streetDDL.Items.Add(new ListItem("Select Street...", ""));

streetDDL.AppendDataBoundItems = true;
DataClassesDataContext db = new DataClassesDataContext();
var selectStreets = from t in db.Streets
where t.cityId == Convert.ToInt32(cityDDL.SelectedItem.Value)
orderby t.streetName
select t;
streetDDL.DataSource = selectStreets;
streetDDL.DataTextField = "streetName";
streetDDL.DataValueField = "streetId";
streetDDL.DataBind();

if (streetDDL.Items.Count > 1)
{
streetDDL.Enabled = true;
}
else
{
streetDDL.Enabled = false;
}
}
}