[ Home | Syllabus | Course Notes | Assignments | Search]
With ASP.NET we enter the world of distributed processing using standard internet protocols
Accessing the class .NET server
About the Web.
HMTL revolutionized the way information is delivered over the internet
Can use any text editor to create HTML pages
However support for dynamic content has been a challenge
CGI (Common Gateway Interface) - mostly PERL - UNIX oriented servers
ASP - microsoft's server side programming
The Hypertext Transfer Protocol, better known as HTTP, is the protocol that drives the World Wide Web. Invented by Tim Berners-Lee ("father of the Web")
Here is a simple HTML page
<html> <body> Hello, world </body> </html>
If stored on a web server it can be accessed used its URL (e.g. http://www.cs.odu.edu/~wild/cs477/spring04/simple.html)
GET ~wild/cs477/spring04/simple.html HTTP/1.1 Accept: */* Accept-Language: en-us Accept-Encoding: gzip, deflate If-Modified-Since: Wed, 24 Oct 2001 14:12:36 GMT If-None-Match: "50b0d3ee955cc11:a78" User-Agent: Mozilla/4.0.(compatible; MSIE.6.0; Windows NT 5.1) Host: www.cs.odu.edu Connection: Keep-Alive [blank line]
HTTP/1.1 200 OK Server: Microsoft-IIS/5.0 Date: Wed, 24 Oct 2001 14:12:37 GMT Content-Type: text/html Accept-Ranges: bytes Last-Modified: Wed, 24 Oct 2001 14:00:53 GMT ETag: "d02acf81975cc11:a78" Content-Length: 46 [blank line] <html> <body> Hello, world </body> </html>
Need a program at the server to generate HTML pages dynamically when requested (latest weather, etc).
<html> <body> <form> <input type="text" name="op1" /> + <input type="text" name="op2" /> <input type="submit" value=" = " /> </form> </body> </html>
http://www.cs.odu.edu/~wild/cs477/spring03/Examples/Book1/Chap05/Calc/Calc.html?op1=3&op2=4
One disadvantage to the above approaches is that they are slow, first because they use scripting languages (which are not compiled) and second because each server side program runs in it's own process which is expensive to start up and stop.
ISAPI (Internet Server Application
Programming Interface) allows DLLs to be loaded into it's own process space
and run a compiled (e.g. C++) program
(ISAPI was the entry point for the code red virus however)
Here is an exmaple URL http://www.wintellect.com/calc.dll
Difficult to write - need to deal with HTTP at a rather low level
Here is an example in C++ for the calculator program
#include <windows.h> #include <httpext.h> #include <string.h> #include <stdlib.h>
int GetParameter (LPSTR pszQueryString, LPSTR pszParameterName); BOOL WINAPI DllMain (HINSTANCE hInstance, DWORD fdwReason, LPVOID lpvReserved) { return (TRUE); } BOOL WINAPI GetExtensionVersion (HSE_VERSION_INFO* pVer) { pVer->dwExtensionVersion = MAKELONG (HSE_VERSION_MINOR, HSE_VERSION_MAJOR); lstrcpy (pVer->lpszExtensionDesc, "Calc ISAPI Extension"); return (TRUE); } DWORD WINAPI HttpExtensionProc (EXTENSION_CONTROL_BLOCK* pECB) { static char* szPrePostbackMessage = "<html>\r\n" \ "<body>\r\n" \ "<form>\r\n" \ "<input type=\"text\" name=\"op1\" />\r\n" \ "+\r\n" \ "<input type=\"text\" name=\"op2\" />\r\n" \ "<input type=\"submit\" value=\" = \" />\r\n" \ "</form>\r\n" \ "</body>\r\n" \ "</html>"; static char* szPostPostbackMessage = "<html>\r\n" \ "<body>\r\n" \ "<form>\r\n" \ "<input type=\"text\" name=\"op1\" value=\"%d\" />\r\n" \ "+\r\n" \ "<input type=\"text\" name=\"op2\" value=\"%d\" />\r\n" \ "<input type=\"submit\" value=\" = \" />\r\n" \ "%d\r\n" \ "</form>\r\n" \ "</body>\r\n" \ "</html>"; // // Build the response message body. // char szMessage[512]; if (lstrlen (pECB->lpszQueryString) == 0) { // If the query string is empty, return a page that shows // an empty calculator. lstrcpy (szMessage, szPrePostbackMessage); } else { // If the query string is not empty, extract the user input, // process it, and return a page that shows inputs and outputs. int a = GetParameter (pECB->lpszQueryString, "op1"); int b = GetParameter (pECB->lpszQueryString, "op2"); wsprintf (szMessage, szPostPostbackMessage, a, b, a + b); } // // Build the response message header. // char szHeader[128]; DWORD dwCount = lstrlen (szMessage); wsprintf (szHeader, "Content-type: text/html\r\n" \ "Content-Length: %lu\r\n\r\n", dwCount); // // Output the response message header. // HSE_SEND_HEADER_EX_INFO shei; shei.pszStatus = "200 OK"; shei.pszHeader = szHeader; shei.cchStatus = lstrlen (shei.pszStatus); shei.cchHeader = lstrlen (shei.pszHeader); shei.fKeepConn = FALSE; pECB->ServerSupportFunction (pECB->ConnID, HSE_REQ_SEND_RESPONSE_HEADER_EX, &shei, NULL, NULL); // // Output the response message body. // pECB->WriteClient (pECB->ConnID, szMessage, &dwCount, 0); // // Indicate that the request was processed successfully. // return HSE_STATUS_SUCCESS; } int GetParameter (LPSTR pszQueryString, LPSTR pszParameterName) { char* p = strstr (pszQueryString, pszParameterName); if (p != NULL) { p += strlen (pszParameterName) + 1; for (char* tmp = p; *tmp != '&' && *tmp != 0; tmp++) ; //// skip front part of URL int len = tmp - p; char* buffer = new char[len + 1]; strncpy (buffer, p, len); int val = atoi (buffer); delete buffer; return val; } return 0; }
F1: Function called when DLL is loaded by hosting program - can initialize if required
<%@ Language="VBScript" %> <html> <body> <form> <input type="text" name="op1" value="<%= Request("op1") %>"/> + <input type="text" name="op2" value="<%= Request ("op2") %>" /> <input type="submit" value=" = " /> <% If Request ("op1") <> "" And Request ("op2") <> "" Then a = CInt (Request ("op1")) b = CInt (Request ("op2")) Response.Write (CStr (a + b)) End If %> </form> </body> </html>
F2: "<%" and "%>" is an escape from HTML into the ASP scripting engine.
F3: Request returns the parameter value passed in (if any) or the empty string if no form values submitted (like for the first time displayed
F4: here is where the work gets done
Similar in design philosophy with JSP (Java Server Pages) - Compiles into program which is more efficient to execute and which can run in an existing process for additional speed.
Uses .NET libraries
Example
<html> <body> <form runat="server"> <asp:TextBox ID="op1" RunAt="server" /> + <asp:TextBox ID="op2" RunAt="server" /> <asp:Button Text=" = " OnClick="OnAdd" RunAt="server" /> <asp:Label ID="Sum" RunAt="server" /> </form> </body> </html> <script language="C#" runat="server"> void OnAdd (Object sender, EventArgs e)// regular C# code { int a = Convert.ToInt32 (op1.Text); int b = Convert.ToInt32 (op2.Text); Sum.Text = (a + b).ToString (); } </script>
F5: Notice the use of
"property=value" mechanism for setting the properties of the
Web Form's controls
Maps into HTML (see below) so not all controls used in desktop windows
forms are available.
Here is the the HTML generated the first time displayed
(notice - there is no .NET stuff here)
<html> <body> <form name="_ctl0" method="post" action="calc.aspx" id="_ctl0"> <input type="hidden" name="__VIEWSTATE" value="dDwxOTE0NDY4ODE2Ozs+" /> <input name="op1" type="text" id="op1" /> + <input name="op2" type="text" id="op2" /> <input type="submit" name="_ctl1" value=" = " /> <span id="Sum"></span> </form> </body> </html>
F6: Hidden field is used to maintain state (more later)
F7 "span" is used to "label" this area of the HTML page so can set its "text" property
This form expects numbers are input - if not will cause an exception to be thrown - here is how to catch it
void OnAdd (Object sender, EventArgs e) { try { int a = Convert.ToInt32 (op1.Text); int b = Convert.ToInt32 (op2.Text); Sum.Text = (a + b).ToString (); } catch (FormatException) { Sum.Text = "Error"; } }
Translates into .NET program which can be compiled
Defined in "System.Web.UI.WebControls"
Some controls include client side "scripts"
Class Name |
Description |
AdRotator |
Displays rotating banners in Web forms |
Button |
Generates submit buttons |
Calendar |
Displays calendars with selectable dates |
CheckBox |
Displays a check box in a Web form |
CheckBoxList |
Displays a group of check boxes |
CompareValidator |
Validates user input by comparing it to another value |
CustomValidator |
Validates user input using the algorithm of your choice |
DataGrid |
Displays data in tabular format |
DataList |
Displays items in single-column or multicolumn lists using HTML templates |
DropDownList |
Generates HTML drop-down lists |
HyperLink |
Generates hyperlinks |
Image |
Displays images in Web forms |
ImageButton |
Displays graphical push buttons |
Label |
Generates programmable text fields |
LinkButton |
Generates hyperlinks that post back to the server |
ListBox |
Generates HTML list boxes |
Literal |
Generates literal text in a Web form |
Panel |
Groups other controls |
RadioButton |
Displays a radio button in a Web form |
RadioButtonList |
Displays a group of check boxes |
RangeValidator |
Verifies that user input falls within a specified range |
RegularExpressionValidator |
Validates user input using regular expressions |
Repeater |
Displays items using HTML templates |
RequiredFieldValidator |
Verifies that an input field isn’t empty |
Table |
Generates HTML tables |
TextBox |
Generates text input fields |
ValidationSummary |
Displays a summary of validation errors |
Xml |
Displays XML documents and optionally formats them using XSLT |
HTML Controls
The runat="server" turns ordinary HTML into a HTML control which are defined in FCL’s System.Web.UI.HtmlControls namespace.
See documentation for events fired by each control.
Used to ease burden of translating existing HTML forms
Tag |
Corresponding HTML Control |
<a runat=“server”> |
HtmlAnchor |
<button runat=“server”> |
HtmlButton |
<form runat=“server”> |
HtmlForm |
<img runat=“server”> |
HtmlImage |
<input type=“button” runat=“server”> |
HtmlInputButton |
<input type=“reset” runat=“server”> |
HtmlInputButton |
<input type=“submit” runat=“server”> |
HtmlInputButton |
<input type=“checkbox” runat=“server”> |
HtmlInputCheckBox |
<input type=“file” runat=“server”> |
HtmlInputFile |
<input type=“hidden” runat=“server”> |
HtmlInputHidden |
<input type=“image” runat=“server”> |
HtmlInputImage |
<input type=“radio” runat=“server”> |
HtmlInputRadioButton |
<input type=“password” runat=“server”> |
HtmlInputText |
<input type=“text” runat=“server”> |
HtmlInputText |
<select runat=“server”> |
HtmlSelect |
<table runat=“server”> |
HtmlTable |
<td runat=“server”> |
HtmlTableCell |
<th runat=“server”> |
HtmlTableCell |
<tr runat=“server”> |
HtmlTableRow |
<textarea runat=“server”> |
HtmlTextArea |
Any other tag with runat=“server” |
HtmlGenericControl |
How ASP.NET processes an .ASPX page
It creates a temporary file containing a class derived from System.Web.UI.Page. The Page class is one of the most important classes in ASP.NET; it represents ASP.NET Web pages.
ASP.NET copies the code in the ASPX file, as well as some code of its own, to the Page-derived class. A method named OnAdd in a <script> block in an ASPX file becomes a member method of the derived class.
ASP.NET compiles the derived class and places the resulting DLL in a system folder. The DLL is cached so that steps 1 and 2 won’t have to be repeated unless the contents of the ASPX file change.
ASP.NET instantiates the derived class and “executes” it by calling a series of methods on it. It is during this execution phase that the Page object instantiates any controls declared inside it and solicits their output.
Page Level Events can be used to execute event handlers. For example. Suppose you wanted today's date and the next four dates in a drop down list - you can statically initialize like this
<asp:DropDownList ID="MyList" RunAt="server"> <asp:ListItem Text="February 21, 2003" RunAt="server" /> <asp:ListItem Text="February 22, 2003" RunAt="server" /> <asp:ListItem Text="February 23, 2003" RunAt="server" /> <asp:ListItem Text="February 24, 2003" RunAt="server" /> <asp:ListItem Text="February 25, 2003" RunAt="server" /> </asp:DropDownList>
But this is only good for one day - to generate list as needed
<asp:DropDownList ID="MyList" RunAt="server" /> . . . <script language="C#" runat="server"> void Page_Load (Object sender, EventArgs e) { if (!IsPostBack) { for (int i=0; i<5; i++) { DateTime date = DateTime.Today + new TimeSpan (i, 0, 0, 0); MyList.Items.Add (date.ToString ("MMMM dd, yyyy")); } } } </script>
Directive |
Description |
@ Page |
Defines general attributes and compilation settings for ASPX files |
@ Control |
Defines general attributes and compilation settings for ASCX files |
@ Import |
Imports a namespace |
@ Assembly |
Enables linkage to assemblies not linked to by default |
@ Register |
Registers user controls and custom controls for use in a Web form |
@ OutputCache |
Exerts declarative control over page caching and fragment caching |
@ Reference |
Adds a reference to an external ASPX or ASCX file |
@ Implements |
Identifies an interface implemented by a Web page |
<%@ Import Namespace=System.Data %> <html> <body> <h1>Currency Converter</h1> <hr> <form runat="server"> Target Currency<br> <asp:ListBox ID="Currencies" Width="256" RunAt="server" /><br> <br> Amount in U.S. Dollars<br> <asp:TextBox ID="USD" Width="256" RunAt="server" /><br> <br>
<asp:Button Text="Convert" ID="ConvertButton" Width="256" RunAt="server" /><br> <br> <asp:Label ID="Output" RunAt="server" /> </form> </body> </html> <script language="C#" runat="server"> void Page_Init (Object sender, EventArgs e) { // Wire the Convert button to OnConvert ConvertButton.Click += new EventHandler (OnConvert); } void Page_Load (Object sender, EventArgs e) { // If this isn't a postback, initialize the ListBox if (!IsPostBack) { DataSet ds = new DataSet (); ds.ReadXml (Server.MapPath ("Rates.xml")); foreach (DataRow row in ds.Tables[0].Rows) Currencies.Items.Add (row["Currency"].ToString ()); Currencies.SelectedIndex = 0; } } void OnConvert (Object sender, EventArgs e) { // Perform the conversion and display the results try { decimal dollars = Convert.ToDecimal (USD.Text); DataSet ds = new DataSet (); ds.ReadXml (Server.MapPath ("Rates.xml")); DataRow[] rows = ds.Tables[0].Select ("Currency = '" + Currencies.SelectedItem.Text + "'"); decimal rate = Convert.ToDecimal (rows[0]["Exchange"]); decimal amount = dollars * rate; Output.Text = amount.ToString ("f2"); } catch (FormatException) { Output.Text = "Error"; } } </script>
F8: Serves same function as "Using" in C# program
F9: uses XML file as a data source
F10: Treats XML file like a 1 table database
F11: Uses SQL "Select" statement
Look at the XML file
<?xml version="1.0"?> <Rates> <Rate> <Currency>British Pound</Currency> <Exchange>0.698544</Exchange> </Rate>
<Rate> <Currency>Canadian Dollar</Currency> <Exchange>1.57315</Exchange> </Rate> <Rate> <Currency>French Franc</Currency> <Exchange>7.32593</Exchange> </Rate> <Rate> <Currency>German Mark</Currency> <Exchange>2.18433</Exchange> </Rate> <Rate> <Currency>Italian Lira</Currency> <Exchange>2162.67</Exchange> </Rate> <Rate> <Currency>Japanese Yen</Currency> <Exchange>122.742</Exchange> </Rate> <Rate> <Currency>Mexican Peso</Currency> <Exchange>9.22841</Exchange> </Rate> <Rate> <Currency>Swiss Franc</Currency> <Exchange>1.64716</Exchange> </Rate> </Rates>