The final purpose for creating ASP.NET pages is to extract information from data sources, manipulate that information through server scripts, combine it with hard-coded page content, and present the output on XHTML pages delivered to the browser. Before this can be accomplished, however, quite a bit of groundwork needs to be laid. Notably, you need to gain facility with the set of server controls that make it all happen. For the next several tutorials these Web Form controls are described and demonstrated, beginning with output controls used to display server-generated information on the page.
The <asp:Label> control is one of the primary output controls. It defines an area on the Web page to which output can be written. This control can be used to display static text, or it can be used as a dynamic output area controlled by scripts. The general format for this control is shown in Figure 4-1.
<asp:Label id="id" Runat="Server" Text="string" property="value"... />
The control requires an id value to identify it to scripts and the Runat="Server" attribute required of all server controls. The Text attribute is optional and can be set to display a static message on the page or to display an initial message that is replaced by a script-generated message. The displayed text string can appear in the Text attribute of an empty tag or between a pair of opening and closing container tags. If the control is used only to display a static message, then it does not require the id for script reference.
Both text and XHTML can be displayed in the Label control. XHTML is rendered in the same fashion as if it were coded directly on the page. The Label's text display can be styled with the common set of server style properties along with CSS styling coded in its Style property. The Label can appear anywhere within the body of the document, located at the position on the page where its text will display. The control is converted by the ASP.NET processor into an XHTML <span> tag when the page is rebuilt for display in the browser.
Displaying Static Text
The following Label displays a static message when the page is loaded. The message is supplied in the Text property of the control and is styled through various server style properties (see "Style Properties" topic). No script is required to produce this static output.
<asp:Label Runat="Server" Text="Welcome to my page." Font-Size="14pt" Font-Bold="True" ForeColor="#0000FF"/>
Notice that no id needs to be supplied for this control since it does not require an identifier for reference by a script. Of course, this page output can be produced with hard-coded XHTML without use of the Label control. Normally, the control is needed only when using script to write to the page. Initial text display can be coded in the control with server script replacing the text in response to user or page events.
Displaying Scripted Text
The primary use of a Label control is as a target for script output. A script writes to the control by assigning a value to its Text property. The value assigned can be text characters, XHTML tags, and/or data values generated by the script. The following button, for example, activates a script to display a text message which includes server-generated output.
The following listing shows coding for a stand-alone Web page to display this message.
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <%@ Page Language="vb" Debug="True" %> <SCRIPT Runat="Server"> Sub Display_Message (Src As Object, Args As EventArgs) MyLabel.Text = "Thanks for clicking my button today, " & _ Format(DateString, "Long Date") & "." End Sub </SCRIPT> <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en"> <head> <title>Scripting a Label</title> </head> <body> <form Runat="Server"> <asp:Button Text="Click Me" OnClick="Display_Message" Runat="Server"/> <br/> <br/> <asp:Label id="MyLabel" Runat="Server" Font-Size="12pt" Font-Bold="True" ForeColor="#0000FF"/> </form> </body> </html>
The Label control requires an id because it is referenced by a script which assigns text characters to the Text property of the control. The text string assigned to the control is made up of three parts. A string of literal characters ("Thanks for clicking my button today ") is concatenated with the current date taken from the server clock and formatted with the Visual Basic Format function (Format(DateString, "Long Date")), concatenated with a final literal period ("."). This composed text string appears at the location on the page where the Label control is coded. When the string is displayed, server style properties coded in the control are applied to the output.
Displaying Database Sources
The Label control is not limited to short text messages. Multiple text and XHTML strings along with script-generated data can be concatenated to produce output. This usage is illustrated below in displaying selected information from the BooksDB.mdb database. The called subprogram selects books with inventory quantities less than 10. This information is formatted as a table by concatenating XHTML table tags interspersed with database fields and assigning these strings to the Text property of the control.
Code to produce this page is shown below. Again, this code can be interspersed within other page content, remembering to place the Label control wherever the output is to appear.
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <%@ Page Language="vb" Debug="True" %> <%@ Import Namespace="System.Data.OleDb" %> <SCRIPT Runat="Server"> Sub Show_Qty (Src As Object, Args As EventArgs) Dim DBConnection As OleDbConnection Dim DBCommand As OleDbCommand Dim DBReader As OleDbDataReader Dim SQLString As String DBConnection = New OleDbConnection( _ "Provider=Microsoft.Jet.OLEDB.4.0;" & _ "Data Source=" & Server.MapPath("../Databases/BooksDB.mdb")) DBConnection.Open() SQLString = "SELECT BookID, BookTitle, BookQty " & _ "FROM Books WHERE BookQty < 10 " & _ "ORDER BY BookQty DESC" DBCommand = New OleDbCommand(SQLString, DBConnection) DBReader = DBCommand.ExecuteReader() Output.Text = "<table border=""1"">" Output.Text &= "<tr style=""background-color:#F0F0F0"">" Output.Text &= "<th>Qty</th>" Output.Text &= "<th>ID</th>" Output.Text &= "<th>Title</th>" Output.Text &= "</tr>" While DBReader.Read() Output.Text &= "<tr>" Output.Text &= "<td>" & DBReader("BookQty") & "</td>" Output.Text &= "<td>" & DBReader("BookID") & "</td>" Output.Text &= "<td>" & DBReader("BookTitle") & "</td>" Output.Text &= "</tr>" End While Output.Text &= "</table>" DBReader.Close() DBConnection.Close() End Sub </SCRIPT> <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en"> <head> <title>Scripting a Label</title> </head> <body> <form Runat="Server"> <asp:Button Text="Show Quantities < 10" OnClick="Show_Qty" Runat="Server"/> <br/> <br/> <asp:Label id="Output" Runat="Server"/> </form> </body> </html>
In an earlier tutorial an introduction is given to writing scripts to access data sources. Here, that process is repeated for access to and reporting of records from a database table. Since a Label control cannot be associated with a data source control such as an AccessDataSource, scripting must be used to link to the database and explicitly process a returned recordset.
Namespace Importing
The standard Page directive is coded to assist in script debugging. Also, since the script accesses a database, an Import directive is coded to supply the page with necessary software classes to process an Access database. All of the database processing objects are declared prior to their use.
<%@ Page Language="vb" Debug="True" %> <%@ Import Namespace="System.Data.OleDb" %> Dim DBConnection As OleDbConnection Dim DBCommand As OleDbCommand Dim DBReader As OleDbDataReader Dim SQLString As String
Database Access
Script access to the database uses the common set of Connection, Command, and DataReader objects described previously. A Connection object (DBConnection) is created and supplied with information about the database type (Provider) and the server location of the database (Data Source). Location of the database is given by a relative path (relative to the page) converted to a physical path with the ServerMapPath() method. The connection is then opened to give the script access to the database.
DBConnection = New OleDbConnection( _ "Provider=Microsoft.Jet.OLEDB.4.0;" & _ "Data Source=" & Server.MapPath("../Databases/BooksDB.mdb")) DBConnection.Open()
An SQL statement is composed to select all records from the database which have a BookQty field value of less than 10. This statement is coded as a continuation of three lines of code in which three text strings are concatenated to produce the final SELECT statement. The statement is assigned to variable SQLString for ease of handling. It is then issued through a Command object (DBCommand) against the previously opened Connection.
SQLString = "SELECT BookID, BookTitle, BookQty " & _ "FROM Books WHERE BookQty < 10 " & _ "ORDER BY BookQty DESC" DBCommand = New OleDbCommand(SQLString, DBConnection)
The set of selected records are retrieved from the database and assigned to a DataReader object (DBReader). This returned recordset includes 15 records composed of the BookID, BookTitle, and BookQty fields selected from the Books table. The records are in descending order by the BookQty field.
DBReader = DBCommand.ExecuteReader()
Iterating the Recordset
A set of records is now available to the script. The processing task is to move through the recordset one record at a time displaying their data fields within the rows of an XHTML table. Before creating table rows, however, XHTML tags to define the table and to create a row of column headings is coded. This output is a series of string concatenations assigned to the Label control to build the table header prior to initiating the program loop.
Output.Text = "<table border=""1"">" Output.Text &= "<tr style=""background-color:#F0F0F0"">" Output.Text &= "<th>Qty</th>" Output.Text &= "<th>ID</th>" Output.Text &= "<th>Title</th>" Output.Text &= "</tr>"
Strings of XHTML tags are concatentated to the Text property of the Output Label. It does not particularly matter how the tags are broken up into separate strings. In this example, the individual strings resemble the individual lines of XHTML that would be hard-coded on a Web page. Just remember that tags containing quoted attributes must enclose their attribute values inside double quote marks to distinguish them from the quotes surrounding the entire tag string.
Once the header tags are written to the Output control, a Visual Basic program loop is set up to iterate the records using a While...End While statement. It is inside this loop that a table row is created for each record, executing the DataReader's Read() method to read the next record from the recordset.
While DBReader.Read() Output.Text &= "<tr>" Output.Text &= "<td>" & DBReader("BookQty") & "</td>" Output.Text &= "<td>" & DBReader("BookID") & "</td>" Output.Text &= "<td>" & DBReader("BookTitle") & "</td>" Output.Text &= "</tr>" End While
Although the output table contains 15 rows, the script only needs to format one row. This single row definition is repeated for as many records as there are in the recordset. Data fields from each record in the DataReader (DBReader("fieldname")) are concatenated inside XHTML tags for a row, and the table row is appended to the Text property of the Output Label, growing the table one row at a time.
After all rows have been written to the output Label, the table definition is completed by appending a closing </table> tag to the end of the previous output.
Output.Text &= "</table>"
Closing the Database
At this point the script is done with the DataReader and database Connection. Therefore, they are closed by issuing their respective Close() methods, and the script ends having produced an XHTML table containing information from the database.
DBReader.Close() DBConnection.Close()
Other Output Formats
You can write any XHTML and intermixed data values to a page by assigning them to the Text property of a Label control; plus, you do not always have to format the data in an XHTML table. Below is shown different output of the same database information using a different set of XHTML tags. In this case, output is enclosed inside a bordered <div> tag, with data fields enclosed in <span> tags.
The same general model for database processing is used. Differences between this and the previous script are in the XHTML tags assigned to the output Label; also, the DataReader's HasRows property is tested for a returned recordset. Where there is the possibility of no records being returned by an SQL query, this test should be made. It permits taking positive programmatic steps to inform the user about missing information rather than simply displaying "nothing" with no explanation.
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <%@ Page Language="vb" Debug="True" %> <%@ Import Namespace="System.Data.OleDb" %> <SCRIPT Runat="Server"> Sub Show_Qty (Src As Object, Args As EventArgs) Dim DBConnection As OleDbConnection Dim DBCommand As OleDbCommand Dim DBReader As OleDbDataReader Dim SQLString As String DBConnection = New OleDbConnection( _ "Provider=Microsoft.Jet.OLEDB.4.0;" & _ "Data Source=" & Server.MapPath("../Databases/BooksDB.mdb")) DBConnection.Open() SQLString = "SELECT BookID, BookTitle, BookQty " & _ "FROM Books WHERE BookQty < 10 " & _ "ORDER BY BookQty DESC" DBCommand = New OleDbCommand(SQLString, DBConnection) DBReader = DBCommand.ExecuteReader() If DBReader.HasRows Then Output.Text = "<div style=""width:320px; border:solid 1; padding:10px"">" While DBReader.Read() Output.Text &= "<span style=""width:25px"">" Output.Text &= DBReader("BookQty") Output.Text &= "</span>" Output.Text &= "<span style=""width:70px"">" Output.Text &= DBReader("BookID") Output.Text &= "</span>" Output.Text &= "<span style=""width:200px"">" Output.Text &= DBReader("BookTitle") Output.Text &= "</span><br/>" End While Output.Text &= "</div>" Else Output.Text = "No matching records" End If DBReader.Close() DBConnection.Close() End Sub </SCRIPT> <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en"> <head> <title>Scripting a Label</title> </head> <body> <form Runat="Server"> <asp:Button Text="Show Quantities < 10" OnClick="Show_Qty" Runat="Server"/> <br/> <br/> <asp:Label id="Output" Runat="Server"/> </form> </body> </html>
Displaying Calculated Values
By using script to access a data source you have full control over processing. You can, for instance, perform calculations to produce new information for display. In the following example, the BooksDB.mdb database is accessed to determine inventory values. For each book, the price and quantity fields are multiplied to derive its value; also the total inventory value is determined by summing the individual amounts. All information is written to a Label control formatted as an XHTML table.
The script to produce this table appears in the Page_Load subprogram to run automatically when the page opens. This code is shown below along with the Label control that serves as the target for script output.
(In this and subsequent code listings only the code pertinent to the discussion at hand is shown, not a complete Web page. You need to remember to include necessary page directives, namespaces, script tags, and XHTML tags surrounding this code when creating your own pages.)
<%@ Import Namespace="System.Data.OleDb" %> <SCRIPT Runat="Server"> Sub Page_Load Dim DBConnection As OleDbConnection Dim DBCommand As OleDbCommand Dim DBReader As OleDbDataReader Dim SQLString As String Dim Amount As Decimal Dim Total As Decimal = 0.00 DBConnection = New OleDbConnection( _ "Provider=Microsoft.Jet.OLEDB.4.0;" & _ "Data Source=" & Server.MapPath("../Databases/BooksDB.mdb")) DBConnection.Open() SQLString = "SELECT BookID, BookTitle, BookPrice, BookQty " & _ "FROM Books ORDER BY BookID" DBCommand = New OleDbCommand(SQLString, DBConnection) DBReader = DBCommand.ExecuteReader() If DBReader.HasRows Then Output.Text = "<style type=""text/css"">" Output.Text &= "table#INV {border-collapse:collapse}" Output.Text &= "table#INV th {font-size:11pt; background-color:#F0F0F0}" Output.Text &= "table#INV td {font-size:11pt}" Output.Text &= ".right {text-align:right}" Output.Text &= ".rightb {text-align:right; font-weight:bold}" Output.Text &= "h4 {text-align:center}" Output.Text &= "</style>" Output.Text &= "<h4>Book Inventory</h4>" Output.Text &= "<table id=""INV"" border=""1"">" Output.Text &= "<tr>" Output.Text &= "<th>Book ID</th>" Output.Text &= "<th>Book Title</th>" Output.Text &= "<th>Book Price</th>" Output.Text &= "<th>Book Qty</th>" Output.Text &= "<th>Amount</th>" Output.Text &= "</tr>" While DBReader.Read() Amount = DBReader("BookPrice") * DBReader("BookQty") Total += Amount Output.Text &= "<tr>" Output.Text &= "<td>" & DBReader("BookID") & "</td>" Output.Text &= "<td>" & DBReader("BookTitle") & "</td>" Output.Text &= "<td class=""right"">" & DBReader("BookPrice") & "</td>" Output.Text &= "<td class=""right"">" & DBReader("BookQty") & "</td>" Output.Text &= "<td class=""right"">" & FormatNumber(Amount) & "</td>" Output.Text &= "</tr>" End While Output.Text &= "<tr>" Output.Text &= "<th colspan=""4"" class=""rightbold"">Total: </th>" Output.Text &= "<td class=""rightb"">" & FormatCurrency(Total) & "</td>" Output.Text &= "</tr>" Output.Text &= "</table>" End If DBReader.Close() DBConnection.Close() End Sub </SCRIPT> <form Runat="Server"> <asp:Label id="Output" Runat="Server"/> </form>
Notice in this script that a style sheet is written to the page for formatting of the inventory value table. If there were an embedded style sheet already coded on the page, these dynamic styles would supplement the hard-coded style sheet.
The script follows the general model for producing an output table from a recordset returned from a database. In addition, variable Amount is declared to store the individual book inventory amounts calculated by multiplying the book price times its quantity on hand. Variable Total is declared and initialized as an accumulator for the total inventory amount.
Dim Amount As Decimal Dim Total As Decimal = 0.00
During processing of individual book records, the BookPrice field is multiplied times the BookQty field and assigned to variable Amount. This variable is added to variable Total to accumulate these amounts. As you can see, DataReader fields can be used just like script variables in making computations. Individual amounts are displayed in the last column of the output table.
While DBReader.Read() Amount = DBReader("BookPrice") * DBReader("BookQty") Total += Amount ... Output.Text &= "<td class=""right"">" & FormatNumber(Amount) & "</td>" ... End While
At the close of loop processing, the total value of the book inventory has been accumulated in variable Total. This variable is written in the final row of the table prior to writing the closing </table> tag to end the table description.
Output.Text &= "<td class=""rightb"">" & FormatCurrency(Total) & "</td>"
As mentioned, this script is quite typical for accessing, iterating, and displaying database information. It is well to keep in mind this general model as a common scripting approach to database display.
Applying Styles to the Label Control
Recall previous discussions about the variety of methods available for styling controls. One option is to use server style propertiesbased on CSS styles but often using different style namescoded in the control. The following Label applies a set of common server styles to decorate its enclosed content. Since there is no server property equivalent to the CSS padding style for a Label, a Style attribute is needed to apply this CSS style to surround the text with spacing.
<asp:Label id="MyLabel" Text="Welcome to my page." Runat="Server" BackColor="#990000" ForeColor="#FFFFFF" BorderStyle="Dotted" BorderWidth="2" BorderColor="#000000" Font-Names="Times New Roman" Font-Bold="True" Font-Size="12pt" Width="170px" Height="43px" Style="padding:10px"/>
Style properties for Label controls and other server controls can be changed under script control. When applying server styles through script, just remember to import the System.Drawing namespace and use the special color and unit conversion methods. The following Label has its styling changed using server styles.
<%@ Import Namespace="System.Drawing" %> <SCRIPT Runat="Server"> Sub Change_Styles (Src As Object, Args As EventArgs) MyLabel.BackColor = Color.FromName("black") MyLabel.ForeColor = Color.FromName("white") MyLabel.BorderStyle = BorderStyle.Dotted MyLabel.BorderWidth = Unit.Parse("2px") MyLabel.BorderColor = Color.FromName("#990000") MyLabel.Font.Name = "Arial" MyLabel.Font.Size = FontUnit.Parse("10pt") MyLabel.Font.Bold = True End Sub </SCRIPT> <form Runat="Server"> <asp:Label id="MyLabel" Text="Welcome to my page." Runat="Server" BackColor="#990000" ForeColor="#FFFFFF" BorderStyle="Dotted" BorderWidth="2" BorderColor="#000000" Font-Names="Times New Roman" Font-Bold="True" Font-Size="12pt" Width="170px" Height="43px" Style="padding:10px"/> <asp:Button Text="Change Styles" onClick="Change_Styles" Runat="Server"/> </form>
You may prefer to declare and change control styles using the Style attribute along with standard CSS style properties. The following Label has the same look as the previous Label, this time produced with a Style attribute that sets CSS style properties. The accompanying button calls a script to change these style settings, again using Style properties and common CSS conventions.
<SCRIPT Runat="Server"> Sub Change_Styles (Src As Object, Args As EventArgs) MyLabel.Style("background-color") = "#000000" MyLabel.Style("color") = "#FFFFFF" MyLabel.Style("border") = "dotted 2px #990000" MyLabel.Style("font") = "bold 10pt arial" End Sub </SCRIPT> <form Runat="Server"> <asp:Label id="MyLabel" Text="Welcome to my page." Runat="Server" Style="background-color:#990000; color:#FFFFFF; border:dotted 2px #000000; font:bold 12pt times new roman; width:170px; height:43px; padding:10px"/> <asp:Button Text="Change Styles" OnClick="Change_Styles" Runat="Server"/> </form>
Scripting Conventional HTML Tags
It is noteworthy that ASP.NET scripts can interact with conventional XHTML tags in addition to the special server controls introduced by the .NET framework. The only requirement is that the XHTML tag include the Runat="Server" attribute and that it be assigned an id value for reference by scripts. When these two conditions are met, any XHTML tag can be made script accessible.
As mentioned previously, Label controls are translated into standard XHTML <span> tags by the ASP.NET processor prior to returning the page to the browser. As you might suspect, then, a <span> tag itself can be made script accessible. In the following example, a <span> tag is used to display a welcome message styled with an in-line style sheet. Since the tag includes an id value and the Runat="Server" attribute, it is accessible by server scripts. The accompanying button calls a subprogram to change the style of this XHTML tag.
<SCRIPT Runat="Server"> Sub Style_Message (Src As Object, Args As EventArgs) MyOutput.Style("border") = "ridge 3px" MyOutput.Style("padding") = "5px" MyOutput.Style("background-color") = "#CC6666" MyOutput.Style("color") = "#FFFFFF" MyOutput.InnerText = "Won't you come back soon?" End Sub </SCRIPT> <form Runat="Server"> <span id="MyOutput" Runat="Server" Style="font-family:times new roman; font-size:14pt; font-weight:bold; color:#0000FF"> Welcome to my Web page. </span> <input type="button" value="Style Message" Runat="Server" OnServerClick="Style_Message"/> </form>
The <span> tag is restyled in script by applying CSS style properties. Its content is changed through its innerText property, a reference to the text area appearing between the opening and closing tags.
The button is created with an XHTML <input type="button"/> tag. Since this is an XHTML tag and not a server control, an OnClick event handler added to this tag implies a call to a browser-based JavaScript function, not to a server script. In order to call a server subprogram from an XHTML tag, the special OnServerClick event handler must be used in place of OnClick.
Although all XHTML tags can be made into scriptable controls, it is still best to use equivalent ASP.NET controls as replacements for conventional XHTML tags unless special situations warrant. Server controls have greater built-in scripting functionality than normal XHTML tags.