Microsoft ASP .NET Professional Projects - Premier Press
.pdf</asp:BoundColumn>
<asp:BoundColumn HeaderText="Title" DataField="title"> <HeaderStyle Width="250px">
</HeaderStyle>
</asp:BoundColumn>
<asp:BoundColumn HeaderText="Published" DataField="pubdate" DataFormatString="{0:MMM yyyy}">
<HeaderStyle Width="100px"> </HeaderStyle>
</asp:BoundColumn>
<asp:BoundColumn HeaderText="Price" DataField="price" DataFormatString="{0:c}">
<HeaderStyle Width="50px"> </HeaderStyle>
<ItemStyle HorizontalAlign="Right"> </ItemStyle>
</asp:BoundColumn>
</Columns>
<HeaderStyle BackColor="DarkRed" ForeColor="White" Font-Bold="true">
</HeaderStyle>
<FooterStyle BackColor="Tan"> </FooterStyle>
<ItemStyle ForeColor="DarkSlateBlue"> </ItemStyle>
<AlternatingItemStyle BackColor="Beige"> </AlternatingItemStyle>
</asp:DataGrid>
</td>
</table>
</asp:Panel>
</tr>
</table>
</form>
</body>
</html>
The Code Behind for this form is MasterChild.vb:
MasterChild.vb
Imports System
Imports System.Collections
Imports System.Text
Imports System.Data
Imports System.Data.OleDb
Imports System.Web.UI
Imports System.Web.UI.WebControls
Public Class BaseClass
Inherits System.Web.UI.Page
Protected AuthorsGrid as DataGrid
Protected titlesGrid as DataGrid
Protected detailsPanel as Panel
Public currentAuthor as object
Dim myConnection As OleDbConnection Dim myCommand As OleDbDataAdapter Dim ds As New DataSet
Dim ConnStr As String
Dim SQL As String
Sub Page_Load(Source As Object, E As EventArgs)
ConnStr = "Provider=SQLOLEDB; Data Source=(local); Initial Catalog=pubs;User
ID=sa;"
myConnection = New OleDbConnection(ConnStr) if NOT (isPostBack)
rebind end if
End Sub
Sub FillDs
sql = " select * , au_lname + ',' + au_fname as au_name" sql = sql + " From authors a, titles t, titleauthor ta"
sql = sql + " Where a.au_id = ta.au_id AND t.title_id = ta.title_id" myCommand = New OleDbDataAdapter(SQL, myConnection) 'use Fill method of DataSetCommand to populate dataset myCommand.Fill(ds, "Authors")
End Sub
Sub ReBind()
FillDs
'Binding a Grid
AuthorsGrid.DataSource=ds.Tables("Authors").DefaultView
AuthorsGrid.DataBind()
End Sub
Sub Grid_Select(sender as Object , e as EventArgs)
Dim vIndex As Integer
Dim vkey As string
vIndex = AuthorsGrid.SelectedIndex
vkey =AuthorsGrid.DataKeys(vIndex).ToString UpdateSelection(vkey)
End Sub
Sub UpdateSelection(vkey as string)
Dim myConnection2 As OleDbConnection
Dim myCommand2 As OleDbDataAdapter
Dim ds2 As New DataSet
Dim ConnStr2 As String
Dim SQL2 As String
Dim itemcount As Integer
sql2 = " select * , au_lname + ',' + au_fname as au_name"
sql2 = sql2 + " From authors a, titles t, titleauthor ta"
sql2 = sql2 + " Where a.au_id = ta.au_id AND t.title_id = ta.title_id"
sql2 = sql2 + " AND a.au_id = '" + vkey + "'"
myCommand2 = New OleDbDataAdapter(SQL2, myConnection)
myCommand2.Fill(ds2, "Authors")
'Bind the Grid
titlesGrid.DataSource=ds2.Tables("Authors").DefaultView
titlesGrid.DataBind()
itemcount = titlesGrid.Items.Count
if itemcount >= 1 then
detailsPanel.Visible = true
Else
detailsPanel.Visible = false
response.write("No rows found")
end if
End Sub
End Class
The Master-Grid implementation is comprised of two DataGrids: the AuthorsGrid and the titlesGrid. The AuthorsGrid is bound to a query, which is a join between the Authors, titles, and TitleAuthors table. The query is as follows:
sql = " select * , au_lname + ',' + au_fname as au_name"
sql = sql + " From authors a, titles t, titleauthor ta"
sql = sql + " Where a.au_id = ta.au_id AND t.title_id = ta.title_id"
I have created a ButtonColumn with CommandName = "select". The "select" CommandName informs the DataGrid that an item has been selected and fires the
"OnSelectedIndexChanged" event, which in turn fires the "Grid_Select" function.
The Grid_Select function retrieves the au_id (the DataKeyField) of the row that has changed and calls the UpdateSelection function. The UpdateSelection function binds the titlesGrid with the following query:
sql2 = " select * , au_lname + ',' + au_fname as au_name"
sql2 = sql2 + " From authors a, titles t, titleauthor ta"
sql2 = sql2 + " Where a.au_id = ta.au_id AND t.title_id = ta.title_id"
sql2 = sql2 + " AND a.au_id = '" + vkey + "'"
This query limits the original query to the selected author only. Note that the titlesGrid is enclosed within a Panel which has an id of DetailsPanel, which is initially invisible. The UpdateSelection binds the titlesGrid and makes the Panel visible. This in turn displays the detail records.
Summary
I have covered quite a lot of ground in this chapter. I have shown how the "list bound" controls are bound to a datasource. Practical examples of using the DataRepeater, the DataList, and DataGrid were provided. Working with XML datasources was also explained. Further chapters in this book build on these concepts and the project section of the book shows how to use them in actual applications.
Chapter 5: Input Validation
Overview
Input validation is a dull, dreary task. I don't see too many developers getting excited about writing validation code. However, the value of good validation techniques cannot be discounted. Without appropriate validation, our script routines would break, and we would get garbage in our database. ASP.NET makes the task of implementing validation routines a breeze. Implementing a validation routine is as simple as creating a validation control and telling it what control to validate.
The ASP.NET team did detailed research of a number of data entry forms. They found that most validation tasks revolved around the following activities:
§Checking for "regular expressions" such as ZIP codes and telephone numbers
§Comparing two users' input values
§Checking for required fields
§Checking if a given input falls within a range of values
In addition they found that the user could be informed of a wrong input value immediat ely. Also, all wrong input values could be summarized and shown together.
Armed with this knowledge they set out to develop an object that could encompass all these activities and take the yoke of writing validation code off our necks. Writing such an object in an ActiveX environment would have meant overloading the functionality of all the requirements listed above into a single component that behaved differently in different modes. However, the .NET framework allowed them to create six controls that all inherit from a common object (BaseValidator). Each object specializes in providing certain functionality. Since the scope of each object is focused, it is a lean, but very effective control. The following list shows the controls they came up with:
§RequiredFieldValidator
§RegularExpressionValidator
§CompareValidator
§RangeValidator
§CustomValidator
§ValidationSummary
There are five validation controls and one ValidationSummary control. The work of the first four validation controls is evident from their names. You can write your own validation function and associate it with the CustomValidator. Finally, the ValidationSummary control presents a summary of all the errors on the page in one location.
A Two-Pronged Approach to Validation
A good validation approach requires that you validate user input both at the client and server side. Client side validation is nice to have. Users get immediate feedback of illegal input values. The downside of client side validation is that it is quite cumbersome to implement using just HTML 3.2. Scripting languages and DHTML make this task easy. However, this makes an assumption that users will use browsers that support these technologies. This is not a valid assumption to make. Using only client side validation can also pose a security risk. It is quite easy to tamper, replace, or bypass a script page. It is for this reason that the validation controls use a two-pronged approach. They use the client side validation to provide immediate feedback and then repeat the validation at server side. Client side validation is automatic with Internet Explorer 4.0 and above. For script-disabled browsers, validation is carried out server side.
The client side validation has number of features. An immediate feedback (say an error message in red) is given to users regarding illegal entries, which goes away after the error is rectified. If an error is trapped at the client side, a post back to the server is avoided. The validation summary updates itself, again without a post back. No ActiveX objects or applets are used to implement the client side functionality as the logic is contained in a JScript library.
Validation Controls
I have created a Web page with a sample of each validation control. I shall be using this in my discussions. Figure 5.1 displays the result of the validate.aspx code.
Figure 5.1: Validation controls. validate.aspx
<%@ Page language="VB" %>
<html>
<head>
<script runat=server>
Sub ServerValidate (sender As Object, value As ServerValidateEventArgs) Dim num As Int32 = Int32.Parse(value.Value)
response.write(num) if num= "10" then
value.IsValid = True else
value.IsValid = False end if
End Sub
public sub OnSubmit(source as Object, e as EventArgs) if Page.IsValid then
' Check before update to database end if
end sub </script>
<title>Validating with ASP+ Controls</title> </head>
<body style="background-color='beige'; font-family='verdana'; font -size='10pt'"> <h2>ASP .NET Control Validation</h2>
<hr>
<asp:ValidationSummary runat=server headertext="There were errors on the page:" /> <form RunAt="server">
<B>Required Field :</B><br><br>
Name : <input type=text runat=server id=txtName> <asp:RequiredFieldValidator runat=server
controltovalidate=txtName errormessage="Name is required.">*
</asp:RequiredFieldValidator>
<hr>
Password:<asp:TextBox id="txtPassword" RunAt="server"/> <br>
Confirm:<asp:TextBox id="txtConfirm" RunAt="server"/> <asp:CompareValidator
id="cvPassword"
ControlToValidate="txtPassword"
ControlToCompare="txtConfirm"
Type="String"
Operator=Equal
Display="dynamic"
ErrorMessage="The password does not match the confirm password!" RunAt="server">
*
</asp:CompareValidator>
<hr>
Range Validator <br><br>
IQ (180 - 265):<asp:TextBox id="iq" RunAt="server"/> <asp:RangeValidator
id="rvIQ"
ControlToValidate="iq"
Display="dynamic"
ErrorMessage="IQ must be between 180 and 265 to run this example" MinimumValue=180
MaximumValue=265
Type="Integer"
RunAt="server">
</asp:RangeValidator>
<br>
Regular Expression: <br> <br>
validation expression : [0-9]{3}\s[0-9]{3}-[0-9]{4}<br>
Example : 214 345-0458 <br><br>
Phone:<asp:TextBox id="txtPhone" RunAt="server" /> <asp:RegularExpressionValidator
id="revPassword"
ControlToValidate="txtPhone"
Display="dynamic" ValidationExpression="[0-9]{3}\s[0-9]{3}-[0-9]{4}" ErrorMessage="Phone number must be xxx xxx-xxxx" RunAt="server">
</asp:RegularExpressionValidator>
<hr>
Custom Validation: <br><br>
Must be the number 10
<asp:TextBox id=Text11 runat="server" />   
<asp:CustomValidator id="CustomValidator1" runat="server" ControlToValidate="Text11" OnServerValidate="ServerValidate"
Display="Static"
Font-Name="verdana" Font-Size="10pt">
This field must be the number 10!
</asp:CustomValidator>
<br>
<hr>
<input type=submit runat=server id=cmdSubmit value=Submit onserverclick=OnSubmit>
</form>
</body>
</html>
Required Field
The required field validation control ensures that specified fields get filled in. The example of a required field is as follows:
Name : <input type=text runat=server id=txtName>
<asp:RequiredFieldValidator runat=server
controltovalidate=txtName
errormessage="Name is required.">*
</asp:RequiredFieldValidator>
The user is supposed to fill out the txtName textbox. If he leaves it blank and hits the submit button, an error is displayed ("Name is required") by the ValidationSummary control. An asterisk (*) is also displayed next to the textbox. The ControlToValidate property specifies the ID of the control to validate, which in this case is txtName.
Compare Validator
The CompareValidator compares the content of two controls and if they don't match, reports an error. A typical use of the CompareValidator is to match a password and a password reentry value. The following is an example:
Password:<asp:TextBox id="txtPassword" RunAt="server"/>
<br>
Confirm:<asp:TextBox id="txtConfirm" RunAt="server"/>
<asp:CompareValidator
id="cvPassword"
ControlToValidate="txtPassword"
ControlToCompare="txtConfirm"
Type="String"
Operator=Equal
Display="dynamic"
ErrorMessage="The password does not match the confirm password!"
RunAt="server">
*
</asp:CompareValidator>
Here I am comparing two fields. If they don't match, a * is displayed and the error message "The password does not match the confirm password!" is displayed by the validation control when the submit button is clicked. You can specify the data type of the values and the comparison operator.
1.If you get rid of the * in the CompareValidator tag, the error message is displayed instead of the * to provide immediate feedback to the user.
2.The Type property can be of the following:
§String
§Integer
§Double
§DateTime
§Currency
3.The Operator property can be of the following: