<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/rss2full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><rss xmlns:blogChannel="http://backend.userland.com/blogChannelModule" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:pingback="http://madskills.com/public/xml/rss/module/pingback/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:geo="http://www.w3.org/2003/01/geo/wgs84_pos#" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" version="2.0">
  <channel>
    <title>jrummell.ToString()</title>
    <description>another .Net weblog</description>
    <link>http://john.rummell.info/john/blog/</link>
    <docs>http://www.rssboard.org/rss-specification</docs>
    <generator>BlogEngine.NET 1.5.0.7</generator>
    <language>en-US</language>
    <blogChannel:blogRoll>http://john.rummell.info/john/blog/opml.axd</blogChannel:blogRoll>
    <blogChannel:blink>http://www.dotnetblogengine.net/syndication.axd</blogChannel:blink>
    <dc:creator>jrummell</dc:creator>
    <dc:title>jrummell.ToString()</dc:title>
    <geo:lat>0.000000</geo:lat>
    <geo:long>0.000000</geo:long>
    <atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" href="http://feeds.feedburner.com/JohnRummell" type="application/rss+xml" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com" /><item>
      <title>Mocking Controller.User</title>
      <description>&lt;p&gt;I’m currently working on my first &lt;a href="http://www.asp.net/mvc/" target="_blank"&gt;ASP.NET MVC&lt;/a&gt; project. Naturally, I’m writing a good number of unit tests. I ran into a problem tonight with mocking &lt;a href="http://msdn.microsoft.com/en-us/library/system.web.mvc.controller.user.aspx" target="_blank"&gt;Controller.User&lt;/a&gt;. Thankfully, someone at &lt;a href="http://stackoverflow.com/" target="_blank"&gt;Stack Overflow&lt;/a&gt; had already asked a &lt;a href="http://stackoverflow.com/questions/1314370/how-to-setup-iprincipal-for-a-mockup" target="_blank"&gt;question about this&lt;/a&gt;. I took &lt;a href="http://stackoverflow.com/questions/1314370/how-to-setup-iprincipal-for-a-mockup/1314472#1314472" target="_blank"&gt;Bruno Reis’ answer&lt;/a&gt;:&lt;/p&gt;  &lt;pre class="csharpcode"&gt;var principal = &lt;span class="kwrd"&gt;new&lt;/span&gt; Moq.Mock&amp;lt;IPrincipal&amp;gt;();
&lt;span class="rem"&gt;// ... mock IPrincipal as you wish&lt;/span&gt;

var httpContext = &lt;span class="kwrd"&gt;new&lt;/span&gt; Moq.Mock&amp;lt;HttpContextBase&amp;gt;();
httpContext.Setup(x =&amp;gt; x.User).Returns(principal.Object);
&lt;span class="rem"&gt;// ... mock other httpContext's properties, methods, as needed&lt;/span&gt;

var reqContext = &lt;span class="kwrd"&gt;new&lt;/span&gt; RequestContext(httpContext.Object, &lt;span class="kwrd"&gt;new&lt;/span&gt; RouteData());

&lt;span class="rem"&gt;// now create the controller:&lt;/span&gt;
var controller = &lt;span class="kwrd"&gt;new&lt;/span&gt; MyController();
controller.ControllerContext =
    &lt;span class="kwrd"&gt;new&lt;/span&gt; ControllerContext(reqContext, controller);&lt;/pre&gt;

&lt;p&gt;and I rewrote it using NUnit.Mocks and wrapped it into an implementation of HttpContextBase:&lt;/p&gt;

&lt;pre class="csharpcode"&gt;&lt;span class="rem"&gt;/// &amp;lt;summary&amp;gt;&lt;/span&gt;
&lt;span class="rem"&gt;/// A mock &amp;lt;see cref=&amp;quot;HttpContextBase&amp;quot;/&amp;gt; that implements &amp;lt;see cref=&amp;quot;HttpContextBase.User&amp;quot;/&amp;gt;.&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;class&lt;/span&gt; MockHttpContext : HttpContextBase
{
    &lt;span class="kwrd"&gt;private&lt;/span&gt; IPrincipal _user;

    &lt;span class="kwrd"&gt;public&lt;/span&gt; MockHttpContext()
    {
        DynamicMock identity = &lt;span class="kwrd"&gt;new&lt;/span&gt; DynamicMock(&lt;span class="kwrd"&gt;typeof&lt;/span&gt; (IIdentity));
        identity.ExpectAndReturn(&lt;span class="str"&gt;&amp;quot;get_Name&amp;quot;&lt;/span&gt;, &lt;span class="str"&gt;&amp;quot;testUser&amp;quot;&lt;/span&gt;);

        DynamicMock user = &lt;span class="kwrd"&gt;new&lt;/span&gt; DynamicMock(&lt;span class="kwrd"&gt;typeof&lt;/span&gt; (IPrincipal));
        user.ExpectAndReturn(&lt;span class="str"&gt;&amp;quot;get_Identity&amp;quot;&lt;/span&gt;, identity.MockInstance);

        _user = (IPrincipal) user.MockInstance;
    }

    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;override&lt;/span&gt; IPrincipal User
    {
        get { &lt;span class="kwrd"&gt;return&lt;/span&gt; _user; }
        set { _user = &lt;span class="kwrd"&gt;value&lt;/span&gt;; }
    }
}&lt;/pre&gt;

&lt;p&gt;Now mocking Controller.User is as easy as this:&lt;/p&gt;

&lt;pre class="csharpcode"&gt;&lt;span class="rem"&gt;// create an instance of RequestContext using MockHttpContext.&lt;/span&gt;
RequestContext requestContext =
    &lt;span class="kwrd"&gt;new&lt;/span&gt; RequestContext(&lt;span class="kwrd"&gt;new&lt;/span&gt; MockHttpContext(), &lt;span class="kwrd"&gt;new&lt;/span&gt; RouteData());

&lt;span class="rem"&gt;// initialize the controller's ControllerContext&lt;/span&gt;
_controller.ControllerContext = &lt;span class="kwrd"&gt;new&lt;/span&gt; ControllerContext(requestContext, _controller);&lt;/pre&gt;&lt;img src="http://feeds.feedburner.com/~r/JohnRummell/~4/gn6Xt3HTFhs" height="1" width="1"/&gt;</description>
      <link>http://feedproxy.google.com/~r/JohnRummell/~3/gn6Xt3HTFhs/post.aspx</link>
      <author>jrummell</author>
      <comments>http://john.rummell.info/john/blog/post/Mocking-ControllerUser.aspx#comment</comments>
      <guid isPermaLink="false">http://john.rummell.info/john/blog/post.aspx?id=d7cdcd87-52b7-4714-9f0b-961c07d8b8b0</guid>
      <pubDate>Thu, 17 Sep 2009 21:26:42 -0400</pubDate>
      <category>ASP.Net</category>
      <dc:publisher>jrummell</dc:publisher>
      <pingback:server>http://john.rummell.info/john/blog/pingback.axd</pingback:server>
      <pingback:target>http://john.rummell.info/john/blog/post.aspx?id=d7cdcd87-52b7-4714-9f0b-961c07d8b8b0</pingback:target>
      <slash:comments>0</slash:comments>
      <trackback:ping>http://john.rummell.info/john/blog/trackback.axd?id=d7cdcd87-52b7-4714-9f0b-961c07d8b8b0</trackback:ping>
      <wfw:comment>http://john.rummell.info/john/blog/post/Mocking-ControllerUser.aspx#comment</wfw:comment>
      <wfw:commentRss>http://john.rummell.info/john/blog/syndication.axd?post=d7cdcd87-52b7-4714-9f0b-961c07d8b8b0</wfw:commentRss>
    <feedburner:origLink>http://john.rummell.info/john/blog/post.aspx?id=d7cdcd87-52b7-4714-9f0b-961c07d8b8b0</feedburner:origLink></item>
    <item>
      <title>Apply the same CSS class to all validators in a web project</title>
      <description>&lt;p&gt;I recently had to add a CSS class to all validators in an ASP.NET web application.&amp;#160; I started with the theme’s &lt;a href="http://msdn.microsoft.com/en-us/library/ykzx33wh.aspx" target="_blank"&gt;skin&lt;/a&gt; file:&lt;/p&gt;  &lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;asp:CompareValidator&lt;/span&gt; &lt;span class="attr"&gt;runat&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;server&amp;quot;&lt;/span&gt; 
    &lt;span class="attr"&gt;CssClass&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;error&amp;quot;&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:CustomValidator&lt;/span&gt; &lt;span class="attr"&gt;runat&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;server&amp;quot;&lt;/span&gt; 
    &lt;span class="attr"&gt;CssClass&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;error&amp;quot;&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:RequiredFieldValidator&lt;/span&gt; &lt;span class="attr"&gt;runat&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;server&amp;quot;&lt;/span&gt; 
    &lt;span class="attr"&gt;CssClass&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;error&amp;quot;&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;belCommon:ZipCodeValidator&lt;/span&gt; &lt;span class="attr"&gt;runat&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;server&amp;quot;&lt;/span&gt; 
    &lt;span class="attr"&gt;CssClass&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;error&amp;quot;&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;belCommon:PhoneNumberValidator&lt;/span&gt; &lt;span class="attr"&gt;runat&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;server&amp;quot;&lt;/span&gt; 
    &lt;span class="attr"&gt;CssClass&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;error&amp;quot;&lt;/span&gt; &lt;span class="kwrd"&gt;/&amp;gt;&lt;/span&gt;&lt;/pre&gt;

&lt;p&gt;But what if I decide to use another validator down the road? I would have to remember to add it to the skin. Knowing that I was bound to forget, I sought out another method. After doing some digging, I found that ASP.NET generates a JavaScript variable called Page_Validators. This is an array of all the validator span elements on the current page. Now that I have access to the spans, I could write a script in the site’s &lt;a href="http://msdn.microsoft.com/en-us/library/wtxbf3hh.aspx" target="_blank"&gt;Master Page&lt;/a&gt; to apply the class:&lt;/p&gt;

&lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;if&lt;/span&gt; (Page_Validators != &lt;span class="kwrd"&gt;null&lt;/span&gt;)
{
    &lt;span class="kwrd"&gt;for&lt;/span&gt; (i = 0; i &amp;lt; Page_Validators.length; i++)
    {
        Page_Validators[i].className = &lt;span class="str"&gt;&amp;quot;error&amp;quot;&lt;/span&gt;;
    }
}&lt;/pre&gt;

&lt;p&gt;To have it run when the page is loaded, I added it as an &lt;a href="http://msdn.microsoft.com/en-us/library/bb397532.aspx" target="_blank"&gt;Sys.Application.init&lt;/a&gt; handler:&lt;/p&gt;

&lt;pre class="csharpcode"&gt;Sys.Application.add_init(&lt;span class="kwrd"&gt;function&lt;/span&gt;(sender, args)
{
    &lt;span class="kwrd"&gt;if&lt;/span&gt; (Page_Validators != &lt;span class="kwrd"&gt;null&lt;/span&gt;)
    {
        &lt;span class="kwrd"&gt;for&lt;/span&gt; (i = 0; i &amp;lt; Page_Validators.length; i++)
        {
            Page_Validators[i].className = &lt;span class="str"&gt;&amp;quot;error&amp;quot;&lt;/span&gt;;
        }
    }
});&lt;/pre&gt;

&lt;p&gt;You could also use jQuery’s &lt;a href="http://docs.jquery.com/Events/ready#fn" target="_blank"&gt;document.ready&lt;/a&gt; handler:&lt;/p&gt;

&lt;pre class="csharpcode"&gt;$(document).ready(&lt;span class="kwrd"&gt;function&lt;/span&gt;()
{
    &lt;span class="kwrd"&gt;if&lt;/span&gt; (Page_Validators != &lt;span class="kwrd"&gt;null&lt;/span&gt;)
    {
        &lt;span class="kwrd"&gt;for&lt;/span&gt; (i = 0; i &amp;lt; Page_Validators.length; i++)
        {
            Page_Validators[i].className = &lt;span class="str"&gt;&amp;quot;error&amp;quot;&lt;/span&gt;;
        }
    }
});&lt;/pre&gt;&lt;img src="http://feeds.feedburner.com/~r/JohnRummell/~4/SqZupjRXBKU" height="1" width="1"/&gt;</description>
      <link>http://feedproxy.google.com/~r/JohnRummell/~3/SqZupjRXBKU/post.aspx</link>
      <author>jrummell</author>
      <comments>http://john.rummell.info/john/blog/post/Apply-the-same-CSS-class-to-all-validators-in-a-web-project.aspx#comment</comments>
      <guid isPermaLink="false">http://john.rummell.info/john/blog/post.aspx?id=d4e374a9-41ac-4dba-9a72-5d054227f4ad</guid>
      <pubDate>Sun, 16 Aug 2009 14:33:01 -0400</pubDate>
      <category>ASP.Net</category>
      <dc:publisher>jrummell</dc:publisher>
      <pingback:server>http://john.rummell.info/john/blog/pingback.axd</pingback:server>
      <pingback:target>http://john.rummell.info/john/blog/post.aspx?id=d4e374a9-41ac-4dba-9a72-5d054227f4ad</pingback:target>
      <slash:comments>0</slash:comments>
      <trackback:ping>http://john.rummell.info/john/blog/trackback.axd?id=d4e374a9-41ac-4dba-9a72-5d054227f4ad</trackback:ping>
      <wfw:comment>http://john.rummell.info/john/blog/post/Apply-the-same-CSS-class-to-all-validators-in-a-web-project.aspx#comment</wfw:comment>
      <wfw:commentRss>http://john.rummell.info/john/blog/syndication.axd?post=d4e374a9-41ac-4dba-9a72-5d054227f4ad</wfw:commentRss>
    <feedburner:origLink>http://john.rummell.info/john/blog/post.aspx?id=d4e374a9-41ac-4dba-9a72-5d054227f4ad</feedburner:origLink></item>
    <item>
      <title>xVal with WebForms Part 2</title>
      <description>&lt;p&gt;Since my &lt;a href="http://john.rummell.info/john/blog/post/xVal-with-WebForms.aspx"&gt;last post&lt;/a&gt;, I’ve completely rethought and re-implemented my take on &lt;a href="http://xval.codeplex.com/" target="_blank"&gt;xVal&lt;/a&gt; for WebForms. If you’re not familiar with xVal, stop now and read the &lt;a href="http://blog.codeville.net/2009/01/10/xval-a-validation-framework-for-aspnet-mvc/" target="_blank"&gt;tutorial&lt;/a&gt;. Now that you’re back, lets talk about xVal and WebForms.&lt;/p&gt;  &lt;h2&gt;Model&lt;/h2&gt;  &lt;p&gt;This is the model we’ll be using (you should recognize it from the xVal tutorial):&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; Booking
{
    [Required]
    [StringLength(15)]
    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt; ClientName { get; set; }

    [Range(1, 20)]
    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;int&lt;/span&gt; NumberOfGuests { get; set; }

    [Required]
    [DataType(DataType.Date)]
    &lt;span class="kwrd"&gt;public&lt;/span&gt; DateTime ArrivalDate { get; set; }
}&lt;/pre&gt;

&lt;h2&gt;Form&lt;/h2&gt;

&lt;p&gt;And here is the form:&lt;/p&gt;

&lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;asp:ValidationSummary&lt;/span&gt; &lt;span class="attr"&gt;ID&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;valSummary&amp;quot;&lt;/span&gt; &lt;span class="attr"&gt;runat&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;server&amp;quot;&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;label&lt;/span&gt; &lt;span class="attr"&gt;for&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;txtClientName&amp;quot;&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
    Your name:&lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;label&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:TextBox&lt;/span&gt; &lt;span class="attr"&gt;ID&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;txtClientName&amp;quot;&lt;/span&gt; &lt;span class="attr"&gt;runat&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;server&amp;quot;&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;label&lt;/span&gt; &lt;span class="attr"&gt;for&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;txtNumberOfGuests&amp;quot;&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
    Number of guests:&lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;label&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:TextBox&lt;/span&gt; &lt;span class="attr"&gt;ID&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;txtNumberOfGuests&amp;quot;&lt;/span&gt; &lt;span class="attr"&gt;runat&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;server&amp;quot;&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;label&lt;/span&gt; &lt;span class="attr"&gt;for&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;txtArrivalDate&amp;quot;&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
    Arrival date:&lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;label&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:TextBox&lt;/span&gt; &lt;span class="attr"&gt;ID&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;txtArrivalDate&amp;quot;&lt;/span&gt; &lt;span class="attr"&gt;runat&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;server&amp;quot;&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:Button&lt;/span&gt; &lt;span class="attr"&gt;ID&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;btnSubmit&amp;quot;&lt;/span&gt; &lt;span class="attr"&gt;runat&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;server&amp;quot;&lt;/span&gt; &lt;span class="attr"&gt;Text&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;Submit&amp;quot;&lt;/span&gt; &lt;span class="attr"&gt;OnClick&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;btnSubmit_Click&amp;quot;&lt;/span&gt; &lt;span class="kwrd"&gt;/&amp;gt;&lt;/span&gt;&lt;/pre&gt;

&lt;h2&gt;ModelValidator&lt;/h2&gt;

&lt;p&gt;My first try at validation was adding a validator control for each input field. After playing with it a bit, I decided that it would be better to have one validator for the entire model. This control defines the model’s type (ModelType), and then maps each property (PropertyName) to an input control (ControlToValidate).&lt;/p&gt;

&lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;val:ModelValidator&lt;/span&gt; &lt;span class="attr"&gt;ID&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;valBooking&amp;quot;&lt;/span&gt; &lt;span class="attr"&gt;runat&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;server&amp;quot;&lt;/span&gt; &lt;span class="attr"&gt;ModelType&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;xVal.WebForms.Demo.Booking, xVal.WebForms.Demo&amp;quot;&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;ModelProperties&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;val:ModelProperty&lt;/span&gt; &lt;span class="attr"&gt;PropertyName&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;ClientName&amp;quot;&lt;/span&gt; &lt;span class="attr"&gt;ControlToValidate&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;txtClientName&amp;quot;&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;val:ModelProperty&lt;/span&gt; &lt;span class="attr"&gt;PropertyName&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;NumberOfGuests&amp;quot;&lt;/span&gt; &lt;span class="attr"&gt;ControlToValidate&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;txtNumberOfGuests&amp;quot;&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;val:ModelProperty&lt;/span&gt; &lt;span class="attr"&gt;PropertyName&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;ArrivalDate&amp;quot;&lt;/span&gt; &lt;span class="attr"&gt;ControlToValidate&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;txtArrivalDate&amp;quot;&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;ModelProperties&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;val:ModelValidator&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;

&lt;h2&gt;ControlToValidate&lt;/h2&gt;

&lt;p&gt;The biggest challenge was figuring out how to reference the input controls by given ID instead of by the elementPrefix + PropertyName convention. In other words, MVC xVal assumes that your ClientName input control ID is booking.ClientName, where booking is the elementPrefix and ClientName is the name of the property. This doesn’t work out so well with web forms and generated IDs. I got around this with the ModelProperties collection of ModelValidator. Then I updated the json formatted rule script to include each property’s control ID.&lt;/p&gt;

&lt;h2&gt;Complete Source and Demo&lt;/h2&gt;

&lt;p&gt;Get the &lt;a href="http://xvalwebforms.codeplex.com/Release/ProjectReleases.aspx?ReleaseId=31487" target="_blank"&gt;complete source&lt;/a&gt; (with Bookings demo) at the &lt;a href="http://xvalwebforms.codeplex.com/" target="_blank"&gt;xVal.WebForms&lt;/a&gt; project page on CodePlex.&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/JohnRummell/~4/_U9fBWQmkKQ" height="1" width="1"/&gt;</description>
      <link>http://feedproxy.google.com/~r/JohnRummell/~3/_U9fBWQmkKQ/post.aspx</link>
      <author>jrummell</author>
      <comments>http://john.rummell.info/john/blog/post/xVal-with-WebForms-Part-2.aspx#comment</comments>
      <guid isPermaLink="false">http://john.rummell.info/john/blog/post.aspx?id=4b1e3234-3c40-45ad-a9cb-c1004ed0a2d5</guid>
      <pubDate>Wed, 12 Aug 2009 22:17:01 -0400</pubDate>
      <category>ASP.Net</category>
      <dc:publisher>jrummell</dc:publisher>
      <pingback:server>http://john.rummell.info/john/blog/pingback.axd</pingback:server>
      <pingback:target>http://john.rummell.info/john/blog/post.aspx?id=4b1e3234-3c40-45ad-a9cb-c1004ed0a2d5</pingback:target>
      <slash:comments>2</slash:comments>
      <trackback:ping>http://john.rummell.info/john/blog/trackback.axd?id=4b1e3234-3c40-45ad-a9cb-c1004ed0a2d5</trackback:ping>
      <wfw:comment>http://john.rummell.info/john/blog/post/xVal-with-WebForms-Part-2.aspx#comment</wfw:comment>
      <wfw:commentRss>http://john.rummell.info/john/blog/syndication.axd?post=4b1e3234-3c40-45ad-a9cb-c1004ed0a2d5</wfw:commentRss>
    <feedburner:origLink>http://john.rummell.info/john/blog/post.aspx?id=4b1e3234-3c40-45ad-a9cb-c1004ed0a2d5</feedburner:origLink></item>
    <item>
      <title>xVal with WebForms</title>
      <description>&lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;Update&lt;/strong&gt;: See &lt;a href="http://john.rummell.info/john/blog/post/xVal-with-WebForms-Part-2.aspx"&gt;xVal with WebForms Part 2&lt;/a&gt; for a better implementation.&lt;/p&gt;  &lt;h2&gt;What is xVal and why would anyone want to use it? &lt;/h2&gt;  &lt;blockquote&gt;   &lt;p&gt;xVal is a validation framework for ASP.NET MVC applications. It makes it easy to link up your choice of server-side validation mechanism with your choice of client-side validation library, neatly fitting both into ASP.NET MVC architecture and conventions.&lt;/p&gt; &lt;/blockquote&gt; &lt;img src="http://blog.codeville.net/wp-content/uploads/2009/01/image-thumb.png" /&gt;   &lt;p&gt;&lt;/p&gt;  &lt;p&gt;See the &lt;a href="http://xval.codeplex.com/" target="_blank"&gt;CodePlex&lt;/a&gt; page for more information.&lt;/p&gt;  &lt;p&gt;Basically, what xVal does, is take your validation rules and perform server and client side validation based on those rules. That means you don’t have to duplicate model validation at the page level. Now you’re probably thinking, “Isn’t it for MVC?”.&amp;#160; It is. But I, and at least &lt;a href="http://xval.codeplex.com/Thread/View.aspx?ThreadId=60906" target="_blank"&gt;two others&lt;/a&gt;, would like to take advantage of xVal’s features in traditional ASP.NET WebForm projects. &lt;/p&gt;  &lt;h2&gt;Getting it to work with WebForms&lt;/h2&gt;  &lt;p&gt;I finally found some time last night to see what it would take to get xVal working in an ASP.NET Web Application Project.&amp;#160; After a few hours I had something. I only needed to add two classes on top of xVal, DataAnnotationsValidationRunner and ModelValidator.&lt;/p&gt;  &lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;static&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; DataAnnotationsValidationRunner
{
    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;static&lt;/span&gt; IEnumerable&amp;lt;ErrorInfo&amp;gt; GetErrors(&lt;span class="kwrd"&gt;object&lt;/span&gt; instance, &lt;span class="kwrd"&gt;string&lt;/span&gt; propertyName)
    {
        &lt;span class="kwrd"&gt;return&lt;/span&gt; from prop &lt;span class="kwrd"&gt;in&lt;/span&gt; TypeDescriptor.GetProperties(instance).Cast&amp;lt;PropertyDescriptor&amp;gt;()
               from attribute &lt;span class="kwrd"&gt;in&lt;/span&gt; prop.Attributes.OfType&amp;lt;ValidationAttribute&amp;gt;()
               &lt;span class="kwrd"&gt;where&lt;/span&gt; prop.Name == propertyName &amp;amp;&amp;amp; !attribute.IsValid(prop.GetValue(instance))
               select &lt;span class="kwrd"&gt;new&lt;/span&gt; ErrorInfo(prop.Name, attribute.FormatErrorMessage(&lt;span class="kwrd"&gt;string&lt;/span&gt;.Empty), instance);
    }
}&lt;/pre&gt;

&lt;p&gt;This is based on the implementation in the &lt;a href="http://blog.codeville.net/2009/01/10/xval-a-validation-framework-for-aspnet-mvc/" target="_blank"&gt;xVal demo&lt;/a&gt;. I added a second parameter to GetErrors() that allows the runner to check a specific property.&lt;/p&gt;

&lt;p&gt;&amp;#160;&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; ModelValidator : BaseValidator
{
    &lt;span class="kwrd"&gt;private&lt;/span&gt; ValidationInfo _validationInfo;

    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt; ModelType
    {
        get { &lt;span class="kwrd"&gt;return&lt;/span&gt; (&lt;span class="kwrd"&gt;string&lt;/span&gt;) ViewState[&lt;span class="str"&gt;&amp;quot;ModelType&amp;quot;&lt;/span&gt;]; }
        set { ViewState[&lt;span class="str"&gt;&amp;quot;ModelType&amp;quot;&lt;/span&gt;] = &lt;span class="kwrd"&gt;value&lt;/span&gt;; }
    }

    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt; ModelProperty
    {
        get { &lt;span class="kwrd"&gt;return&lt;/span&gt; (&lt;span class="kwrd"&gt;string&lt;/span&gt;) ViewState[&lt;span class="str"&gt;&amp;quot;ModelProperty&amp;quot;&lt;/span&gt;]; }
        set { ViewState[&lt;span class="str"&gt;&amp;quot;ModelProperty&amp;quot;&lt;/span&gt;] = &lt;span class="kwrd"&gt;value&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;bool&lt;/span&gt; EvaluateIsValid()
    {
        Type type = Type.GetType(ModelType);

        &lt;span class="kwrd"&gt;object&lt;/span&gt; model = Activator.CreateInstance(type);

        IEnumerable&amp;lt;ErrorInfo&amp;gt; errors = DataAnnotationsValidationRunner.GetErrors(model, ModelProperty);

        StringBuilder errorBuilder = &lt;span class="kwrd"&gt;new&lt;/span&gt; StringBuilder();
        &lt;span class="kwrd"&gt;foreach&lt;/span&gt; (ErrorInfo error &lt;span class="kwrd"&gt;in&lt;/span&gt; errors)
        {
            errorBuilder.AppendLine(error.ErrorMessage);
        }

        ErrorMessage = errorBuilder.ToString();

        &lt;span class="kwrd"&gt;return&lt;/span&gt; ErrorMessage.Length &amp;gt; 0;
    }

    &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; Render(HtmlTextWriter writer)
    {
        Type type = Type.GetType(ModelType);
        _validationInfo = &lt;span class="kwrd"&gt;new&lt;/span&gt; ValidationInfo(ActiveRuleProviders.GetRulesForType(type), String.Empty);

        writer.Write(_validationInfo.ToString());
    }
}&lt;/pre&gt;

&lt;p&gt;This is the ASP.NET WebForms version of &amp;lt;%= Html.ClientSideValidation&amp;lt;Booking&amp;gt;(&amp;quot;booking&amp;quot;) %&amp;gt;, an implementation of &lt;a href="http://msdn.microsoft.com/en-us/library/system.web.ui.webcontrols.basevalidator.aspx" target="_blank"&gt;BaseValidator&lt;/a&gt;. It uses &lt;a href="http://xval.codeplex.com/sourcecontrol/changeset/view/21650?projectName=xval#260910" target="_blank"&gt;ValidationInfo&lt;/a&gt; for rendering the client validation script and DataAnnotationsValidationRunner for the server side validation.&lt;/p&gt;

&lt;p&gt;You can use it like this:&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; Customer
{
    [Required, StringLength(20)]
    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt; Name { get; set; }
}&lt;/pre&gt;

&lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;script&lt;/span&gt; &lt;span class="attr"&gt;type&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;text/javascript&amp;quot;&lt;/span&gt; &lt;span class="attr"&gt;src&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;xVal.AspNetNative.js&amp;quot;&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;script&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;
    &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;ID&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;lblName&amp;quot;&lt;/span&gt; &lt;span class="attr"&gt;runat&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;server&amp;quot;&lt;/span&gt; &lt;span class="attr"&gt;AssociatedControlID&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;Name&amp;quot;&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;Customer Name:&lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;asp:Label&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:TextBox&lt;/span&gt; &lt;span class="attr"&gt;ID&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;Name&amp;quot;&lt;/span&gt; &lt;span class="attr"&gt;runat&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;server&amp;quot;&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;val:ModelValidator&lt;/span&gt; &lt;span class="attr"&gt;ID&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;validator&amp;quot;&lt;/span&gt; &lt;span class="attr"&gt;runat&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;server&amp;quot;&lt;/span&gt; &lt;span class="attr"&gt;ModelType&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;xVal.WebForms.Test.Customer, xVal.WebForms.Test&amp;quot;&lt;/span&gt;
        &lt;span class="attr"&gt;ModelProperty&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;Name&amp;quot;&lt;/span&gt; &lt;span class="attr"&gt;ControlToValidate&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;Name&amp;quot;&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;
&lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;asp:Button&lt;/span&gt; &lt;span class="attr"&gt;ID&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;btnSubmit&amp;quot;&lt;/span&gt; &lt;span class="attr"&gt;runat&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;server&amp;quot;&lt;/span&gt; &lt;span class="attr"&gt;Text&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;Submit&amp;quot;&lt;/span&gt; &lt;span class="kwrd"&gt;/&amp;gt;&lt;/span&gt;&lt;/pre&gt;

&lt;p&gt;There are a few things to note here:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;The TextBox ID must be the same as the model’s property name. This is because the xVal javascript is expecting the control’s ID to be PropertyName or prefix.PropertyName (MVC naming conventions). This could probably be fixed by modifying the &lt;a href="http://xval.codeplex.com/sourcecontrol/changeset/view/21650?projectName=xval#279841" target="_blank"&gt;client&lt;/a&gt; &lt;a href="http://xval.codeplex.com/sourcecontrol/changeset/view/21650?projectName=xval#279846" target="_blank"&gt;side&lt;/a&gt; plugins. &lt;/li&gt;

  &lt;li&gt;The ControlToValidate property on ModelValidator doesn’t do anything, but it’s required by any implementation of BaseValidator (it will throw an exception if you omit it). This could probably be avoided by having ModelValidator inherit from &lt;a href="http://msdn.microsoft.com/en-us/library/system.web.ui.control.aspx" target="_blank"&gt;Control&lt;/a&gt; and implement &lt;a href="http://msdn.microsoft.com/en-us/library/system.web.ui.ivalidator.aspx" target="_blank"&gt;IValidator&lt;/a&gt; instead. &lt;/li&gt;

  &lt;li&gt;xVal depends on System.Web.Mvc. It uses the TagBuilder and ModelState classes in a &lt;a href="http://xval.codeplex.com/sourcecontrol/changeset/view/21650?projectName=xval#260910" target="_blank"&gt;few&lt;/a&gt; &lt;a href="http://xval.codeplex.com/sourcecontrol/changeset/view/21650?projectName=xval#72733" target="_blank"&gt;places&lt;/a&gt;. There’s really now way around this without refactoring the MVC specific stuff into a separate assembly. &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I’ll post an update when I have a chance to work on the first two items.&lt;/p&gt;

&lt;div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:fb3a1972-4489-4e52-abe7-25a00bb07fdf:cae34c0a-e527-43b6-873e-c25784f5fccd" class="wlWriterEditableSmartContent"&gt;&lt;p&gt; &lt;a href="http://john.rummell.info/john/blog/file.axd?file=WindowsLiveWriter/xValwithWebForms/08AAA814/xVal.WebForms.zip" target="_blank"&gt;Download&lt;/a&gt;&lt;/p&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/JohnRummell/~4/VTL2RmnwRVc" height="1" width="1"/&gt;</description>
      <link>http://feedproxy.google.com/~r/JohnRummell/~3/VTL2RmnwRVc/post.aspx</link>
      <author>jrummell</author>
      <comments>http://john.rummell.info/john/blog/post/xVal-with-WebForms.aspx#comment</comments>
      <guid isPermaLink="false">http://john.rummell.info/john/blog/post.aspx?id=e8593338-ee21-454b-972f-bc088901472d</guid>
      <pubDate>Wed, 15 Jul 2009 22:32:00 -0400</pubDate>
      <category>ASP.Net</category>
      <dc:publisher>jrummell</dc:publisher>
      <pingback:server>http://john.rummell.info/john/blog/pingback.axd</pingback:server>
      <pingback:target>http://john.rummell.info/john/blog/post.aspx?id=e8593338-ee21-454b-972f-bc088901472d</pingback:target>
      <slash:comments>2</slash:comments>
      <trackback:ping>http://john.rummell.info/john/blog/trackback.axd?id=e8593338-ee21-454b-972f-bc088901472d</trackback:ping>
      <wfw:comment>http://john.rummell.info/john/blog/post/xVal-with-WebForms.aspx#comment</wfw:comment>
      <wfw:commentRss>http://john.rummell.info/john/blog/syndication.axd?post=e8593338-ee21-454b-972f-bc088901472d</wfw:commentRss>
    <feedburner:origLink>http://john.rummell.info/john/blog/post.aspx?id=e8593338-ee21-454b-972f-bc088901472d</feedburner:origLink></item>
    <item>
      <title>Send a Completed Form Email Without a StringBuilder</title>
      <description>&lt;p&gt;
Have you ever had to create a large web form for users to fill out and then receive an email copy after its submitted? That can be tedious work. The first few times I did it, I used a &lt;a href="http://msdn.microsoft.com/en-us/library/system.text.stringbuilder.aspx" target="_blank"&gt;StringBuilder&lt;/a&gt; to build the email HTML one control at a time. Later, I viewed the HTML output of the page and replaced all input controls with spans, and then put that HTML in a StringBuilder. Either of these methods work, but it gets real annoying when I later have to add a field or two to the form and therefore to the email HTML. 
&lt;/p&gt;
  
&lt;p&gt;
I knew there had to be a way to do this programmatically without copying and pasting into a StringBuilder. Well, there is. Here&amp;rsquo;s a rather common code snippet that does just this:
&lt;/p&gt;
  
&lt;pre class="csharpcode"&gt;
&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;static&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt; GetRenderedHtml(&lt;span class="kwrd"&gt;this&lt;/span&gt; Control control)
{
StringBuilder sbHtml = &lt;span class="kwrd"&gt;new&lt;/span&gt; StringBuilder();
&lt;span class="kwrd"&gt;using&lt;/span&gt; (StringWriter stringWriter = &lt;span class="kwrd"&gt;new&lt;/span&gt; StringWriter(sbHtml))
&lt;span class="kwrd"&gt;using&lt;/span&gt; (HtmlTextWriter textWriter = &lt;span class="kwrd"&gt;new&lt;/span&gt; HtmlTextWriter(stringWriter))
{
control.RenderControl(textWriter);
}
&lt;span class="kwrd"&gt;return&lt;/span&gt; sbHtml.ToString();
}
&lt;/pre&gt;
&lt;p&gt;
This is great! Let&amp;rsquo;s try it out on this simple example:
&lt;/p&gt;
&lt;pre class="csharpcode"&gt;
&lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;div&lt;/span&gt; &lt;span class="attr"&gt;id&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;divForm&amp;quot;&lt;/span&gt; &lt;span class="attr"&gt;runat&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;server&amp;quot;&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;fieldset&lt;/span&gt; &lt;span class="attr"&gt;class&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;inputArea&amp;quot;&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;legend&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;Contact&lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;legend&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:Label&lt;/span&gt; &lt;span class="attr"&gt;runat&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;server&amp;quot;&lt;/span&gt; &lt;span class="attr"&gt;AssociatedControlID&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;txtName&amp;quot;&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;asp:Label&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:TextBox&lt;/span&gt; &lt;span class="attr"&gt;runat&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;server&amp;quot;&lt;/span&gt; &lt;span class="attr"&gt;ID&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;txtName&amp;quot;&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:Label&lt;/span&gt; &lt;span class="attr"&gt;runat&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;server&amp;quot;&lt;/span&gt; &lt;span class="attr"&gt;AssociatedControlID&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;txtEmail&amp;quot;&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
Email&lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;asp:Label&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:TextBox&lt;/span&gt; &lt;span class="attr"&gt;runat&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;server&amp;quot;&lt;/span&gt; &lt;span class="attr"&gt;ID&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;txtEmail&amp;quot;&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:Label&lt;/span&gt; &lt;span class="attr"&gt;runat&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;server&amp;quot;&lt;/span&gt; &lt;span class="attr"&gt;AssociatedControlID&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;txtWebsite&amp;quot;&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
Website&lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;asp:Label&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:TextBox&lt;/span&gt; &lt;span class="attr"&gt;runat&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;server&amp;quot;&lt;/span&gt; &lt;span class="attr"&gt;ID&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;txtWebsite&amp;quot;&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:Label&lt;/span&gt; &lt;span class="attr"&gt;runat&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;server&amp;quot;&lt;/span&gt; &lt;span class="attr"&gt;AssociatedControlID&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;txtComment&amp;quot;&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
Comment&lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;asp:Label&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:TextBox&lt;/span&gt; &lt;span class="attr"&gt;runat&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;server&amp;quot;&lt;/span&gt; &lt;span class="attr"&gt;ID&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;txtComment&amp;quot;&lt;/span&gt; &lt;span class="attr"&gt;TextMode&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;MultiLine&amp;quot;&lt;/span&gt; &lt;span class="attr"&gt;Rows&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;4&amp;quot;&lt;/span&gt; &lt;span class="attr"&gt;cols&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;30&amp;quot;&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:Button&lt;/span&gt; &lt;span class="attr"&gt;ID&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;btnSubmit&amp;quot;&lt;/span&gt; &lt;span class="attr"&gt;runat&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;server&amp;quot;&lt;/span&gt; &lt;span class="attr"&gt;Text&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;Submit&amp;quot;&lt;/span&gt; &lt;span class="attr"&gt;OnClick&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;btnSubmit_Click&amp;quot;&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;fieldset&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;
&lt;/pre&gt;
&lt;p&gt;
&amp;nbsp;
&lt;/p&gt;
&lt;pre class="csharpcode"&gt;
&lt;span class="kwrd"&gt;protected&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; btnSubmit_Click(&lt;span class="kwrd"&gt;object&lt;/span&gt; sender, EventArgs e)
{
txtRenderedHtml.Text = divForm.GetRenderedHtml();
}
&lt;/pre&gt;
&lt;p&gt;
Here is what we get:
&lt;/p&gt;
&lt;h4&gt;&lt;em&gt;Control &amp;#39;txtName&amp;#39; of type &amp;#39;TextBox&amp;#39; must be placed inside a form tag with runat=server.&lt;/em&gt;&lt;/h4&gt;
&lt;p&gt;
So how do you get around that? Well, lets think about this. I&amp;rsquo;m trying to capture a form and render it as HTML to be included in an email, so I don&amp;rsquo;t want any &lt;a href="http://msdn.microsoft.com/en-us/library/system.web.ui.webcontrols.textbox.aspx" target="_blank"&gt;TextBoxes&lt;/a&gt;. Lets replace the TextBoxes (and any other editable controls) with &lt;a href="http://msdn.microsoft.com/en-us/library/system.web.ui.webcontrols.label.aspx" target="_blank"&gt;Labels&lt;/a&gt; and try again.
&lt;/p&gt;
&lt;pre class="csharpcode"&gt;
&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;static&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; ReplaceEditableControls(&lt;span class="kwrd"&gt;this&lt;/span&gt; Control control)
{
&lt;span class="rem"&gt;// don&amp;#39;t bother with controls that aren&amp;#39;t visible&lt;/span&gt;
&lt;span class="kwrd"&gt;if&lt;/span&gt; (!control.Visible)
{
&lt;span class="kwrd"&gt;return&lt;/span&gt;;
}
ListControl listControl = control &lt;span class="kwrd"&gt;as&lt;/span&gt; ListControl;
IButtonControl buttonControl = control &lt;span class="kwrd"&gt;as&lt;/span&gt; IButtonControl;
IValidator validator = control &lt;span class="kwrd"&gt;as&lt;/span&gt; IValidator;
IEditableTextControl textControl = control &lt;span class="kwrd"&gt;as&lt;/span&gt; IEditableTextControl;
UpdatePanel updatePanel = control &lt;span class="kwrd"&gt;as&lt;/span&gt; UpdatePanel;
&lt;span class="kwrd"&gt;if&lt;/span&gt; (validator != &lt;span class="kwrd"&gt;null&lt;/span&gt; || buttonControl != &lt;span class="kwrd"&gt;null&lt;/span&gt;)
{
control.Visible = &lt;span class="kwrd"&gt;false&lt;/span&gt;;
}
&lt;span class="kwrd"&gt;else&lt;/span&gt; &lt;span class="kwrd"&gt;if&lt;/span&gt; (listControl != &lt;span class="kwrd"&gt;null&lt;/span&gt; &amp;amp;&amp;amp; listControl.SelectedItem != &lt;span class="kwrd"&gt;null&lt;/span&gt;)
{
Label label = &lt;span class="kwrd"&gt;new&lt;/span&gt; Label {Text = listControl.SelectedItem.Text, CssClass = &lt;span class="str"&gt;&amp;quot;text&amp;quot;&lt;/span&gt;};
Replace(listControl, label);
}
&lt;span class="kwrd"&gt;else&lt;/span&gt; &lt;span class="kwrd"&gt;if&lt;/span&gt; (textControl != &lt;span class="kwrd"&gt;null&lt;/span&gt;)
{
Label label = &lt;span class="kwrd"&gt;new&lt;/span&gt; Label {Text = textControl.Text, CssClass = &lt;span class="str"&gt;&amp;quot;text&amp;quot;&lt;/span&gt;};
Replace((Control) textControl, label);
}
&lt;span class="kwrd"&gt;else&lt;/span&gt; &lt;span class="kwrd"&gt;if&lt;/span&gt; (updatePanel != &lt;span class="kwrd"&gt;null&lt;/span&gt;)
{
&lt;span class="rem"&gt;// replace the update panel with a place holder&lt;/span&gt;
PlaceHolder holder = &lt;span class="kwrd"&gt;new&lt;/span&gt; PlaceHolder();
Control[] panelControls = &lt;span class="kwrd"&gt;new&lt;/span&gt; Control[updatePanel.ContentTemplateContainer.Controls.Count];
updatePanel.ContentTemplateContainer.Controls.CopyTo(panelControls, 0);
&lt;span class="kwrd"&gt;foreach&lt;/span&gt; (Control panelControl &lt;span class="kwrd"&gt;in&lt;/span&gt; panelControls)
{
holder.Controls.Add(panelControl);
}
ReplaceEditableControls(holder);
Replace(updatePanel, holder);
}
&lt;span class="kwrd"&gt;else&lt;/span&gt; &lt;span class="kwrd"&gt;if&lt;/span&gt; (control.HasControls())
{
Control[] controlsCopy = &lt;span class="kwrd"&gt;new&lt;/span&gt; Control[control.Controls.Count];
control.Controls.CopyTo(controlsCopy, 0);
&lt;span class="kwrd"&gt;foreach&lt;/span&gt; (Control controlCopy &lt;span class="kwrd"&gt;in&lt;/span&gt; controlsCopy)
{
ReplaceEditableControls(controlCopy);
}
}
}
&lt;/pre&gt;
&lt;p&gt;
There are a few things to note here. 
&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;
	&lt;p&gt;
	The check for &lt;a href="http://msdn.microsoft.com/en-us/library/system.web.ui.webcontrols.listcontrol.aspx" target="_blank"&gt;ListControl&lt;/a&gt; is before &lt;a href="http://msdn.microsoft.com/en-us/library/system.web.ui.ieditabletextcontrol.aspx" target="_blank"&gt;IEditableTextControl&lt;/a&gt; because of the way it implements IEditableTextControl. &lt;a href="http://msdn.microsoft.com/en-us/library/system.web.ui.webcontrols.listcontrol.text.aspx" target="_blank"&gt;ListControl.Text&lt;/a&gt; returns &lt;a href="http://msdn.microsoft.com/en-us/library/system.web.ui.webcontrols.listcontrol.selectedvalue.aspx" target="_blank"&gt;ListControl.SelectedValue&lt;/a&gt;, but &lt;a href="http://msdn.microsoft.com/en-us/library/system.web.ui.webcontrols.listcontrol.selectedvalue.aspx" target="_blank"&gt;ListControl.SelectedItem.Text&lt;/a&gt; makes more sense.
	&lt;/p&gt;
	&lt;/li&gt;
	&lt;li&gt;
	&lt;p&gt;
	&lt;a href="http://msdn.microsoft.com/en-us/library/system.web.ui.updatepanel.aspx" target="_blank"&gt;UpdatePanels&lt;/a&gt; are a special case because of &lt;a href="http://msdn.microsoft.com/en-us/library/system.web.ui.updatepanel.contenttemplate.aspx" target="_blank"&gt;ContentTemplate&lt;/a&gt;. They are replaced with a &lt;a href="http://msdn.microsoft.com/en-us/library/system.web.ui.webcontrols.placeholder.aspx" target="_blank"&gt;PlaceHolder&lt;/a&gt; and then the method is recursively called on each child control.
	&lt;/p&gt;
	&lt;/li&gt;
	&lt;li&gt;
	&lt;p&gt;
	Finally, if the control has a control collection of its own, a recursive call is made on each child control.
	&lt;/p&gt;
	&lt;/li&gt;
	&lt;li&gt;
	&lt;p&gt;
	Notice that the control collection is copied to an array before making the recursive call. This is because the control collection is modified and you can&amp;rsquo;t modify a collection while iterating it. Well, you can, but you will have problems.
	&lt;/p&gt;
	&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;
Now we can change the button handler to:
&lt;/p&gt;
&lt;pre class="csharpcode"&gt;
&lt;span class="kwrd"&gt;protected&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; btnSubmit_Click(&lt;span class="kwrd"&gt;object&lt;/span&gt; sender, EventArgs e)
{
divForm.ReplaceEditableControls();
}
&lt;/pre&gt;
&lt;pre class="csharpcode"&gt;
Which will render the following HTML:
&lt;/pre&gt;
&lt;pre class="csharpcode"&gt;
&lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;div&lt;/span&gt; &lt;span class="attr"&gt;id&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;divForm&amp;quot;&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;fieldset&lt;/span&gt; &lt;span class="attr"&gt;class&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;inputArea&amp;quot;&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;legend&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;Contact&lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;legend&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;label&lt;/span&gt; &lt;span class="attr"&gt;for&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;txtName&amp;quot;&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;label&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;id&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;txtName&amp;quot;&lt;/span&gt; &lt;span class="attr"&gt;class&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;text&amp;quot;&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;John Rummell&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;label&lt;/span&gt; &lt;span class="attr"&gt;for&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;txtEmail&amp;quot;&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
Email&lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;label&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;id&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;txtEmail&amp;quot;&lt;/span&gt; &lt;span class="attr"&gt;class&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;text&amp;quot;&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;jrummell@example.com&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;label&lt;/span&gt; &lt;span class="attr"&gt;for&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;txtWebsite&amp;quot;&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
Website&lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;label&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;id&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;txtWebsite&amp;quot;&lt;/span&gt; &lt;span class="attr"&gt;class&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;text&amp;quot;&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;john.rummell.info&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;label&lt;/span&gt; &lt;span class="attr"&gt;for&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;txtComment&amp;quot;&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
Comment&lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;label&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;id&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;txtComment&amp;quot;&lt;/span&gt; &lt;span class="attr"&gt;class&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;text&amp;quot;&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;Check out this new post!&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;fieldset&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;
&lt;/pre&gt;
&lt;p&gt;
&lt;span class="kwrd"&gt;To capture this as a string, just add a call to GetRenderedHtml:&lt;/span&gt;
&lt;/p&gt;
&lt;pre class="csharpcode"&gt;
&lt;span class="kwrd"&gt;protected&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; btnSubmit_Click(&lt;span class="kwrd"&gt;object&lt;/span&gt; sender, EventArgs e)
{
divForm.ReplaceEditableControls();
&lt;span class="kwrd"&gt;string&lt;/span&gt; html = divForm.GetRenderedHtml();
&lt;span class="rem"&gt;//TODO: send email&lt;/span&gt;
}
&lt;/pre&gt;
&lt;p&gt;
&amp;nbsp;
&lt;/p&gt;
&lt;div id="scid:fb3a1972-4489-4e52-abe7-25a00bb07fdf:1a9b69db-0844-4224-b751-117b2dba06c7" class="wlWriterEditableSmartContent" style="margin: 0px; padding: 0px; display: inline; float: none"&gt;
&lt;p&gt;
 &lt;a href="http://john.rummell.info/john/blog/file.axd?file=WindowsLiveWriter/SendaCompletedFormEmailWithoutaStringBui/6C3AE8D5/Blog.FormRender.zip" target="_blank"&gt;Download the example&lt;/a&gt;
&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;
&amp;nbsp;
&lt;/p&gt;
&lt;p&gt;
(The form style is a slight variation of &lt;a href="http://www.jankoatwarpspeed.com/post/2008/07/27/Enhance-your-input-fields-with-simple-CSS-tricks.aspx" target="_blank"&gt;Janko&amp;rsquo;s tutorial&lt;/a&gt;)
&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/JohnRummell/~4/T5K7TFy2F8U" height="1" width="1"/&gt;</description>
      <link>http://feedproxy.google.com/~r/JohnRummell/~3/T5K7TFy2F8U/post.aspx</link>
      <author>jrummell</author>
      <comments>http://john.rummell.info/john/blog/post/Send-a-Completed-Form-Email-Without-a-StringBuilder.aspx#comment</comments>
      <guid isPermaLink="false">http://john.rummell.info/john/blog/post.aspx?id=de61db04-cf3d-40d2-a890-fe07a2762bfc</guid>
      <pubDate>Mon, 29 Jun 2009 23:09:00 -0400</pubDate>
      <category>ASP.Net</category>
      <dc:publisher>jrummell</dc:publisher>
      <pingback:server>http://john.rummell.info/john/blog/pingback.axd</pingback:server>
      <pingback:target>http://john.rummell.info/john/blog/post.aspx?id=de61db04-cf3d-40d2-a890-fe07a2762bfc</pingback:target>
      <slash:comments>1</slash:comments>
      <trackback:ping>http://john.rummell.info/john/blog/trackback.axd?id=de61db04-cf3d-40d2-a890-fe07a2762bfc</trackback:ping>
      <wfw:comment>http://john.rummell.info/john/blog/post/Send-a-Completed-Form-Email-Without-a-StringBuilder.aspx#comment</wfw:comment>
      <wfw:commentRss>http://john.rummell.info/john/blog/syndication.axd?post=de61db04-cf3d-40d2-a890-fe07a2762bfc</wfw:commentRss>
    <feedburner:origLink>http://john.rummell.info/john/blog/post.aspx?id=de61db04-cf3d-40d2-a890-fe07a2762bfc</feedburner:origLink></item>
    <item>
      <title>jQuery/ASP.Net AJAX 1.0/3.5 gotcha</title>
      <description>&lt;p&gt;&lt;span class="Apple-style-span" style="font-weight: bold"&gt;Update&lt;/span&gt;: If you are curious as to why MS added the .d attribute, find out why at &lt;a href="http://encosia.com/2009/02/10/a-breaking-change-between-versions-of-aspnet-ajax/" target="_blank"&gt;Encosia&lt;/a&gt;.&lt;/p&gt;  &lt;p&gt;I was very frustrated the other day trying to figure out why a jQuery ajax call worked on my dev box but not on the server.&amp;#160; It looked something like this:&lt;/p&gt;  &lt;pre class="csharpcode"&gt;json(_serviceUrl, &lt;span class="str"&gt;&amp;quot;{}&amp;quot;&lt;/span&gt;, &lt;span class="kwrd"&gt;true&lt;/span&gt;,
    &lt;span class="kwrd"&gt;function&lt;/span&gt;(result) { fillSelect($(&lt;span class="str"&gt;&amp;quot;#ddlDepartment&amp;quot;&lt;/span&gt;)[0], result.d); },
    &lt;span class="kwrd"&gt;function&lt;/span&gt;(ajax) { &lt;span class="rem"&gt;/* handle error */&lt;/span&gt; });
    
&lt;span class="rem"&gt;// calls a json web service&lt;/span&gt;
&lt;span class="kwrd"&gt;function&lt;/span&gt; json(url, data, async, onSuccess, onFailed)
{
    $.ajax({
        async: async,
        type: &lt;span class="str"&gt;&amp;quot;POST&amp;quot;&lt;/span&gt;,
        url: url,
        data: data,
        contentType: &lt;span class="str"&gt;&amp;quot;application/json; charset=utf-8&amp;quot;&lt;/span&gt;,
        dataType: &lt;span class="str"&gt;&amp;quot;json&amp;quot;&lt;/span&gt;,
        success: onSuccess,
        error: onFailed
    });
}&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;(The code inside the &lt;strong&gt;json&lt;/strong&gt; function is straight from &lt;a href="http://encosia.com/" target="_blank"&gt;Dave Ward's&lt;/a&gt; post on &lt;a href="http://encosia.com/2008/03/27/using-jquery-to-consume-aspnet-json-web-services/"&gt;Using jQuery to Consume ASP.NET JSON Web Services&lt;/a&gt;. Dave's blog is an excellent resource full of information on jQuery, AJAX, ASP.Net and how to make them play nice together.)&lt;/p&gt;

&lt;p&gt;I figured out the problem was &lt;strong&gt;result.d;&lt;/strong&gt; on the server it was null, but on my machine it was a ListItem[], as expected. It turns out that on my machine, the web service at _&lt;strong&gt;serviceUrl&lt;/strong&gt; was compiled against .Net 3.5. while on the server it was compiled against .Net 2.0 with ASP.NET AJAX Extensions 1.0. In order to get it working on the server, I had to change &lt;strong&gt;result.d&lt;/strong&gt; to &lt;strong&gt;result&lt;/strong&gt;. Apparently they changed a few things in System.Web.Extensions v3.5. Unfortunately, I'm unable to install .Net 3.5 on the server. So I came up with this helper function to get things working in both 1.0 and 3.5:&lt;/p&gt;

&lt;pre class="csharpcode"&gt;&lt;span class="rem"&gt;// gets the ajaxResult. Returns ajaxResult.d is if it is not null, else ajaxResult.&lt;/span&gt;
&lt;span class="rem"&gt;// System.Web.Extensions v3.5 web services will result in ajaxResult.d while v1.0 will be ajaxResult.&lt;/span&gt;
&lt;span class="kwrd"&gt;function&lt;/span&gt; getResult(ajaxResult)
{
    &lt;span class="kwrd"&gt;return&lt;/span&gt; ajaxResult.d == &lt;span class="kwrd"&gt;null&lt;/span&gt; ? ajaxResult : ajaxResult.d;
}&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;So now after replacing &lt;strong&gt;result&lt;/strong&gt; with &lt;strong&gt;getResult(result),&lt;/strong&gt; the json call looks like this:&lt;/p&gt;

&lt;pre class="csharpcode"&gt;json(_serviceUrl, &lt;span class="str"&gt;&amp;quot;{}&amp;quot;&lt;/span&gt;, &lt;span class="kwrd"&gt;true&lt;/span&gt;,
    &lt;span class="kwrd"&gt;function&lt;/span&gt;(result) { fillSelect($(&lt;span class="str"&gt;&amp;quot;#ddlDepartment&amp;quot;&lt;/span&gt;)[0], getResult(result)); },
    &lt;span class="kwrd"&gt;function&lt;/span&gt;(ajax) { &lt;span class="rem"&gt;/* handle error */&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;Hopefully this will save someone out there some frustration!&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/JohnRummell/~4/IlTy890gMxQ" height="1" width="1"/&gt;</description>
      <link>http://feedproxy.google.com/~r/JohnRummell/~3/IlTy890gMxQ/post.aspx</link>
      <author>jrummell</author>
      <comments>http://john.rummell.info/john/blog/post/jQueryASPNet-AJAX-1035-gotcha.aspx#comment</comments>
      <guid isPermaLink="false">http://john.rummell.info/john/blog/post.aspx?id=172900a2-2f4a-4ac9-a4f4-0de3015451eb</guid>
      <pubDate>Thu, 18 Dec 2008 22:39:00 -0400</pubDate>
      <category>ASP.Net</category>
      <dc:publisher>jrummell</dc:publisher>
      <pingback:server>http://john.rummell.info/john/blog/pingback.axd</pingback:server>
      <pingback:target>http://john.rummell.info/john/blog/post.aspx?id=172900a2-2f4a-4ac9-a4f4-0de3015451eb</pingback:target>
      <slash:comments>3</slash:comments>
      <trackback:ping>http://john.rummell.info/john/blog/trackback.axd?id=172900a2-2f4a-4ac9-a4f4-0de3015451eb</trackback:ping>
      <wfw:comment>http://john.rummell.info/john/blog/post/jQueryASPNet-AJAX-1035-gotcha.aspx#comment</wfw:comment>
      <wfw:commentRss>http://john.rummell.info/john/blog/syndication.axd?post=172900a2-2f4a-4ac9-a4f4-0de3015451eb</wfw:commentRss>
    <feedburner:origLink>http://john.rummell.info/john/blog/post.aspx?id=172900a2-2f4a-4ac9-a4f4-0de3015451eb</feedburner:origLink></item>
    <item>
      <title>WebIconProvider</title>
      <description>&lt;p&gt;
How do you handle sharing icon sets across your web projects?&amp;nbsp; I started out with an icon folder in each project.&amp;nbsp; Keeping folders up to date was a bit of a pain - having to remember to update each change across all projects.&amp;nbsp; Eventually I moved the icons into a class library and compiled them as web resources.&amp;nbsp; This was great because I could access them from any web project.&amp;nbsp; But then I wanted to use a different icon set for one project.&amp;nbsp; I could have just replaced the library icons with the new set, but I didn&amp;#39;t want the new set for all of web projects.&amp;nbsp; All of my projects use the same kinds of icons, e.g. save, edit, delete, new, comment, etc.&amp;nbsp; So then it hit me, &amp;quot;What if I had an icon set interface that could be used to plug in any number of different icon sets?&amp;quot; 
&lt;/p&gt;
  
&lt;p&gt;
&amp;nbsp; 
&lt;/p&gt;
  
&lt;h2&gt;Provider Model&lt;/h2&gt;  
&lt;p&gt;
The &lt;a href="http://msdn.microsoft.com/en-us/library/aa479030.aspx" target="_blank"&gt;Provider Model&lt;/a&gt; seemed like the logical approach.&amp;nbsp; I had already worked with it when creating custom &lt;a href="http://msdn.microsoft.com/en-us/library/f1kyba5e.aspx" target="_blank"&gt;Membership&lt;/a&gt; and &lt;a href="http://msdn.microsoft.com/en-us/library/8fw7xh74.aspx" target="_blank"&gt;Role&lt;/a&gt; providers, as well as a &lt;a href="http://msdn.microsoft.com/en-us/library/aa479320.aspx" target="_blank"&gt;SiteMap&lt;/a&gt; &lt;a href="http://john.rummell.info/blog/post/2007/08/A-SiteMapProvider-for-Static-Web-Sites.aspx"&gt;provider&lt;/a&gt;.&amp;nbsp; The great thing about the provider model is that you can swap providers without recompiling and even do it at runtime.&amp;nbsp; Here&amp;#39;s a class diagram of my provider implementation. 
&lt;/p&gt;
  
&lt;p&gt;
&lt;a href="http://john.rummell.info/john/blog/image.axd?picture=WindowsLiveWriter/WebIconProvider_12D0B/ProviderClasses_2.png"&gt;&lt;img style="border-width: 0px" src="http://john.rummell.info/john/blog/image.axd?picture=WindowsLiveWriter/WebIconProvider_12D0B/ProviderClasses_thumb.png" border="0" alt="Provider Classes" width="644" height="399" /&gt;&lt;/a&gt; 
&lt;/p&gt;
  
&lt;p&gt;
Following the provider model, I have the following four classes: 
&lt;/p&gt;
  
&lt;p&gt;
&lt;strong&gt;WebIconProvider&lt;/strong&gt; is the abstract icon &lt;a href="http://msdn.microsoft.com/en-us/library/system.configuration.provider.providerbase.aspx" target="_blank"&gt;ProviderBase&lt;/a&gt; class that does most of the heavy lifting.&amp;nbsp; The most important method here is GetImageUrl(WebIcon icon). This an abstract method that returns the url of an image based on the given WebIcon enum value.&amp;nbsp; WebIcon contains all of the required image types (save, edit, delete, new, comment, etc). 
&lt;/p&gt;
  
&lt;p&gt;
&lt;strong&gt;WebIconProviderCollection&lt;/strong&gt; is a strongly typed collection of WebIconProviders. 
&lt;/p&gt;
  
&lt;p&gt;
&lt;strong&gt;WebIconService&lt;/strong&gt; is a static class that gives access to the providers and a few methods that perform operations using the default provider. 
&lt;/p&gt;
  
&lt;p&gt;
&lt;strong&gt;WebIconSection&lt;/strong&gt; is the &lt;a href="http://msdn.microsoft.com/en-us/library/system.configuration.configurationsection.aspx" target="_blank"&gt;ConfigurationSection&lt;/a&gt; implementation that contains the configuration settings required for WebIconProviders. 
&lt;/p&gt;
  
&lt;p&gt;
&amp;nbsp; 
&lt;/p&gt;
  
&lt;h2&gt;WebIconProvider&lt;/h2&gt;  
&lt;p&gt;
Now the next step is to implement WebIconProvider.&amp;nbsp; After implementing it with a few different icon sets, I realized I could refactor out two more abstract classes. 
&lt;/p&gt;
  
&lt;p&gt;
&lt;a href="http://john.rummell.info/john/blog/image.axd?picture=WindowsLiveWriter/WebIconProvider_12D0B/WebIconProviderClasses_2.png"&gt;&lt;img style="border-width: 0px" src="http://john.rummell.info/john/blog/image.axd?picture=WindowsLiveWriter/WebIconProvider_12D0B/WebIconProviderClasses_thumb.png" border="0" alt="WebIconProvider Classes" width="500" height="484" /&gt;&lt;/a&gt;&amp;nbsp; 
&lt;/p&gt;
  
&lt;p&gt;
&lt;strong&gt;FileWebIconProvider&lt;/strong&gt; is a virtual path based implementation that provides an ImagePath property that is set in the provider&amp;#39;s configuration.&amp;nbsp; The implementing class must provide the filename of each WebIcon image when it implements WebIconProvider.GetImageUrl(WebIcon icon). 
&lt;/p&gt;
  
&lt;p&gt;
&lt;strong&gt;ResourceWebIconProvider&lt;/strong&gt; is a &lt;a href="http://msdn.microsoft.com/en-us/library/system.web.ui.webresourceattribute.aspx" target="_blank"&gt;WebResource&lt;/a&gt; implementation that provides a static GetImageUrl(Type type, string resourceName) method that handles retrieving the web resource url.&amp;nbsp; The implementing class must provide an implementation of IIconResources in it&amp;#39;s constructor.&amp;nbsp; IIconResources is an interface that defines a web resource url for each WebIcon enum value.&amp;nbsp; ResourceWebIconProvider also provides an implementation of WebIconProvider.GetImageUrl(WebIcon icon) that maps WebIcon values to the appropriate IIconResources property. 
&lt;/p&gt;
  
&lt;p&gt;
&amp;nbsp; 
&lt;/p&gt;
  
&lt;h2&gt;&lt;strong&gt;ResourceWebIconProvider&lt;/strong&gt; &lt;/h2&gt;  
&lt;p&gt;
FileWebIconProvider is pretty much self explanatory.&amp;nbsp; Creating a new ResourceWebIconProvider icon set is also fairly simple.&amp;nbsp; First you need to pick out your icons! A few free sets that I like are &lt;a href="http://www.famfamfam.com/lab/icons/silk/" target="_blank"&gt;Silk Icons&lt;/a&gt;, &lt;a href="http://www.somerandomdude.net/srd-projects/sanscons/" target="_blank"&gt;Sancons&lt;/a&gt;, and &lt;a href="http://www.aspneticons.com" target="_blank"&gt;ASP.Net Icons&lt;/a&gt;. Then you&amp;#39;ll need to add them to a class library project and set their build action to Embedded Resource.&amp;nbsp; The next step is to implement IIconResources. 
&lt;/p&gt;
  
&lt;div class="csharpcode"&gt;
   
&lt;pre class="alt"&gt;
    &lt;span class="rem"&gt;/// &amp;lt;summary&amp;gt;&lt;/span&gt;
&lt;/pre&gt;
&lt;pre&gt;
    &lt;span class="rem"&gt;/// The SilkIcon implementation of &amp;lt;see cref=&amp;quot;IIconResources&amp;quot;/&amp;gt;.&lt;/span&gt;
&lt;/pre&gt;
&lt;pre class="alt"&gt;
    &lt;span class="rem"&gt;/// &amp;lt;/summary&amp;gt;&lt;/span&gt;
&lt;/pre&gt;
&lt;pre&gt;
    &lt;span class="kwrd"&gt;internal&lt;/span&gt; &lt;span class="kwrd"&gt;struct&lt;/span&gt; SilkIconResources : IIconResources
&lt;/pre&gt;
&lt;pre class="alt"&gt;
    {
&lt;/pre&gt;
&lt;pre&gt;
        &lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;const&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt; __baseResourcePath = &lt;span class="str"&gt;&amp;quot;SilkIcons.Icons.&amp;quot;&lt;/span&gt;;
&lt;/pre&gt;
&lt;pre class="alt"&gt;
        &lt;span class="kwrd"&gt;internal&lt;/span&gt; &lt;span class="kwrd"&gt;const&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt; _Add = __baseResourcePath + &lt;span class="str"&gt;&amp;quot;add.png&amp;quot;&lt;/span&gt;;
&lt;/pre&gt;
&lt;pre&gt;
        &lt;span class="kwrd"&gt;internal&lt;/span&gt; &lt;span class="kwrd"&gt;const&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt; _Calendar = __baseResourcePath + &lt;span class="str"&gt;&amp;quot;calendar.png&amp;quot;&lt;/span&gt;;
&lt;/pre&gt;
&lt;pre class="alt"&gt;
        &lt;span class="kwrd"&gt;internal&lt;/span&gt; &lt;span class="kwrd"&gt;const&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt; _Check = __baseResourcePath + &lt;span class="str"&gt;&amp;quot;tick.png&amp;quot;&lt;/span&gt;;
&lt;/pre&gt;
&lt;pre&gt;
        
&lt;/pre&gt;
&lt;pre class="alt"&gt;
        &lt;span class="rem"&gt;/* snip */&lt;/span&gt;
&lt;/pre&gt;
&lt;pre&gt;
&amp;nbsp;
&lt;/pre&gt;
&lt;pre class="alt"&gt;
        &lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;static&lt;/span&gt; &lt;span class="kwrd"&gt;readonly&lt;/span&gt; SilkIconResources _default = &lt;span class="kwrd"&gt;new&lt;/span&gt; SilkIconResources();
&lt;/pre&gt;
&lt;pre&gt;
&amp;nbsp;
&lt;/pre&gt;
&lt;pre class="alt"&gt;
        &lt;span class="rem"&gt;/// &amp;lt;summary&amp;gt;&lt;/span&gt;
&lt;/pre&gt;
&lt;pre&gt;
        &lt;span class="rem"&gt;/// Gets the default instance.&lt;/span&gt;
&lt;/pre&gt;
&lt;pre class="alt"&gt;
        &lt;span class="rem"&gt;/// &amp;lt;/summary&amp;gt;&lt;/span&gt;
&lt;/pre&gt;
&lt;pre&gt;
        &lt;span class="rem"&gt;/// &amp;lt;value&amp;gt;The default instance.&amp;lt;/value&amp;gt;&lt;/span&gt;
&lt;/pre&gt;
&lt;pre class="alt"&gt;
        &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;static&lt;/span&gt; IIconResources Default
&lt;/pre&gt;
&lt;pre&gt;
        {
&lt;/pre&gt;
&lt;pre class="alt"&gt;
            get { &lt;span class="kwrd"&gt;return&lt;/span&gt; _default; }
&lt;/pre&gt;
&lt;pre&gt;
        }
&lt;/pre&gt;
&lt;pre class="alt"&gt;
&amp;nbsp;
&lt;/pre&gt;
&lt;pre&gt;
        &lt;span class="preproc"&gt;#region&lt;/span&gt; IIconResources Members
&lt;/pre&gt;
&lt;pre class="alt"&gt;
&amp;nbsp;
&lt;/pre&gt;
&lt;pre&gt;
        &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt; Add
&lt;/pre&gt;
&lt;pre class="alt"&gt;
        {
&lt;/pre&gt;
&lt;pre&gt;
            get { &lt;span class="kwrd"&gt;return&lt;/span&gt; _Add; }
&lt;/pre&gt;
&lt;pre class="alt"&gt;
        }
&lt;/pre&gt;
&lt;pre&gt;
        
&lt;/pre&gt;
&lt;pre class="alt"&gt;
        &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt; Calendar
&lt;/pre&gt;
&lt;pre&gt;
        {
&lt;/pre&gt;
&lt;pre class="alt"&gt;
            get { &lt;span class="kwrd"&gt;return&lt;/span&gt; _Calendar; }
&lt;/pre&gt;
&lt;pre&gt;
        }
&lt;/pre&gt;
&lt;pre class="alt"&gt;
&amp;nbsp;
&lt;/pre&gt;
&lt;pre&gt;
        &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt; Check
&lt;/pre&gt;
&lt;pre class="alt"&gt;
        {
&lt;/pre&gt;
&lt;pre&gt;
            get { &lt;span class="kwrd"&gt;return&lt;/span&gt; _Check; }
&lt;/pre&gt;
&lt;pre class="alt"&gt;
        }
&lt;/pre&gt;
&lt;pre&gt;
        
&lt;/pre&gt;
&lt;pre class="alt"&gt;
        &lt;span class="rem"&gt;/* snip */&lt;/span&gt;
&lt;/pre&gt;
&lt;pre&gt;
&amp;nbsp;
&lt;/pre&gt;
&lt;pre class="alt"&gt;
        &lt;span class="preproc"&gt;#endregion&lt;/span&gt;
&lt;/pre&gt;
&lt;pre&gt;
    }
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;
The next step is adding the &lt;a href="http://msdn.microsoft.com/en-us/library/system.web.ui.webresourceattribute.aspx" target="_blank"&gt;WebResourceAttributes&lt;/a&gt;.&amp;nbsp; ContentType is a struct with string constants that contain the valid web resource content types, such as &amp;quot;image/png&amp;quot;. 
&lt;/p&gt;
&lt;div class="csharpcode"&gt;
&lt;pre class="alt"&gt;
[assembly: WebResource(SilkIconResources._Edit, ContentType.Png)]
&lt;/pre&gt;
&lt;pre&gt;
[assembly: WebResource(SilkIconResources._Delete, ContentType.Png)]
&lt;/pre&gt;
&lt;pre class="alt"&gt;
[assembly: WebResource(SilkIconResources._Add, ContentType.Png)]
&lt;/pre&gt;
&lt;pre&gt;
[assembly: WebResource(SilkIconResources._Calendar, ContentType.Png)]
&lt;/pre&gt;
&lt;pre class="alt"&gt;
        &lt;span class="rem"&gt;/* snip */&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;
The final step is implementing ResourceWebIconProvider, which is only a few lines of code. 
&lt;/p&gt;
&lt;div class="csharpcode"&gt;
&lt;pre class="alt"&gt;
    &lt;span class="rem"&gt;/// &amp;lt;summary&amp;gt;&lt;/span&gt;
&lt;/pre&gt;
&lt;pre&gt;
    &lt;span class="rem"&gt;/// A &amp;lt;see cref=&amp;quot;WebIconProvider&amp;quot;/&amp;gt; for Silk Icons (http://www.famfamfam.com/lab/icons/silk/).&lt;/span&gt;
&lt;/pre&gt;
&lt;pre class="alt"&gt;
    &lt;span class="rem"&gt;/// &amp;lt;/summary&amp;gt;&lt;/span&gt;
&lt;/pre&gt;
&lt;pre&gt;
    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; SilkIconProvider : ResourceWebIconProvider
&lt;/pre&gt;
&lt;pre class="alt"&gt;
    {
&lt;/pre&gt;
&lt;pre&gt;
        &lt;span class="rem"&gt;/// &amp;lt;summary&amp;gt;&lt;/span&gt;
&lt;/pre&gt;
&lt;pre class="alt"&gt;
        &lt;span class="rem"&gt;/// Initializes a new instance of the &amp;lt;see cref=&amp;quot;SilkIconProvider&amp;quot;/&amp;gt; class.&lt;/span&gt;
&lt;/pre&gt;
&lt;pre&gt;
        &lt;span class="rem"&gt;/// &amp;lt;/summary&amp;gt;&lt;/span&gt;
&lt;/pre&gt;
&lt;pre class="alt"&gt;
        &lt;span class="kwrd"&gt;public&lt;/span&gt; SilkIconProvider()
&lt;/pre&gt;
&lt;pre&gt;
            : &lt;span class="kwrd"&gt;base&lt;/span&gt;(SilkIconResources.Default, &lt;span class="str"&gt;&amp;quot;Mark James&amp;quot;&lt;/span&gt;, &lt;span class="str"&gt;&amp;quot;http://www.famfamfam.com/lab/icons/silk/&amp;quot;&lt;/span&gt;)
&lt;/pre&gt;
&lt;pre class="alt"&gt;
        {
&lt;/pre&gt;
&lt;pre&gt;
        }
&lt;/pre&gt;
&lt;pre class="alt"&gt;
    }
&lt;/pre&gt;
&lt;/div&gt;
&lt;h2&gt;WebControls&lt;/h2&gt;
&lt;p&gt;
I also created a few &lt;a href="http://msdn.microsoft.com/en-us/library/system.web.ui.webcontrols.webcontrol.aspx" target="_blank"&gt;WebControls&lt;/a&gt; to make displaying the icons easier. 
&lt;/p&gt;
&lt;p&gt;
&lt;a href="http://john.rummell.info/john/blog/image.axd?picture=WindowsLiveWriter/WebIconProvider_12D0B/Controls_2.png"&gt;&lt;img style="border-width: 0px" src="http://john.rummell.info/john/blog/image.axd?picture=WindowsLiveWriter/WebIconProvider_12D0B/Controls_thumb.png" border="0" alt="Control Classes" width="623" height="349" /&gt;&lt;/a&gt; 
&lt;/p&gt;
&lt;p&gt;
WebIconImage is a control that inherits &lt;a href="http://msdn.microsoft.com/en-us/library/system.web.ui.webcontrols.image.aspx" target="_blank"&gt;Image&lt;/a&gt; and adds a couple WebIconProvider related properties. You can use it just like an &amp;lt;asp:Image&amp;gt; except that you can specify the icon you want to display and it uses a WebIconProvider to determine the url.&amp;nbsp; The following markup would display the default WebIconProvider&amp;#39;s help image. 
&lt;/p&gt;
&lt;div class="csharpcode"&gt;
&lt;pre class="alt"&gt;
&lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;webicons:WebIconImage&lt;/span&gt; &lt;span class="attr"&gt;id&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;WebIconImage1&amp;quot;&lt;/span&gt; &lt;span class="attr"&gt;icon&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;Help&amp;quot;&lt;/span&gt; &lt;span class="attr"&gt;runat&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;server&amp;quot;&lt;/span&gt; &lt;span class="kwrd"&gt;/&amp;gt;&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;
&amp;nbsp; 
&lt;/p&gt;
&lt;p&gt;
WebIconCredit is control that displays the name of the icon set creator and a link to the creator&amp;#39;s web site.&amp;nbsp; The name and link come from the configuration settings.&amp;nbsp; This control&amp;#39;s markup is very simple. 
&lt;/p&gt;
&lt;div class="csharpcode"&gt;
&lt;pre class="alt"&gt;
&lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;webIcons:WebIconCredit&lt;/span&gt; &lt;span class="attr"&gt;ID&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;WebIconCredit1&amp;quot;&lt;/span&gt; &lt;span class="attr"&gt;runat&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;server&amp;quot;&lt;/span&gt; &lt;span class="kwrd"&gt;/&amp;gt;&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;
&amp;nbsp; 
&lt;/p&gt;
&lt;h2&gt;Configuration&lt;/h2&gt;
&lt;p&gt;
The configuration looks a lot like any provider configuration. 
&lt;/p&gt;
&lt;div class="csharpcode"&gt;
&lt;pre class="alt"&gt;
    &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;webIcons&lt;/span&gt; &lt;span class="attr"&gt;defaultProvider&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;Silk&amp;quot;&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
&lt;/pre&gt;
&lt;pre&gt;
        &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;providers&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
&lt;/pre&gt;
&lt;pre class="alt"&gt;
            &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;add&lt;/span&gt; &lt;span class="attr"&gt;name&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;Sanscons&amp;quot;&lt;/span&gt;
&lt;/pre&gt;
&lt;pre&gt;
                 &lt;span class="attr"&gt;type&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;Sanscons.SansconsIconProvider, Sanscons&amp;quot;&lt;/span&gt;
&lt;/pre&gt;
&lt;pre class="alt"&gt;
                 &lt;span class="attr"&gt;cssClass&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;icon&amp;quot;&lt;/span&gt;&lt;span class="kwrd"&gt;/&amp;gt;&lt;/span&gt;
&lt;/pre&gt;
&lt;pre&gt;
            &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;add&lt;/span&gt; &lt;span class="attr"&gt;name&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;Silk&amp;quot;&lt;/span&gt;
&lt;/pre&gt;
&lt;pre class="alt"&gt;
                 &lt;span class="attr"&gt;type&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;SilkIcons.SilkIconProvider, SilkIcons&amp;quot;&lt;/span&gt;&lt;span class="kwrd"&gt;/&amp;gt;&lt;/span&gt;
&lt;/pre&gt;
&lt;pre&gt;
        &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;providers&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
&lt;/pre&gt;
&lt;pre class="alt"&gt;
    &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;webIcons&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;
&amp;nbsp; 
&lt;/p&gt;
&lt;h2&gt;Source Code&lt;/h2&gt;
&lt;p&gt;
The following zip file contains four WebIconProvider implementations and a test web site. 
&lt;/p&gt;
&lt;p&gt;
&lt;a rel="enclosure" href="http://john.rummell.info/john/blog/file.axd?file=WebIcons.zip"&gt;WebIcons.zip (2.18 mb)&lt;/a&gt;
&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/JohnRummell/~4/aTiowMCDelY" height="1" width="1"/&gt;</description>
      <link>http://feedproxy.google.com/~r/JohnRummell/~3/aTiowMCDelY/post.aspx</link>
      <author>jrummell</author>
      <comments>http://john.rummell.info/john/blog/post/WebIconProvider.aspx#comment</comments>
      <guid isPermaLink="false">http://john.rummell.info/john/blog/post.aspx?id=c1cc3456-625c-44a7-8ea8-968ea06afdf6</guid>
      <pubDate>Thu, 21 Aug 2008 22:11:00 -0400</pubDate>
      <category>ASP.Net</category>
      <dc:publisher>jrummell</dc:publisher>
      <pingback:server>http://john.rummell.info/john/blog/pingback.axd</pingback:server>
      <pingback:target>http://john.rummell.info/john/blog/post.aspx?id=c1cc3456-625c-44a7-8ea8-968ea06afdf6</pingback:target>
      <slash:comments>2</slash:comments>
      <trackback:ping>http://john.rummell.info/john/blog/trackback.axd?id=c1cc3456-625c-44a7-8ea8-968ea06afdf6</trackback:ping>
      <wfw:comment>http://john.rummell.info/john/blog/post/WebIconProvider.aspx#comment</wfw:comment>
      <wfw:commentRss>http://john.rummell.info/john/blog/syndication.axd?post=c1cc3456-625c-44a7-8ea8-968ea06afdf6</wfw:commentRss>
    <feedburner:origLink>http://john.rummell.info/john/blog/post.aspx?id=c1cc3456-625c-44a7-8ea8-968ea06afdf6</feedburner:origLink></item>
    <item>
      <title>A SiteMapProvider for Static Web Sites</title>
      <description>&lt;p&gt;
The new navigation features of ASP.Net 2.0 are pretty cool. If you haven&amp;#39;t seen them yet, check out &lt;a href="http://weblogs.asp.net/scottgu/archive/2006/02/14/438241.aspx"&gt;ScottGu&amp;#39;s blog&lt;/a&gt; for more information. 
&lt;/p&gt;
&lt;p&gt;
I&amp;#39;ve
seen a few blog posts on SiteMapProvider implementations for dynamic
web sites, but not a whole lot on providers for static web sites. Sure,
you could use the default implementation and manually update the
web.sitemap xml file, but what about large sites? In my opinion, its
not worth the effort. 
&lt;/p&gt;
&lt;p&gt;
Here are my requirements for a static SiteMapProvider:
&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;Must automagically update whenever pages are added/removed.&lt;/li&gt;
	&lt;li&gt;Must be able to only include specified file types.&lt;/li&gt;
	&lt;li&gt;Must be able to exclude specified directories under the application&amp;#39;s virtual directory.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;
So I went searching and didn&amp;#39;t find anything. The closest I found was a &lt;a href="http://odetocode.com/Blogs/scott/archive/2005/11/29/2537.aspx"&gt;macro by K. Scott Allen&lt;/a&gt;
that generates a web.sitemap file from a web project. A noble effort,
but I needed a bit more. So I set off to implement my own provider.
Using the &lt;a href="http://msdn2.microsoft.com/en-us/library/Aa479033.aspx"&gt;SqlSiteMapProvider example&lt;/a&gt; as a reference, I had created my own &lt;strong&gt;StaticFileSiteMapProvider&lt;/strong&gt; by lunch time.
&lt;/p&gt;
&lt;p&gt;
The
implementation is rather straighforword. It starts at the application
path (~/) and recurses each of its sub directories. There is a &lt;strong&gt;FileExtensions&lt;/strong&gt; property that defines the types of files to include (e.g. aspx, html) and there is also a &lt;strong&gt;DirExclusions&lt;/strong&gt; property that defines the directory name patterns to exclude (e.g. bin, App_*). The &lt;strong&gt;DefaultDocuments&lt;/strong&gt; property defines the default document names for a directory (e.g index, default). 
&lt;/p&gt;
&lt;p&gt;
Why do I need a &lt;strong&gt;DefaultDocuments&lt;/strong&gt;
property? I can answer that with another question. What happens when
you&amp;#39;ve got a directory in your app that doesn&amp;#39;t have an index page?
Well, the provider will generate a link to that folder, but clicking on
it will result in a Directory Listing Denied error (at least I hope you
would have your site set up that way). In&lt;br /&gt;
BuildSiteMap(SiteMapNode
parentNode, string directory), if the current node&amp;#39;s directory doesn&amp;#39;t
have a default document page, then the node&amp;#39;s url isn&amp;#39;t set, ensuring
that its not hyperlinked.
&lt;/p&gt;
&lt;p&gt;
On to the code. I&amp;#39;ve included the main parts of the class below. For a full listing, use the link at the end of this post.
&lt;/p&gt;
&lt;!-- code formatted by http://manoli.net/csharpformat/ --&gt;&lt;br /&gt;
&lt;pre class="csharpcode"&gt;
&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;override&lt;/span&gt; SiteMapNode BuildSiteMap()
{
&lt;span class="kwrd"&gt;lock&lt;/span&gt; (&lt;span class="kwrd"&gt;this&lt;/span&gt;)
{
&lt;span class="kwrd"&gt;if&lt;/span&gt; (isBuilt)
{
&lt;span class="kwrd"&gt;return&lt;/span&gt; root;
}
&lt;span class="kwrd"&gt;string&lt;/span&gt; physicalAppPath = HttpContext.Current.Server.MapPath(&lt;span class="str"&gt;&amp;quot;~/&amp;quot;&lt;/span&gt;);
BuildSiteMap(&lt;span class="kwrd"&gt;null&lt;/span&gt;, physicalAppPath);
isBuilt = &lt;span class="kwrd"&gt;true&lt;/span&gt;;
&lt;span class="kwrd"&gt;return&lt;/span&gt; root;
}
}
&lt;span class="rem"&gt;/// &amp;lt;summary&amp;gt;&lt;/span&gt;
&lt;span class="rem"&gt;/// Recursive method to build the site map.&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=&amp;quot;parentNode&amp;quot;&amp;gt;The parent node.&amp;lt;/param&amp;gt;&lt;/span&gt;
&lt;span class="rem"&gt;/// &amp;lt;param name=&amp;quot;directory&amp;quot;&amp;gt;The directory.&amp;lt;/param&amp;gt;&lt;/span&gt;
&lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; BuildSiteMap(SiteMapNode parentNode, &lt;span class="kwrd"&gt;string&lt;/span&gt; directory)
{
&lt;span class="rem"&gt;// create the current node&lt;/span&gt;
&lt;span class="kwrd"&gt;string&lt;/span&gt; url = GetUrlFromPhysicalPath(directory);
&lt;span class="kwrd"&gt;string&lt;/span&gt; title = parentNode == &lt;span class="kwrd"&gt;null&lt;/span&gt; ? &lt;span class="str"&gt;&amp;quot;Home&amp;quot;&lt;/span&gt; : Path.GetFileName(directory);
SiteMapNode node = &lt;span class="kwrd"&gt;new&lt;/span&gt; SiteMapNode(&lt;span class="kwrd"&gt;this&lt;/span&gt;, url, url, title);
&lt;span class="rem"&gt;// set the root&lt;/span&gt;
&lt;span class="kwrd"&gt;if&lt;/span&gt; (parentNode == &lt;span class="kwrd"&gt;null&lt;/span&gt;)
{
root = node;
}
&lt;span class="rem"&gt;// add a node foreach file&lt;/span&gt;
&lt;span class="kwrd"&gt;string&lt;/span&gt;[] files = GetFiles(directory);
&lt;span class="kwrd"&gt;foreach&lt;/span&gt; (&lt;span class="kwrd"&gt;string&lt;/span&gt; file &lt;span class="kwrd"&gt;in&lt;/span&gt; files)
{
url = GetUrlFromPhysicalPath(file);
SiteMapNode fileNode = &lt;span class="kwrd"&gt;new&lt;/span&gt; SiteMapNode(&lt;span class="kwrd"&gt;this&lt;/span&gt;, url, url, Path.GetFileNameWithoutExtension(file));
AddNode(fileNode, node);
}
&lt;span class="rem"&gt;// unset the url if there isn&amp;#39;t an index file in the directory&lt;/span&gt;
&lt;span class="kwrd"&gt;if&lt;/span&gt; (!Array.Exists(files, &lt;span class="kwrd"&gt;delegate&lt;/span&gt;(&lt;span class="kwrd"&gt;string&lt;/span&gt; match)
{
&lt;span class="kwrd"&gt;foreach&lt;/span&gt; (&lt;span class="kwrd"&gt;string&lt;/span&gt; index &lt;span class="kwrd"&gt;in&lt;/span&gt; DefaultDocuments.Split(&lt;span class="str"&gt;&amp;#39;,&amp;#39;&lt;/span&gt;))
{
&lt;span class="kwrd"&gt;if&lt;/span&gt; (String.Compare(Path.GetFileNameWithoutExtension(match), index.Trim(),
StringComparison.OrdinalIgnoreCase) == 0)
{
&lt;span class="kwrd"&gt;return&lt;/span&gt; &lt;span class="kwrd"&gt;true&lt;/span&gt;;
}
}
&lt;span class="kwrd"&gt;return&lt;/span&gt; &lt;span class="kwrd"&gt;false&lt;/span&gt;;
}))
{
&lt;span class="rem"&gt;// Note: setting node.Url to null doesn&amp;#39;t change the value, so I&amp;#39;m setting it to String.Empty, &lt;/span&gt;
&lt;span class="rem"&gt;// which is its default value&lt;/span&gt;
node.Url = String.Empty;
}
&lt;span class="rem"&gt;// recurse sub directories&lt;/span&gt;
&lt;span class="kwrd"&gt;string&lt;/span&gt;[] directories = GetDirectories(directory);
&lt;span class="kwrd"&gt;foreach&lt;/span&gt; (&lt;span class="kwrd"&gt;string&lt;/span&gt; dir &lt;span class="kwrd"&gt;in&lt;/span&gt; directories)
{
BuildSiteMap(node, dir);
}
&lt;span class="rem"&gt;// only add the current node if it has children&lt;/span&gt;
&lt;span class="rem"&gt;// Note: node.HasChildren throws an InvalidOperationException, so I&amp;#39;m checking the &lt;/span&gt;
&lt;span class="rem"&gt;// file and directory arrays instead&lt;/span&gt;
&lt;span class="kwrd"&gt;if&lt;/span&gt; (files.Length &amp;gt; 0  directories.Length &amp;gt; 0)
{
AddNode(node, parentNode);
}
}
&lt;/pre&gt;
&lt;br /&gt;
&lt;p&gt;
web.config settings:&lt;!-- code formatted by http://manoli.net/csharpformat/ --&gt;
&lt;/p&gt;
&lt;pre class="csharpcode"&gt;
&lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;siteMap&lt;/span&gt; &lt;span class="attr"&gt;defaultProvider&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;StaticFileSiteMapProvider&amp;quot;&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;providers&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;add&lt;/span&gt; &lt;span class="attr"&gt;name&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;StaticFileSiteMapProvider&amp;quot;&lt;/span&gt; &lt;span class="attr"&gt;type&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;Providers.StaticFileSiteMapProvider&amp;quot;&lt;/span&gt;
&lt;span class="attr"&gt;fileExtensions&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;asp, htm&amp;quot;&lt;/span&gt;
&lt;span class="attr"&gt;defaultDocuments&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;index&amp;quot;&lt;/span&gt;
&lt;span class="attr"&gt;dirExclusions&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;bin, obj, Properties, App_*, DMS, old&amp;quot;&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;providers&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;siteMap&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
&lt;/pre&gt;
&lt;br /&gt;
&lt;p&gt;
&lt;a rel="enclosure" href="http://john.rummell.info/john/blog/file.axd?file=StaticSiteMapProvider.cs"&gt;
StaticSiteMapProvider.cs (11.85 kb)&lt;/a&gt;
&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/JohnRummell/~4/EUuHfuzHPj4" height="1" width="1"/&gt;</description>
      <link>http://feedproxy.google.com/~r/JohnRummell/~3/EUuHfuzHPj4/post.aspx</link>
      <author>jrummell</author>
      <comments>http://john.rummell.info/john/blog/post/A-SiteMapProvider-for-Static-Web-Sites.aspx#comment</comments>
      <guid isPermaLink="false">http://john.rummell.info/john/blog/post.aspx?id=dab07e26-6da3-41f5-a6c0-d33201d204d6</guid>
      <pubDate>Fri, 03 Aug 2007 20:34:00 -0400</pubDate>
      <category>ASP.Net</category>
      <dc:publisher>jrummell</dc:publisher>
      <pingback:server>http://john.rummell.info/john/blog/pingback.axd</pingback:server>
      <pingback:target>http://john.rummell.info/john/blog/post.aspx?id=dab07e26-6da3-41f5-a6c0-d33201d204d6</pingback:target>
      <slash:comments>1</slash:comments>
      <trackback:ping>http://john.rummell.info/john/blog/trackback.axd?id=dab07e26-6da3-41f5-a6c0-d33201d204d6</trackback:ping>
      <wfw:comment>http://john.rummell.info/john/blog/post/A-SiteMapProvider-for-Static-Web-Sites.aspx#comment</wfw:comment>
      <wfw:commentRss>http://john.rummell.info/john/blog/syndication.axd?post=dab07e26-6da3-41f5-a6c0-d33201d204d6</wfw:commentRss>
    <feedburner:origLink>http://john.rummell.info/john/blog/post.aspx?id=dab07e26-6da3-41f5-a6c0-d33201d204d6</feedburner:origLink></item>
    <item>
      <title>Converting DateTime to String and back</title>
      <description>I spent about 20 frustrating minutes the other day wondering why a sql
query wasn&amp;#39;t selecting the record I wanted. Everything looked right
until I stepped through my code the 3rd time. Then I discovered my
problem.&lt;br /&gt;
&lt;br /&gt;
In a web form, I allow a user to select a row in a
GridView that fires an event to populate a DetailsView using an
ObjectDataSource. The select method of the ObjectDataSource takes two
parameters, a DateTime and a string. Since the date is coming from the
GridView, I was just using Convert.ToDateTime([date cell].ToString()).&lt;br /&gt;
&lt;br /&gt;
I
discovered that the DateTime displayed in the GridView was &amp;#39;5/21/2007
8:51:42 AM&amp;#39; while the DateTime in the database was &amp;#39;2007-05-21
08:51:42.153&amp;#39;. They&amp;#39;re close, but not exactly the same. It&amp;#39;s that
missing fraction of a second that made my where clause incorrect.&lt;br /&gt;
&lt;br /&gt;
So
then I thought, &amp;quot;How can I successfully convert a DateTime to a string
and back?&amp;quot; After a short pause it hit me, &amp;quot;Ticks&amp;quot;. No, not the kind of &lt;a href="http://en.wikipedia.org/wiki/Tick"&gt;ticks&lt;/a&gt; I&amp;#39;m afraid of getting when backpacking in woods, but &lt;a href="http://msdn2.microsoft.com/en-us/library/system.datetime.ticks.aspx"&gt;DateTime.Ticks&lt;/a&gt;.  I used a &lt;a href="http://msdn2.microsoft.com/en-us/library/system.web.ui.webcontrols.hiddenfield%28vs.80%29.aspx"&gt;HiddenField&lt;/a&gt;
to store the string representation of the selected DateTime in ticks,
and then added an overloaded select method that takes a ticks (long)
parameter. In the new method I simply construct a DateTime from the
ticks and call the original select method.&lt;br /&gt;
&lt;br /&gt;
So in summary, to convert from DateTime to string and back, use ticks.&lt;img src="http://feeds.feedburner.com/~r/JohnRummell/~4/27V3cTbk-pg" height="1" width="1"/&gt;</description>
      <link>http://feedproxy.google.com/~r/JohnRummell/~3/27V3cTbk-pg/post.aspx</link>
      <author>jrummell</author>
      <comments>http://john.rummell.info/john/blog/post/Converting-DateTime-to-String-and-back.aspx#comment</comments>
      <guid isPermaLink="false">http://john.rummell.info/john/blog/post.aspx?id=bec3a5a4-8b8e-42a2-ade5-a8f832d3a5d3</guid>
      <pubDate>Mon, 21 May 2007 11:32:00 -0400</pubDate>
      <category>ASP.Net</category>
      <dc:publisher>jrummell</dc:publisher>
      <pingback:server>http://john.rummell.info/john/blog/pingback.axd</pingback:server>
      <pingback:target>http://john.rummell.info/john/blog/post.aspx?id=bec3a5a4-8b8e-42a2-ade5-a8f832d3a5d3</pingback:target>
      <slash:comments>0</slash:comments>
      <trackback:ping>http://john.rummell.info/john/blog/trackback.axd?id=bec3a5a4-8b8e-42a2-ade5-a8f832d3a5d3</trackback:ping>
      <wfw:comment>http://john.rummell.info/john/blog/post/Converting-DateTime-to-String-and-back.aspx#comment</wfw:comment>
      <wfw:commentRss>http://john.rummell.info/john/blog/syndication.axd?post=bec3a5a4-8b8e-42a2-ade5-a8f832d3a5d3</wfw:commentRss>
    <feedburner:origLink>http://john.rummell.info/john/blog/post.aspx?id=bec3a5a4-8b8e-42a2-ade5-a8f832d3a5d3</feedburner:origLink></item>
    <item>
      <title>Using ASP.Net to open a new browser window - Part II, the web control</title>
      <description>&lt;p&gt;
This a follow up to my previous post, &lt;a href="http://john.rummell.info/blog/post/2007/02/Using-ASPNet-to-open-a-new-browser-window---Part-I.aspx"&gt;Using ASP.Net to open a new browser window - Part I&lt;/a&gt;.
There I used a static helper class to register a javascript function to
open a new browser window. I&amp;#39;ve scratched the static class and replaced
it with a BrowserWindow class and a PopUpWindow WebControl.
BrowserWindow simply encapsulates all of the parameters passed to
RegisterOpenWindowScript(), and PopUpWindow registers the javascript
function and the call to the function.&lt;br /&gt;
&lt;br /&gt;
Here&amp;#39;s an example:
&lt;/p&gt;
&lt;br /&gt;
&lt;!-- code formatted by http://manoli.net/csharpformat/ --&gt;&lt;br /&gt;
&lt;pre class="csharpcode"&gt;
&lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;cc1:PopUpWindow&lt;/span&gt; &lt;span class="attr"&gt;ID&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;PopUpWindow1&amp;quot;&lt;/span&gt; &lt;span class="attr"&gt;runat&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;server&amp;quot;&lt;/span&gt; &lt;span class="attr"&gt;OpenOnLoad&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;false&amp;quot;&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:Button&lt;/span&gt; &lt;span class="attr"&gt;ID&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;Button1&amp;quot;&lt;/span&gt; &lt;span class="attr"&gt;runat&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;server&amp;quot; &lt;/span&gt;&lt;span class="attr"&gt;Text&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;Open Window&amp;quot;&lt;/span&gt; &lt;span class="attr"&gt;OnClick&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;Button1_Click&amp;quot;&lt;/span&gt; &lt;span class="kwrd"&gt;/&amp;gt;&lt;/span&gt;
&lt;/pre&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;!-- code formatted by http://manoli.net/csharpformat/ --&gt;&lt;br /&gt;
&lt;pre class="csharpcode"&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)
{
BrowserWindow window = &lt;span class="kwrd"&gt;new&lt;/span&gt; BrowserWindow(
&lt;span class="str"&gt;&amp;quot;http://john.rummell.info/blog&amp;quot;&lt;/span&gt;, 800, 600);
window.Resizable = &lt;span class="kwrd"&gt;true&lt;/span&gt;;
window.Scrollbars = &lt;span class="kwrd"&gt;true&lt;/span&gt;;
PopUpWindow1.BrowserWindow = window;
}
&lt;span class="kwrd"&gt;protected&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; Button1_Click(&lt;span class="kwrd"&gt;object&lt;/span&gt; sender, EventArgs e)
{
PopUpWindow1.OpenWindow();
}
&lt;/pre&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
PopUpWindow
exposes a few of BrowserWindow&amp;#39;s properties: Width, Height, and Url.
For more options, create a BrowserWindow object and set PopUpWindow&amp;#39;s
BroswerWindow property with it, as shown in Page_Load. You can use the
OpenWindow() method of PopUpWindow to open the window as shown in
Button1_Click, or you can set OpenOnLoad to true to have it open when
the page loads.&lt;br /&gt;
&lt;p&gt;
&lt;a rel="enclosure" href="http://john.rummell.info/john/blog/file.axd?file=BrowserWindow.cs"&gt;BrowserWindow.cs (7.56 kb)&lt;/a&gt;,
&lt;a rel="enclosure" href="http://john.rummell.info/john/blog/file.axd?file=PopUpWindow.cs"&gt;PopUpWindow.cs (6.91 kb)&lt;/a&gt;
&lt;/p&gt;
&lt;p&gt;
&amp;nbsp;
&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/JohnRummell/~4/Fq-S8SLWWOE" height="1" width="1"/&gt;</description>
      <link>http://feedproxy.google.com/~r/JohnRummell/~3/Fq-S8SLWWOE/post.aspx</link>
      <author>jrummell</author>
      <comments>http://john.rummell.info/john/blog/post/Using-ASPNet-to-open-a-new-browser-window-Part-II-the-web-control.aspx#comment</comments>
      <guid isPermaLink="false">http://john.rummell.info/john/blog/post.aspx?id=58c51123-e17a-45d5-b685-2ab7f79d1d79</guid>
      <pubDate>Tue, 20 Feb 2007 13:24:00 -0400</pubDate>
      <category>ASP.Net</category>
      <dc:publisher>jrummell</dc:publisher>
      <pingback:server>http://john.rummell.info/john/blog/pingback.axd</pingback:server>
      <pingback:target>http://john.rummell.info/john/blog/post.aspx?id=58c51123-e17a-45d5-b685-2ab7f79d1d79</pingback:target>
      <slash:comments>1</slash:comments>
      <trackback:ping>http://john.rummell.info/john/blog/trackback.axd?id=58c51123-e17a-45d5-b685-2ab7f79d1d79</trackback:ping>
      <wfw:comment>http://john.rummell.info/john/blog/post/Using-ASPNet-to-open-a-new-browser-window-Part-II-the-web-control.aspx#comment</wfw:comment>
      <wfw:commentRss>http://john.rummell.info/john/blog/syndication.axd?post=58c51123-e17a-45d5-b685-2ab7f79d1d79</wfw:commentRss>
    <feedburner:origLink>http://john.rummell.info/john/blog/post.aspx?id=58c51123-e17a-45d5-b685-2ab7f79d1d79</feedburner:origLink></item>
    <item>
      <title>Using ASP.Net to open a new browser window - Part I</title>
      <description>&lt;p&gt;
I recently needed to add a &amp;#39;pop-up&amp;#39; window to a website. Now I&amp;#39;m not
a fan of javascript, never have been. I like my code to be type safe
and compile. So I came up with a C# helper class to do the dirty work
for me. I must give credit to where I found the idea. I saw something
like this in Chapter 4 of &lt;span style="font-style: italic"&gt;Developing Web Applications with Microsoft VB .Net and VC#&lt;/span&gt;
.Net by Jeff Webb and MS Corp. In this book they create BrowserWindow
class and use it inside some javascript. I&amp;#39;ve take a different
approach, so that I can avoid having to write the javascript in the
future.&lt;br /&gt;
&lt;br /&gt;
I created a static helper class that contains the
following method. I also provided some methods that overload this, but
you get the idea.&lt;br /&gt;
&lt;!-- code formatted by http://manoli.net/csharpformat/ --&gt;
&lt;/p&gt;
&lt;br /&gt;
&lt;pre class="csharpcode"&gt;
&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;static&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; RegisterOpenWindowScript(
Page page, &lt;span class="kwrd"&gt;string&lt;/span&gt; key, &lt;span class="kwrd"&gt;string&lt;/span&gt; url,
WindowName name, &lt;span class="kwrd"&gt;int&lt;/span&gt; width, &lt;span class="kwrd"&gt;int&lt;/span&gt; height,
&lt;span class="kwrd"&gt;int&lt;/span&gt; left, &lt;span class="kwrd"&gt;int&lt;/span&gt; top,
&lt;span class="kwrd"&gt;bool&lt;/span&gt; location, &lt;span class="kwrd"&gt;bool&lt;/span&gt; menubar, &lt;span class="kwrd"&gt;bool&lt;/span&gt; resizable,
&lt;span class="kwrd"&gt;bool&lt;/span&gt; scrollbars, &lt;span class="kwrd"&gt;bool&lt;/span&gt; status, &lt;span class="kwrd"&gt;bool&lt;/span&gt; titlebar)
{
&lt;span class="kwrd"&gt;if&lt;/span&gt; (!page.ClientScript.IsClientScriptBlockRegistered(
&lt;span class="kwrd"&gt;typeof&lt;/span&gt;(OpenWindowHelper), key))
{
&lt;span class="kwrd"&gt;string&lt;/span&gt; script = String.Format(&lt;span class="str"&gt;@&amp;quot;
function {12}()
{{
var win = window.open(&amp;#39;{0}&amp;#39;, &amp;#39;{1}&amp;#39;,
&amp;#39;width={2},height={3},left={4},top={5},location={6},
menubar={7},resizable={8},scrollbars={9},
status={10},titlebar={11}&amp;#39;);
win.focus();
}}
&amp;quot;&lt;/span&gt;, url, name, width, height, left, top,
GetInt(location), GetInt(menubar),
GetInt(resizable), GetInt(scrollbars), GetInt(status),                    
GetInt(titlebar), openFunctionName);
page.ClientScript.RegisterClientScriptBlock(
&lt;span class="kwrd"&gt;typeof&lt;/span&gt;(OpenWindowHelper), key, script, &lt;span class="kwrd"&gt;true&lt;/span&gt;);
}
}
&lt;/pre&gt;
&lt;br /&gt;
&lt;br /&gt;
WindowName
is an enum that defines the possible window names: _blank, _parent,
_self, _top. GetInt() simply returns 1 if true and 0 if false.&lt;br /&gt;
&lt;br /&gt;
As
I&amp;#39;m writing this I&amp;#39;m realizing that it would be a cool idea to merge
this static class with the BrowserWindow class. You could define a
BrowserWindow object and perform the Open() operation to open the
window. Hmm ... I&amp;#39;m seeing a follow up post in the near future.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;a href="http://john.rummellcc.com/files/OpenWindowHelper.cs"&gt;&lt;/a&gt;
&lt;p&gt;
&lt;a rel="enclosure" href="http://john.rummell.info/john/blog/file.axd?file=OpenWindowHelper.cs"&gt;OpenWindowHelper.cs (5.24 kb)&lt;/a&gt;
&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/JohnRummell/~4/SVXOi_tucH4" height="1" width="1"/&gt;</description>
      <link>http://feedproxy.google.com/~r/JohnRummell/~3/SVXOi_tucH4/post.aspx</link>
      <author>jrummell</author>
      <comments>http://john.rummell.info/john/blog/post/Using-ASPNet-to-open-a-new-browser-window-Part-I.aspx#comment</comments>
      <guid isPermaLink="false">http://john.rummell.info/john/blog/post.aspx?id=f3e35b61-ced7-431e-a9a8-f05af2d72988</guid>
      <pubDate>Mon, 19 Feb 2007 23:15:00 -0400</pubDate>
      <category>ASP.Net</category>
      <dc:publisher>jrummell</dc:publisher>
      <pingback:server>http://john.rummell.info/john/blog/pingback.axd</pingback:server>
      <pingback:target>http://john.rummell.info/john/blog/post.aspx?id=f3e35b61-ced7-431e-a9a8-f05af2d72988</pingback:target>
      <slash:comments>1</slash:comments>
      <trackback:ping>http://john.rummell.info/john/blog/trackback.axd?id=f3e35b61-ced7-431e-a9a8-f05af2d72988</trackback:ping>
      <wfw:comment>http://john.rummell.info/john/blog/post/Using-ASPNet-to-open-a-new-browser-window-Part-I.aspx#comment</wfw:comment>
      <wfw:commentRss>http://john.rummell.info/john/blog/syndication.axd?post=f3e35b61-ced7-431e-a9a8-f05af2d72988</wfw:commentRss>
    <feedburner:origLink>http://john.rummell.info/john/blog/post.aspx?id=f3e35b61-ced7-431e-a9a8-f05af2d72988</feedburner:origLink></item>
    <item>
      <title>NUnint C# Templates for Visual Studio 2005</title>
      <description>I recently upgraded to Visual Studio 2005. I wrote a few classes and
began the testing process. I added a new class library project and then
added a reference to nunit.framework, added a new testing class and
typed out all of the NUnint attributes .... and then I stopped. There
has to be a faster way to set up a test class. A quick Google search
returned a few results for VB templates, but no C# templates =/.&lt;br /&gt;
&lt;br /&gt;
So
I got out my thin VS 2005 manual and decided to make my own template.
It was much easier than expected, since I had made previous templates
in VS 2003. And now I share them with you, my fellow readers.&lt;br /&gt;
&lt;br /&gt;
&lt;a href="http://john.rummellcc.com/files/code/NUnit%20Test%20Class%20Library.zip"&gt;NUnit Class Library&lt;/a&gt;&lt;br /&gt;
&lt;a href="http://john.rummellcc.com/files/code/NUnit%20Test%20Class.zip"&gt;NUnit Class&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
Just
drop the NUnit Class Library in your &amp;quot;My Documents\Visual Studio
2005\Templates\ProjectTemplates&amp;quot; folder and the NUnit Class in your &amp;quot;My
Documents\Visual Studio 2005\Templates\ItemTemplates&amp;quot; folder.&lt;img src="http://feeds.feedburner.com/~r/JohnRummell/~4/tdBEBpTbRlY" height="1" width="1"/&gt;</description>
      <link>http://feedproxy.google.com/~r/JohnRummell/~3/tdBEBpTbRlY/post.aspx</link>
      <author>jrummell</author>
      <comments>http://john.rummell.info/john/blog/post/NUnint-C-Templates-for-Visual-Studio-2005.aspx#comment</comments>
      <guid isPermaLink="false">http://john.rummell.info/john/blog/post.aspx?id=9209cb37-bb3d-4c6a-aa71-f4b56e491e2b</guid>
      <pubDate>Sat, 30 Dec 2006 15:08:00 -0400</pubDate>
      <category>ASP.Net</category>
      <dc:publisher>jrummell</dc:publisher>
      <pingback:server>http://john.rummell.info/john/blog/pingback.axd</pingback:server>
      <pingback:target>http://john.rummell.info/john/blog/post.aspx?id=9209cb37-bb3d-4c6a-aa71-f4b56e491e2b</pingback:target>
      <slash:comments>1</slash:comments>
      <trackback:ping>http://john.rummell.info/john/blog/trackback.axd?id=9209cb37-bb3d-4c6a-aa71-f4b56e491e2b</trackback:ping>
      <wfw:comment>http://john.rummell.info/john/blog/post/NUnint-C-Templates-for-Visual-Studio-2005.aspx#comment</wfw:comment>
      <wfw:commentRss>http://john.rummell.info/john/blog/syndication.axd?post=9209cb37-bb3d-4c6a-aa71-f4b56e491e2b</wfw:commentRss>
    <feedburner:origLink>http://john.rummell.info/john/blog/post.aspx?id=9209cb37-bb3d-4c6a-aa71-f4b56e491e2b</feedburner:origLink></item>
  </channel>
</rss>
