Introduction
Ajax Control Toolkit is one of the finest supports provided by Microsoft to compete with modern web development technology. Use of Ajax makes a web application faster for access, gives responsiveness while interacting with the application, avoids full postback of the page and uses partial postback to perform the related operations. The following example is demonstrated using GridView
and RequiredFieldValidator
provided as server side control and UpdatePanel
, ValidatorCalloutExtender
and ModalPopupExtender
provided as Ajax controls.
Background
The drawback of ASP.NET is that the web applications which are developed in ASP.NET are slower than other web applications. That's why Ajax came into the picture to solve the problem and increase the usability. This example shows how applications are developed in real time environment and what measures we should take into consideration to make ASP.NET websites have faster accessibility and good performance.
Goal
ASP.NET GridView
control does not provide popup editing by default which is provided by Kendo-UI grid[^] and DevExpress grid[^], as this grid looks more interactive and provides ease while interacting with grid data. This type of interactive grid can be developed with the help of controls provided by AjaxControlToolkit
. The following example is designed using ModelPopupExtender
control which is available in AjaxControlToolkit
to extend the functionality of GridView
by providing editing/adding/deleting options within the popup window.
Using the Code
- Create two tables. Emloyee to store employee's records and Dept to store department related records using SQL Server Management Studio as follows with primary key-foreign key relation on column
deptno
: Employee
table contains columns for storing empid
, ename
, job
, salary
and deptno
.
Dept
table contains columns for storing deptno
and dname
(department name).
- Write three StoredProcedures to perform Add, Edit and Delete operations on database.
- Assuming that AjaxControlToolKit.dll is already added to the project and registered in web.config file as following in system.web tag:
<pages>
<controls>
<add tagPrefix="ajaxToolkit" assembly="AjaxControlToolkit" namespace="AjaxControlToolkit"/>
</controls>
</pages>
- Add one
appSettings
tag in Configuration
tag as follows to set UnobtrusiveValidatonMode
to false
:
<appSettings>
<add key="ValidationSettings:UnobtrusiveValidationMode" value="none"/>
</appSettings>
- Write
ConnectionString
in Configuration
tag of web.config file - Add ASP.NET empty website template to the website project and name it as Default.aspx. In source view of Default.aspx, write the following code.
- In
head
tag, add modalBackground
class in style
tag:
<head runat="server">
<style type="text/css">
.modalBackground {
background-color:silver;
opacity:0.7;
}
</style>
</head>
The above CSS class is added to use with BackgroundCssClass
property of ModalPopupExtender
. It will apply blackish effect on the web page during popup window display.
- Now in form tag of Default.aspx page
In UpdatePanel->
- Add one
Button
control to Add new records - Add one
GridView
as follows:
<asp:GridView ID="gv" runat="server" AutoGenerateColumns="False" Width="100%"
DataKeyNames="empid" BackColor="White" BorderColor="#CCCCCC"
BorderStyle="Solid" BorderWidth="1px" CellPadding="4">
<Columns>
<asp:TemplateField HeaderText="Edit">
<ItemTemplate>
<asp:LinkButton ID="lnkEdit" Text="Edit"
OnClick="lnkEdit_Click"
runat="server"></asp:LinkButton>
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="Delete">
<ItemTemplate>
<asp:LinkButton ID="lnkDel" Text="Delete"
OnClick="lnkDel_Click"
runat="server"></asp:LinkButton>
</ItemTemplate>
</asp:TemplateField>
<asp:BoundField DataField="empid" HeaderText="Emp ID" />
<asp:BoundField DataField="ename" HeaderText="Name" />
<asp:BoundField DataField="job" HeaderText="Job" />
<asp:BoundField DataField="sal"
HeaderText="Salary" DataFormatString="{0:N}"/>
<asp:BoundField DataField="dname" HeaderText="Department" />
</Columns>
</GridView>
- Add panels for displaying popup window to add, delete and edit records along with
ModalPopupExtender
as follows:
<!--
<ajaxToolkit:ModalPopupExtender ID="mpe1" runat="server"
TargetControlID="btnAddNew1" PopupControlID="panelAddNew"
RepositionMode="RepositionOnWindowResizeAndScroll" DropShadow="true"
PopupDragHandleControlID="panelAddNewTitle"
BackgroundCssClass="modalBackground" ></ajaxToolkit:ModalPopupExtender>
<asp:Panel ID="panelAddNew" runat="server" style="display:none;
background-color:gray;" ForeColor="Black"
Width="500" Height="210">
<asp:Panel ID="panelAddNewTitle" runat="server"
style="cursor:move;font-family:Tahoma;padding:2px;"
HorizontalAlign="Center" BackColor="Blue"
ForeColor="White" Height="25" ><b>Add New</b>
</asp:Panel>
<table width="100%" style="padding:5px">
<tr>
<td colspan="3">
<asp:Label ID="lblStatus1" runat="server">
</asp:Label>
</td>
</tr>
<tr>
<td><b>Enter Employee Name</b></td>
<td><b>:</b></td>
<td><asp:TextBox ID="txtName1" runat="server">
</asp:TextBox>
<asp:RequiredFieldValidator ID="rfv1" runat="server"
ErrorMessage="Enter Name" Display="None"
ControlToValidate="txtName1" ValidationGroup="add">
</asp:RequiredFieldValidator>
<ajaxToolkit:ValidatorCalloutExtender ID="vce1"
TargetControlID="rfv1" runat="server">
</ajaxToolkit:ValidatorCalloutExtender>
</td>
</tr>
<tr>
<td><b>Enter Job</b></td>
<td><b>:</b></td>
<td><asp:TextBox ID="txtJob1" runat="server">
</asp:TextBox>
<asp:RequiredFieldValidator ID="rfv2" runat="server"
ErrorMessage="Enter Job" Display="None"
ControlToValidate="txtJob1" ValidationGroup="add">
</asp:RequiredFieldValidator>
<ajaxToolkit:ValidatorCalloutExtender ID="vce2"
runat="server" TargetControlID="rfv2" >
</ajaxToolkit:ValidatorCalloutExtender>
</td>
</tr>
<tr>
<td><b>Enter Salary</b></td>
<td><b>:</b></td>
<td><asp:TextBox ID="txtSal1" runat="server">
</asp:TextBox>
<asp:RequiredFieldValidator ID="rfv3" runat="server"
ErrorMessage="Enter Salary" Display="None"
ControlToValidate="txtSal1" ValidationGroup="add">
</asp:RequiredFieldValidator>
<ajaxToolkit:ValidatorCalloutExtender runat="server"
ID="vce3" TargetControlID="rfv3" >
</ajaxToolkit:ValidatorCalloutExtender>
</td>
</tr>
<tr>
<td><b>Select Department</b></td>
<td><b>:</b></td>
<td><asp:DropDownList ID="ddlAdd" runat="server">
</asp:DropDownList>
<asp:RequiredFieldValidator ID="rfv4" runat="server"
InitialValue="0" ErrorMessage="Select Department"
Display="None" ControlToValidate="ddlAdd"
ValidationGroup="add"></asp:RequiredFieldValidator>
<ajaxToolkit:ValidatorCalloutExtender runat="server"
ID="vce4" TargetControlID="rfv4" >
</ajaxToolkit:ValidatorCalloutExtender>
</td>
</tr>
</table>
<br />
<div align="center">
<asp:Button ID="btnAddNew2" runat="server"
Width="70" Text="Add"
OnClick="btnAddNew_Click" ValidationGroup="add"/>
<asp:Button ID="btnCancel1" runat="server"
Width="70" Text="Cancel"
CausesValidation="false" OnClick="Cancel_Click"
ValidationGroup="add"/>
</div>
</asp:Panel>
<!--
like above add panels to edit and delete records.
Understanding the controls used in this example:
Control | ID | Description |
GridView | gv | Display record in grid format |
ModalPopupExtender | mpe1 ,mpe2 ,mpe3 | mpe1 is for adding new record, mpe2 is to edit existing record, mpe3 is to delete selected record |
RequiredFieldValidator | rfv1 to rfv8 | Validating TextBoxes and DropdownList in web application |
ValidatorCalloutExtender | vce1 to vce2 | Extending RequiredFieldValidators to enhance the default functionality |
Panel | panelAddNew , panelEdit , panelDelete | panelAddNew , panelEdit , panelDelete are added display popup windows to perform add, edit and delete operations |
Button | btnDummy1 , btnDummy2 | Used for TargetContolID property of ModalPopupExtender because Linkbuttons are child control of GridView and cannot be use for TargetControlID property of ModalPopupExtender
|
Note:
ModalPopupExtender
and Panel
control can be used in ItemTemplate
of GridView
but the problem is that all these controls will repeat for each record in GridView
. So to avoid this un-necessary repetition, these controls are taken outside of GridView
.
Now in Default.aspx.cs file, add the following code:
public partial class _Default : System.Web.UI.Page
{
SqlConnection cn = null;
SqlDataAdapter da = null;
SqlDataReader dr = null;
SqlCommand cmd = null;
DataSet ds = null;
string sqlQry = null;
protected void Page_Load(object sender, EventArgs e)
{
cn = new SqlConnection();
cn.ConnectionString = ConfigurationManager.ConnectionStrings["conStr"].ConnectionString;
if (!Page.IsPostBack)
{
Bind_Data();
Bind_Data_Ddl(ddlAdd);
Bind_Data_Ddl(ddlEdit);
}
}
void Bind_Data_Ddl(DropDownList ddl)
{
sqlQry = "select deptno,dname from dept";
da = new SqlDataAdapter(sqlQry, cn);
ds = new DataSet();
da.Fill(ds, "dept");
ddl.DataSource = ds.Tables["dept"];
ddl.DataTextField = "dname";
ddl.DataValueField = "deptno";
ddl.DataBind();
ddl.Items.Insert(0,new ListItem ("Select","0"));
}
void Bind_Data()
{
sqlQry = "select e.empid,e.ename,e.job,e.sal,
d.dname from employee e,dept d where e.deptno=d.deptno";
da = new SqlDataAdapter(sqlQry, cn);
ds = new DataSet();
da.Fill(ds, "emp");
gv.DataSource = ds;
gv.DataMember = "emp";
gv.DataBind();
}
void End_Block(Panel p)
{
foreach (dynamic txtBox in p.Controls)
{
if(txtBox is TextBox)
txtBox.Text = String.Empty;
}
ddlEdit.ClearSelection();
ddlAdd.ClearSelection();
mpe1.Hide();
mpe2.Hide();
mpe3.Hide();
}
protected void btnAddNew_Click(object sender, EventArgs e)
{
try
{
if (cn.State != ConnectionState.Open)
cn.Open();
cmd = new SqlCommand();
cmd.CommandText = "prcAddEmployee";
cmd.Connection = cn;
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.AddWithValue("@tename", txtName1.Text);
cmd.Parameters.AddWithValue("@tjob", txtJob1.Text);
cmd.Parameters.AddWithValue("@tsal", txtSal1.Text);
cmd.Parameters.AddWithValue("@tdeptno", ddlAdd.SelectedValue);
cmd.ExecuteNonQuery();
mpe1.Hide();
}
catch(SqlException e)
{
lblStatus1.Text = "Record is not added";
mpe1.Show();
}
finally
{
Bind_Data();
cmd.Dispose();
cn.Close();
}
}
protected void Cancel1_Click(object sender, EventArgs e)
{
End_Block(panelAddNew);
}
protected void lnkEdit_Click(object sender, EventArgs e)
{
try
{
LinkButton lnk = sender as LinkButton;
GridViewRow gr = (GridViewRow)lnk.NamingContainer;
string tempID = gv.DataKeys[gr.RowIndex].Value.ToString();
ViewState["tempId"] = tempID;
sqlQry = "select ename,job,sal,
deptno from employee where empid=" + tempID;
if (cn.State != ConnectionState.Open)
cn.Open();
cmd = new SqlCommand(sqlQry, cn);
dr = cmd.ExecuteReader();
if (dr.Read())
{
txtName2.Text = dr["ename"].ToString();
txtJob2.Text = dr["job"].ToString();
txtSal2.Text = dr["sal"].ToString();
ddlEdit.SelectedIndex = ddlEdit.Items.IndexOf
(ddlEdit.Items.FindByValue(dr["deptno"].ToString()));
}
mpe2.Show();
}
catch(SqlException e)
{
return;
}
finally
{
cmd.Dispose();
dr.Close();
cn.Close();
}
}
protected void btnUpdate_Click(object sender, EventArgs e)
{
try
{
if (cn.State != ConnectionState.Open)
cn.Open();
cmd = new SqlCommand();
cmd.CommandText = "prcUpdateEmployee";
cmd.Connection = cn;
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.AddWithValue("@tempid",
Convert.ToInt16(ViewState["tempId"].ToString()));
cmd.Parameters.AddWithValue("@tename", txtName2.Text);
cmd.Parameters.AddWithValue("@tjob", txtJob2.Text);
cmd.Parameters.AddWithValue("@tsal", txtSal2.Text);
cmd.Parameters.AddWithValue("@tdeptno", ddlEdit.SelectedValue);
cmd.ExecuteNonQuery();
}
catch(SqlException e)
{
lblStatus2.Text = "Record is not updated";
mpe2.Show();
}
finally
{
Bind_Data();
cmd.Dispose();
cn.Close();
}
}
protected void Cancel2_Click(object sender, EventArgs e)
{
End_Block(panelEdit);
}
protected void lnkDel_Click(object sender, EventArgs e)
{
try
{
LinkButton lnk = sender as LinkButton;
GridViewRow gr = (GridViewRow)lnk.NamingContainer;
string tempID = gv.DataKeys[gr.RowIndex].Value.ToString();
ViewState["tempId"] = tempID;
sqlQry = "select empid from employee where empid=" + tempID;
if (cn.State != ConnectionState.Open)
cn.Open();
cmd = new SqlCommand(sqlQry, cn);
dr = cmd.ExecuteReader();
if (dr.Read())
{
lblId.Text = dr.GetValue(0).ToString();
}
mpe3.Show();
}
catch(SqlException e)
{
return;
}
finally
{
cmd.Dispose();
dr.Close();
cn.Close();
}
}
protected void btnDelete_Click(object sender, EventArgs e)
{
try
{
if (cn.State != ConnectionState.Open)
cn.Open();
cmd = new SqlCommand();
cmd.CommandText = "prcDeleteEmployee";
cmd.Connection = cn;
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.AddWithValue("@tempid",
Convert.ToInt16(ViewState["tempId"].ToString()));
cmd.ExecuteNonQuery();
mpe3.Hide();
}
catch(SqlException e)
{
lblStatus3.Text = "Record not deleted";
mpe3.Show();
}
finally
{
Bind_Data();
cmd.Dispose();
cn.Close();
}
}
}
Run the project to check the output.
Output Widows
Default.aspx web page
Web page for adding new record
Web page for editing existing record
Web page for deleting record
Points of Interest
Measures which are taken into consideration while implementing this example are as follows:
- Use of AjaxControlToolKit controls to make the web application faster, interactive and responsive.
- Use of stored procedures to avoid SQL Injection attacks.
- Writing
ConnectionStrings
into web.config file so that it can be accessed anywhere in the project by using ConfigurationManager
class.