Windows Systems Programming: Spring 2004

[ Home | Syllabus | Course Notes | Assignments | Search]


ASP.NET Applications

Application is a grouping of (in a common directory)

NOTE: An assembly can consist of multiple DLLs in general (see pages 94-)

HTTPContext object contains the following properties


Web.config File

Configuration information is stored in the directory instead of the registry (allows simple copies of application to the server -XCOPY). This is an XML file, here is the general structure

<configuration>
  <appSettings>
    <!-- appSettings values go here -->
  </appSettings>
  <system.web>
    <!-- ASP.NET configuration settings go here -->
  </system.web>
</configuration>

<appSettings>

associative memory of strings that can be used by the application.

Example, consider the following code in a PageLoad event handler for connecting to a database

SqlDataAdapter adapter = new SqlDataAdapter
    ("select * from titles where price != 0",
     "server=hawkeye;database=pubs;uid=sa;pwd="); 
DataSet ds = new DataSet ();
adapter.Fill (ds);

Suppose many page load information from the same data base and the data base server information changes. - Would have to edit all web pages - one solution is to put the connection information in the web.config file

<configuration>
  <appSettings>
    <add key="MyConnectionString"
      value="server=hawkeye;database=pubs;uid=sa;pwd=" />
  </appSettings>
</configuration>

Now the code in the pageLoad handler is

string conn = ConfigurationSettings.AppSettings["MyConnectionString"];
SqlDataAdapter adapter = new SqlDataAdapter
    ("select * from titles where price != 0", conn);
DataSet ds = new DataSet ();
adapter.Fill (ds);

<system.web>

<system.web> Subsections 

Section Name

Description

authentication

Sets the authentication mode and specifies settings for the mode selected

authorization

Specifies who is allowed to access resources in this directory and its subdirectories

browserCaps

Maps user-agent data to browser capabilities

clientTarget

Maps user-agent data to browser types

compilation

Specifies run-time compilation settings such as whether executables should be compiled with debug symbols, maps file name extensions and Language attributes to compilers, and identifies the assemblies that ASP.NET links to

customErrors

Enables the use of custom error pages and specifies how errors should be reported on clients and servers

httpRuntime

Specifies request time-outs and other settings used by the ASP.NET runtime

globalization

Specifies character encodings for requests and responses

httpHandlers

Maps URLs to HTTP handlers (for example, maps requests for ASPX files to System.Web.UI.PageHandlerFactory)

httpModules

Identifies HTTP modules called in response to HTTP requests

identity

Controls the identity that ASP.NET assigns to individual requests

machineKey

Specifies encryption and validation settings (for example, the key and algorithm used to encrypt authentication cookies)

pages

Specifies page-level configuration settings such as whether output buffering, session state, and view state are enabled

processModel

Specifies configuration settings for ASP.NET worker processes

securityPolicy

Maps trust levels to CONFIG files containing security policies

sessionState

Specifies session state settings (for example, where session state is stored)

trace

Enables and disables tracing and specifies trace settings

trust

Specifies the code access security trust level

webControls

Identifies the location on the server of client scripts used by ASP.NET Web controls

webServices

Contains Web service settings

example

<configuration>
  <system.web>
    <trace enabled="true" />
  </system.web>
</configuration>

Here’s another Web.config file that enables tracing, instructs ASP.NET to compile debug executables, moves session state to a back-end SQL Server database (a topic you’ll learn about later in this chapter), tells ASP.NET to assume code found in the application’s files is written in C# unless otherwise noted, and enables view state validation by appending hashes to view state values round-tripped to the client:

<configuration>
  <system.web>
    <trace enabled="true" />
    <sessionState
      mode="SQLServer"
      sqlConnectionString="server=localhost;uid=sa;pwd="
    />
    <compilation debug="true" defaultLanguage="c#" />
    <pages enableViewStateMac="true" />
  </system.web>
</configuration>

The ultimate source of reference is Machine.config.

Configuration inheritance in the application directory structure is supported


The Global.asax File

  • Optional

  • But likely to be useful, contains

  • directives

  • event handlers

  • object tags

Directives: 

  • @ Application directives - can add descriptive information
    <%@ Application Description="My First ASP.NET Application" %>
    or inheritance
    <%@ Application Inherits="MyApp" %>
    For code behind

  • @ Import directives
    <%@ Import Namespace="System.Data" %>

  • @ Assembly directives
    <%@ Import Namespace="System.DirectoryServices" %>
    <%@ Assembly Name="System.DirectoryServices" %>

Event Handlers

Most common reason for having a global.asax file

  • Start and End events (for the application and for the session)
Per-Request Events

Global.asax can also include handlers for events fired by HttpApplication instances. If present in Global.asax, the following methods are called in every request in response to HttpApplication events. They’re listed in the order in which they’re called.

Per-Request Global Event Handlers

Method

Description

Application_BeginRequest

Called at the beginning of each request

Application_AuthenticateRequest

Called to authenticate the caller

Application_AuthorizeRequest

Called to determine whether the caller is authorized to access the requested resource

Application_ResolveRequestCache

Called to resolve the current request by providing content from a cache

Application_AcquireRequestState

Called to associate the current request with a session and populate session state

Application_PreRequestHandlerExecute

Called to prepend content to the HTTP response

Application_PostRequestHandlerExecute

Called to append content to the HTTP response

Application_ReleaseRequestState

Called to release (store) any state associated with this session

Application_UpdateRequestCache

Called to update a cache with content returned in the response

Application_EndRequest

Called at the end of each request

e.g

<script language="C#" runat="server">
  void Application_PostRequestHandlerExecute (Object sender, EventArgs e)
  {
      HttpApplication app = (HttpApplication) sender;
      app.Context.Response.Write ("<hr><center><i>" +
          "Copyright © 2002 by Me, Myself, and I</i></center>");
  }
</script>

Error Events

<%@ Import Namespace="System.Diagnostics" %> 

<script language="C#" runat="server"> 
  void Application_Error (Object sender, EventArgs e)
  {
      // Formulate a message to write to the event log
      string msg = "Error accessing " + Request.Path + "\n" +
          Server.GetLastError ().ToString ();

      // Write an entry to the event log
      EventLog log = new EventLog ();
      log.Source = "My ASP.NET Application";
      log.WriteEntry (msg, EventLogEntryType.Error);
  }
</script>

Global Object Tags

Global object tags create object instances declaratively. Suppose you want a new instance of ShoppingCart created for each user that visits your site. Rather than do this:

<script>
  void Session_Start ()
  {
      Session["MyShoppingCart"] = new ShoppingCart ();
  }
</script>

you can do this:

<object id="MyShoppingCart" class="ShoppingCart" scope="session"
  runat="server" />

Application State/Cache

Similar but Cache allows expiration dates and is preferred for that reason

  • In memory information about the application (cannot be persisted)

Example

HttpApplicationState properties and methods expose the contents of application state. The following statements add three stock prices keyed by stock symbols to application state and work equally in an ASPX file, in Global.asax, or in a code-behind file:

Application["AMZN"] = 10.00m;
Application["INTC"] = 20.00m;
Application["MSFT"] = 30.00m;

You can also add items to application state using HttpApplicationState.Add:

Application.Add ("AMZN", 10.00m);
Application.Add ("INTC", 20.00m);
Application.Add ("MSFT", 30.00m);

However, Add and [] behave slightly differently when adding items to application state. Add adds an item even if an item with the specified key already exists; [] does not. These statements add two separate items to application state:

Application.Add ("AMZN", 10.00m);
Application.Add ("AMZN", 11.00m);

You can retrieve both items by iterating over the contents of application state, but if you simply ask for the item keyed by “AMZN,” you’ll get back 10. The following example, by contrast, adds just one item to application state. The first statement creates the item and assigns it the value 10. The second statement changes the item’s value to 11:

Application["AMZN"] = 10.00m;
Application["AMZN"] = 11.00m;

How do you read values from application state? The following statements retrieve the stock prices inserted earlier:

decimal amzn = (decimal) Application["AMZN"];
decimal intc = (decimal) Application["INTC"];
decimal msft = (decimal) Application["MSFT"];

Locking and Unlocking

Application.Lock ();
Application["ItemsSold"] = (int) Application["ItemsSold"] + 1;
Application["ItemsLeft"] = (int) Application["ItemsLeft"] - 1;
Application.UnLock ();

An Example

Global.asax
<%@ Import NameSpace="System.IO" %>

<script language="C#" runat="server">
  static string _path;

  void Application_Start ()
  {
      StreamReader reader = null;

      try {
          // If Count.txt exists, read the count from it and
          // store the count in application state
          _path = Server.MapPath ("/Count.txt");
          reader = new StreamReader (_path);
          string line = reader.ReadLine ();
          int count = Convert.ToInt32 (line);
          Application["Count"] = count;
      }
      catch (Exception) {
          // If Count.txt does not exist or contains an invalid
          // count, store a 0 in application state
          Application["Count"] = 0;
      }
      finally {
          // Close the StreamReader
          if (reader != null)
              reader.Close ();
      }
  }

  void Application_End ()
  {
      StreamWriter writer = null;

      try {
          // Save the current count in Count.txt
          writer = new StreamWriter (_path, false);
          writer.Write (Application["Count"]);
      }
      finally {
          // Close the StreamWriter
          if (writer != null)
              writer.Close ();
      }
  }
</script

ASPX page

<%@ Page Language="C#" %>

<html>
  <body>
    <%
      // Fetch the count and increment it by 1. Lock application state
      // to prevent the count from changing as it's being updated.
      Application.Lock ();
      int count = (int) Application["Count"] + 1;
      Application["Count"] = count;
      Application.UnLock ();

      // Write the count to the page
      Response.Write ("Pages in this application " +
          "have been requested " + count + " time");
      if (count > 1)
          Response.Write ("s");
      Response.Write (".");
    %>
  </body>
</html>

To test - run this application, close browser and run again.


The Application Cache

Supports

  • Expiration dates

  • callbacks when item expires (thus could update the value by reinserting)

  • discards least recently accessed when space is needed

  • Can store any managed type (lie dataSet and HashTable)

Example

<script language="C#" runat="server">
  void Application_Start ()
  {
      Hashtable stocks = new Hashtable ();
      stocks.Add ("AMZN", 10.00m);
      stocks.Add ("INTC", 20.00m);
      stocks.Add ("MSFT", 30.00m);

      Context.Cache.Insert ("Stocks", stocks, null,
          DateTime.Now.AddMinutes (5), Cache.NoSlidingExpiration);
  }
</script>

Can also be conditional on changes to datasource files,e.g

DataSet ds = new DataSet (); ds.ReadXml (Server.MapPath ("Stocks.xml")); Context.Cache.Insert ("Stocks", ds,     new CacheDependency (Server.MapPath ("Stocks.xml")));

Call also set priorities for removing when space is short OR  use NotRemovable

Using a callback

<%@ Import Namespace="System.Data" %>

<script language="C#" runat="server">
  static Cache _cache;
  static string _path;

  void Application_Start ()
  {
      _cache = Context.Cache;
      _path = Context.Server.MapPath ("Stocks.xml");

      DataSet ds = new DataSet ();
      ds.ReadXml (_path);

      _cache.Insert ("Stocks", ds, new CacheDependency (_path),
          Cache.NoAbsoluteExpiration, Cache.NoSlidingExpiration,
          CacheItemPriority.Default,
          new CacheItemRemovedCallback (RefreshDataSet));
  }

  static void RefreshDataSet (String key, Object item,
      CacheItemRemovedReason reason)
  {
      DataSet ds = new DataSet ();
      ds.ReadXml (_path);

      _cache.Insert ("Stocks", ds, new CacheDependency (_path),
          Cache.NoAbsoluteExpiration, Cache.NoSlidingExpiration,
          CacheItemPriority.Default,
          new CacheItemRemovedCallback (RefreshDataSet));
  }
</script>

Cache demonstration

Global.asax
<%@ Import NameSpace="System.IO" %>

<script language="C#" runat="server">

  static Cache _cache = null;
  static string _path = null;

  void Application_Start ()
  {
      _cache = Context.Cache;
      _path = Server.MapPath ("Quotes.txt");

      ArrayList quotes = ReadQuotes ();

      if (quotes != null) {
          _cache.Insert ("Quotes", quotes, new CacheDependency (_path),
              Cache.NoAbsoluteExpiration, Cache.NoSlidingExpiration,
              CacheItemPriority.Default,
              new CacheItemRemovedCallback (RefreshQuotes));
      }
  }

  static void RefreshQuotes (String key, Object item,
      CacheItemRemovedReason reason)
  {
      ArrayList quotes = ReadQuotes ();

      if (quotes != null) {
          _cache.Insert ("Quotes", quotes, new CacheDependency (_path),
              Cache.NoAbsoluteExpiration, Cache.NoSlidingExpiration,
              CacheItemPriority.Default,
              new CacheItemRemovedCallback (RefreshQuotes));
      }
  }

  static ArrayList ReadQuotes ()
  {
      ArrayList quotes = new ArrayList ();
      StreamReader reader = null;

      try {
          reader = new StreamReader (_path);
          for (string line = reader.ReadLine (); line != null;
              line = reader.ReadLine ())
              quotes.Add (line);
      }
      catch (IOException) {
          return null;
      }
      finally {
          if (reader != null)
              reader.Close ();
      }
      return quotes;
  }
</script>
SmartQuotes.aspx
<%@ Import Namespace="System.IO" %>

<html>
  <body>
    <asp:Label ID="Output" RunAt="server" />
  </body>
</html>

<script language="C#" runat="server">
  void Page_Load (Object sender, EventArgs e)
  {
      ArrayList quotes = (ArrayList) Cache["Quotes"];

      if (quotes != null) {
          Random rand = new Random ();
          int index = rand.Next (0, quotes.Count - 1);
          Output.Text = (string) quotes[index];
      }
      else {
          Output.Text = "Server busy";
      }
  }
</script>

Session State

An example

SessionSpy.aspx
<%@ Page Language="C#" %>
	
<html>
  <body>
    <%
      if (Session.IsNewSession ││ Session["Count"] == null) {
          Session["Count"] = 1;
          Response.Write ("Welcome! Because this is your first " +
              "visit to this site, a new session has been created " +
              "for you. Your session ID is " + Session.SessionID +
              ".");
      }
      else {
          Session["Count"] = (int) Session["Count"] + 1;
          Response.Write ("You have visited this site " +
              Session["Count"] + " times. Your session ID is still " +
              Session.SessionID + ".");
      }
    %>
  </body>
</html>

Session State Process Models

Model

Description

In-proc

Stores session state in-process to ASP.NET (that is, in Aspnet_wp.exe)

State server

Stores session state in an external “state server” process on the Web server or on a remote machine

SQL Server

Stores session state in a Microsoft SQL Server database on the Web server or on a remote machine

  • Serializable

  • Session Lifetimes

 

 

 

 

 


Copyright chris wild 1999-2004.
For problems or questions regarding this web contact [Dr. Wild].
Last updated: December 22, 2003.