Tag Archives: Web Development

DOCTYPE and Table Height

I’ve been pulling out my hair for the last 30 minutes trying to get an HTML table with height 100% to work in my ASP.NET 2.0 application.  I’m trying to render a block of HTML in the center of my application page.

I finally found the solution to my problem – it seems that turning on XHTML compliance with the DOCTYPE declarator breaks the table height attribute – ASP.NET 2.0 is XHTML compliant out of the box, and since the height attribute is no longer supported in this manner, my page broke.

This article helps to clarify…. http://www.apptools.com/examples/tableheight.php

The article suggests, applying the following style to the page, and declaring a top level table with id “wrapper” containing a single column and row – align center and valign middle – to obtain desired center page behavior.

<style type="text/css">
    html, body, #wrapper
    {
        height:90%;
        margin: 0;
        padding: 0;
        border: none;
        text-align: center;
    }
    form
    {
        margin: 0;
        padding: 0;
    }
    #wrapper
    {
        margin: 0 auto;
        text-align: left;
        vertical-align: middle;
        width: 400px;
    }
</style>

<table id="wrapper" cellpadding="0" cellspacing="0">
    <tr>
        <td align="center" valign="middle">
            <form id="mainForm" runat="server">
                <asp:PlaceHolder ID="CONTENT" runat="server"></asp:PlaceHolder>
            </form>
        </td>
    </tr>
</table>

Sadly, placing the wrapper table inside the form tags breaks the behavior, so I applied centering to the entire page contents, form tags and all.  This works for my current situation, but isn’t ideal.

Embedding Windows Media and Quicktime into ASP.NET pages

I know there are numerous web sites and blogs about this subject.  Since I had to write some code for “Fred” to render on-line video, and embedding video in web pages can be somewhat fiddly to get right, I figured I’d blog the C# code for my future reference.  If hosting on-line video in your web site interests you, be sure to check out Sahil Malik’s post on the subject.

Below are two examples, which create the HTML for embedding Windows Media and Quicktime sources.  To use this code, compile either or both examples into your ASP.NET project (or into a referenced class library assembly), bung a PlaceHolder on your page and during the load event of your page pass the instance of your PlaceHolder control to the desired method.  The location should either be a relative URL or absolute URL to the hosted video file, which can be a streaming location or an HTTP location.

Embedding Windows Media:

private void CreateMediaPlayerEmbeddedControl(PlaceHolder ph, string location, int width, int height)
{
HtmlGenericControl result = new HtmlGenericControl();
ph.Controls.Add(result);
HtmlGenericControl embed = new HtmlGenericControl();
result.Controls.Add(embed);
// Embed tag.
embed.TagName = “embed”;
embed.Attributes.Add(“type”, “application/x-mplayer2”);
embed.Attributes.Add(“pluginspage”, “http://www.microsoft.com/netshow/download/player.htm”);
embed.Attributes.Add(“name”, “mediaPlayer”);
embed.Attributes.Add(“width”, width.ToString());
embed.Attributes.Add(“height”, height.ToString());
embed.Attributes.Add(“AllowChangeDisplaySize”, “1”);
embed.Attributes.Add(“AllowSize”, “0”);
embed.Attributes.Add(“AutoSize”, “0”);
embed.Attributes.Add(“AutoStart”, “1”);
embed.Attributes.Add(“DisplaySize”, “4”);
embed.Attributes.Add(“EnableContextMenu”, “0”);
embed.Attributes.Add(“Enabled”, “1”);
embed.Attributes.Add(“InvokeURLs”, “0”);
embed.Attributes.Add(“ShowCaptioning”, “0”);
embed.Attributes.Add(“ShowStatusBar”, “0”);
embed.Attributes.Add(“ShowControls”, “1”);
embed.Attributes.Add(“WindowlessVideo”, “1”);
embed.Attributes.Add(“uiMode”, “None”);
embed.Attributes.Add(“src”, location);
// Object tag
result.TagName = “object”;
result.Attributes.Add(“classid”, “clsid:22D6F312-B0F6-11D0-94AB-0080C74C7E95”);
result.Attributes.Add(“standby”, “Loading Microsoft Windows Media Player components…”);
result.Attributes.Add(“codebase”, “http://activex.microsoft.com/activex/controls/mplayer/en/nsmp2inf.cab#Version=5,1,52,701”);
result.Attributes.Add(“type”, “application/x-oleobject”);
result.Attributes.Add(“width”, width.ToString());
result.Attributes.Add(“height”, height.ToString());
result.Controls.Add(new LiteralControl(“”));
result.Controls.Add(new LiteralControl(“”));
result.Controls.Add(new LiteralControl(“”));
result.Controls.Add(new LiteralControl(“”));
result.Controls.Add(new LiteralControl(“”));
result.Controls.Add(new LiteralControl(“”));
result.Controls.Add(new LiteralControl(“”));
result.Controls.Add(new LiteralControl(“”));
result.Controls.Add(new LiteralControl(“”));
result.Controls.Add(new LiteralControl(“”));
result.Controls.Add(new LiteralControl(“”));
result.Controls.Add(new LiteralControl(“”));
result.Controls.Add(new LiteralControl(“”));
result.Controls.Add(new LiteralControl(“”));
}

Embedding Quicktime:

private void CreateQuickTimeEmbeddedControl(PlaceHolder ph, string location, int width, int height)
{
HtmlGenericControl result = new HtmlGenericControl();
ph.Controls.Add(result);
HtmlGenericControl embed = new HtmlGenericControl();
result.Controls.Add(embed);
// Embed tag.
embed.TagName = “embed”;
embed.Attributes.Add(“width”, width.ToString());
embed.Attributes.Add(“height”, height.ToString());
embed.Attributes.Add(“scale”, “tofit”);
embed.Attributes.Add(“autoplay”, “true”);
embed.Attributes.Add(“controller”, “true”);
embed.Attributes.Add(“target”, “myself”);
embed.Attributes.Add(“type”, bo.MimeType);
embed.Attributes.Add(“pluginspage”, “http://www.apple.com/quicktime/download/index.html”);
embed.Attributes.Add(“src”, location);
// Object tag
result.TagName = “object”;
result.Attributes.Add(“classid”, “clsid:02BF25D5-8C17-4B23-BC80-D3488ABDDC6B”);
result.Attributes.Add(“codebase”, “http://www.apple.com/qtactivex/qtplugin.cab#version=6,0,2,0”);
result.Attributes.Add(“width”, width.ToString());
result.Attributes.Add(“height”, height.ToString());
result.Controls.Add(new LiteralControl(“”));
result.Controls.Add(new LiteralControl(“”));
result.Controls.Add(new LiteralControl(“”));
result.Controls.Add(new LiteralControl(“”));
result.Controls.Add(new LiteralControl(“”));
result.Controls.Add(new LiteralControl(“”));
result.Controls.Add(new LiteralControl(“”));
}

That’s it…. now if you’re really good, you can detect the client operating system, by looking for the word “Windows” in the user agent string (hint:Request.UserAgent) and calling the correct method above.

I tested the above code using FireFox and IE (Windows and Mac).  Windows Media will play in FireFox if you have the Windows Media Plugin (Windows version ships with latest version of Windows Media Player) installed, and the rendering Quicktime requires the plugin from Apple (duh).

WebResource.axd

Winform applications have been using resources (embedded images etc) for some time.  .NET allows developers to embed binary files into assemblies, which can later be retrieved by code at runtime.  ASP.NET is no exception.  How many times have you written a web control, which requires images, and you’ve had to rely on the client web site, using your control, having the correct images in the right location?  A better solution is to embed the images in the web control assembly and have ASP.NET pull the image at runtime.  This is where WebResource.axd comes in.  WebResource.axd is a build in ASP.NET  web handler that manages the rendering of resourced images on a client web browsers.

The following steps inform developers how to add an image resource to a web control assembly, and then have ASP.NET render the image using WebResource.axd.

1. Add the image to your web control project.
2. In the solution explorer, click the file, and in the property window, change build action to “embedded resource.”
3. Add the following to your AssemblyInfo.cs file in the web control project:
[assembly: WebResourceAttribute(“MyNameSpaces.MyControl.Images.MyImage.gif”, “image/gif”)]
Note:  “MyNameSpaces.MyControl” comes from the default
namespace indicated in the web control project properties. “Images” is a folder in the web control project that contains “MyImage.gif”
.
4. In your control rendering code, you’ll need the following to produce a usable URL for the image:
Page.ClientScript.GetWebResourceUrl(typeof(MyNameSpaces.MyControl), “MyNameSpaces.MyControl.Images.MyImage.gif”)

The above steps produce a URL in your rendered control that looks something like:
/WebResource.axd?d=PhPk80h_UWEcbheb-NHNP5WshV_47UOpWqAOl1_li
UFfN4cNofL74cFlQ1fvpFSf0&t=632573240669964903

Event catch-up in ASP.NET 2.0 Controls

Pop quiz, what is wrong with the following class?

public class MyPlaceHolder : PlaceHolder
{
protected override void OnInit(EventArgs e)
{
Page.Trace.Write(this.ID, “In OnInit”);
base.OnInit(e);
}

protected override void OnLoad(EventArgs e)
{
Page.Trace.Write(this.ID, “In OnLoad”);
base.OnLoad(e);
}

protected override void OnUnload(EventArgs e)
{
Page.Trace.Write(this.ID, “In OnUnload”);
base.OnUnload(e);
}

protected override void OnPreRender(EventArgs e)
{
DropDownList myDropDownList1 = new DropDownList();
myDropDownList1.ID = “_myDropDownListDynamic1”;
myDropDownList1.Items.Add(new ListItem(“One”, “one”));
myDropDownList1.Items.Add(new ListItem(“Two”, “two”));
this.Controls.Add(myDropDownList1);
base.OnPreRender(e);
}
}

The class above is a custom server control that derives from an ASP.NET
PlaceHolder control.  This example is a stripped down version of a
class I am currently working on this week (which loads controls
dynamically from custom XML).  I chose the PlaceHolder control to
derive from because I needed a container control, in which to hold my
dynamically instantiated controls – the PlaceHolder control is designed for,
and ideal for this purpose.

I ran into a problem with persistence of property values belonging to
dynamic controls when contained in my custom MyPlaceHolder
control.  In the above example I have created a DropDownList
control dynamically in the OnPreRender method, and added it to the
controls collection of MyPlaceHolder, which, as it turns out is a problem…..

Those of you who know enough about how ASP.NET works (1.1 and 2.0), will know about “catch-up”:

When controls are declared statically in an ASPX page, ASP.NET
instantiates these controls, adds them to an in-memory control tree,
and then calls various event methods on each control, and child
controls recursively, before the page is rendered.  (I have
included the order of events of all controls in ASP.NET later in this
post).

When a control is created dynamically, the time in which the control is
instantiated is at the mercy of the developer. For this reason, ASP.NET
plays “catch-up” and arranges to call all missed event methods so that
the control is in sync with it’s container. Using the above code as an
example – after instantiating the drop down list control and adding this
control to the controls collection of the placeholder, ASP.NET will
call the OnInit, LoadViewState, and OnLoad event methods of the drop down list control,
after which the drop down list control will have caught up to the pre-render event of the
placeholder container.

So, why do I loose persistence of property values in my drop down list control, specifically the selected index property? 

When ASP.NET plays “catch up”, the framework will call some, or all of
the OnInit, LoadViewState, OnLoad, and OnPreRender methods, depending
on the current state of the containing control.  The methods to process post back data are not called during catch-up.

The following AddedControl method exists as part of the Control class
in the ASP.NET 2.0 framework (version 1.1 will have similar code), and
demonstrates “catch-up”, using the current state of the control. Notice
that no call exists to load post data.

protected internal virtual void AddedControl(Control control, int index)
{
if (control.OwnerControl != null)
{
throw new InvalidOperationException(SR.GetString(“Substitution_NotAllowed”));
}
if (control._parent != null)
{
control._parent.Controls.Remove(control);
}
control._parent = this;
control._page = this.Page;
control.flags.Clear(0x20000);
Control control1 = this.flags[0x80] ? this : this._namingContainer;
if (control1 != null)
{
control._namingContainer = control1;
if ((control._id == null) && !control.flags[0x40])
{
control.GenerateAutomaticID();
}
else if ((control._id != null) || ((control._occasionalFields != null) && (control._occasionalFields.Controls != null)))
{
control1.DirtyNameTable();
}
}
if (this._controlState >= ControlState.ChildrenInitialized)
{
control.InitRecursive(control1);
if (((control._controlState == ControlState.Initialized) && (control.RareFields != null)) && control.RareFields.RequiredControlState)
{
this.Page.RegisterRequiresControlState(control);
}
if (this._controlState >= ControlState.ViewStateLoaded)
{
object obj1 = null;
if ((this._occasionalFields != null) && (this._occasionalFields.ControlsViewState != null))
{
obj1 = this._occasionalFields.ControlsViewState[index];
if (this.LoadViewStateByID)
{
control.EnsureID();
obj1 = this._occasionalFields.ControlsViewState[control.ID];
this._occasionalFields.ControlsViewState.Remove(control.ID);
}
else
{
obj1 = this._occasionalFields.ControlsViewState[index];
this._occasionalFields.ControlsViewState.Remove(index);
}
}
control.LoadViewStateRecursive(obj1);
if (this._controlState >= ControlState.Loaded)
{
control.LoadRecursive();
if (this._controlState >= ControlState.PreRendered)
{
control.PreRenderRecursiveInternal();
}
}
}
}
}

My drop down list box  looses persistence because, by the time the
control is instantiated at the pre-render stage, the time for loading
post back data has passed. 

Loading of post back data is in fact performed by the Page class in the
ProcessPostData method, which is called twice by the ProcessRequestMain
method – once before the OnLoad method (before OnPreLoad in ASP.NET
2.0), and again (if not called prior) just after the OnLoad method
completes. This loading of post data before and after OnLoad allows the
developer to add dynamic control instantiation code in the most derived
version of OnLoad method without having to worry about when the base
version is called.

More details about event “catch-up” can be on this excellent post. Also,
check out the Page.ProcessRequestMain, Page.ProcessPostData and
Control.AddedControl methods in the framework using Lutz Roeder’s
Reflector
.

As promised earlier, here is a list of the event methods called by ASP.NET 2.0 in a page render life cycle:

Page Life cycle methods in ASP.NET 2.0

Method Active
Constructor Always
Construct Always
TestDeviceFilter Always
AddParsedSubObject Always
DeterminePostBackMode Always
OnPreInit Always
LoadPersonalizationData Always
InitializeThemes Always
OnInit Always
ApplyControlSkin Always
ApplyPersonalization Always
OnInitComplete Always
LoadPageStateFromPersistenceMedium PostBack
LoadControlState PostBack
LoadViewState PostBack
ProcessPostData1 PostBack
OnPreLoad Always
OnLoad Always
ProcessPostData2 PostBack
RaiseChangedEvents PostBack
RaisePostBackEvent PostBack
OnLoadComplete Always
OnPreRender Always
OnPreRenderComplete Always
SavePersonalizationData Always
SaveControlState Always
SaveViewState Always
SavePageStateToPersistenceMedium Always
Render Always
OnUnload Always

HTML to XHTML using SGMLReader

Chris Lovett wrote a wonderful .NET library called SGMLReader, which,
when passed a regular HTML file will spit out XHTML.  The library
relies on SGML parsing and uses a DTD (Document Type Definition) file to parse
unformatted HTML. 

I’ve been playing with Chris’s library this
week and trying to convert HTML to XHTML on the fly using an ASP.NET
Http Filter. The code below consists of the following:

  • An HttpModule, which sets the filter property of the response object for all ASPX page requests.
  • An Http filter, which is a custom stream, to manipulate the HTML content for the requested page.
  • The entry in the web.config file, required for the module to operate.

So, how does the code work?

To understand my code, you should know a little about how Http modules
work in ASP.NET. I am not going to breach this subject in this post,
but you can out all you need to know about Http modules on MSDN
My module code interjects with each incoming web request sent through
IIS, checks to see if an ASPX page has been requested, and if so, sets
the filter property of the response object to a new instance of XhtmlFilter.

When ASP.NET is ready to push processed HTML content back to the client
browser, via IIS, it uses the filter property in the response
object.  The default filter used by ASP.NET is -:
System.Web.HttpResponseStreamFilterSink.  However, it is possible
to reassign the filter property a custom filer, which will perform so
additional processing before forwarding the content to the default
filter.  This exactly what my filtering code does.  My XhtmlFilter
class is a stream derived class, which captures incoming HTML data from
ASP.NET, converts it to XHTML using SGMLReader, and then forwards the
changed content to the default filter.

The XhtmlFilter class inherits from a base class – HttpFilterBase, which abstracts away the stream functions not supported by Http
filters.  Inside my filter class I make use of a MemoryStream
object to capture all the HTML content pushed by the framework before
processing content with SGMLReader. As the SGMLReader parses the HTML
data the converted XHTML is streamed out to the default filter, and out
to the client browser.

The code follows….

XhtmlFilterModule.cs

using System;
using System.Web;

namespace HTML2XHTML.HttpFilters
{
public class XhtmlFilterModule : IHttpModule
{
public void Dispose() {}

public void Init(HttpApplication context)
{
context.BeginRequest += new EventHandler(ModuleBeginRequest);
}

private void ModuleBeginRequest(object sender, EventArgs e)
{
// See if request is for a ASPX page.
HttpRequest request = HttpContext.Current.Request;
if (request.Url.AbsolutePath.EndsWith(“.aspx”))
{
// Install the filter.
HttpResponse response = HttpContext.Current.Response;
response.Filter = new XhtmlFilter(response.Filter);
}
}
}
}

XhtmlFilter.cs

using System;
using System.IO;
using System.Text;
using System.Xml;
using Sgml;

namespace HTML2XHTML.HttpFilters
{
public class XhtmlFilter : HttpFilterBase
{
private MemoryStream _memStream = null;
private BinaryWriter _writer = null;

public XhtmlFilter(Stream baseStream) : base(baseStream)
{
_memStream = new MemoryStream();
_writer = new BinaryWriter(_memStream);
}

public override void Write(byte[] buffer, int offset, int count)
{
// Check if stream is open.
if (Closed)
throw new ObjectDisposedException(“XhtmlFilter”);
// Write to the memory stream.
_writer.Write(buffer, offset, count);

}

public override void Flush()
{
_writer.Flush();
}

public override void Close()
{
// Seek to the beginning of the memory stream.
_memStream.Seek(0, SeekOrigin.Begin);
// All output has been written to the stream – process the HTML.
SgmlReader sgmlReader = new SgmlReader();
StreamReader streamReader = new StreamReader(_memStream);
XmlTextWriter xmlWriter = new XmlTextWriter(BaseStream, Encoding.UTF8);
sgmlReader.CaseFolding = CaseFolding.None;
sgmlReader.DocType = “HTML”;
sgmlReader.InputStream = streamReader;
sgmlReader.Read();
while (!sgmlReader.EOF)
xmlWriter.WriteNode(sgmlReader, true);
// Close the writer.
xmlWriter.Flush();
xmlWriter.Close();
// Close the reader.
streamReader.Close();
sgmlReader.Close();
// Close the base version.
base.Close();
}
}
}

HttpFilerBase.cs

using System;
using System.IO;

namespace HTML2XHTML.HttpFilters
{
public abstract class HttpFilterBase : Stream
{
private Stream _baseStream;
private bool _closed;

protected Stream BaseStream
{
get { return this._baseStream; }
}

public override bool CanRead
{
get { return false; }
}

public override bool CanWrite
{
get { return !_closed; }
}

public override bool CanSeek
{
get { return false; }
}

protected bool Closed
{
get { return _closed; }
}

public override long Length
{
get { throw new NotSupportedException(); }
}

public override long Position
{
get { throw new NotSupportedException(); }
set { throw new NotSupportedException(); }
}

protected HttpFilterBase(Stream _baseStream)
{
this._baseStream = _baseStream;
this._closed = false;
}

public override void Close()
{
if (!_closed)
{
_closed = true;
_baseStream.Close();
}
}

public override void Flush()
{
_baseStream.Flush();
}

public override int Read(byte[] buffer, int offset, int count)
{
throw new NotSupportedException();
}

public override long Seek(long offset, SeekOrigin origin)
{
throw new NotSupportedException();
}

public override void SetLength(long value)
{
throw new NotSupportedException();
}
}
}

Module entry in web.config

ViewState Tracking in ASP.NET Controls

Let’s say you have the following snippet of code below. The code
dynamically
instantiates a new ASP.NET control, changes the title property and then
adds the control to the control collection of a placeholder on the
page – a typical approach to dynamically creating controls.  When
the control loads, it adds an item into the drop down list
items collection with the same name as the current title property
value.  The title property of the control stores it’s value in the
ViewState, so that the title value is retained between page post
backs.  The problem is, this code does not work as expected. After
a post back the value of the title property is lost – why?

using System;
using System.Web.UI.WebControls;
using System.Collections.Generic;

public class MyDropDownList : DropDownList
{
public string Title
{
get { return ViewState[“myTitle”] as string; }
set { ViewState[“myTitle”] = value; }
}

protected override void OnLoad(EventArgs e)
{
this.Items.Clear();
this.Items.Add(new ListItem(Title));
}
}

public partial class _Default : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
MyDropDownList ctrl = new MyDropDownList();
ctrl.Title = “Hello World!”;
myPlaceHolder.Controls.Add(ctrl);
}
else
{
MyDropDownList ctrl = new MyDropDownList();
// No need to assign title as it should be in the viewstate – right?
myPlaceHolder.Controls.Add(ctrl);
}
}
}

Finding the answer to this problem took some digging buy a co-worker –
The problem occurs because the control is not tracked by the ViewState
until the control is added to the parent container’s control
collection. Once the control is added to the control collection of the
placeholder, ViewState tracking is turned on and changes to the title
property are then stored in the ViewState.  In the above example, the
title of the control was assigned before the control was added to the
placeholder control collection, so the ViewState had not tracked a
change to the title, and therefore did not persist the value.

When dynamically creating user or server controls in ASP.NET always add
the control to the container controls collection before manipulating
the ViewState
.

The code below fixes the problem:

using System;
using System.Web.UI.WebControls;
using System.Collections.Generic;

public class MyDropDownList : DropDownList
{
public string Title
{
get { return ViewState[“myTitle”] as string; }
set { ViewState[“myTitle”] = value; }
}

protected override void OnLoad(EventArgs e)
{
this.Items.Clear();
this.Items.Add(new ListItem(Title));
}
}

public partial class _Default : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
MyDropDownList ctrl = new MyDropDownList();
// Add the control to the placeholder controls collection to enable ViewState tracking.
myPlaceHolder.Controls.Add(ctrl);
ctrl.Title = “Hello World!”;
}
else
{
MyDropDownList ctrl = new MyDropDownList();
myPlaceHolder.Controls.Add(ctrl);
}
}
}

ASP.NET Execution Process

In my previous post I mentioned the steps involved in the process of an ASP.NET page. As promised, here are the details on the slide that was covered in Chris Mazzanti’s presentation at this months Rockville WinProteam user group meeting.

Firstly, all ASPX and ASCX pages are just serialized control trees – object structures. If you turn on tracing for your ASPX page (see image below) you can see the control tree, server side controls are listed and HTML controls are listed as literal controls. This is helpful to understand the steps outlined below.

Before I start with the steps, a quick mention of what the View State is. The View State is a property bag used to stored object / key pairs. The View State persists objects between server postbacks, which can then be accessed using a key from the a pair. View State persists the changed state of all controls on a page, as well as any objects added to the View State by the page developer, during the postback. This marvel is achieved by encoding the property bag as a base 64 encoded string into a hidden form variable, which is a transmitted along with rendered HTML to the client browser and later posted back to the server when the win form is submitted.

When the ASP.NET framework loads an ASPX or ASCX serialized page it immediately deserializes the page into a control tree. The following operations are executed using this object model:

Instantiate – Instantiation of the control tree, described.

Initialize – The Init event is fired and preliminary initialization of controls is started. Dynamic child controls of the page are typically loaded here.

Begin Tracking View State – ASP.NET starts monitoring changes to objects in the view state. Only objects in the View State that change (dirty objects) have their new state saved to the View State encoded output.

Load View State (Postback only) – The View State encoded string is loaded from the post data in the HTTP request.

Load Postback Data (Postback only) – Postback data for all controls loaded.

Load – The Load event is fired. Most developers know this step as the Page_Load method.

Raise Changed Events (Postback only) – Control events fired as a result of some data changed in the control on the client.

Raise Postback Events (Postback only) – Postback events fired (see Chris’s note on control events and postback events at the bottom of this post).

Prerender – The Prerender event is fired. Called before controls are rendered.

Save View State – The View State is saved as a base 64 encoded string.

Render – The RenderControl method of each control in the control tree is called and the output HTML is captured and packaged into the HTTP response, which is sent to the client browser.

Unload – The Unload event is fired.

Dispose – The control tree structure is released from memory and page execution is complete.

The above steps make it easier for developers to understand why certainly functionality is not possible in ASP.NET. For example, how many of us have tried to access the View State information for a control during the initialization step? Since the View State has not let been loaded yet, all controls still have their default value. Another hole that developers fall into (I did) is to attempt to manipulate the View State of a server control within the render step. The View State is already saved at this point, so any changes are pointless.

I want to thank Chris for presenting the above information in his presentation yesterday, it certainly cleared up some confusion with ASP.NET for me.

Here is Chris’s comments on the changed events and postback events steps:

In terms of PostBack events and Changed events, the differences are subtle. A “change” event is an event that a server control will raise during the postback phase if its data has changed while it was on the client. For example, you can have a TextBox generate a change event, and if the user changes the data in that control, the control will raise a data changed event during the postback phase.

It is important to keep in mind that these server side events are not the same as the event that generated the postback itself. For example, if you have a change event setup on a textbox control, simply changing the text will not (necessarily) cause the page to post back. However, if the user clicks the save button, the page will be posted to the server, the textbox will see that it’s data has changed, and fire a changed event. After all the changed events have fired, the “post back” event will fire. This is the event that is raise by the control that actually caused the page to the be sent back to the server in the first place.

View State Improvements in ASP.NET 2.0

http://msdn.microsoft.com/msdnmag/issues/04/10/View State/default.aspx

What is the View State?

The view state is a hidden form variable containing data encoded in base-64 to represent the state of server side controls on an ASP.NET page.

What’s wrong with the View State?

The view state can become large on pages that include a large number of controls, or complex controls like the DataGrid, that retain state. The view state is embedded in web pages posted to the browser. A large view state could significantly affect the responsiveness of an ASP.NET page if a large view state is downloaded and reposted for each round-trip.

Can the View State be turned off?

Yes, and in cases where no state is required, turning off state at the control level can reduce the size of the view state. However, some controls, such as the DataGrid control, use state to manage the operation of the control as well as the data associated with it. For example the DataGrid control uses the view state to control pagination.

Disabling the view state for some controls may affect post-back events. Text boxes and drop-down lists rely on the view state to determine if the content of the control has changed before firing a changed event.

Improvements in ASP.NET 2:

Serialization – The view state is binary serialized data, generated by each control retaining state, which is then encoded in base-64. ASP.NET 1.x used a number of less-than and greater-than characters to define field separation. ASP.NET 2 now uses single binary control characters, and requires fewer to encode the state of a control.

Base-64 adds a 30% overhead to serialized data.

Control State – The view state is now partitioned into two separate categories: control state and view state. The control state manages core behavioral functionality, whereas the view state is now only used to manage the controls content (UI). The control state is stored alongside the view state as base-64 in the hidden field, as before, only disabling the view state for a control will only disable the content management portion, retaining the control state for correct control behavior.

ASP.NET Vulnerability

This alert is to advise you of the availability of a web page that discusses an investigation Microsoft is currently conducting into public reports of a security vulnerability in ASP.NET. A malicious user could provide a specially-formed URL that could result in the unintended serving of secured content.

This alert is also to advise you of the availability of a new Microsoft Knowledge Base article: 887459. This article contains prescriptive guidance with steps customers can implement on their ASP.NET applications to help protect against a wide variety of malformed URL attacks.

Microsoft is providing this prescriptive guidance in order to inform customers as quickly as possible about the vulnerability and information on how to prevent an attack. Microsoft is actively investigating this issue and plans to release additional guidance and a security update to remedy the issue as soon as possible.
The Microsoft Knowledge Base article can be viewed here: http://support.microsoft.com/?kbid=887459

The web page that discusses the current investigation into the public reports of a vulnerability in ASP.Net can be viewed here: http://www.microsoft.com/security/incident/aspnet.mspx [ASP.Net Forums]