<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://blogs.msdn.com/utility/FeedStylesheets/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/"><channel><title>Dan Crevier's Blog : ASP.NET</title><link>http://blogs.msdn.com/dancre/archive/tags/ASP.NET/default.aspx</link><description>Tags: ASP.NET</description><dc:language>en-US</dc:language><generator>CommunityServer 2.1 SP1 (Build: 61025.2)</generator><item><title>A pattern for unit testable Asp.net pages: Part 4</title><link>http://blogs.msdn.com/dancre/archive/2007/07/31/a-pattern-for-unit-testable-asp-net-pages-part-4.aspx</link><pubDate>Wed, 01 Aug 2007 06:52:19 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:4159856</guid><dc:creator>dancre</dc:creator><slash:comments>3</slash:comments><comments>http://blogs.msdn.com/dancre/comments/4159856.aspx</comments><wfw:commentRss>http://blogs.msdn.com/dancre/commentrss.aspx?PostID=4159856</wfw:commentRss><description>&lt;p&gt;Okay, now for unit tests of the code from &lt;a href="http://blogs.msdn.com/dancre/archive/2007/07/25/a-pattern-for-unit-testable-asp-net-pages-part-3.aspx"&gt;part 3&lt;/a&gt;. The goal is to completely cover RenamePageModel. First we need mock implementations of IPageContext and IDataAccess. For IPageContext, we are going to use special exception types for page not found and server errors. And, we'll add an accessor to track redirects. It's all pretty straightforward.&lt;/p&gt;&lt;pre class="csharpcode"&gt;    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; MockPageContext : IPageContext
    {
        &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;bool&lt;/span&gt; IsSecureConnection
        {
            get { &lt;span class="kwrd"&gt;return&lt;/span&gt; _isSecureConnection; }
            set { _isSecureConnection = &lt;span class="kwrd"&gt;value&lt;/span&gt;; }
        }

        &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;bool&lt;/span&gt; IsPost
        {
            get { &lt;span class="kwrd"&gt;return&lt;/span&gt; _isPost; }
            set { _isPost = &lt;span class="kwrd"&gt;value&lt;/span&gt;; }
        }

        &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; ThrowPageNotFound()
        {
            &lt;span class="kwrd"&gt;throw&lt;/span&gt; &lt;span class="kwrd"&gt;new&lt;/span&gt; MockPageNotFoundException();
        }

        &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; ThrowServerError()
        {
            &lt;span class="kwrd"&gt;throw&lt;/span&gt; &lt;span class="kwrd"&gt;new&lt;/span&gt; MockServerErrorException();
        }

        &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; Redirect(&lt;span class="kwrd"&gt;string&lt;/span&gt; destination)
        {
            _redirectString = destination;
        }

        &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;bool&lt;/span&gt; HasRedirected
        {
            get { &lt;span class="kwrd"&gt;return&lt;/span&gt; _redirectString != &lt;span class="kwrd"&gt;null&lt;/span&gt;; }
        }

        &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt; RedirectUrl
        {
            get { &lt;span class="kwrd"&gt;return&lt;/span&gt; _redirectString; }
        }

        &lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;bool&lt;/span&gt; _isSecureConnection;
        &lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;bool&lt;/span&gt; _isPost;
        &lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt; _redirectString;
    }

    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; MockPageNotFoundException : Exception
    {
    }

    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; MockServerErrorException : Exception
    {
    }
&lt;/pre&gt;
&lt;p&gt;
&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }
&lt;/style&gt;
&lt;/p&gt;
&lt;p&gt;The IDataAccess mock is also pretty straightforward. It's simply got properties that can be used to set the return value for the function, or to throw exceptions if desired.&lt;/p&gt;&lt;pre class="csharpcode"&gt;    &lt;span class="kwrd"&gt;class&lt;/span&gt; MockDataAccess : IDataAccess
    {
        &lt;span class="kwrd"&gt;public&lt;/span&gt; MockDataAccess(&lt;span class="kwrd"&gt;string&lt;/span&gt; getItemNameResult, Exception getItemNameException, &lt;span class="kwrd"&gt;string&lt;/span&gt; setItemNameResult, Exception setItemNameException)
        {
            _getItemNameResult = getItemNameResult;
            _getItemNameException = getItemNameException;
            _setItemNameResult = setItemNameResult;
            _setItemNameException = setItemNameException;
        }

        &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt; GetItemName(&lt;span class="kwrd"&gt;string&lt;/span&gt; path)
        {
            &lt;span class="kwrd"&gt;if&lt;/span&gt; (_getItemNameException != &lt;span class="kwrd"&gt;null&lt;/span&gt;)
            {
                &lt;span class="kwrd"&gt;throw&lt;/span&gt; _getItemNameException;
            }

            &lt;span class="kwrd"&gt;return&lt;/span&gt; _getItemNameResult;
        }

        &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt; SetItemName(&lt;span class="kwrd"&gt;string&lt;/span&gt; path, &lt;span class="kwrd"&gt;string&lt;/span&gt; newName)
        {
            &lt;span class="kwrd"&gt;if&lt;/span&gt; (_setItemNameException != &lt;span class="kwrd"&gt;null&lt;/span&gt;)
            {
                &lt;span class="kwrd"&gt;throw&lt;/span&gt; _setItemNameException;
            }

            &lt;span class="kwrd"&gt;return&lt;/span&gt; _setItemNameResult;
        }

        &lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt; _getItemNameResult;
        &lt;span class="kwrd"&gt;private&lt;/span&gt; Exception _getItemNameException;
        &lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt; _setItemNameResult;
        &lt;span class="kwrd"&gt;private&lt;/span&gt; Exception _setItemNameException;
    }
&lt;/pre&gt;
&lt;p&gt;And, now for the actual unit tests. Basically there's a test for each code path on load or post.&lt;/p&gt;&lt;pre class="csharpcode"&gt;    [TestClass]
    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; RenamePageModelTests
    {
        [TestMethod]
        &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; TestLoadSuccess()
        {
            MockDataAccess mockDataAccess = &lt;span class="kwrd"&gt;new&lt;/span&gt; MockDataAccess(&lt;span class="str"&gt;"name"&lt;/span&gt;, &lt;span class="kwrd"&gt;null&lt;/span&gt;, &lt;span class="kwrd"&gt;null&lt;/span&gt;, &lt;span class="kwrd"&gt;null&lt;/span&gt;);
            RenamePageModel model = &lt;span class="kwrd"&gt;new&lt;/span&gt; RenamePageModel(mockDataAccess, &lt;span class="str"&gt;"foo"&lt;/span&gt;);
            model.Load(&lt;span class="kwrd"&gt;new&lt;/span&gt; MockPageContext());
            Assert.AreEqual(&lt;span class="str"&gt;"name"&lt;/span&gt;, model.Name, &lt;span class="str"&gt;"Name not set from item name"&lt;/span&gt;);
        }

        [TestMethod]
        [ExpectedException(&lt;span class="kwrd"&gt;typeof&lt;/span&gt;(MockPageNotFoundException))]
        &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; TestLoadFileNotFoundException()
        {
            MockDataAccess mockDataAccess = &lt;span class="kwrd"&gt;new&lt;/span&gt; MockDataAccess(&lt;span class="str"&gt;"name"&lt;/span&gt;, &lt;span class="kwrd"&gt;new&lt;/span&gt; FileNotFoundException(), &lt;span class="kwrd"&gt;null&lt;/span&gt;, &lt;span class="kwrd"&gt;null&lt;/span&gt;);
            RenamePageModel model = &lt;span class="kwrd"&gt;new&lt;/span&gt; RenamePageModel(mockDataAccess, &lt;span class="str"&gt;"foo"&lt;/span&gt;);
            model.Load(&lt;span class="kwrd"&gt;new&lt;/span&gt; MockPageContext());
        }

        [TestMethod]
        [ExpectedException(&lt;span class="kwrd"&gt;typeof&lt;/span&gt;(MockPageNotFoundException))]
        &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; TestLoadUnauthorizedAccessException()
        {
            MockDataAccess mockDataAccess = &lt;span class="kwrd"&gt;new&lt;/span&gt; MockDataAccess(&lt;span class="str"&gt;"name"&lt;/span&gt;, &lt;span class="kwrd"&gt;new&lt;/span&gt; UnauthorizedAccessException(), &lt;span class="kwrd"&gt;null&lt;/span&gt;, &lt;span class="kwrd"&gt;null&lt;/span&gt;);
            RenamePageModel model = &lt;span class="kwrd"&gt;new&lt;/span&gt; RenamePageModel(mockDataAccess, &lt;span class="str"&gt;"foo"&lt;/span&gt;);
            model.Load(&lt;span class="kwrd"&gt;new&lt;/span&gt; MockPageContext());
        }

        [TestMethod]
        [ExpectedException(&lt;span class="kwrd"&gt;typeof&lt;/span&gt;(MockServerErrorException))]
        &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; TestLoadIOException()
        {
            MockDataAccess mockDataAccess = &lt;span class="kwrd"&gt;new&lt;/span&gt; MockDataAccess(&lt;span class="str"&gt;"name"&lt;/span&gt;, &lt;span class="kwrd"&gt;new&lt;/span&gt; IOException(), &lt;span class="kwrd"&gt;null&lt;/span&gt;, &lt;span class="kwrd"&gt;null&lt;/span&gt;);
            RenamePageModel model = &lt;span class="kwrd"&gt;new&lt;/span&gt; RenamePageModel(mockDataAccess, &lt;span class="str"&gt;"foo"&lt;/span&gt;);
            model.Load(&lt;span class="kwrd"&gt;new&lt;/span&gt; MockPageContext());
        }

        [TestMethod]
        &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; TestPostSuccess()
        {
            MockPageContext pageContext = &lt;span class="kwrd"&gt;new&lt;/span&gt; MockPageContext();
            pageContext.IsPost = &lt;span class="kwrd"&gt;true&lt;/span&gt;;
            MockDataAccess mockDataAccess = &lt;span class="kwrd"&gt;new&lt;/span&gt; MockDataAccess(&lt;span class="str"&gt;"name"&lt;/span&gt;, &lt;span class="kwrd"&gt;null&lt;/span&gt;, &lt;span class="str"&gt;"newpath"&lt;/span&gt;, &lt;span class="kwrd"&gt;null&lt;/span&gt;);
            RenamePageModel model = &lt;span class="kwrd"&gt;new&lt;/span&gt; RenamePageModel(mockDataAccess, &lt;span class="str"&gt;"foo"&lt;/span&gt;);
            model.Load(pageContext);
            Assert.AreEqual(&lt;span class="str"&gt;"rename.aspx?path=newpath"&lt;/span&gt;, pageContext.RedirectUrl, &lt;span class="str"&gt;"Did not redirect to correct url"&lt;/span&gt;);
        }

        [TestMethod]
        &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; TestPostArgumentException()
        {
            MockPageContext pageContext = &lt;span class="kwrd"&gt;new&lt;/span&gt; MockPageContext();
            pageContext.IsPost = &lt;span class="kwrd"&gt;true&lt;/span&gt;;
            MockDataAccess mockDataAccess = &lt;span class="kwrd"&gt;new&lt;/span&gt; MockDataAccess(&lt;span class="str"&gt;"name"&lt;/span&gt;, &lt;span class="kwrd"&gt;null&lt;/span&gt;, &lt;span class="kwrd"&gt;null&lt;/span&gt;, &lt;span class="kwrd"&gt;new&lt;/span&gt; ArgumentException());
            RenamePageModel model = &lt;span class="kwrd"&gt;new&lt;/span&gt; RenamePageModel(mockDataAccess, &lt;span class="str"&gt;"foo"&lt;/span&gt;);
            model.Name = &lt;span class="str"&gt;"errorName"&lt;/span&gt;;
            model.Load(pageContext);
            Assert.AreEqual(&lt;span class="str"&gt;"errorName"&lt;/span&gt;, model.Name, &lt;span class="str"&gt;"New name not returned in model.Name"&lt;/span&gt;);
            Assert.IsNotNull(model.ErrorString, &lt;span class="str"&gt;"Error string not set"&lt;/span&gt;);
        }

        [TestMethod]
        [ExpectedException(&lt;span class="kwrd"&gt;typeof&lt;/span&gt;(MockPageNotFoundException))]
        &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; TestPostFileNotFoundException()
        {
            MockPageContext pageContext = &lt;span class="kwrd"&gt;new&lt;/span&gt; MockPageContext();
            pageContext.IsPost = &lt;span class="kwrd"&gt;true&lt;/span&gt;;
            MockDataAccess mockDataAccess = &lt;span class="kwrd"&gt;new&lt;/span&gt; MockDataAccess(&lt;span class="str"&gt;"name"&lt;/span&gt;, &lt;span class="kwrd"&gt;null&lt;/span&gt;, &lt;span class="kwrd"&gt;null&lt;/span&gt;, &lt;span class="kwrd"&gt;new&lt;/span&gt; FileNotFoundException());
            RenamePageModel model = &lt;span class="kwrd"&gt;new&lt;/span&gt; RenamePageModel(mockDataAccess, &lt;span class="str"&gt;"foo"&lt;/span&gt;);
            model.Load(pageContext);
        }

        [TestMethod]
        [ExpectedException(&lt;span class="kwrd"&gt;typeof&lt;/span&gt;(MockPageNotFoundException))]
        &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; TestPostUnauthorizedAccessException()
        {
            MockPageContext pageContext = &lt;span class="kwrd"&gt;new&lt;/span&gt; MockPageContext();
            pageContext.IsPost = &lt;span class="kwrd"&gt;true&lt;/span&gt;;
            MockDataAccess mockDataAccess = &lt;span class="kwrd"&gt;new&lt;/span&gt; MockDataAccess(&lt;span class="str"&gt;"name"&lt;/span&gt;, &lt;span class="kwrd"&gt;null&lt;/span&gt;, &lt;span class="kwrd"&gt;null&lt;/span&gt;, &lt;span class="kwrd"&gt;new&lt;/span&gt; UnauthorizedAccessException());
            RenamePageModel model = &lt;span class="kwrd"&gt;new&lt;/span&gt; RenamePageModel(mockDataAccess, &lt;span class="str"&gt;"foo"&lt;/span&gt;);
            model.Load(pageContext);
        }

        [TestMethod]
        [ExpectedException(&lt;span class="kwrd"&gt;typeof&lt;/span&gt;(MockServerErrorException))]
        &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; TestPostIOException()
        {
            MockPageContext pageContext = &lt;span class="kwrd"&gt;new&lt;/span&gt; MockPageContext();
            pageContext.IsPost = &lt;span class="kwrd"&gt;true&lt;/span&gt;;
            MockDataAccess mockDataAccess = &lt;span class="kwrd"&gt;new&lt;/span&gt; MockDataAccess(&lt;span class="str"&gt;"name"&lt;/span&gt;, &lt;span class="kwrd"&gt;null&lt;/span&gt;, &lt;span class="kwrd"&gt;null&lt;/span&gt;, &lt;span class="kwrd"&gt;new&lt;/span&gt; IOException());
            RenamePageModel model = &lt;span class="kwrd"&gt;new&lt;/span&gt; RenamePageModel(mockDataAccess, &lt;span class="str"&gt;"foo"&lt;/span&gt;);
            model.Load(pageContext);
        }
&lt;/pre&gt;
&lt;p&gt;If you use Visual Studio .Net's handy code coverage coloring, you'll see that we are covering all the code in the model, except for some closing tags in exceptions that are never hit because of the IPageContext functions that throw exceptions.&lt;/p&gt;
&lt;p&gt;Well, that's it! I've put the entire project on&amp;nbsp;Windows Live&amp;nbsp;SkyDrive:&lt;/p&gt;&lt;iframe style="border-right: #dde5e9 1px solid; padding-right: 0px; border-top: #dde5e9 1px solid; padding-left: 0px; padding-bottom: 0px; margin: 3px; border-left: #dde5e9 1px solid; width: 240px; padding-top: 0px; border-bottom: #dde5e9 1px solid; height: 66px; background-color: #ffffff" marginwidth="0" marginheight="0" src="http://cid-f9dac4c43e9a681d.skydrive.live.com/embedrowdetail.aspx/Blog/PageModelPattern.zip" frameborder="0" scrolling="no"&gt;&lt;/iframe&gt;
&lt;p&gt;Let me know if you have any questions on it. And, let me know if there are other areas you'd like me to write about, such as using the asynchronous model. I'm interested to hear feedback on how this model can be adapted for other types of web apps.&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=4159856" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/dancre/archive/tags/ASP.NET/default.aspx">ASP.NET</category><category domain="http://blogs.msdn.com/dancre/archive/tags/PageModel/default.aspx">PageModel</category></item><item><title>A pattern for unit testable Asp.net pages: Part 3</title><link>http://blogs.msdn.com/dancre/archive/2007/07/25/a-pattern-for-unit-testable-asp-net-pages-part-3.aspx</link><pubDate>Thu, 26 Jul 2007 07:16:49 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:4053965</guid><dc:creator>dancre</dc:creator><slash:comments>5</slash:comments><comments>http://blogs.msdn.com/dancre/comments/4053965.aspx</comments><wfw:commentRss>http://blogs.msdn.com/dancre/commentrss.aspx?PostID=4053965</wfw:commentRss><description> &lt;style type="text/css"&gt;.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }
&lt;/style&gt;  &lt;p&gt;In this post, I'm going to give an example of the pattern in action, built on the classes described in the &lt;a href="http://blogs.msdn.com/dancre/archive/2007/07/23/a-pattern-for-unit-testable-asp-net-pages-part-2.aspx"&gt;last post&lt;/a&gt;. For the example, I've chosen something similar to the rename page on &lt;a href="http://folders.live.com"&gt;Live Folders&lt;/a&gt;. Here's how it should work:&lt;/p&gt; &lt;ul&gt; &lt;li&gt;The Url should be of the form http://&amp;lt;server&amp;gt;/rename.aspx?path=&amp;lt;path to item&amp;gt;.  &lt;li&gt;If the item does not exist or the user does not have access, a 404 error should be returned.  &lt;li&gt;If there is any error talking to the back end storage, a 500 error should be returned.  &lt;li&gt;The page should have a text box for the name, prepopulated with the current item name.  &lt;li&gt;There should be a submit button.  &lt;li&gt;On submit, it should rename the item.  &lt;ul&gt; &lt;li&gt;If successful, it should redirect to another page (in my example, I just redirect to the rename page with the new path)  &lt;li&gt;If the new name has illegal characters, it should show an error inline.&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;Let's start by looking at the .aspx. Note: The page actually looks horrible. I made no attempt to make it look pretty!&lt;/p&gt;&lt;pre class="csharpcode"&gt;&lt;span class="asp"&gt;&amp;lt;%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Rename.aspx.cs" Inherits="PageModelPattern.RenamePage" %&amp;gt;&lt;/span&gt;
&lt;span class="asp"&gt;&amp;lt;%@ Import Namespace="Microsoft.Security.Application" %&amp;gt;&lt;/span&gt;

&lt;span class="kwrd"&gt;&amp;lt;!&lt;/span&gt;&lt;span class="html"&gt;DOCTYPE&lt;/span&gt; &lt;span class="attr"&gt;html&lt;/span&gt; &lt;span class="attr"&gt;PUBLIC&lt;/span&gt; &lt;span class="kwrd"&gt;"-//W3C//DTD XHTML 1.0 Transitional//EN"&lt;/span&gt; &lt;span class="kwrd"&gt;"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;

&lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;html&lt;/span&gt; &lt;span class="attr"&gt;xmlns&lt;/span&gt;&lt;span class="kwrd"&gt;="http://www.w3.org/1999/xhtml"&lt;/span&gt; &lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;head&lt;/span&gt; &lt;span class="attr"&gt;runat&lt;/span&gt;&lt;span class="kwrd"&gt;="server"&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;title&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;Rename&lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;title&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;head&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;body&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;form&lt;/span&gt; &lt;span class="attr"&gt;id&lt;/span&gt;&lt;span class="kwrd"&gt;="form1"&lt;/span&gt; &lt;span class="attr"&gt;runat&lt;/span&gt;&lt;span class="kwrd"&gt;="server"&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;asp:Panel&lt;/span&gt; &lt;span class="attr"&gt;runat&lt;/span&gt;&lt;span class="kwrd"&gt;="server"&lt;/span&gt; &lt;span class="attr"&gt;Visible&lt;/span&gt;&lt;span class="kwrd"&gt;="&amp;lt;%# !string.IsNullOrEmpty(this.PageModel.ErrorString) %&amp;gt;"&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;span&lt;/span&gt; &lt;span class="attr"&gt;style&lt;/span&gt;&lt;span class="kwrd"&gt;="color: Red"&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;span class="asp"&gt;&amp;lt;%&lt;/span&gt;# &lt;span class="kwrd"&gt;this&lt;/span&gt;.PageModel.ErrorString &lt;span class="asp"&gt;%&amp;gt;&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;span&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;asp:Panel&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
    
        &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;div&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;Name: &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;input&lt;/span&gt; &lt;span class="attr"&gt;name&lt;/span&gt;&lt;span class="kwrd"&gt;="name"&lt;/span&gt; &lt;span class="attr"&gt;value&lt;/span&gt;&lt;span class="kwrd"&gt;="&amp;lt;%# AntiXss.HtmlAttributeEncode(this.PageModel.Name) %&amp;gt;"&lt;/span&gt; &lt;span class="kwrd"&gt;/&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;div&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;div&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;asp:Button&lt;/span&gt; &lt;span class="attr"&gt;runat&lt;/span&gt;&lt;span class="kwrd"&gt;="server"&lt;/span&gt; &lt;span class="attr"&gt;Text&lt;/span&gt;&lt;span class="kwrd"&gt;="Submit"&lt;/span&gt; &lt;span class="kwrd"&gt;/&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;div&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;form&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;body&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;html&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;Notice that the page uses the &amp;lt;%# %&amp;gt; binding syntax. For more information about this, see my previous &lt;a href="http://blogs.msdn.com/dancre/archive/2007/02/13/the-difference-between-lt-and-lt-in-asp-net.aspx"&gt;post&lt;/a&gt;. Basically, the expression inside will be evaluated when the page is data bound. This happens after the model has been loaded by PageModelBasedPage. In these expressions, we can access public properties exposed by the mode. We use two properties here. The first it the error string. We have an &amp;lt;asp:Panel&amp;gt; that's visible when the error string is non empty or null. In that case, it will render as a div. There is also an &amp;lt;input&amp;gt; field for the name which is populated from this.PageModel.Name. Since the name will untrusted input, we need to escape it to avoid cross site scripting attacks. I chose to use the &lt;a href="http://msdn2.microsoft.com/en-us/security/aa973814.aspx"&gt;Microsoft AntiXss Library&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Now, let's look at the code behind.&lt;/p&gt;&lt;pre class="csharpcode"&gt;    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;partial&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; RenamePage : PageModelBasedPage&amp;lt;RenamePageModel&amp;gt;
    {
        &lt;span class="rem"&gt;/// &amp;lt;summary&amp;gt;&lt;/span&gt;
        &lt;span class="rem"&gt;/// Create a RenamePageModel.&lt;/span&gt;
        &lt;span class="rem"&gt;/// &amp;lt;/summary&amp;gt;&lt;/span&gt;
        &lt;span class="rem"&gt;/// &amp;lt;returns&amp;gt;RenamePageModel.&amp;lt;/returns&amp;gt;&lt;/span&gt;
        &lt;span class="kwrd"&gt;protected&lt;/span&gt; &lt;span class="kwrd"&gt;override&lt;/span&gt; RenamePageModel CreateModel()
        {
            &lt;span class="kwrd"&gt;return&lt;/span&gt; &lt;span class="kwrd"&gt;new&lt;/span&gt; RenamePageModel(&lt;span class="kwrd"&gt;new&lt;/span&gt; DataAccess(), &lt;span class="kwrd"&gt;this&lt;/span&gt;.Request.QueryString[&lt;span class="str"&gt;"path"&lt;/span&gt;]);
        }

        &lt;span class="rem"&gt;/// &amp;lt;summary&amp;gt;&lt;/span&gt;
        &lt;span class="rem"&gt;/// Collect data about a post back.&lt;/span&gt;
        &lt;span class="rem"&gt;/// &amp;lt;/summary&amp;gt;&lt;/span&gt;
        &lt;span class="kwrd"&gt;protected&lt;/span&gt; &lt;span class="kwrd"&gt;override&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; CollectPostData()
        {
            &lt;span class="kwrd"&gt;base&lt;/span&gt;.CollectPostData();

            &lt;span class="kwrd"&gt;this&lt;/span&gt;.PageModel.Name = &lt;span class="kwrd"&gt;this&lt;/span&gt;.Request.Form[&lt;span class="str"&gt;"name"&lt;/span&gt;];
        }
    }
&lt;/pre&gt;
&lt;p&gt;It's very simple, but that's the point! This is the code we can't unit test. CreateModel creates the RenamePageModel. I'll go into the DataAccess part in a moment. The other thing it passes in is the path, which it grabs from the query string. The other thing it does is populate the name property in the model on a postback from the form value.&lt;/p&gt;
&lt;p&gt;To abstract the access to the data layer, I created a simple interface for the purpose of this demo:&lt;/p&gt;&lt;pre class="csharpcode"&gt;    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;interface&lt;/span&gt; IDataAccess
    {
        &lt;span class="rem"&gt;/// &amp;lt;summary&amp;gt;&lt;/span&gt;
        &lt;span class="rem"&gt;/// Get the name of an item from its path.&lt;/span&gt;
        &lt;span class="rem"&gt;/// &amp;lt;/summary&amp;gt;&lt;/span&gt;
        &lt;span class="rem"&gt;/// &amp;lt;param name="path"&amp;gt;The path to the item.&amp;lt;/param&amp;gt;&lt;/span&gt;
        &lt;span class="rem"&gt;/// &amp;lt;returns&amp;gt;The item name.&amp;lt;/returns&amp;gt;&lt;/span&gt;
        &lt;span class="rem"&gt;/// &amp;lt;exception cref="FileNotFoundExcetion"&amp;gt;If the item does not exist.&amp;lt;/exception&amp;gt;&lt;/span&gt;
        &lt;span class="rem"&gt;/// &amp;lt;exception cref="UnauthorizedAccessException"&amp;gt;If the user does not have read access to the item.&amp;lt;/exception&amp;gt;&lt;/span&gt;
        &lt;span class="rem"&gt;/// &amp;lt;exception cref="IOException"&amp;gt;General i/o exception.&amp;lt;/exception&amp;gt;&lt;/span&gt;
        &lt;span class="kwrd"&gt;string&lt;/span&gt; GetItemName(&lt;span class="kwrd"&gt;string&lt;/span&gt; path);

        &lt;span class="rem"&gt;/// &amp;lt;summary&amp;gt;&lt;/span&gt;
        &lt;span class="rem"&gt;/// Sets the name of an item.&lt;/span&gt;
        &lt;span class="rem"&gt;/// &amp;lt;/summary&amp;gt;&lt;/span&gt;
        &lt;span class="rem"&gt;/// &amp;lt;param name="path"&amp;gt;The path to the item.&amp;lt;/param&amp;gt;&lt;/span&gt;
        &lt;span class="rem"&gt;/// &amp;lt;param name="newName"&amp;gt;The new name.&amp;lt;/param&amp;gt;&lt;/span&gt;
        &lt;span class="rem"&gt;/// &amp;lt;returns&amp;gt;The new path.&amp;lt;/returns&amp;gt;&lt;/span&gt;
        &lt;span class="rem"&gt;/// &amp;lt;exception cref="FileNotFoundExcetion"&amp;gt;If the item does not exist.&amp;lt;/exception&amp;gt;&lt;/span&gt;
        &lt;span class="rem"&gt;/// &amp;lt;exception cref="ArgumentException"&amp;gt;If the new name is invalid.&amp;lt;/exception&amp;gt;&lt;/span&gt;
        &lt;span class="rem"&gt;/// &amp;lt;exception cref="UnauthorizedAccessException"&amp;gt;If the user does not have write access to the item.&amp;lt;/exception&amp;gt;&lt;/span&gt;
        &lt;span class="rem"&gt;/// &amp;lt;exception cref="IOException"&amp;gt;General i/o exception.&amp;lt;/exception&amp;gt;&lt;/span&gt;
        &lt;span class="kwrd"&gt;string&lt;/span&gt; SetItemName(&lt;span class="kwrd"&gt;string&lt;/span&gt; path, &lt;span class="kwrd"&gt;string&lt;/span&gt; newName);
    }
&lt;/pre&gt;
&lt;p&gt;The functions should be pretty self explanatory based on the comments above. The most important part is the exceptions they can throw because the model depends on these. It's abstracted through an interface so that it can be mocked out when unit testing the page model. DataAccess is a placeholder implementation I created for this sample. I won't include the source for it here, but I'll include it in the project that I'll post when I finish the series.&lt;/p&gt;
&lt;p&gt;Now, here's the page model. It has the real business logic that we'll be able to unit test:&lt;/p&gt;&lt;pre class="csharpcode"&gt;    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; RenamePageModel : PageModel
    {
        &lt;span class="kwrd"&gt;public&lt;/span&gt; RenamePageModel(IDataAccess dataAccess, &lt;span class="kwrd"&gt;string&lt;/span&gt; path)
        {
            _dataAccess = dataAccess;
            _path = path;
        }

        &lt;span class="rem"&gt;/// &amp;lt;summary&amp;gt;&lt;/span&gt;
        &lt;span class="rem"&gt;/// Gets the name to display in the UI or sets the name to rename to.&lt;/span&gt;
        &lt;span class="rem"&gt;/// &amp;lt;/summary&amp;gt;&lt;/span&gt;
        &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt; Name
        {
            get { &lt;span class="kwrd"&gt;return&lt;/span&gt; _nameToDisplay; }
            set { _newName = &lt;span class="kwrd"&gt;value&lt;/span&gt;; }
        }

        &lt;span class="rem"&gt;/// &amp;lt;summary&amp;gt;&lt;/span&gt;
        &lt;span class="rem"&gt;/// The error string to display (or null)&lt;/span&gt;
        &lt;span class="rem"&gt;/// &amp;lt;/summary&amp;gt;&lt;/span&gt;
        &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt; ErrorString
        {
            get { &lt;span class="kwrd"&gt;return&lt;/span&gt; _errorString; }
        }

        &lt;span class="rem"&gt;/// &amp;lt;summary&amp;gt;&lt;/span&gt;
        &lt;span class="rem"&gt;/// Called when the page loads.&lt;/span&gt;
        &lt;span class="rem"&gt;/// &amp;lt;/summary&amp;gt;&lt;/span&gt;
        &lt;span class="kwrd"&gt;protected&lt;/span&gt; &lt;span class="kwrd"&gt;override&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; OnLoaded()
        {
            &lt;span class="kwrd"&gt;if&lt;/span&gt; (&lt;span class="kwrd"&gt;this&lt;/span&gt;.PageContext.IsPost)
            {
                HandlePost();

            }
            &lt;span class="kwrd"&gt;else&lt;/span&gt;
            {
                &lt;span class="kwrd"&gt;try&lt;/span&gt;
                {
                    &lt;span class="rem"&gt;// Get the name of the item.&lt;/span&gt;
                    _originalName = _dataAccess.GetItemName(_path);
                }
                &lt;span class="kwrd"&gt;catch&lt;/span&gt; (FileNotFoundException)
                {
                    &lt;span class="rem"&gt;// The item does not exist.&lt;/span&gt;
                    &lt;span class="kwrd"&gt;this&lt;/span&gt;.PageContext.ThrowPageNotFound();
                }
                &lt;span class="kwrd"&gt;catch&lt;/span&gt; (UnauthorizedAccessException)
                {
                    &lt;span class="rem"&gt;// The user does not have access.&lt;/span&gt;
                    &lt;span class="kwrd"&gt;this&lt;/span&gt;.PageContext.ThrowPageNotFound();
                }
                &lt;span class="kwrd"&gt;catch&lt;/span&gt; (IOException)
                {
                    &lt;span class="rem"&gt;// Some other error.&lt;/span&gt;
                    &lt;span class="kwrd"&gt;this&lt;/span&gt;.PageContext.ThrowServerError();
                }

                _nameToDisplay = _originalName;
            }
        }

        &lt;span class="rem"&gt;/// &amp;lt;summary&amp;gt;&lt;/span&gt;
        &lt;span class="rem"&gt;/// Handle a post by renaming the item.&lt;/span&gt;
        &lt;span class="rem"&gt;/// &amp;lt;/summary&amp;gt;&lt;/span&gt;
        &lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; HandlePost()
        {
            &lt;span class="kwrd"&gt;try&lt;/span&gt;
            {
                &lt;span class="kwrd"&gt;string&lt;/span&gt; newPath = _dataAccess.SetItemName(_path, _newName);
                &lt;span class="rem"&gt;// Redirect to next page - just back to the rename page with the new path&lt;/span&gt;
                &lt;span class="rem"&gt;// for the purpose of this example.&lt;/span&gt;
                &lt;span class="kwrd"&gt;this&lt;/span&gt;.PageContext.Redirect(&lt;span class="str"&gt;"rename.aspx?path="&lt;/span&gt; + AntiXss.UrlEncode(newPath));
            }
            &lt;span class="kwrd"&gt;catch&lt;/span&gt; (FileNotFoundException)
            {
                &lt;span class="rem"&gt;// The item does not exist.&lt;/span&gt;
                &lt;span class="kwrd"&gt;this&lt;/span&gt;.PageContext.ThrowPageNotFound();
            }
            &lt;span class="kwrd"&gt;catch&lt;/span&gt; (UnauthorizedAccessException)
            {
                &lt;span class="rem"&gt;// The user does not have access.&lt;/span&gt;
                &lt;span class="kwrd"&gt;this&lt;/span&gt;.PageContext.ThrowPageNotFound();
            }
            &lt;span class="kwrd"&gt;catch&lt;/span&gt; (IOException)
            {
                &lt;span class="rem"&gt;// There was some other error.&lt;/span&gt;
                &lt;span class="kwrd"&gt;this&lt;/span&gt;.PageContext.ThrowServerError();
            }
            &lt;span class="kwrd"&gt;catch&lt;/span&gt; (ArgumentException)
            {
                &lt;span class="rem"&gt;// The new name has illegal characters.&lt;/span&gt;
                _errorString = &lt;span class="str"&gt;"The name has illegal characters."&lt;/span&gt;;
                _nameToDisplay = _newName;
            }
        }

        &lt;span class="kwrd"&gt;private&lt;/span&gt; IDataAccess _dataAccess;
        &lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt; _path;
        &lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt; _newName;
        &lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt; _originalName;
        &lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt; _nameToDisplay;
        &lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt; _errorString;
    }
&lt;/pre&gt;
&lt;p&gt;Hopefully the code is pretty straightforward to read. It basically follows the requirements I outlined at the beginning of the post.&lt;/p&gt;
&lt;p&gt;The result is that we have straightforward data binding in the .aspx and .aspx.cs which we can't unit test, and a model that only depends on IPageContext and IDataAccess which we can easily mock out for unit testing. The &lt;a href="http://blogs.msdn.com/dancre/archive/2007/07/31/a-pattern-for-unit-testable-asp-net-pages-part-4.aspx"&gt;next post&lt;/a&gt; will wrap things up by showing some unit tests.&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=4053965" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/dancre/archive/tags/ASP.NET/default.aspx">ASP.NET</category><category domain="http://blogs.msdn.com/dancre/archive/tags/PageModel/default.aspx">PageModel</category></item><item><title>A pattern for unit testable Asp.net pages: Part 2</title><link>http://blogs.msdn.com/dancre/archive/2007/07/23/a-pattern-for-unit-testable-asp-net-pages-part-2.aspx</link><pubDate>Tue, 24 Jul 2007 07:13:56 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:4021350</guid><dc:creator>dancre</dc:creator><slash:comments>2</slash:comments><comments>http://blogs.msdn.com/dancre/comments/4021350.aspx</comments><wfw:commentRss>http://blogs.msdn.com/dancre/commentrss.aspx?PostID=4021350</wfw:commentRss><description> &lt;style type="text/css"&gt;.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }
&lt;/style&gt;  &lt;p&gt;In &lt;a href="http://blogs.msdn.com/dancre/archive/2007/07/20/a-pattern-for-unit-testable-asp-net-pages-part-1.aspx"&gt;part 1&lt;/a&gt;, I gave an overview of the pattern. In this part, I will describe some of the core classes. Let's start off with the PageModel itself. It's&amp;nbsp;the most simple. It is an abstract class. Subclasses must implement OnLoaded. It has an associated IPageContext (see below) that the model will use to interface with the page.&lt;/p&gt;&lt;pre class="csharpcode"&gt;    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;abstract&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; PageModel
    {
        &lt;span class="rem"&gt;/// &amp;lt;summary&amp;gt;&lt;/span&gt;
        &lt;span class="rem"&gt;/// The context associated with the model.&lt;/span&gt;
        &lt;span class="rem"&gt;/// &amp;lt;/summary&amp;gt;&lt;/span&gt;
        &lt;span class="kwrd"&gt;protected&lt;/span&gt; IPageContext PageContext
        {
            get { &lt;span class="kwrd"&gt;return&lt;/span&gt; _pageContext; }
        }

        &lt;span class="rem"&gt;/// &amp;lt;summary&amp;gt;&lt;/span&gt;
        &lt;span class="rem"&gt;/// Called to load the page model.&lt;/span&gt;
        &lt;span class="rem"&gt;/// &amp;lt;/summary&amp;gt;&lt;/span&gt;
        &lt;span class="rem"&gt;/// &amp;lt;param name="pageContext"&amp;gt;The page context.&amp;lt;/param&amp;gt;&lt;/span&gt;
        &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; Load(IPageContext pageContext)
        {
            _pageContext = pageContext;
            OnLoaded();
        }

        &lt;span class="rem"&gt;/// &amp;lt;summary&amp;gt;&lt;/span&gt;
        &lt;span class="rem"&gt;/// Override to provide behavior for the model.&lt;/span&gt;
        &lt;span class="rem"&gt;/// &amp;lt;/summary&amp;gt;&lt;/span&gt;
        &lt;span class="kwrd"&gt;protected&lt;/span&gt; &lt;span class="kwrd"&gt;abstract&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; OnLoaded();

        &lt;span class="kwrd"&gt;private&lt;/span&gt; IPageContext _pageContext;
    }&lt;/pre&gt;
&lt;p&gt;The IPageContext will allow the model to get some Asp.net specific information about the page and to do some Asp.net specific operations. When unit testing, a mock implementation of IPageContext can be used to test the model in isolation. IPageContext looks like this:&lt;/p&gt;&lt;pre class="csharpcode"&gt;    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;interface&lt;/span&gt; IPageContext
    {
        &lt;span class="rem"&gt;/// &amp;lt;summary&amp;gt;&lt;/span&gt;
        &lt;span class="rem"&gt;/// Gets if the connection is secure.&lt;/span&gt;
        &lt;span class="rem"&gt;/// &amp;lt;/summary&amp;gt;&lt;/span&gt;
        &lt;span class="kwrd"&gt;bool&lt;/span&gt; IsSecureConnection { get; }

        &lt;span class="rem"&gt;/// &amp;lt;summary&amp;gt;&lt;/span&gt;
        &lt;span class="rem"&gt;/// Gets if this is a post.&lt;/span&gt;
        &lt;span class="rem"&gt;/// &amp;lt;/summary&amp;gt;&lt;/span&gt;
        &lt;span class="kwrd"&gt;bool&lt;/span&gt; IsPost { get; }

        &lt;span class="rem"&gt;/// &amp;lt;summary&amp;gt;&lt;/span&gt;
        &lt;span class="rem"&gt;/// Throws a page not found exception.&lt;/span&gt;
        &lt;span class="rem"&gt;/// &amp;lt;/summary&amp;gt;&lt;/span&gt;
        &lt;span class="kwrd"&gt;void&lt;/span&gt; ThrowPageNotFound();

        &lt;span class="rem"&gt;/// &amp;lt;summary&amp;gt;&lt;/span&gt;
        &lt;span class="rem"&gt;/// Throws a server error.&lt;/span&gt;
        &lt;span class="rem"&gt;/// &amp;lt;/summary&amp;gt;&lt;/span&gt;
        &lt;span class="kwrd"&gt;void&lt;/span&gt; ThrowServerError();

        &lt;span class="rem"&gt;/// &amp;lt;summary&amp;gt;&lt;/span&gt;
        &lt;span class="rem"&gt;/// Redirects to another page. Note: Execution continues after this call.&lt;/span&gt;
        &lt;span class="rem"&gt;/// &amp;lt;/summary&amp;gt;&lt;/span&gt;
        &lt;span class="rem"&gt;/// &amp;lt;param name="destination"&amp;gt;Page to redirect to.&amp;lt;/param&amp;gt;&lt;/span&gt;
        &lt;span class="kwrd"&gt;void&lt;/span&gt; Redirect(&lt;span class="kwrd"&gt;string&lt;/span&gt; destination);

        &lt;span class="rem"&gt;/// &amp;lt;summary&amp;gt;&lt;/span&gt;
        &lt;span class="rem"&gt;/// Has a redirect taken place?&lt;/span&gt;
        &lt;span class="rem"&gt;/// &amp;lt;/summary&amp;gt;&lt;/span&gt;
        &lt;span class="kwrd"&gt;bool&lt;/span&gt; HasRedirected { get; }
    }
&lt;/pre&gt;
&lt;p&gt;Note: This interface can be extended as needed. The interface here is a simple starting point.&lt;/p&gt;
&lt;p&gt;Now, let's look at PageModelBasedPage, which is a base class for pages that will use PageModels. It's a generic class, parametized by the PageModel subclass. Subclasses of PageModelBasedPage must implement CreateModel to actually create the model. When the page is loaded, it will create the model with an AspPageContext. If it's a post, it will call a function CollectPostData() which can be overridden to collect post data. Finally, when the page load process is finished, it will do data binding on the page, unless there's been a redirect, in which case it will hide the controls on the page to avoid any unnecessary rendering.&lt;/p&gt;&lt;pre class="csharpcode"&gt;    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;abstract&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; PageModelBasedPage&amp;lt;ModelType&amp;gt; : Page &lt;span class="kwrd"&gt;where&lt;/span&gt; ModelType : PageModel
    {
        &lt;span class="kwrd"&gt;protected&lt;/span&gt; PageModelBasedPage()
        {
            &lt;span class="kwrd"&gt;this&lt;/span&gt;.LoadComplete += OnLoad;
            &lt;span class="kwrd"&gt;this&lt;/span&gt;.PreRenderComplete += OnPreRenderComplete;
        }

        &lt;span class="rem"&gt;/// &amp;lt;summary&amp;gt;&lt;/span&gt;
        &lt;span class="rem"&gt;/// Derived class must implement CreateModel and return the model.&lt;/span&gt;
        &lt;span class="rem"&gt;/// &amp;lt;/summary&amp;gt;&lt;/span&gt;
        &lt;span class="rem"&gt;/// &amp;lt;returns&amp;gt;PageModel subclass.&amp;lt;/returns&amp;gt;&lt;/span&gt;
        &lt;span class="kwrd"&gt;protected&lt;/span&gt; &lt;span class="kwrd"&gt;abstract&lt;/span&gt; ModelType CreateModel();

        &lt;span class="rem"&gt;/// &amp;lt;summary&amp;gt;&lt;/span&gt;
        &lt;span class="rem"&gt;/// Base classes can override for any special data binding.&lt;/span&gt;
        &lt;span class="rem"&gt;/// &amp;lt;/summary&amp;gt;&lt;/span&gt;
        &lt;span class="kwrd"&gt;protected&lt;/span&gt; &lt;span class="kwrd"&gt;virtual&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; DoDataBinding()
        {
            &lt;span class="kwrd"&gt;if&lt;/span&gt; (_pageContext.HasRedirected)
            {
                &lt;span class="rem"&gt;// No need to render the page on a redirect.&lt;/span&gt;
                &lt;span class="kwrd"&gt;this&lt;/span&gt;.Visible = &lt;span class="kwrd"&gt;false&lt;/span&gt;;
            }
            &lt;span class="kwrd"&gt;else&lt;/span&gt;
            {
                &lt;span class="kwrd"&gt;this&lt;/span&gt;.DataBind();
            }
        }

        &lt;span class="rem"&gt;/// &amp;lt;summary&amp;gt;&lt;/span&gt;
        &lt;span class="rem"&gt;/// Derived class can do any manipulation of the Form values and set properties&lt;/span&gt;
        &lt;span class="rem"&gt;/// on the PageModel after a post.&lt;/span&gt;
        &lt;span class="rem"&gt;/// &amp;lt;/summary&amp;gt;&lt;/span&gt;
        &lt;span class="kwrd"&gt;protected&lt;/span&gt; &lt;span class="kwrd"&gt;virtual&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; CollectPostData()
        {
        }

        &lt;span class="rem"&gt;/// &amp;lt;summary&amp;gt;&lt;/span&gt;
        &lt;span class="rem"&gt;/// The current page model for the page.&lt;/span&gt;
        &lt;span class="rem"&gt;/// &amp;lt;/summary&amp;gt;&lt;/span&gt;
        &lt;span class="kwrd"&gt;protected&lt;/span&gt; ModelType PageModel
        {
            get { &lt;span class="kwrd"&gt;return&lt;/span&gt; _model; }
        }

        &lt;span class="rem"&gt;/// &amp;lt;summary&amp;gt;&lt;/span&gt;
        &lt;span class="rem"&gt;/// Called by Asp.net when the page loads.&lt;/span&gt;
        &lt;span class="rem"&gt;/// &amp;lt;/summary&amp;gt;&lt;/span&gt;
        &lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; OnLoad(&lt;span class="kwrd"&gt;object&lt;/span&gt; sender, EventArgs e)
        {
            _model = CreateModel();
            _pageContext = &lt;span class="kwrd"&gt;new&lt;/span&gt; AspPageContext(&lt;span class="kwrd"&gt;this&lt;/span&gt;);

            &lt;span class="kwrd"&gt;if&lt;/span&gt; (_pageContext.IsPost)
            {
                &lt;span class="rem"&gt;// WARNING: You may be vulerable to cross site request forgery attacks&lt;/span&gt;
                &lt;span class="rem"&gt;// if you do not implement some sort of canary. For more info, see:&lt;/span&gt;
                &lt;span class="rem"&gt;// &lt;a href="http://en.wikipedia.org/wiki/Csrf"&gt;http://en.wikipedia.org/wiki/Csrf&lt;/a&gt;&lt;/span&gt;
                CollectPostData();
            }

            _model.Load(_pageContext);
        }

        &lt;span class="rem"&gt;/// &amp;lt;summary&amp;gt;&lt;/span&gt;
        &lt;span class="rem"&gt;/// Called by Asp.net when page loading is complete (including any asynchronous&lt;/span&gt;
        &lt;span class="rem"&gt;/// tasks)&lt;/span&gt;
        &lt;span class="rem"&gt;/// &amp;lt;/summary&amp;gt;&lt;/span&gt;
        &lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; OnPreRenderComplete(&lt;span class="kwrd"&gt;object&lt;/span&gt; sender, EventArgs e)
        {
            DoDataBinding();
        }

        &lt;span class="kwrd"&gt;private&lt;/span&gt; ModelType _model;
        &lt;span class="kwrd"&gt;private&lt;/span&gt; AspPageContext _pageContext;
    }&lt;/pre&gt;
&lt;p&gt;As mentioned in the code, as written, this code is vulnerable to cross site request forgery attacks. The solution to this issue will depend on your application.&lt;/p&gt;
&lt;p&gt;By using OnPreRenderComplete, our pattern is compatible with Asp.net's asynchronous pattern. I can write more about that if there is interest.&lt;/p&gt;
&lt;p&gt;AspPageContext, the IPageContext used by PageModelBasedPage is as follows:&lt;/p&gt;&lt;pre class="csharpcode"&gt;    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; AspPageContext : IPageContext
    {
        &lt;span class="kwrd"&gt;public&lt;/span&gt; AspPageContext(Page page)
        {
            _page = page;
        }

        &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;bool&lt;/span&gt; IsSecureConnection
        {
            get { &lt;span class="kwrd"&gt;return&lt;/span&gt; _page.Request.IsSecureConnection; }
        }

        &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;bool&lt;/span&gt; IsPost
        {
            get { &lt;span class="kwrd"&gt;return&lt;/span&gt; _page.IsPostBack; }
        }

        &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; ThrowPageNotFound()
        {
            &lt;span class="kwrd"&gt;throw&lt;/span&gt; &lt;span class="kwrd"&gt;new&lt;/span&gt; HttpException(404, &lt;span class="str"&gt;"Page not found."&lt;/span&gt;);
        }

        &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; ThrowServerError()
        {
            &lt;span class="kwrd"&gt;throw&lt;/span&gt; &lt;span class="kwrd"&gt;new&lt;/span&gt; HttpException(500, &lt;span class="str"&gt;"Server error."&lt;/span&gt;);
        }

        &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; Redirect(&lt;span class="kwrd"&gt;string&lt;/span&gt; destination)
        {
            _page.Response.Redirect(destination);
            _hasRedirected = &lt;span class="kwrd"&gt;true&lt;/span&gt;;
        }

        &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;bool&lt;/span&gt; HasRedirected
        {
            get { &lt;span class="kwrd"&gt;return&lt;/span&gt; _hasRedirected; }
        }

        &lt;span class="kwrd"&gt;private&lt;/span&gt; Page _page;
        &lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;bool&lt;/span&gt; _hasRedirected;
    }&lt;/pre&gt;
&lt;p&gt;That's it for the basics! To use the pattern, you need to:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Create a PageModel subclass with the business logic for the page. 
&lt;li&gt;Derive your Page from PageModelBasedPage. 
&lt;li&gt;Populate any data in the model at creation time or in CollectPostData. 
&lt;li&gt;Use databinding on the page to bind the results to the UI.&lt;/li&gt;&lt;/ol&gt;
&lt;p&gt;The &lt;a href="http://blogs.msdn.com/dancre/archive/2007/07/25/a-pattern-for-unit-testable-asp-net-pages-part-3.aspx"&gt;next part&lt;/a&gt; will contain a full example.&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=4021350" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/dancre/archive/tags/ASP.NET/default.aspx">ASP.NET</category><category domain="http://blogs.msdn.com/dancre/archive/tags/PageModel/default.aspx">PageModel</category></item><item><title>A pattern for unit testable Asp.net pages: Part 1</title><link>http://blogs.msdn.com/dancre/archive/2007/07/20/a-pattern-for-unit-testable-asp-net-pages-part-1.aspx</link><pubDate>Sat, 21 Jul 2007 07:35:02 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:3984761</guid><dc:creator>dancre</dc:creator><slash:comments>2</slash:comments><comments>http://blogs.msdn.com/dancre/comments/3984761.aspx</comments><wfw:commentRss>http://blogs.msdn.com/dancre/commentrss.aspx?PostID=3984761</wfw:commentRss><description>&lt;p&gt;I previously &lt;a href="http://blogs.msdn.com/dancre/archive/tags/DM-V-VM/default.aspx"&gt;blogged about&lt;/a&gt;&amp;nbsp;the pattern we used in our&amp;nbsp;WPF application to separate business logic from the presentation,&amp;nbsp;making the&amp;nbsp;business logic&amp;nbsp;view and&amp;nbsp;data models highly unit testable. Now that I'm working on&amp;nbsp;Asp.net code for &lt;a href="http://folders.live.com"&gt;Live Folders&lt;/a&gt;, we've worked to come up with a similar model&amp;nbsp;that separates the business logic from the presentation. The model we use may not apply to everyone, but I thought I'd present it in a series of posts to&amp;nbsp;hopefully help people out and to get some good feedback.&lt;/p&gt; &lt;p&gt;&lt;a href="http://folders.live.com"&gt;Live Folders&lt;/a&gt;&amp;nbsp;is a pretty basic (Web 1.0!) type application that doesn't make heavy use of client-side JavaScript. It also doesn't use view state or any of the complex Asp.net controls. If your application model is significantly different, this pattern may not work for you.&lt;/p&gt; &lt;p&gt;This pattern breaks a page into two parts. The PageModel is the unit testable business logic for the page, which has no Asp.net dependencies. Then, there's the Page subclass, which collects data about the request (query parameters, form post values, etc), runs the model, and then binds data from the model into its controls. The Page subclass is not unit testable because of its Asp.net dependencies (the Asp.net code should tested with scenario tests that automate the browser).&lt;/p&gt; &lt;p&gt;The PageModel may need to do things like redirect the user or throw a page not found error. These sorts of Asp.net dependencies are abstracted out with an interface called IPageContext. A mock implementation is used for unit testing, and an Asp.net specific implementation is used in the real pages.&lt;/p&gt; &lt;p&gt;This series will consist of the following parts:&lt;/p&gt; &lt;p&gt;&lt;a href="http://blogs.msdn.com/dancre/archive/2007/07/23/a-pattern-for-unit-testable-asp-net-pages-part-2.aspx"&gt;Part 2&lt;/a&gt;: The core classes (PageModel, PageModelBasedPage, IPageContext)&lt;/p&gt; &lt;p&gt;&lt;a href="http://blogs.msdn.com/dancre/archive/2007/07/25/a-pattern-for-unit-testable-asp-net-pages-part-3.aspx"&gt;Part 3&lt;/a&gt;: An example&lt;/p&gt; &lt;p&gt;&lt;a href="http://blogs.msdn.com/dancre/archive/2007/07/31/a-pattern-for-unit-testable-asp-net-pages-part-4.aspx"&gt;Part 4&lt;/a&gt;: Unit testing the example&lt;/p&gt; &lt;p&gt;The resulting code is available at &lt;a href="http://folders.live.com/self.aspx/+drExD6aaB0/Blog/PageModelPattern.zip"&gt;http://folders.live.com/self.aspx/+drExD6aaB0/Blog/PageModelPattern.zip&lt;/a&gt;.&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=3984761" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/dancre/archive/tags/ASP.NET/default.aspx">ASP.NET</category><category domain="http://blogs.msdn.com/dancre/archive/tags/PageModel/default.aspx">PageModel</category></item><item><title>Gotcha with HttpResponse.Redirect</title><link>http://blogs.msdn.com/dancre/archive/2007/03/27/gotcha-with-httpresponse-redirect.aspx</link><pubDate>Wed, 28 Mar 2007 07:37:54 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:1971586</guid><dc:creator>dancre</dc:creator><slash:comments>1</slash:comments><comments>http://blogs.msdn.com/dancre/comments/1971586.aspx</comments><wfw:commentRss>http://blogs.msdn.com/dancre/commentrss.aspx?PostID=1971586</wfw:commentRss><description>&lt;p&gt;HttpResponse.Redirect is used to redirect to another page using a 302 response code. It can be used in two modes. One terminates the thread immediately so that execution does not continue to the next line of code. The other version continues execution, but returns a 302 response. The latter version is the only one that works from asynchronous callbacks (at least when using Page.RegisterAsyncTask). I guess it doesn't like threads being terminated out from under it. There's on gotcha with HttpResponse.Redirect(url, false) though. It will actually render the page, so the 302 response may have a bunch of unwanted data. The solution is to call Page.Visiable = false after doing the redirect. This will avoid rendering any content for the page. Good catch on this one, Josh!&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=1971586" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/dancre/archive/tags/ASP.NET/default.aspx">ASP.NET</category></item><item><title>The difference between &lt;%= and &lt;%# in ASP.NET</title><link>http://blogs.msdn.com/dancre/archive/2007/02/13/the-difference-between-lt-and-lt-in-asp-net.aspx</link><pubDate>Wed, 14 Feb 2007 06:21:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:1673019</guid><dc:creator>dancre</dc:creator><slash:comments>3</slash:comments><comments>http://blogs.msdn.com/dancre/comments/1673019.aspx</comments><wfw:commentRss>http://blogs.msdn.com/dancre/commentrss.aspx?PostID=1673019</wfw:commentRss><description>&lt;p&gt;I was a little confused about the difference between &amp;lt;%= &lt;i&gt;expression&lt;/i&gt; %&amp;gt; and &amp;lt;%# &lt;i&gt;expression&lt;/i&gt; %&amp;gt; in ASP.NET. It seems like both work in a lot of cases, but in other cases, only the # (data binding) version works. So, I decided to dig into it a little bit. To try it out I built this simple page:&lt;/p&gt;&lt;pre class="csharpcode"&gt;&lt;span class="asp"&gt;&amp;lt;%@ Page Language="C#" AutoEventWireup="true"  CodeFile="Default.aspx.cs" Inherits="_Default" %&amp;gt;&lt;/span&gt;&lt;br&gt;&lt;br&gt;&lt;span class="kwrd"&gt;&amp;lt;!&lt;/span&gt;&lt;span class="html"&gt;DOCTYPE&lt;/span&gt; &lt;span class="attr"&gt;html&lt;/span&gt; &lt;span class="attr"&gt;PUBLIC&lt;/span&gt; &lt;span class="kwrd"&gt;"-//W3C//DTD XHTML 1.0 Transitional//EN"&lt;/span&gt; &lt;span class="kwrd"&gt;"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;br&gt;&lt;br&gt;&lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;html&lt;/span&gt; &lt;span class="attr"&gt;xmlns&lt;/span&gt;&lt;span class="kwrd"&gt;="http://www.w3.org/1999/xhtml"&lt;/span&gt; &lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;br&gt;&lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;head&lt;/span&gt; &lt;span class="attr"&gt;runat&lt;/span&gt;&lt;span class="kwrd"&gt;="server"&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;br&gt;    &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;title&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;Untitled Page&lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;title&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;br&gt;&lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;head&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;br&gt;&lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;body&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;br&gt;    &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;form&lt;/span&gt; &lt;span class="attr"&gt;id&lt;/span&gt;&lt;span class="kwrd"&gt;="form1"&lt;/span&gt; &lt;span class="attr"&gt;runat&lt;/span&gt;&lt;span class="kwrd"&gt;="server"&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;br&gt;    &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;div&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;br&gt;        &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;p&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;Equals: &lt;span class="asp"&gt;&amp;lt;%&lt;/span&gt;= &lt;span class="kwrd"&gt;this&lt;/span&gt;.TestValue &lt;span class="asp"&gt;%&amp;gt;&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;p&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;br&gt;        &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;p&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;Pound: &lt;span class="asp"&gt;&amp;lt;%&lt;/span&gt;# &lt;span class="kwrd"&gt;this&lt;/span&gt;.TestValue &lt;span class="asp"&gt;%&amp;gt;&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;p&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;br&gt;        &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;p&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;Equals label: &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;asp:Label&lt;/span&gt; &lt;span class="attr"&gt;runat&lt;/span&gt;&lt;span class="kwrd"&gt;="server"&lt;/span&gt; &lt;span class="attr"&gt;ID&lt;/span&gt;&lt;span class="kwrd"&gt;="_equals"&lt;/span&gt; &lt;span class="attr"&gt;Text&lt;/span&gt;&lt;span class="kwrd"&gt;="&amp;lt;%= this.TestValue %&amp;gt;"&lt;/span&gt; &lt;span class="kwrd"&gt;/&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;p&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;br&gt;        &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;p&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;Pound label: &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;asp:Label&lt;/span&gt; &lt;span class="attr"&gt;runat&lt;/span&gt;&lt;span class="kwrd"&gt;="server"&lt;/span&gt; &lt;span class="attr"&gt;ID&lt;/span&gt;&lt;span class="kwrd"&gt;="_pound"&lt;/span&gt; &lt;span class="attr"&gt;Text&lt;/span&gt;&lt;span class="kwrd"&gt;="&amp;lt;%# this.TestValue %&amp;gt;"&lt;/span&gt; &lt;span class="kwrd"&gt;/&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;p&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;br&gt;    &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;div&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;br&gt;    &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;form&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;br&gt;&lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;body&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;br&gt;&lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;html&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
&lt;/pre&gt;
&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }
&lt;/style&gt;

&lt;p&gt;And the code behind is:&lt;/p&gt;&lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;partial&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; _Default : System.Web.UI.Page &lt;br&gt;{&lt;br&gt;    &lt;span class="kwrd"&gt;protected&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; Page_Load(&lt;span class="kwrd"&gt;object&lt;/span&gt; sender, EventArgs e)&lt;br&gt;    {&lt;br&gt;        _testValue = &lt;span class="str"&gt;"2"&lt;/span&gt;;&lt;br&gt;    }&lt;br&gt;&lt;br&gt;    &lt;span class="kwrd"&gt;protected&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; Page_PreRenderComplete(&lt;span class="kwrd"&gt;object&lt;/span&gt; sender, EventArgs e)&lt;br&gt;    {&lt;br&gt;        &lt;span class="rem"&gt;// DataBind();&lt;/span&gt;&lt;br&gt;        _testValue = &lt;span class="str"&gt;"3"&lt;/span&gt;;&lt;br&gt;    }&lt;br&gt;&lt;br&gt;    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt; TestValue&lt;br&gt;    {&lt;br&gt;        get { &lt;span class="kwrd"&gt;return&lt;/span&gt; _testValue; }&lt;br&gt;    }&lt;br&gt;&lt;br&gt;    &lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt; _testValue = &lt;span class="str"&gt;"1"&lt;/span&gt;;&lt;br&gt;}&lt;br&gt;&lt;/pre&gt;
&lt;p&gt;Here's what the result is when the DataBind() line is commented out:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Equals: 3 
&lt;/p&gt;&lt;p&gt;Pound: 
&lt;/p&gt;&lt;p&gt;Equals label: 
&lt;/p&gt;&lt;p&gt;Pound label: &lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;And, when it's not commented out: 
&lt;/p&gt;&lt;blockquote&gt;
&lt;p&gt;Equals: 3 
&lt;/p&gt;&lt;p&gt;Pound: 2 
&lt;/p&gt;&lt;p&gt;Equals label: 
&lt;/p&gt;&lt;p&gt;Pound label: 2&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;At first glance it looks like the Equals label case did nothing. But, if you view source, you see: 
&lt;/p&gt;&lt;blockquote&gt;
&lt;p&gt;&amp;lt;p&amp;gt;Equals label: &amp;lt;span id="_equals"&amp;gt;&amp;lt;%= this.TestValue %&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;The literal expression made it down to the browser and it's just invalid HTML. What you can see as a result is: 
&lt;/p&gt;&lt;ul&gt;
&lt;li&gt;The &amp;lt;%= expressions are evaluated at render time 
&lt;/li&gt;&lt;li&gt;The &amp;lt;%# expressions are evaluated at DataBind() time and are not evaluated at all if DataBind() is not called. 
&lt;/li&gt;&lt;li&gt;&amp;lt;%# expressions can be used as properties in server-side controls. &amp;lt;%= expressions cannot.&lt;/li&gt;&lt;/ul&gt;
&lt;p&gt;Now, let's look at the generated code to see how it works. It builds the control tree using the following code:&lt;/p&gt;&lt;pre class="csharpcode"&gt;        &lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; @__BuildControlTree(default_aspx @__ctrl) {&lt;br&gt;            &lt;span class="kwrd"&gt;this&lt;/span&gt;.InitializeCulture();&lt;br&gt;            &lt;br&gt;            System.Web.UI.IParserAccessor @__parser = ((System.Web.UI.IParserAccessor)(@__ctrl));&lt;br&gt;            @__parser.AddParsedSubObject(&lt;span class="kwrd"&gt;new&lt;/span&gt; &lt;br&gt;                        System.Web.UI.LiteralControl(&lt;span class="str"&gt;"\r\n\r\n&amp;lt;!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3"&lt;/span&gt; +&lt;br&gt;                        &lt;span class="str"&gt;".org/TR/xhtml1/DTD/xhtml1-transitional.dtd\"&amp;gt;\r\n\r\n&amp;lt;html xmlns=\"http://www.w3.org/1"&lt;/span&gt; +&lt;br&gt;                        &lt;span class="str"&gt;"999/xhtml\" &amp;gt;\r\n"&lt;/span&gt;));&lt;br&gt;            &lt;br&gt;            global::System.Web.UI.HtmlControls.HtmlHead @__ctrl1;&lt;br&gt;            @__ctrl1 = &lt;span class="kwrd"&gt;this&lt;/span&gt;.@__BuildControl__control2();&lt;br&gt;            @__parser.AddParsedSubObject(@__ctrl1);            &lt;br&gt;            @__parser.AddParsedSubObject(&lt;span class="kwrd"&gt;new&lt;/span&gt; System.Web.UI.LiteralControl(&lt;span class="str"&gt;"\r\n&amp;lt;body&amp;gt;\r\n    "&lt;/span&gt;));&lt;br&gt;            &lt;br&gt;            global::System.Web.UI.HtmlControls.HtmlForm @__ctrl2;&lt;br&gt;            @__ctrl2 = &lt;span class="kwrd"&gt;this&lt;/span&gt;.@__BuildControlform1();&lt;br&gt;            @__parser.AddParsedSubObject(@__ctrl2);&lt;br&gt;            &lt;br&gt;            @__parser.AddParsedSubObject(&lt;span class="kwrd"&gt;new&lt;/span&gt; System.Web.UI.LiteralControl(&lt;span class="str"&gt;"\r\n&amp;lt;/body&amp;gt;\r\n&amp;lt;/html&amp;gt;\r\n"&lt;/span&gt;));&lt;br&gt;        }&lt;/pre&gt;
&lt;p&gt;@__BuildControl__control2() isn't that intersting, it's just the &amp;lt;head&amp;gt; stuff. The guts are in @__BuildControlform1():&lt;/p&gt;&lt;pre class="csharpcode"&gt;        &lt;span class="kwrd"&gt;private&lt;/span&gt; global::System.Web.UI.HtmlControls.HtmlForm @__BuildControlform1() {&lt;br&gt;            global::System.Web.UI.HtmlControls.HtmlForm @__ctrl;&lt;br&gt;            @__ctrl = &lt;span class="kwrd"&gt;new&lt;/span&gt; global::System.Web.UI.HtmlControls.HtmlForm();&lt;br&gt;            &lt;span class="kwrd"&gt;this&lt;/span&gt;.form1 = @__ctrl;&lt;br&gt;            @__ctrl.ID = &lt;span class="str"&gt;"form1"&lt;/span&gt;;&lt;br&gt;            &lt;br&gt;            global::System.Web.UI.DataBoundLiteralControl @__ctrl1;&lt;br&gt;            @__ctrl1 = &lt;span class="kwrd"&gt;this&lt;/span&gt;.@__BuildControl__control4();&lt;br&gt;            System.Web.UI.IParserAccessor @__parser = ((System.Web.UI.IParserAccessor)(@__ctrl));&lt;br&gt;            @__parser.AddParsedSubObject(@__ctrl1);&lt;br&gt;            &lt;br&gt;            global::System.Web.UI.WebControls.Label @__ctrl2;&lt;br&gt;            @__ctrl2 = &lt;span class="kwrd"&gt;this&lt;/span&gt;.@__BuildControl_equals();&lt;br&gt;            @__parser.AddParsedSubObject(@__ctrl2);&lt;br&gt;            &lt;br&gt;            global::System.Web.UI.WebControls.Label @__ctrl3;&lt;br&gt;            @__ctrl3 = &lt;span class="kwrd"&gt;this&lt;/span&gt;.@__BuildControl_pound();&lt;br&gt;            @__parser.AddParsedSubObject(@__ctrl3);&lt;br&gt;            &lt;br&gt;            @__ctrl.SetRenderMethodDelegate(&lt;span class="kwrd"&gt;new&lt;/span&gt; System.Web.UI.RenderMethod(&lt;span class="kwrd"&gt;this&lt;/span&gt;.@__Renderform1));&lt;br&gt;            &lt;span class="kwrd"&gt;return&lt;/span&gt; @__ctrl;&lt;br&gt;        }&lt;/pre&gt;
&lt;p&gt;This is building all of the controls in the form. First let's look at the control built with @__BuildControl__control4():&lt;/p&gt;&lt;pre class="csharpcode"&gt;        &lt;span class="kwrd"&gt;private&lt;/span&gt; global::System.Web.UI.DataBoundLiteralControl @__BuildControl__control4() {&lt;br&gt;            global::System.Web.UI.DataBoundLiteralControl @__ctrl;&lt;br&gt;            &lt;br&gt;            @__ctrl = &lt;span class="kwrd"&gt;new&lt;/span&gt; global::System.Web.UI.DataBoundLiteralControl(2, 1);&lt;br&gt;            @__ctrl.SetStaticString(0, &lt;span class="str"&gt;"&amp;lt;/p&amp;gt;\r\n        &amp;lt;p&amp;gt;Pound: "&lt;/span&gt;);&lt;br&gt;            @__ctrl.SetStaticString(1, &lt;span class="str"&gt;"&amp;lt;/p&amp;gt;\r\n        &amp;lt;p&amp;gt;Equals label: "&lt;/span&gt;);&lt;br&gt;            @__ctrl.DataBinding += &lt;span class="kwrd"&gt;new&lt;/span&gt; System.EventHandler(&lt;span class="kwrd"&gt;this&lt;/span&gt;.@__DataBind__control4);&lt;br&gt;            &lt;br&gt;            &lt;span class="kwrd"&gt;return&lt;/span&gt; @__ctrl;&lt;br&gt;        }&lt;/pre&gt;
&lt;p&gt;And related to this is:&lt;/p&gt;&lt;pre class="csharpcode"&gt;        &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; @__DataBind__control4(&lt;span class="kwrd"&gt;object&lt;/span&gt; sender, System.EventArgs e) {&lt;br&gt;            System.Web.UI.Page Container;&lt;br&gt;            System.Web.UI.DataBoundLiteralControl target;&lt;br&gt;            &lt;br&gt;            target = ((System.Web.UI.DataBoundLiteralControl)(sender));&lt;br&gt;            Container = ((System.Web.UI.Page)(target.BindingContainer));&lt;br&gt;            target.SetDataBoundString(0, System.Convert.ToString(&lt;span class="kwrd"&gt;this&lt;/span&gt;.TestValue, System.Globalization.CultureInfo.CurrentCulture));&lt;br&gt;        }&lt;/pre&gt;
&lt;p&gt;This is the part of the page up to the first &amp;lt;%#. You can see that it uses a DataBoundLiteralControl which is divided between static strings and data bound strings. When DataBind is called on the page, the event handler is called and SetDataBoundString is called on the control. This is why the value is captured at bind time. If you want to see how DataBoundLiteralControl works, you can use .NET Reflector. You can see that it's Render function looks like:&lt;/p&gt;&lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;    protected&lt;/span&gt; &lt;span class="kwrd"&gt;internal&lt;/span&gt; &lt;span class="kwrd"&gt;override&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; Render(HtmlTextWriter output)&lt;br&gt;    {&lt;br&gt;        &lt;span class="kwrd"&gt;int&lt;/span&gt; num1 = &lt;span class="kwrd"&gt;this&lt;/span&gt;._dataBoundLiteral.Length;&lt;br&gt;        &lt;span class="kwrd"&gt;for&lt;/span&gt; (&lt;span class="kwrd"&gt;int&lt;/span&gt; num2 = 0; num2 &amp;lt; &lt;span class="kwrd"&gt;this&lt;/span&gt;._staticLiterals.Length; num2++)&lt;br&gt;        {&lt;br&gt;            &lt;span class="kwrd"&gt;if&lt;/span&gt; (&lt;span class="kwrd"&gt;this&lt;/span&gt;._staticLiterals[num2] != &lt;span class="kwrd"&gt;null&lt;/span&gt;)&lt;br&gt;            {&lt;br&gt;                output.Write(&lt;span class="kwrd"&gt;this&lt;/span&gt;._staticLiterals[num2]);&lt;br&gt;            }&lt;br&gt;            &lt;span class="kwrd"&gt;if&lt;/span&gt; ((num2 &amp;lt; num1) &amp;amp;&amp;amp; (&lt;span class="kwrd"&gt;this&lt;/span&gt;._dataBoundLiteral[num2] != &lt;span class="kwrd"&gt;null&lt;/span&gt;))&lt;br&gt;            {&lt;br&gt;                output.Write(&lt;span class="kwrd"&gt;this&lt;/span&gt;._dataBoundLiteral[num2]);&lt;br&gt;            }&lt;br&gt;        }&lt;br&gt;    }&lt;br&gt;&lt;/pre&gt;
&lt;p&gt;So, it basically outputs the static and data bound fields alternately. That's how it renders the first &amp;lt;%# value on the page if DataBind() is called. Next, let's look at the "_equals" control:&lt;/p&gt;&lt;pre class="csharpcode"&gt;        &lt;span class="kwrd"&gt;private&lt;/span&gt; global::System.Web.UI.WebControls.Label @__BuildControl_equals() {&lt;br&gt;            global::System.Web.UI.WebControls.Label @__ctrl;&lt;br&gt;            &lt;br&gt;            @__ctrl = &lt;span class="kwrd"&gt;new&lt;/span&gt; global::System.Web.UI.WebControls.Label();&lt;br&gt;            @__ctrl.ApplyStyleSheetSkin(&lt;span class="kwrd"&gt;this&lt;/span&gt;);&lt;br&gt;            @__ctrl.ID = &lt;span class="str"&gt;"_equals"&lt;/span&gt;;&lt;br&gt;            @__ctrl.Text = &lt;span class="str"&gt;"&amp;lt;%= this.TestValue %&amp;gt;"&lt;/span&gt;;&lt;br&gt;            &lt;br&gt;            &lt;span class="kwrd"&gt;return&lt;/span&gt; @__ctrl;&lt;br&gt;        }&lt;/pre&gt;
&lt;p&gt;You can see that the &amp;lt;%= is not in any way special. It's just literal text. The "_pound" control, which uses &amp;lt;%# on the other hand, looks like:&lt;/p&gt;&lt;pre class="csharpcode"&gt;        &lt;span class="kwrd"&gt;private&lt;/span&gt; global::System.Web.UI.WebControls.Label @__BuildControl_pound() {&lt;br&gt;            global::System.Web.UI.WebControls.Label @__ctrl;&lt;br&gt;            &lt;br&gt;            @__ctrl = &lt;span class="kwrd"&gt;new&lt;/span&gt; global::System.Web.UI.WebControls.Label();&lt;br&gt;            @__ctrl.ApplyStyleSheetSkin(&lt;span class="kwrd"&gt;this&lt;/span&gt;);&lt;br&gt;            @__ctrl.ID = &lt;span class="str"&gt;"_pound"&lt;/span&gt;;&lt;br&gt;            @__ctrl.DataBinding += &lt;span class="kwrd"&gt;new&lt;/span&gt; System.EventHandler(&lt;span class="kwrd"&gt;this&lt;/span&gt;.@__DataBinding_pound);&lt;br&gt;            &lt;br&gt;            &lt;span class="kwrd"&gt;return&lt;/span&gt; @__ctrl;&lt;br&gt;        }&lt;br&gt;        &lt;br&gt;        &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; @__DataBinding_pound(&lt;span class="kwrd"&gt;object&lt;/span&gt; sender, System.EventArgs e) {&lt;br&gt;            System.Web.UI.WebControls.Label dataBindingExpressionBuilderTarget;&lt;br&gt;            System.Web.UI.Page Container;&lt;br&gt;            dataBindingExpressionBuilderTarget = ((System.Web.UI.WebControls.Label)(sender));&lt;br&gt;            Container = ((System.Web.UI.Page)(dataBindingExpressionBuilderTarget.BindingContainer));&lt;br&gt;            &lt;br&gt;            dataBindingExpressionBuilderTarget.Text = System.Convert.ToString( &lt;span class="kwrd"&gt;this&lt;/span&gt;.TestValue , System.Globalization.CultureInfo.CurrentCulture);&lt;br&gt;        }&lt;/pre&gt;
&lt;p&gt;As compared to the &amp;lt;%= version, &amp;lt;%# is treated specially in parameters. It adds a data binding handler and sets the property at data bind time. That's why &amp;lt;%# does work in parameters and why it picks up the value at data bind time. 
&lt;/p&gt;&lt;p&gt;So, how does the first &amp;lt;%= work? We can see this by looking at the following function:&lt;/p&gt;&lt;pre class="csharpcode"&gt;        &lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; @__Renderform1(System.Web.UI.HtmlTextWriter @__w, System.Web.UI.Control parameterContainer) {&lt;br&gt;            @__w.Write(&lt;span class="str"&gt;"        &amp;lt;p&amp;gt;Equals: "&lt;/span&gt;);&lt;br&gt;            @__w.Write( &lt;span class="kwrd"&gt;this&lt;/span&gt;.TestValue );&lt;br&gt;&lt;br&gt;            parameterContainer.Controls[0].RenderControl(@__w);&lt;br&gt;            parameterContainer.Controls[1].RenderControl(@__w);&lt;br&gt;            @__w.Write(&lt;span class="str"&gt;"&amp;lt;/p&amp;gt;\r\n        &amp;lt;p&amp;gt;Pound label: "&lt;/span&gt;);&lt;br&gt;            parameterContainer.Controls[2].RenderControl(@__w);&lt;br&gt;            @__w.Write(&lt;span class="str"&gt;"&amp;lt;/p&amp;gt;\r\n    &amp;lt;/div&amp;gt;\r\n    "&lt;/span&gt;);&lt;br&gt;        }&lt;/pre&gt;
&lt;p&gt;Here we can see the @__w.Write(this.TestValue) line which is the result of the &amp;lt;%= line in the source. It's outputting the value of this.TestValue at render time, which explains the behavior we saw. 
&lt;/p&gt;&lt;p&gt;So, it all makes sense to me now. I hope it makes sense to you too :-)&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=1673019" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/dancre/archive/tags/ASP.NET/default.aspx">ASP.NET</category></item><item><title>What does runat=&amp;quot;server&amp;quot; do for HTML controls</title><link>http://blogs.msdn.com/dancre/archive/2006/12/17/what-does-runat-server-do-for-html-controls.aspx</link><pubDate>Sun, 17 Dec 2006 20:27:15 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:1311701</guid><dc:creator>dancre</dc:creator><slash:comments>6</slash:comments><comments>http://blogs.msdn.com/dancre/comments/1311701.aspx</comments><wfw:commentRss>http://blogs.msdn.com/dancre/commentrss.aspx?PostID=1311701</wfw:commentRss><description>&lt;p&gt;One thing I didn't fully understand when I first started using ASP.NET is exactly what runat="server" does. It sounds like some magical thing where code is running on the server for your control and not on the client. In some cases something like that does happen, but the basics are much simpler than that.&lt;/p&gt; &lt;p&gt;Let's take a look at the source code generated for a simple control using the &lt;a href="http://blogs.msdn.com/dancre/archive/2006/12/16/playing-with-asp-net.aspx"&gt;trick I blogged about yesterday&lt;/a&gt;. We'll start with this simple page:&lt;/p&gt;&lt;pre class="code"&gt;&lt;span style="background: rgb(255,255,0)"&gt;&amp;lt;%&lt;span style="color: rgb(0,0,255)"&gt;&lt;/span&gt;@&lt;/span&gt; &lt;span style="color: rgb(128,0,0)"&gt;Page&lt;/span&gt; &lt;span style="color: rgb(255,0,0)"&gt;Language&lt;/span&gt;&lt;span style="color: rgb(0,0,255)"&gt;="C#"&lt;/span&gt; &lt;span style="color: rgb(255,0,0)"&gt;AutoEventWireup&lt;/span&gt;&lt;span style="color: rgb(0,0,255)"&gt;="true"&lt;/span&gt;  &lt;span style="color: rgb(255,0,0)"&gt;CodeFile&lt;/span&gt;&lt;span style="color: rgb(0,0,255)"&gt;="Default.aspx.cs"&lt;/span&gt; &lt;span style="color: rgb(255,0,0)"&gt;Inherits&lt;/span&gt;&lt;span style="color: rgb(0,0,255)"&gt;="_Default"&lt;/span&gt; &lt;span style="background: rgb(255,255,0)"&gt;%&amp;gt;

&lt;span style="color: rgb(0,0,255)"&gt;&lt;/span&gt;&amp;lt;!&lt;/span&gt;&lt;span style="color: rgb(128,0,0)"&gt;DOCTYPE&lt;/span&gt; &lt;span style="color: rgb(255,0,0)"&gt;html&lt;/span&gt; &lt;span style="color: rgb(255,0,0)"&gt;PUBLIC&lt;/span&gt; &lt;span style="color: rgb(0,0,255)"&gt;"-//W3C//DTD XHTML 1.0 Transitional//EN"&lt;/span&gt; &lt;span style="color: rgb(0,0,255)"&gt;"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"&amp;gt;

&amp;lt;&lt;/span&gt;&lt;span style="color: rgb(128,0,0)"&gt;html&lt;/span&gt; &lt;span style="color: rgb(255,0,0)"&gt;xmlns&lt;/span&gt;&lt;span style="color: rgb(0,0,255)"&gt;="http://www.w3.org/1999/xhtml"&lt;/span&gt; &lt;span style="color: rgb(0,0,255)"&gt;&amp;gt;
&amp;lt;&lt;/span&gt;&lt;span style="color: rgb(128,0,0)"&gt;head&lt;/span&gt;&lt;span style="color: rgb(0,0,255)"&gt;&amp;gt;
&lt;/span&gt;    &lt;span style="color: rgb(0,0,255)"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: rgb(128,0,0)"&gt;title&lt;/span&gt;&lt;span style="color: rgb(0,0,255)"&gt;&amp;gt;&lt;/span&gt;Untitled Page&lt;span style="color: rgb(0,0,255)"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: rgb(128,0,0)"&gt;title&lt;/span&gt;&lt;span style="color: rgb(0,0,255)"&gt;&amp;gt;
&amp;lt;/&lt;/span&gt;&lt;span style="color: rgb(128,0,0)"&gt;head&lt;/span&gt;&lt;span style="color: rgb(0,0,255)"&gt;&amp;gt;
&amp;lt;&lt;/span&gt;&lt;span style="color: rgb(128,0,0)"&gt;body&lt;/span&gt;&lt;span style="color: rgb(0,0,255)"&gt;&amp;gt;
&lt;/span&gt;    &lt;span style="color: rgb(0,0,255)"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: rgb(128,0,0)"&gt;button&lt;/span&gt;&lt;span style="color: rgb(0,0,255)"&gt;&amp;gt;&lt;/span&gt;foo&lt;span style="color: rgb(0,0,255)"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: rgb(128,0,0)"&gt;button&lt;/span&gt;&lt;span style="color: rgb(0,0,255)"&gt;&amp;gt;
&amp;lt;/&lt;/span&gt;&lt;span style="color: rgb(128,0,0)"&gt;body&lt;/span&gt;&lt;span style="color: rgb(0,0,255)"&gt;&amp;gt;
&amp;lt;/&lt;/span&gt;&lt;span style="color: rgb(128,0,0)"&gt;html&lt;/span&gt;&lt;span style="color: rgb(0,0,255)"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;
&lt;p&gt;Here's a look at some of the source generated (I've simplified a bunch of the debugging info for clarity):&lt;/p&gt;&lt;pre class="code"&gt;        &lt;span style="color: rgb(0,0,255)"&gt;private&lt;/span&gt; &lt;span style="color: rgb(0,0,255)"&gt;void&lt;/span&gt; @__BuildControlTree(default_aspx @__ctrl) {
            
            &lt;span style="color: rgb(0,0,255)"&gt;this&lt;/span&gt;.InitializeCulture();
            
            System.Web.UI.IParserAccessor @__parser = ((System.Web.UI.IParserAccessor)(@__ctrl));
            
            @__parser.AddParsedSubObject(&lt;span style="color: rgb(0,0,255)"&gt;new&lt;/span&gt; System.Web.UI.LiteralControl(&lt;br&gt;                        &lt;span style="color: rgb(128,0,0)"&gt;"\r\n\r\n&amp;lt;html&amp;gt;\r\n&amp;lt;head&amp;gt;\r\n    &amp;lt;title&amp;gt;Untitled&amp;lt;/title&amp;gt;\r\n&amp;lt;/head&amp;gt;\r\n&amp;lt;body&amp;gt;\r\n    &amp;lt;button&amp;gt;foo"&lt;/span&gt; +
                        &lt;span style="color: rgb(128,0,0)"&gt;"&amp;lt;/button&amp;gt;\r\n&amp;lt;/body&amp;gt;\r\n&amp;lt;/html&amp;gt;\r\n"&lt;/span&gt;));
            
        }&lt;/pre&gt;&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;
&lt;p&gt;Notice that the control tree simply has a LiteralControl with all of the HTML, including the button. Without runat="server", nothing special is done with it. But, if we add runat="server", we get:&lt;/p&gt;&lt;pre class="code"&gt;        &lt;span style="color: rgb(0,0,255)"&gt;private&lt;/span&gt; &lt;span style="color: rgb(0,0,255)"&gt;global&lt;/span&gt;::System.Web.UI.HtmlControls.HtmlButton @__BuildControl__control2() {
            &lt;span style="color: rgb(0,0,255)"&gt;global&lt;/span&gt;::System.Web.UI.HtmlControls.HtmlButton @__ctrl;
            
            @__ctrl = &lt;span style="color: rgb(0,0,255)"&gt;new&lt;/span&gt; &lt;span style="color: rgb(0,0,255)"&gt;global&lt;/span&gt;::System.Web.UI.HtmlControls.HtmlButton();
            
            System.Web.UI.IParserAccessor @__parser = ((System.Web.UI.IParserAccessor)(@__ctrl));
            
            @__parser.AddParsedSubObject(&lt;span style="color: rgb(0,0,255)"&gt;new&lt;/span&gt; System.Web.UI.LiteralControl(&lt;span style="color: rgb(128,0,0)"&gt;"foo"&lt;/span&gt;));
            
            &lt;span style="color: rgb(0,0,255)"&gt;return&lt;/span&gt; @__ctrl;
        }
        
        &lt;span style="color: rgb(0,0,255)"&gt;private&lt;/span&gt; &lt;span style="color: rgb(0,0,255)"&gt;void&lt;/span&gt; @__BuildControlTree(default_aspx @__ctrl) {
            
            &lt;span style="color: rgb(0,0,255)"&gt;this&lt;/span&gt;.InitializeCulture();
            
            System.Web.UI.IParserAccessor @__parser = ((System.Web.UI.IParserAccessor)(@__ctrl));
            
            @__parser.AddParsedSubObject(&lt;span style="color: rgb(0,0,255)"&gt;new&lt;/span&gt; System.Web.UI.LiteralControl(&lt;br&gt;                  &lt;span style="color: rgb(128,0,0)"&gt;"\r\n\r\n&amp;lt;html&amp;gt;\r\n&amp;lt;head&amp;gt;\r\n    &amp;lt;title&amp;gt;Untitled&amp;lt;/title&amp;gt;\r\n&amp;lt;/head&amp;gt;\r\n&amp;lt;body&amp;gt;\r\n    "&lt;/span&gt;));
            
            &lt;span style="color: rgb(0,0,255)"&gt;global&lt;/span&gt;::System.Web.UI.HtmlControls.HtmlButton @__ctrl1;
            
            @__ctrl1 = &lt;span style="color: rgb(0,0,255)"&gt;this&lt;/span&gt;.@__BuildControl__control2();
            
            @__parser.AddParsedSubObject(@__ctrl1);
            
            @__parser.AddParsedSubObject(&lt;span style="color: rgb(0,0,255)"&gt;new&lt;/span&gt; System.Web.UI.LiteralControl(&lt;span style="color: rgb(128,0,0)"&gt;"\r\n&amp;lt;/body&amp;gt;\r\n&amp;lt;/html&amp;gt;\r\n"&lt;/span&gt;));
        }&lt;/pre&gt;&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;
&lt;p&gt;Now BuildControlTree adds a literal control for the stuff before the button, adds an HtmlButton for the button itself (with the text inside the control as a literal), and then another LiteralControl for the rest HTML on the page. What happens is that when the control tree is rendered, the HtmlButton will render itself with a &amp;lt;button&amp;gt; tag. In this case, you'll end up with the exact same HTML in the browser as our first example, but let's see what else we can do.&lt;/p&gt;
&lt;p&gt;One thing you might notice when you set runat="server" is that the set of properties available in the Properties Window changes. When you don't have runat="server", what you are looking at is the standard &amp;lt;button&amp;gt; properties. Once you turn on runat="server" what you are looking at is the properties on HtmlButton (which are generally a superset of the HTML properties). For example, if you try adding visible="false" to the button without runat="server", the visible="false'" is just rendered as part of the LiteralControl for the HTML and the browser ignores it because that's not an HTML property on buttons. But, if you do so with runat="server", you'll see in the server side .cs source code that the HtmlButton's visible property is set to false. When the page is rendered by the server, the HtmlButton doesn't render any code for the button and you don't end up with any HTML for the button on the browser.&lt;/p&gt;
&lt;p&gt;The other thing we can do is get programmatic access to the button in our code behind. To do so, we need to add an id to the button. If we switch the button to:&lt;/p&gt;&lt;pre class="code"&gt;    &lt;span style="color: rgb(0,0,255)"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: rgb(128,0,0)"&gt;button&lt;/span&gt; &lt;span style="color: rgb(255,0,0)"&gt;runat&lt;/span&gt;&lt;span style="color: rgb(0,0,255)"&gt;="server"&lt;/span&gt; &lt;span style="color: rgb(255,0,0)"&gt;id&lt;/span&gt;&lt;span style="color: rgb(0,0,255)"&gt;="_button"&amp;gt;&lt;/span&gt;foo&lt;span style="color: rgb(0,0,255)"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: rgb(128,0,0)"&gt;button&lt;/span&gt;&lt;span style="color: rgb(0,0,255)"&gt;&amp;gt;
&lt;/span&gt;&lt;/pre&gt;&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;
&lt;p&gt;Then, the generated source code will include:&lt;/p&gt;&lt;pre class="code"&gt;    &lt;span style="color: rgb(0,0,255)"&gt;protected&lt;/span&gt; &lt;span style="color: rgb(0,0,255)"&gt;global&lt;/span&gt;::System.Web.UI.HtmlControls.HtmlButton _button;
&lt;/pre&gt;&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;
&lt;p&gt;Now, we could add the following to our Page_Load:&lt;/p&gt;&lt;pre class="code"&gt;    &lt;span style="color: rgb(0,0,255)"&gt;protected&lt;/span&gt; &lt;span style="color: rgb(0,0,255)"&gt;void&lt;/span&gt; Page_Load(&lt;span style="color: rgb(0,0,255)"&gt;object&lt;/span&gt; sender, &lt;span style="color: rgb(0,128,128)"&gt;EventArgs&lt;/span&gt; e)
    {
        _button.InnerText = &lt;span style="color: rgb(128,0,0)"&gt;"bar"&lt;/span&gt;;
    }&lt;/pre&gt;
&lt;p&gt;After the control tree is built, it will get into Page_Load and we'll change the InnerText of the button. When the server renders the control tree, it will output "bar" for the text of the button instead of "foo" and the resulting HTML will have &amp;lt;button id="_button"&amp;gt;bar&amp;lt;/button&amp;gt;.&lt;/p&gt;
&lt;p&gt;Something interesting to note is that this works for any kind of HTML tag. In some cases ASP.NET has richer classes backing the HTML tags (like HtmlButton). But, if you just put something like &amp;lt;foo runat="server"&amp;gt;, it will go through the same process, but give you an HtmlGenericControl.&lt;/p&gt;
&lt;p&gt;One thing you can't do with the &amp;lt;button&amp;gt; is add a click handler that runs code on the server. To do that, you'll need the asp:button Web Server control. Those are somewhat different beasts than HTML controls. I'll discuss those in a future post.&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=1311701" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/dancre/archive/tags/ASP.NET/default.aspx">ASP.NET</category></item><item><title>Playing with ASP.NET</title><link>http://blogs.msdn.com/dancre/archive/2006/12/16/playing-with-asp-net.aspx</link><pubDate>Sun, 17 Dec 2006 07:16:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:1309609</guid><dc:creator>dancre</dc:creator><slash:comments>1</slash:comments><comments>http://blogs.msdn.com/dancre/comments/1309609.aspx</comments><wfw:commentRss>http://blogs.msdn.com/dancre/commentrss.aspx?PostID=1309609</wfw:commentRss><description>&lt;P&gt;I'm doing some ASP.NET work on my current project (more about that in the coming months). I've spent most of my life doing client side code, so it's taken me a little time to really wrap my head around what's happening with ASP.NET. It often seems like there's a lot of magic going on. But, once you look into it, it's not really that complicated.&lt;/P&gt;
&lt;P&gt;The job of an ASP.NET page is really to just respond to an HTTP request, usually with HTML. As with client software you build up a control tree that gets rendered. But, in the case of ASP.NET, it's rendered to HTML and then the control hierarchy is thrown away and there's no code related to the page running on the server backing the page. Postbacks are required to further operate with the server, and ASP.NET makes it fairly transparent that this happens.&lt;/P&gt;
&lt;P&gt;One trick that helped me understand things better was suggested in the Architecture chapter of Fritz Onion's Essential ASP.NET 2.0 book. The trick is to insert something like:&lt;/P&gt;
&lt;P&gt;&amp;lt;div&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; The source is in: &amp;lt;%= System.IO.Path.GetDirectoryName(GetType().Assembly.Location) %&amp;gt;.&lt;BR&gt;&amp;lt;/div&amp;gt;&lt;/P&gt;
&lt;P&gt;into the page. In the default compilation model for an ASP.NET page, the first time the page is loaded, it converts the .aspx file into code and compiles it along with your .aspx.cs files. When in debug mode, it will leave the intermediate .cs files it uses in the temp folder with the generated assembly. The files aren't incredibly human friendly, but they are very enlightening. Note: if edit things in Visual Studio and refresh the page in IE, the directory won't change, so you can comment the line above out after figuring out where it is.&lt;/P&gt;
&lt;P&gt;I'm going to follow up with a couple of posts on what code actually gets generated in a few different cases as an exercise to learn the internals of ASP.NET better.&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=1309609" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/dancre/archive/tags/ASP.NET/default.aspx">ASP.NET</category></item></channel></rss>