12. WebForms: Web-based GUIs in.NET
2 Visual Studio.NET Objectives “Drag-and-drop GUI construction has long been the norm for Windows development. With the arrival of ASP.NET and Visual Studio.NET, the same is now true for web pages with your choice of.NET language…" ASP.NET architecture WebForms ASP.NET programming model
3 Visual Studio.NET Part 1 ASP.NET architecture…
4 Visual Studio.NET Web server IIS ISAPI Extension Manager ASPNET_ISAPI.DLL ASP.NET ISAPI extension ASP.NET ASP.NET is the web-based component of.NET ASP.NET is a plug-in for Microsoft's web server IIS –IIS recognizes extension & routes to ASP.NET for processing –plug-ins also available for Apache, others (?) Browser HTTP Request ASPNET_WP.EXE ASP.NET worker process CLR ASP.NET
5 Visual Studio.NET AppDomains Each web app (virtual directory) runs in a separate domain An AppDomain is a protection boundary, similar to a process –this way web apps are isolated from each other… ASPNET_WP.EXE ASP.NET worker process CLR AppDomain ASP.NET Browser HTTP Request AppDomain ASP.NET Browser HTTP Request
6 Visual Studio.NET Multi-threaded Each AppDomain is multi-threaded, to handle multiple clients ASPNET_WP.EXE ASP.NET worker process CLR AppDomain ASP.NET Browser AppDomain ASP.NET Browser
7 Visual Studio.NET Part 2 WebForms…
8 Visual Studio.NET Traditional form-based web apps HTML already supports the creation of form-based apps Login Please login: Username: Password:
9 Visual Studio.NET WebForms Web-based, form-based.NET apps Based on many technologies: –IIS –ASP.NET (extension to IIS) –.NET Framework SDK (CLR, FCL, tools) –Visual Studio.NET (drag-and-drop creation)
10 Visual Studio.NET Abstraction Like WinForms, WebForms are based on classes in FCL –separates WebForm app from underlying platform System.Web.UI.Page CLR Windows OS instance of FCL class object
11 Visual Studio.NET Creating a WebForm app Good news: much like creating a WinForm app! 1.create appropriate project in Visual Studio 2.design form(s) via drag-and-drop of controls 3.program events 4.run and test
12 Visual Studio.NET Example A simple WebForms app to view attendee info from DB
13 Visual Studio.NET (1) Create ASP.NET Web App project Location = name of web site = " –virtual directory:AttendeeApp –physical directory:C:\Inetpub\wwwroot\AttendeeApp
14 Visual Studio.NET (2) Project layout VS.NET configures IIS for you VS.NET creates web site for you –contains 1 form-based web page –named WebForm1.aspx by default –web.config allows you to config things e.g. debugging
15 Visual Studio.NET (3) Install application support files Manually install needed support files into web app's directory –in this case "C:\Inetpub\wwwroot\AttendeeApp" –component DLLs? –databases? Example: –copy "Attendees.mdb" into root dir –any custom DLLs in \bin sub-directory
16 Visual Studio.NET (4) Design WebForm Just like a WinForm –drag-and-drop from toolbox…
17 Visual Studio.NET Web controls vs. HTML controls Toolbox contains 2 types of controls: –those under Web Forms –those under HTML Both generate pure HTML on client –though sometimes with JavaScript! Web controls: –work like WinForm counterparts HTML controls: –mimic standard HTML controls
18 Visual Studio.NET (5) Implement events WebForms are event-driven, as you would expect: –standard "code-behind" programming with J#, C#, VB.NET, … –on Page_Load, fill list box from database –on Button1_Click, display info about selected attendee public class WebForm1 extends System.Web.UI.Page { private void Page_Load(...) { … } private void Button1_Click (…) { … } {
19 Visual Studio.NET Connection String Connection String will be used throughout –Have program ask where the data is located import System.Data.*; import System.Data.OleDb.*;... String get_sConnection() { String filename = "Attendees.mdb";// DB filename String sConnection = null; // Find the base directory in which the application is running String homeDir = System.AppDomain.get_CurrentDomain().get_BaseDirectory(); sConnection = String.Format("Provider=Microsoft.Jet.OLEDB.4.0;Data Source={0}{1}", homeDir, filename); //System.Diagnostics.Debug.WriteLine(this.sConnection);// for debugging return sConnection; }
20 Visual Studio.NET Page_Load (part 1) Use try-catch to handle errors private void Page_Load(Object sender, System.EventArgs e) { String sql, fn, ln, name, id; IDbConnection dbConn = null; try { // code to connect to database and do read (see next slide…) }//try catch(Exception ex) { this.lblErrorMsg.set_Text( "Error: " + ex.get_Message() ); }//catch finally { if ((dbConn != null) && (dbConn.get_State() != ConnectionState.Closed)) dbConn.Close(); }//finally }//load
21 Visual Studio.NET Page_Load (part 2) try { dbConn = new OleDbConnection( get_sConnection() ); dbConn.Open(); sql = "Select * From Attendees Order By LastName Asc, FirstName Asc;"; IDbCommand dbCmd; dbCmd = new OleDbCommand(); dbCmd.set_CommandText( sql); dbCmd.set_Connection( dbConn); IDataReader dbReader; dbReader = dbCmd.ExecuteReader(); while (dbReader.Read()) { id = String.valueOf(dbReader.get_Item("AID")); fn = String.valueOf(dbReader.get_Item("FirstName")); ln = String.valueOf(dbReader.get_Item("LastName")); name = ln + ", " + fn; // have to add an object, not primitive types this.ListBox1.get_Items().Add( new ListItem( name, id)); } }//try
22 Visual Studio.NET (6) Build When you build app, Visual Studio builds a DLL –recall that ASPNET_WP.EXE is the hosting process –DLL is placed into bin sub-dir of app's IIS directory –DLL is loaded into AppDomain upon 1 st request ASPNET_WP.EXE ASP.NET worker process CLR AppDomain ASP.NET Browser our DLL
23 Visual Studio.NET (7) Run! You can run from within VS You can debug from within VS How does it work? –starts up a session of IE –attaches debugger to IIS –displays.aspx page marked as "Start Page" in your project right-click on.aspx page you want to start with select "Set as Start Page" –NOTE: to debug, you need administrative rights…
24 Visual Studio.NET Client-server relationship The server contains lots of code –see physical directory… –see compiled code in \bin sub-directory… But the client sees only HTML! –"View Source" in browser… –wow, how does that work? Web controls know how to render themselves in HTML…
25 Visual Studio.NET (8) cmdViewInfo_Click (part 1) Ensure an item has been selected from List Box Note error handling private void Button1_Click (Object sender, System.EventArgs e) { if (this.ListBox1.get_SelectedItem() == null) { // nothing selected this.lblErrorMsg.set_Text( "Please select an attendee!"); return; } String sql, name, fn, ln, ; String[] names; IDbConnection dbConn = null;// DB connection IDbCommand dbCmd;// DB sql command, to use above connection IDataReader dbReader;// DB reader, with results from above command // try.. Catch … finally block as in the Page_Load() method }
26 Visual Studio.NET (8) cmdViewInfo_Click (part 2) 1.Retrieve text from Text Box and split into first and last name 2.Use this to build sql query string try { // retrieve the Text, not value part name = (String) this.ListBox1.get_SelectedItem().get_Text(); char delimiter[]={' '}; names = name.Split(delimiter);// create array of strings from text ln = names[0]; fn = names[1]; ln = ln.Substring(0, ln.get_Length() - 1); // remove ',' at end sql = String.Format("Select From Attendees Where FirstName='{0}' and LastName='{1}';", fn.Replace("'", "''"), ln.Replace("'", "''")); // System.Diagnostics.Debug.WriteLine("sql is: " + sql); // for debugging // create DB connection from connection string // … }//try 1. 2.
27 Visual Studio.NET (8) cmdViewInfo_Click (part 3) try { … // create DB connection from connection string dbConn = new OleDbConnection( get_sConnection() ); dbCmd = new OleDbCommand(); // create DB command dbCmd.set_CommandText( sql); // set the sql statement for the command dbCmd.set_Connection( dbConn); // set the connection to be used for command dbConn.Open(); // open the DB connection dbReader = dbCmd.ExecuteReader(); // read from DB using command dbReader.Read(); // get a line from DB reader = String.valueOf(dbReader.get_Item(" ")); // extract field dbReader.Close(); // close connections dbConn.Close(); this.TextBox1.set_Text( fn); // display first name to user this.TextBox2.set_Text( ln); // display last name to user this.TextBox3.set_Text( ); // display value from database }//try Create connection open, read, close set display values
28 Visual Studio.NET Part 3 ASP.NET programming model…
29 Visual Studio.NET ASP.NET programming model On the surface WebForms appear like WinForms But the programming model is different underneath –due to ASP.NET –due to client-server paradigm
30 Visual Studio.NET #1: Traditional dialog doesn't work For example, these do not work: –MessageBox.Show( ) –form1.Show( ) Why not? –think about where form would appear… Solutions: –if you want to tell user something, display via label on page –if you want to show another page, redirect browser
31 Visual Studio.NET Web-based dialogs To display a message to user: private void Button1_Click (...) { if (this.ListBox1.SelectedItem == null) { // nothing selected this.lblErrorMsg.Text = "Please select an attendee!"; return; }.
32 Visual Studio.NET Web-based exceptions Likewise, handle exceptions by displaying messages… private void Page_Load(...) { IDbConnection dbConn = null; try { // open connection and access DB, filling list box.... }//try catch(Exception ex) { this.lblErrorMsg.set_Text( "Error: " + ex.getMessage()); }//catch finally { if ((dbConn != null) && (dbConn.get_State() != ConnectionState.Closed)) dbConn.Close(); }//finally }
33 Visual Studio.NET Web-based redirects Redirect ASP.NET to a different web page… private void cmdLogin_Click(...) { if ( > ) this.get_Response().Redirect(" else this.lblErrorMsg.set_Text( "Login failed!"); }
34 Visual Studio.NET #2: Event ==> round-trip to the server There are fewer events to program in WebForms –primarily Change and Click events only Why? –event code is.NET code, so must be executed by server –event thus triggers 1 round-trip to server for processing –an very expensive activity… IIS client 1. initial request is posted 2. HTML rendering of page 3. same page is "posted- back" for event processing 4. HTML rendering of page ASP.NET engine
35 Visual Studio.NET Example Every button click is a trip to the server –watch IE's status bar along the bottom…
36 Visual Studio.NET #3: Postbacks In general, ASP.NET makes a distinction between: –first request by client C for web page X –subsequent "postbacks" of page X by the same client C IIS client 1. initial request is posted 2. HTML rendering of page 3. same page is "posted- back" for event processing 4. HTML rendering of page ASP.NET engine
37 Visual Studio.NET Interesting side-effects Postback concept leads to interesting side-effects… 1.each postback creates a new WebForm object why? web apps are stateless… example: set breakpoint on Page_Load event 2.yet ASP.NET maintains page state for us contents of list box, text boxes, etc. example: view source on client, see "__ViewState"
38 Visual Studio.NET Example 1 We need to clear error message labels! private void Page_Load(...) { this.lblErrorMsg.set_Text(" "); // clear prev msg.
39 Visual Studio.NET Example 2 List box is growing and growing with duplicates! –click button a few times, look at contents of list box… Solution? –either load list box the first time only, or –clear and reload list box every time private void Page_Load(...) { this.lblErrorMsg.set_Text(" "); if (this.get_IsPostBack() ) // list box already loaded! return;.. // first request, load list box from DB.
40 Visual Studio.NET #4: AutoPostBack Some events aren't posted right away… –event is "queued" until page is eventually posted back –example: list box doesn't postback when you click on an item instead, SelectedIndexChanged event is queued to witness, code event to display msg in custom label notice that multiple clicks on list box yield one event… To force immediate postback? –set control's AutoPostBack property to true (if it has one)
41 Visual Studio.NET Example Set ListBox's AutoPostBack property to True Code SelectedIndexChanged event to display attendee's info: Note: cleaner solution is to route event directly to Button1_Click() –click on list box in design mode – view properties – click yellow lightning bolt icon to see events – click on drop-down for SelectedIndexChanged event – select Button1_Click private void ListBox1_SelectedIndexChanged(object sender, System.EventArgs e) { // view attendee's info by executing button click code… this.Button1_Click(sender, e); }
42 Visual Studio.NET #5: Statelessness Web apps are stateless, kind of… Each page request is a self-contained operation: connection is opened request is posted result is returned connection is closed
43 Visual Studio.NET Implications Implications? –new WebForm object every time, so objects don't have state –however, UI object state *is* maintained for us by ASP.NET –static fields in our code still work for duration of AppDomain… ASPNET_WP.EXE ASP.NET worker process CLR AppDomain ASP.NET Browser DLL static int i;
44 Visual Studio.NET Solutions? Don't try to maintain state, recreate each time Use a database Ask ASP.NET to do it for you… –will maintain session state for you (state per client) –will maintain application state for you (global state)
45 Visual Studio.NET Example: session state Example: –for each client, maintain Attendee objects in a hash table… –Change this.get_Session() to this.get_Application() if you want to store Application state rather than Session state. private void Page_Load(...) { if (this.get_IsPostBack() ) return; Hashtable attendees = new Hashtable(); // create table this.get_Session().Add( "attendees", attendees); // save ref to table while (dbReader.Read()) {. attendees[name] = new Attendee(id, name, ); this.ListBox1.get_Items().Add( new ListItem( name, id)) }
46 Visual Studio.NET Example (cont'd) When state is needed, just pull it out of ASP.NET's cache… private void ListBox1_SelectedIndexChanged(...) { Hashtable attendees; Attendee a; name = (String) this.ListBox1.get_SelectedItem().get_Text(); attendees = (Hashtable) this.get_Session().get_Item ("attendees"); // then extract attendee that matches with name.
47 Visual Studio.NET Caveats for stateful apps Web apps are stateless for a reason Caveats to a stateful design: –too much state will overload server –state should be recoverable in case of network/server crash ASP.NET will keep state in a database if you ask it to via web.config file –web farms (n > 1 servers) require special handling need to config ASP.NET via web.config file
48 Visual Studio.NET Summary ASP.NET and WebForms are a huge improvement –compiled, type-checked languages (no more scripting) –drag-and-drop page creation (no more HTML programming) –full power of FCL available with IntelliSense But it is a different programming model –yet another adjustment you have to make…
49 Visual Studio.NET References Books: –J. Sharp et al., Visual J#.NET –F. Onion, "Essential ASP.NET" (both C# and VB editions) –D. Sussman et al., "Beginning ASP.NET 1.0 with C#" –B. Gaster et al., "Fast Track ASP.NET" (C# edition) Web sites: – –