<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>dev&#124;sushi &#187; asp.net</title>
	<atom:link href="http://devsushi.com/tag/asp-net/feed/" rel="self" type="application/rss+xml" />
	<link>http://devsushi.com</link>
	<description>Discussion on Development in Several Different Flavours</description>
	<lastBuildDate>Sun, 28 Feb 2010 03:03:58 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0</generator>
		<item>
		<title>ASP.Net DropDownList annoyance</title>
		<link>http://devsushi.com/2007/10/19/aspnet-dropdownlist-annoyance/</link>
		<comments>http://devsushi.com/2007/10/19/aspnet-dropdownlist-annoyance/#comments</comments>
		<pubDate>Fri, 19 Oct 2007 21:26:58 +0000</pubDate>
		<dc:creator>Adam</dc:creator>
				<category><![CDATA[miscellaneous]]></category>
		<category><![CDATA[annoyances]]></category>
		<category><![CDATA[asp.net]]></category>

		<guid isPermaLink="false">http://adamhewgill.com/devsushi/2007/10/19/aspnet-dropdownlist-annoyance/</guid>
		<description><![CDATA[I recently ran into a problem with using the ASP.Net DropDownList for toggling the status of an element. The problem stems from how the ASP.Net page object works. In this article I present the problem and then show a solution that seems to work with some caveats. My goal is to create a toggle for [...]]]></description>
			<content:encoded><![CDATA[<p>I recently ran into a problem with using the ASP.Net DropDownList for toggling the status of an element. The problem stems from how the ASP.Net page object works. In this article I present the problem and then show a solution that seems to work with some caveats.<span id="more-51"></span></p>
<p>My goal is to create a toggle for the status of a page. For example I have a report and it has the possible status of <em>Open</em> or <em>Closed</em>. The DropDownList contains only the opposite of the current status of the report so when the report is <em>Open</em> the DropDownList contains an empty item (no change) and <em>Closed</em>. Here is the code.</p>
<pre class="brush: vb">&lt;script runat="server"&gt;
  Sub Page_Load()
    If Not Page.IsPostBack Then
      Session("bool") = "Open"
    End If

    ' Setup drop down
    ddlItems.Items.Clear()
    ddlItems.Items.Add("")
    If Not Session("bool") = "Open" Then ddlItems.Items.Add("Open")
    If Not Session("bool") = "Closed" Then ddlItems.Items.Add("Closed")
  End Sub

  Sub Click_Submit(ByVal s As Object, ByVal e As EventArgs)
    If ddlItems.SelectedValue = "Open" Then
      Session("bool") = "Closed"
    ElseIf ddlItems.SelectedValue = "Open" Then
      Session("bool") = "Closed"
    End If
  End Sub
&lt;/script&gt;

&lt;html&gt;
&lt;head&gt;
  &lt;title&gt;Drop Down Annoyance&lt;/title&gt;
&lt;/head&gt;
&lt;body&gt;
  &lt;form runat="server"&gt;
  &lt;h1&gt;Drop Down Annoyance&lt;/h1&gt;
  &lt;p&gt;Current Status: &lt;%= Session("bool") %&gt;&lt;/p&gt;
  &lt;p&gt;Update to: &lt;asp:DropDownList ID="ddlItems" runat="server" /&gt;&lt;/p&gt;
  &lt;asp:Button ID="btnSubmit" Text="Update" OnClick="Click_Submit" runat="server" /&gt;
  &lt;/form&gt;
&lt;/body&gt;
&lt;/html&gt;
</pre>
<p>There are two problems at work here that cause a complete failure of the intended action. Firstly, during <em>Page_Load</em> the <em>Click_Submit</em> event has not yet fired so the Session variable still contains the old value of <em>Open</em>. The code then rebuilds the DropDownList based on the Session variable being unchanged. Secondly, doing the change of the DropDownList resets which option is selected loosing the users input.</p>
<p>We can fix both of these problems with one change to the code. Simply move the DropDownList change to the very last moment right before its declaration. Make sure to add all possible options to the declaration using ListItems, this is a must for it to work.</p>
<pre class="brush: vb">&lt;%@ Page Language="VB" Debug="True" %&gt;

&lt;script runat="server"&gt;

  Sub Page_Load()
    If Not Page.IsPostBack Then
      Session("bool") = "Open"
    End If
  End Sub

  Sub Click_Submit(ByVal s As Object, ByVal e As EventArgs)
    If ddlItems.SelectedValue = "Open" Then
      Session("bool") = "Open"
    ElseIf ddlItems.SelectedValue = "Closed" Then
      Session("bool") = "Closed"
    End If
  End Sub

&lt;/script&gt;

&lt;html&gt;
&lt;head&gt;
  &lt;title&gt;Drop Down Annoyance&lt;/title&gt;
&lt;/head&gt;
&lt;body&gt;
  &lt;form runat="server"&gt;
  &lt;h1&gt;Drop Down Annoyance&lt;/h1&gt;
  &lt;p&gt;Current Status: &lt;%= Session("bool") %&gt;&lt;/p&gt;
  &lt;%
    ' Setup drop down
    ddlItems.Items.Clear()
    ddlItems.Items.Add("")
    If Not Session("bool") = "Open" Then ddlItems.Items.Add("Open")
    If Not Session("bool") = "Closed" Then ddlItems.Items.Add("Closed")
  %&gt;
  &lt;p&gt;Update to: &lt;asp:DropDownList ID="ddlItems" runat="server"&gt;
    &lt;asp:ListItem Text="" Selected="True" /&gt;
    &lt;asp:ListItem Text="Open" /&gt;
    &lt;asp:ListItem Text="Closed" /&gt;
  &lt;/asp:DropDownList&gt;&lt;/p&gt;
  &lt;asp:Button ID="btnSubmit" Text="Update" OnClick="Click_Submit" runat="server" /&gt;
  &lt;/form&gt;
&lt;/body&gt;
&lt;/html&gt;
</pre>
<p>What is going on here is that when ASP.Net creates the ddlItems object it loads it up with all the ListItems given in the declaration. These items are available throughout the code right up until the point where we Clear and then change the DropDownList. The Session variable has been changed by this time and so everything works out. One very important caveat of this method is that you must not use ddlItems.SelectedIndex since the number of options in the list changes, instead use ddlItems.SelectedValue.</p>
<p>Does anybody else have any novel solutions for working with DropDownList controls?</p>
]]></content:encoded>
			<wfw:commentRss>http://devsushi.com/2007/10/19/aspnet-dropdownlist-annoyance/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>ASP.Net has 9 to 5 appeal</title>
		<link>http://devsushi.com/2007/07/23/aspnet-has-9-to-5-appeal/</link>
		<comments>http://devsushi.com/2007/07/23/aspnet-has-9-to-5-appeal/#comments</comments>
		<pubDate>Mon, 23 Jul 2007 18:13:03 +0000</pubDate>
		<dc:creator>Adam</dc:creator>
				<category><![CDATA[miscellaneous]]></category>
		<category><![CDATA[asp.net]]></category>

		<guid isPermaLink="false">http://adamhewgill.com/devsushi/2007/07/23/aspnet-has-9-to-5-appeal/</guid>
		<description><![CDATA[My first article on this blog was the first in the &#8220;Dynamic Control Creation&#8221; series. I wrote it because I was frustrated with how ASP.Net worked and wanted to share my discoveries/workarounds with other frustrated developers. After a period of time Google picked up my article and I started to receive a decent amount of [...]]]></description>
			<content:encoded><![CDATA[<p><img src='http://devsushi.com/wp-content/uploads/2007/07/9to5appeal.png' alt='9 to 5 Appeal' /><br />
<span id="more-49"></span></p>
<p>My first article on this blog was the first in the &#8220;<a href="http://adamhewgill.com/devsushi/2006/08/27/aspnet-dynamic-control-creation-part-1/">Dynamic Control Creation</a>&#8221; series. I wrote it because I was frustrated with how ASP.Net worked and wanted to share my discoveries/workarounds with other frustrated developers. After a period of time Google picked up my article and I started to receive a decent amount of traffic and some positive feedback. Here at work I use ASP.Net for a majority of my applications and so the blog has continued to focus on it primarily. An interesting thing that I&#8217;ve noticed is that site traffic has a very consistent pattern &mdash; which I attribute to my focus on ASP.Net. Above you see a graph &mdash; from <a href="https://www.google.com/analytics/home/">Google Analytics</a> &mdash; that shows daily traffic over the last five months. Each valley in the graph made up of the numbers for Saturday and Sunday which are consistently very small compared to the weekday traffic.</p>
<p>I&#8217;ve done a few inquiries and looked at a few other sites I have stats for and found that this isn&#8217;t all that common. When other sites match my pattern they have a high number of work time surfers coming to their site as I do.  I use this loose research to conclude that ASP.Net is widely used in the workplace and much less common for personal/weekend projects. PHP blogs and websites have a very consistent amount of traffic on all days of the week as many weekend programmers surf for information.</p>
<p>What does this signify for ASP.Net? Very few people use it for fun for one thing. I certainly don&#8217;t when I don&#8217;t have to. In fact I am phasing it out at work slowly too, starting most new projects in PHP &mdash; which I&#8217;m not really a fan of either. Companies across the globe are buying into Microsoft server products and technologies and forcing it down their employees throats.</p>
<p>How do your traffic statistics look? What is your main theme/topic? Would you prefer to use a different programming language at work? Leave a comment, I&#8217;m very interested.</p>
]]></content:encoded>
			<wfw:commentRss>http://devsushi.com/2007/07/23/aspnet-has-9-to-5-appeal/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>ASP.Net CheckBoxes should be able to have values</title>
		<link>http://devsushi.com/2007/07/16/aspnet-checkboxes-should-be-able-to-have-values/</link>
		<comments>http://devsushi.com/2007/07/16/aspnet-checkboxes-should-be-able-to-have-values/#comments</comments>
		<pubDate>Mon, 16 Jul 2007 19:06:33 +0000</pubDate>
		<dc:creator>Adam</dc:creator>
				<category><![CDATA[miscellaneous]]></category>
		<category><![CDATA[annoyances]]></category>
		<category><![CDATA[asp.net]]></category>
		<category><![CDATA[css/xhtml]]></category>
		<category><![CDATA[web standards]]></category>

		<guid isPermaLink="false">http://adamhewgill.com/devsushi/2007/07/16/aspnet-checkboxes-should-be-able-to-have-values/</guid>
		<description><![CDATA[The ASP.Net CheckBox and CheckBoxList control don&#8217;t allow for the use of the full W3C HTML standard. For some reason Microsoft decided to implement a reduced functionality version that creates more work for the programmer. Come on Microsoft why can&#8217;t you follow even the simplest of standards? In this case it would make coding the [...]]]></description>
			<content:encoded><![CDATA[<p></p>
<p>The ASP.Net <em>CheckBox</em> and <em>CheckBoxList</em> control don&#8217;t allow for the use of the full W3C HTML standard. For some reason Microsoft decided to implement a reduced functionality version that creates more work for the programmer. Come on Microsoft why can&#8217;t you follow even the simplest of standards? In this case it would make coding the .Net framework easier for you not to mention us!<span id="more-47"></span></p>
<p>The W3C HTML 4.01 specification specifically states for the <em>value</em> attribute to:</p>
<blockquote><p>
&#8211; Specify for radio buttons and checkboxes &#8211;<br />
<cite><a href="http://www.w3.org/TR/html401/interact/forms.html#edef-INPUT">W3C HTML 4.01 Specification &#8211; INPUT Element</a></cite>
</p></blockquote>
<p>To me this quote reads as a strong recommendation to specify the <em>value</em> attribute rather than leave it up to the browsers default (generally &quot;On&quot;). Microsoft decided to not even allow the value attribute to be set. They went so far as to have a validation message built into Visual Studio that says:</p>
<blockquote><p>
Attribute &#8216;Value&#8217; is not a valid attribute of element &#8216;CheckBox&#8217;
</p></blockquote>
<p>If you ignore the warning and run the page, the <em>value</em> attribute is missing. I have even tried circumventing the ASP.Net HTML-izer by adding <em>value</em> to the attributes collection with no success. Microsoft intentionally strips it, so I can only assume they have some reasoning behind this behavior and I imagine they will say something about security in defense.</p>
<p>There is one way to circumvent the behavior but it requires not using ASP.Net controls. Simply insert traditional <em>input type=&#8221;checkbox&#8221;</em> elements into your page and collect their values using <em>Request.Form</em>.</p>
<pre class="brush: vb">Sub Page_Load ()
  Dim value As String
  value = Request.Form(&quot;chkItem&quot;)
End Sub
&hellip;
&lt;input type=&quot;checkbox&quot; id=&quot;chkItem&quot; name=&quot;chkItem&quot; /&gt;
&lt;label for=&quot;chkItem&quot;&gt;CheckBox Item Text&lt;/label&gt;
</pre>
<p>I made a big deal out of this issue simply because to me it doesn&#8217;t make any sense. You can get around the issue and still use ASP.Net controls but it requires extra coding.</p>
<pre class="brush: vb">Sub Page_Load ()
  Dim value As String
  If chkItem.Checked Then
    value = &quot;Some Value&quot;
  Else
    value = &quot;Some Other Value&quot;
  End If
End Sub
&hellip;
&lt;asp:CheckBox ID=&quot;chkItem&quot; Text=&quot;CheckBox Item Text&quot; runat=&quot;server&quot; /&gt;
</pre>
<p>When using the <em>CheckBoxList</em> control you will notice ASP.Net uses tables to layout the list. To keep it from doing this you simply need to add a few attributes. It should then use much more standards compliant code. I also show how to access which boxes are checked after postback in a <em>CheckBoxList</em>.</p>
<pre class="brush: vb">Sub Page_Load ()
  ' Find out which boxes were checked
  Dim value As String = &quot;&quot;
  For Each item As ListItem In cblTest.Items
    If item.Selected Then
      value &amp;= item.Value
    End If
  Next
End Sub
&hellip;
&lt;asp:CheckBoxList ID=&quot;cblList&quot; RepeatLayout=&quot;Flow&quot; RepeatDirection=&quot;Horizontal&quot; runat=&quot;server&quot;&gt;
  &lt;asp:ListItem Text=&quot;Item 1&quot; Value=&quot;1&quot; /&gt;
  &lt;asp:ListItem Text=&quot;Item 2&quot; Value=&quot;2&quot; /&gt;
  &lt;asp:ListItem Text=&quot;Item 3&quot; Value=&quot;3&quot; /&gt;
&lt;/asp:CheckBoxList&gt;
</pre>
<p>As always let me know if you have any questions.</p>
<p></p>
]]></content:encoded>
			<wfw:commentRss>http://devsushi.com/2007/07/16/aspnet-checkboxes-should-be-able-to-have-values/feed/</wfw:commentRss>
		<slash:comments>13</slash:comments>
		</item>
		<item>
		<title>ASP.Net file download protection through authentication</title>
		<link>http://devsushi.com/2007/01/31/aspnet-file-download-protection-through-authentication/</link>
		<comments>http://devsushi.com/2007/01/31/aspnet-file-download-protection-through-authentication/#comments</comments>
		<pubDate>Thu, 01 Feb 2007 00:04:28 +0000</pubDate>
		<dc:creator>Adam</dc:creator>
				<category><![CDATA[miscellaneous]]></category>
		<category><![CDATA[asp.net]]></category>

		<guid isPermaLink="false">http://adamhewgill.com/devsushi/2007/01/31/aspnet-file-download-protection-through-authentication/</guid>
		<description><![CDATA[Recently at work I needed to allow for the download of sensitive files over the web. Right away your mind should jump to the security issues involved with such an undertaking. How do you allow for download without compromising the sensitive data? There is a simple but flexible method that will work perfectly. Source code [...]]]></description>
			<content:encoded><![CDATA[<p></p>
<p>Recently at work I needed to allow for the download of sensitive files over the web. Right away your mind should jump to the security issues involved with such an undertaking. How do you allow for download without compromising the sensitive data? There is a simple but flexible method that will work perfectly.<span id="more-34"></span></p>
<p><a href="/files/fileprotection.zip">Source code for this project</a>.</p>
<p>I found the method without any difficulty using Google. The site outlined how to create a <a href="http://www.codeproject.com/aspnet/SecureFileDownload.asp">secure file download page</a>. While implementing this solution I ran into some issues so I figured I would present my improved version and expand on some helpful features of ASP.Net.</p>
<p>The first step is to create a page that will list files available to download. Each link simply gives different parameters to the download script specifying which file was selected.</p>
<pre class="brush: html">&lt;form id=&quot;form1&quot; runat=&quot;server&quot;&gt;
  &lt;p&gt;Select a file to download.&lt;/p&gt;
  &lt;div&gt;
      &lt;ul&gt;
      &lt;li&gt;&lt;a href=&quot;download.aspx?file=&lt;%=Server.URLEncode(&quot;D:\\file1.txt&quot;) %&gt;&quot;&gt;file 1&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;download.aspx?file=&lt;%=Server.URLEncode(&quot;D:\\file2.txt&quot;) %&gt;&quot;&gt;file 2&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;download.aspx?file=&lt;%=Server.URLEncode(&quot;D:\\file3.txt&quot;) %&gt;&quot;&gt;file 3&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;download.aspx?file=&lt;%=Server.URLEncode(&quot;D:\\test\\file4.txt&quot;) %&gt;&quot;&gt;file 4&lt;/a&gt;&lt;/li&gt;
      &lt;/ul&gt;
  &lt;/div&gt;
&lt;/form&gt;</pre>
<p>The Server.URLEncode function is necessary here to make sure the filename doesn&#8217;t get mangled. It replaces any special URL characters (such as : and \) with a % code. For example you have probably seen %20 in a few URLs before, it is a URL encoded space character. Now we will need to receive the file and verify the user is authenticated.</p>
<pre class="brush: vb">' Make sure the user should be able to download using
' your authentication scheme then send file
Sub Page_Load()
    ' Forms authentication check
    If Not User.Identity.IsAuthenticated Then
        ' redirect to login page
    End If
    ' URL key passing
    If CheckKey(Request.QueryString(&quot;key&quot;)) Then
        ' redirect to invalid key page
    End If
    ' Session key
    If CheckKey(Session(&quot;key&quot;)) Then
        ' redirect to invalid key page
    End If

    ' Make sure a file has been specified
    Dim filename As String = Request.QueryString(&quot;file&quot;)
    If String.IsNullOrEmpty(filename) Then
        ' redirect to no file specified page
    End If

    ' Make sure file exists
    If Not File.Exists(filename) Then
        ' redirect to file does not exist page
    End If

    ' Write file to browser
    Response.ContentType = &quot;application/octet-stream&quot;
    Response.AddHeader(&quot;Content-Disposition&quot;, &quot;attachment; filename=&quot;&quot;&quot; &amp; Path.GetFileName(filename) &amp; &quot;&quot;&quot;&quot;)
    Try
        Response.TransmitFile(filename)
    Catch ex As Exception
        ' Redirect to error opening file
    End Try
End Sub

Function CheckKey(ByVal key As String) As Boolean
    ' Validate user key
    Return True
End Function</pre>
<p>I will not cover authentication here but the first step is to check to make sure the request to the download page is by a valid user. I have provided three skeletal checks in the code but you would use the one which matches your authentication scheme. After verifying the user is valid you may wish to check if that valid user is allowed to download this file based on some internal logic. (For example upload/download ratio sites, various user level sites, etc.) Once the user has been validated it is time to validate the request. The first check is to make sure a filename was passed. We then try to open that file and read in its contents. If at any point there is a problem we simply redirect the user to an error page.</p>
<p><strong>Security Note:</strong> This method exposes the internal structure of your servers file system by passing it through the URL to the download page. It is not recommended to use this method AS IS in a production environment. A clever hacker could easily change the URL passed to the download script to point to a file in any directory on your server. Normally this isn&#8217;t an issue since the built in windows permissions should deny IIS/ASP.Net from accessing anything sensitive, however, I have seen incorrectly configured servers before.</p>
<pre class="brush: vb">' Write file to browser
Response.ContentType = &quot;application/octet-stream&quot;
Response.AddHeader(&quot;Content-Disposition&quot;, &quot;attachment; filename=&quot;&quot;&quot; &amp; Path.GetFileName(filename) &amp; &quot;&quot;&quot;&quot;)
Try
    Response.TransmitFile(filename)
Catch ex As Exception
    ' Redirect to error opening file
End Try
</pre>
<p>The final piece of code is the most important. The response object is the output we are going to send the users web browser. At this time we can change anything we like so as to masquerade our ASP.Net page as something else. For example you can set the response up as an image, use an image library and create dynamic thumbnails of images. Then your IMG src would be the .aspx page. In this case we want to send the user a file so we change the response to an octet-stream (binary data) and give the name of the attached file. The major bug that I fixed is to add the quotes to the response around the filename. This is very important since other wise browsers don&#8217;t get the full filename if it contains spaces. Additionally, some browsers have issues with this attachment method without the quotes.</p>
<p>Path.GetFileName is a very handy tool to grab the filename off the end of a path string. There are a whole set of static methods in the Path object that you can use in this fashion to take parts of the path or url that you wish without having to parse them yourself. Make sure to browse throught the <a href="http://msdn2.microsoft.com/en-us/library/system.io.path_members.aspx">MSDN page for the Path class</a> (scroll down to the Public Members section).</p>
<p>One potential caveat is the downloading of very large files as described in <a href="http://support.microsoft.com/kb/812406">this MSDN knowledge base article</a>. However, a method is presented which should work. Another possible issue is with Response.TransmitFile itself, <a href="http://support.microsoft.com/kb/902780">see this Microsoft fix</a>.</p>
<p>If you are interested in some specific topic related to ASP.Net let me know and I&#8217;ll cover it in a future post. I am always interested to hear what types of things people are doing with .Net.</p>
]]></content:encoded>
			<wfw:commentRss>http://devsushi.com/2007/01/31/aspnet-file-download-protection-through-authentication/feed/</wfw:commentRss>
		<slash:comments>9</slash:comments>
		</item>
		<item>
		<title>ASP.Net Dynamic Controls (Part 4)</title>
		<link>http://devsushi.com/2007/01/19/aspnet-dynamic-controls-part-4/</link>
		<comments>http://devsushi.com/2007/01/19/aspnet-dynamic-controls-part-4/#comments</comments>
		<pubDate>Fri, 19 Jan 2007 06:49:49 +0000</pubDate>
		<dc:creator>Adam</dc:creator>
				<category><![CDATA[miscellaneous]]></category>
		<category><![CDATA[asp.net]]></category>

		<guid isPermaLink="false">http://adamhewgill.com/devsushi/2007/01/19/aspnet-dynamic-controls-part-4/</guid>
		<description><![CDATA[I&#8217;ve had several people ask about redrawing a page that contains Dynamic Controls. The idea is that you have a page with a &#8220;Save&#8221; button that posts back but the page reloads exactly as it was. You can think of it like the &#8220;Apply&#8221; button in Windows but on a web page. The heart of [...]]]></description>
			<content:encoded><![CDATA[<p></p>
<p>I&#8217;ve had several people ask about redrawing a page that contains Dynamic Controls. The idea is that you have a page with a &#8220;Save&#8221; button that posts back but the page reloads exactly as it was. You can think of it like the &#8220;Apply&#8221; button in Windows but on a web page. The heart of the issue is what is the proper way to redisplay the data in the dynamic controls since they don&#8217;t have a viewstate.<span id="more-33"></span></p>
<p>In fact they do seem to have a viewstate but only if you regenerate the control exactly as it was before the post back. So if you create a checkbox with an ID of <em>chkbox1</em> during Page_Load, after post back recreate it again during Page_Load with the same ID and it will repopulate from the viewstate. So you don&#8217;t need to use Request.Form to get the values and repopulate by hand which is a major plus.</p>
<pre class="brush: vb">&lt;%@ Page Language=&quot;VB&quot; %&gt;

&lt;script runat=&quot;server&quot;&gt;

    Sub Page_Load()
        lblMessage.Text = &quot;&quot;

        If chkRegen.Checked Then
            Dim rnd As New Random(Date.Now.Millisecond)
            Dim chk As CheckBox
            Dim num As Integer
            ' Generate dynamic controls
            For i As Integer = 1 To 10
                ' Generate a checkbox
                chk = New CheckBox()
                If chkRandom.Checked Then
                    num = rnd.Next
                    chk.ID = &quot;chk&quot; &amp; num
                    chk.Text = &quot;Checkbox &quot; &amp; num
                Else
                    chk.ID = &quot;chk&quot; &amp; i
                    chk.Text = &quot;Checkbox &quot; &amp; i
                End If
                ' Add the checkbox to the placeholder
                phControls.Controls.Add(New LiteralControl(&quot;&lt;div&gt;&quot;))
                phControls.Controls.Add(chk)
                phControls.Controls.Add(New LiteralControl(&quot;&lt;/div&gt;&quot;))
            Next
        End If
    End Sub

    Sub Click_Save(ByVal s As Object, ByVal e As EventArgs)
        lblMessage.Text = &quot;Clicked Save&quot;
    End Sub

&lt;/script&gt;

&lt;!DOCTYPE html PUBLIC &quot;-//W3C//DTD XHTML 1.0 Transitional//EN&quot;
    &quot;http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd&quot;&gt;

&lt;html xmlns=&quot;http://www.w3.org/1999/xhtml&quot; &gt;
&lt;head runat=&quot;server&quot;&gt;
    &lt;title&gt;Dynamic Control Test&lt;/title&gt;
    &lt;style type=&quot;text/css&quot;&gt;
        body { font-family: verdana, sans-serif; }
        div { padding: 5px; }
    &lt;/style&gt;

&lt;/head&gt;
&lt;body&gt;
    &lt;h1&gt;ASP.Net Dynamic Controls (Part 4) Demo&lt;/h1&gt;
    &lt;form id=&quot;form1&quot; runat=&quot;server&quot;&gt;
    &lt;div&gt;
        &lt;asp:Button ID=&quot;btnSave&quot; OnClick=&quot;Click_Save&quot; Text=&quot;Save&quot; runat=&quot;server&quot; /&gt;
        &lt;asp:Label ID=&quot;lblMessage&quot; runat=&quot;server&quot; /&gt;
    &lt;/div&gt;
    &lt;div&gt;&lt;asp:CheckBox ID=&quot;chkRegen&quot; Text=&quot;Regenerate Dynamic Controls&quot; Checked=&quot;true&quot; runat=&quot;server&quot; /&gt;&lt;/div&gt;
    &lt;div&gt;&lt;asp:CheckBox ID=&quot;chkRandom&quot; Text=&quot;Use Different IDs&quot; runat=&quot;server&quot; /&gt;&lt;/div&gt;
    &lt;asp:PlaceHolder ID=&quot;phControls&quot; runat=&quot;server&quot; /&gt;
    &lt;div&gt;&lt;h2&gt;Request.Form Contents&lt;/h2&gt;&lt;dl&gt;
    &lt;%  Dim str As String
        For Each str In Request.Form.AllKeys
            Response.Write(&quot;&lt;dt&gt;&quot; &amp; str &amp; &quot;&lt;/dt&gt;&lt;dd&gt;&quot; &amp; Request.Form(str) &amp; &quot;&lt;/dd&gt;&quot;)
        Next
        %&gt;
    &lt;/dl&gt;&lt;/div&gt;
    &lt;/form&gt;
&lt;/body&gt;
&lt;/html&gt;</pre>
<p>The sample code above shows off this working. There are a total of twelve checkboxes the first two are settings for the post back and the remainder are the dynamic controls. If you uncheck &#8220;Regenerate Dynamic Controls&#8221; and click save you will see that the checkboxes disappear but data remains in the Request.Form collection. Also if you check &#8220;Use Different IDs&#8221; it will randomly generate the IDs and the controls will not be repopulated, <em>the ID must be the same for repopulation</em>.</p>
<p><a href="http://adamhewgill.com/devsushi/2006/08/27/aspnet-dynamic-control-creation-part-1/">ASP.Net Dynamic Controls (Part 1) &laquo;</a><br />
<a href="http://adamhewgill.com/devsushi/2006/09/01/aspnet-dynamic-controls-part-2/">ASP.Net Dynamic Controls (Part 2) &laquo;</a><br />
<a href="http://adamhewgill.com/devsushi/2006/12/23/aspnet-dynamic-controls-part-3/">ASP.Net Dynamic Controls (Part 3) &laquo;</a></p>
]]></content:encoded>
			<wfw:commentRss>http://devsushi.com/2007/01/19/aspnet-dynamic-controls-part-4/feed/</wfw:commentRss>
		<slash:comments>14</slash:comments>
		</item>
		<item>
		<title>ASP.Net Dynamic Controls (Part 3)</title>
		<link>http://devsushi.com/2006/12/23/aspnet-dynamic-controls-part-3/</link>
		<comments>http://devsushi.com/2006/12/23/aspnet-dynamic-controls-part-3/#comments</comments>
		<pubDate>Sat, 23 Dec 2006 10:10:42 +0000</pubDate>
		<dc:creator>Adam</dc:creator>
				<category><![CDATA[miscellaneous]]></category>
		<category><![CDATA[asp.net]]></category>
		<category><![CDATA[css/xhtml]]></category>

		<guid isPermaLink="false">http://adamhewgill.com/devsushi/2006/12/23/aspnet-dynamic-controls-part-3/</guid>
		<description><![CDATA[I have received a few requests via email and in comments for more detail on how to get your data back after postback with dynamic controls. This evening I started to put together some code examples and mulled over the details of the article in my head. The first step was to re-read my previous [...]]]></description>
			<content:encoded><![CDATA[<p></p>
<p>I have received a few requests via email and in comments for more detail on how to get your data back after postback with dynamic controls. This evening I started to put together some code examples and mulled over the details of the article in my head. The first step was to re-read my previous two articles so I could get my bearings on where to start. Part 1 of this series is an initial outline of <a href="http://adamhewgill.com/devsushi/2006/08/27/aspnet-dynamic-control-creation-part-1/">how to create dynamic controls and use Request.Form to collect the data after postback</a>. Part 2 went into detail on <a href="http://adamhewgill.com/devsushi/2006/09/01/aspnet-dynamic-controls-part-2/">how to figure out which button was clicked to cause postback using a JavaScript technique</a>. In the middle of re-reading the second article I had an epiphany. There is a better way to do that! The proper method is standards compliant, accessible and is outlined in the <abbr title="World Wide Web Consortium">W3C</abbr> HTML specifications. So I will put the original article on hold and explain this technique.<span id="more-30"></span></p>
<p>What I didn&#8217;t realize when I wrote Part 2 of this series was that HTML forms have a built in way to recognize what button was clicked. Here is a relevant quote from the spec explaining it (poorly).</p>
<blockquote cite="http://www.w3.org/TR/html4/interact/forms.html#successful-controls"><p>A successful control is &#8220;valid&#8221; for submission. Every successful control has its control name paired with its current value as part of the submitted form data set. A successful control must be defined within a FORM element and must have a control name.</p></blockquote>
<p>So that is just a wordy way to say that form elements have their values returned in a name/value pair after the form is submitted. We have all seen the URL GET version (http://&#8230;../index.php?name=value&#038;name2=value2) of this and the POST version is the same inside the closed POST package. So the only question is &#8220;What is a successful control really?&#8221; which requires more digging. <a href="http://www.w3.org/TR/html4/interact/forms.html#successful-controls">Take a look for yourself there are many reasons</a>. The one that is most interesting is &#8220;If a form contains more than one submit button, only the activated submit button is successful.&#8221; Perfect! So which ever button is clicked will have its name/value pair available to us on the other side of the submit. Lets take a look at an example:</p>
<pre class="brush: html">&lt;form method="get" action="self.php"&gt;
  &lt;input type="submit" name="button1" value="Text on Button1" /&gt;
  &lt;input type="submit" name="button2" value="Text on Button2" /&gt;
&lt;/form&gt;
</pre>
<p>You can see that the name/value pair after the question mark shows which you clicked. Since this does not require JavaScript it is a much more accessible solution to the problem. A wider number of users are now able to participate which takes us closer to our goal of creating a great website. The next step is to figure out how to utilize this information to overcome the chicken and egg problem.</p>
<p>Before going further I thought I would recap the chicken and egg problem so you know why we are doing this in the first place. The simplest example is a dynamic list of, for example, your friends on Facebook. When the page is generated we go to the database and collect all the people you have tagged as friends generating a list on the page. Each entry has some tools so you can interact with your friends, this included a delete button to remove them (perhaps if they Poke you rudely or defamate your wall). In order for the buttons to function we needed to generate the list in the Page_Load event. Now when the user pushes the delete button the page is redrawn. Event handlers fire after Page_Load so we have already added the deleted person back before they are to be deleted. In some cases it wouldn&#8217;t be a problem to simply remove them but it is wasted effort. We need a way of knowing about the click before we regenerate the list</p>
<pre class="brush: vb">Sub Page_Load()
  Dim i As Integer
  Dim btn As Button
  For i = 1 To 10
    btn = New Button
    btn.ID = "btn" &#038; i
    btn.Text = "Button " &#038; i
    phFun.Controls.Add(btn)
  Next

  For i = 1 To 10
    If Not String.IsNullOrEmpty(Request.Form("btn" &#038; i)) Then
      &hellip; ' Perform action on the ith item
    End If
  Next
End Sub
&hellip;
&lt;asp:PlaceHolder ID="phFun" runat="server" /&gt;
</pre>
<p>You will notice that in the last example I don&#8217;t set the name or the value property of the button control. ASP.Net does the work behind the scenes, whatever you put for the ID will be the id and name attributes in the HTML and whatever you put in for Text will be the value attribute. I would like to hear from you, let me know if this works for you or if you need help getting it to fit the bill for your project. I&#8217;ll be back with the article I was initially going to write sometime next week and somewhere down the road I will make the jump to AJAX dynamic controls, stay tuned.</p>
<p><a href="http://adamhewgill.com/devsushi/2006/08/27/aspnet-dynamic-control-creation-part-1/">ASP.Net Dynamic Controls (Part 1) &laquo;</a><br />
<a href="http://adamhewgill.com/devsushi/2006/09/01/aspnet-dynamic-controls-part-2/">ASP.Net Dynamic Controls (Part 2) &laquo;</a><br />
<a href="http://adamhewgill.com/devsushi/2007/01/19/aspnet-dynamic-controls-part-4/">ASP.Net Dynamic Controls (Part 4) &raquo;</a></p>
]]></content:encoded>
			<wfw:commentRss>http://devsushi.com/2006/12/23/aspnet-dynamic-controls-part-3/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>ASP.Net Regular Expressions</title>
		<link>http://devsushi.com/2006/11/28/aspnet-regular-expressions/</link>
		<comments>http://devsushi.com/2006/11/28/aspnet-regular-expressions/#comments</comments>
		<pubDate>Tue, 28 Nov 2006 21:22:48 +0000</pubDate>
		<dc:creator>Adam</dc:creator>
				<category><![CDATA[miscellaneous]]></category>
		<category><![CDATA[asp.net]]></category>

		<guid isPermaLink="false">http://adamhewgill.com/devsushi/2006/11/28/aspnet-regular-expressions/</guid>
		<description><![CDATA[The RegularExpressionValidator control is an often overlooked tool for validation. A lot of people look at the validation expression and are puzzled at how to proceed. Most settle on the RequiredFieldValidator and hand coded filtering in the submit action. I hope to compile here a list of common expressions needed for web form validation so [...]]]></description>
			<content:encoded><![CDATA[<p></p>
<p>The <em><a href="http://msdn2.microsoft.com/en-us/library/system.web.ui.webcontrols.regularexpressionvalidator(VS.80).aspx">RegularExpressionValidator</a></em> control is an often overlooked tool for validation. A lot of people look at the validation expression and are puzzled at how to proceed. Most settle on the <em><a href="http://msdn2.microsoft.com/en-us/library/system.web.ui.webcontrols.requiredfieldvalidator(VS.80).aspx">RequiredFieldValidator</a></em> and hand coded filtering in the submit action. I hope to compile here a list of common expressions needed for web form validation so that your job is easier.<span id="more-23"></span></p>
<h3>Why Regular Expressions</h3>
<p>Forming a regular expression (sometimes shortened to RegEx) is not the easiest task since it requires a lot of &#8220;what if?&#8221; thinking about potential user input. There is also a large barrier to entry for the common programmer since they must first learn all of the special characters and how each of them works, then how they all work together when data is processed. It can take a very long time for a programmer to become proficient at creating the perfect expression. I have had a fair bit of experience at this but by no means would I call myself an expert.</p>
<p>When creating web forms we have the option to make them as flexible or as rigid as we want. On the rigid side we can require that the name is entered separately in first and last name boxes or that the phone number is entered in area code, exchange and number boxes, etc. This makes data collection and reporting very easy after the fact. On the flexible side the name could be one box, as well as the phone number, etc. I have seen both methods in action and the resulting data sets.</p>
<p>Data from the rigid side is very organized and clean and poses few issues when running queries after the fact. Data from the flexible side on the other hand is messy and requires much processing and special considerations to use. You might suspect from this that I think the rigid method is the best but you would be wrong. I am a big proponent of the flexible solution because I know how it can be done right and the result is a much friendlier user entry experience. All data collection issues can be solved with a combination of regular expressions and clean-up algorithms.</p>
<h3>The RegEx List</h3>
<pre class="brush: plain">Email Address
^[a-zA-Z0-9&#92;-&#92;._]+@([a-zA-Z0-9&#92;-_]+&#92;.)+[a-zA-Z]{2,4}$

Phone Number (requires area code)
^&#92;+?1?-?(&#92;(&#92;d{3}&#92;)|&#92;d{3})-?&#92;d{3}-?&#92;d{4}$

Phone Number (optional area code)
^&#92;+?1?-?(&#92;(&#92;d{3}&#92;)|&#92;d{3}|)-?&#92;d{3}-?&#92;d{4}$

Curreny Amount (including dollars and cents)
^&#92;$?&#92;d+(&#92;.&#92;d{2})?$

Name (last, first)
^[a-zA-Z&#92;-'&#92;s]+,&#92;s*[a-zA-Z&#92;-'&#92;.]+(&#92;s+[a-zA-Z&#92;-'&#92;.]+)*$

Name (first, last)
^[a-zA-Z&#92;-'&#92;.]+(&#92;s+[a-zA-Z&#92;-'&#92;.]+)+$

Postal Code
^[a-zA-Z][0-9][a-zA-Z]&#92;s*[0-9][a-zA-Z][0-9]$

Zip Code
^&#92;d{5}(&#92;-?&#92;d{4})?$</pre>
<h3>Clean-up Algorithms</h3>
<p>These regular expressions allow for the user to enter most of the common syntax for a particular item which then allows you to write a clean-up function that changes the information into the format you want to store in the database. These functions would take the user input, check for the various cases (i.e. has area code brackets or not) and return it in the correct format. I recommend starting a module of these functions that each handle a different input type. After a short period of time you will find that you are able to throw together a rock solid flexible form in a few hours.</p>
<p>Feedback and expression requests are much appreciated. Let me know how these work out for you. Here are a few resources which I have found extremely useful: <a href="http://msdn2.microsoft.com/en-us/library/ms972966.aspx">Regular Expressions in ASP.Net</a> (MSDN) and the <a href="http://www.dotnetcoders.com/web/Learning/Regex/RegexTester.aspx">Regular Expression Tester</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://devsushi.com/2006/11/28/aspnet-regular-expressions/feed/</wfw:commentRss>
		<slash:comments>11</slash:comments>
		</item>
		<item>
		<title>Error Handling Correction</title>
		<link>http://devsushi.com/2006/10/11/error-handling-correction/</link>
		<comments>http://devsushi.com/2006/10/11/error-handling-correction/#comments</comments>
		<pubDate>Wed, 11 Oct 2006 15:06:36 +0000</pubDate>
		<dc:creator>Adam</dc:creator>
				<category><![CDATA[miscellaneous]]></category>
		<category><![CDATA[asp.net]]></category>

		<guid isPermaLink="false">http://adamhewgill.com/devsushi/2006/10/11/error-handling-correction/</guid>
		<description><![CDATA[Today I realized a huge problem with the global.asax error handling method that I provided in my last entry. The problem is that if you ever run into compilation errors you are left completely in the dark as to what page it came from. You just have the date, logged in user and ip address [...]]]></description>
			<content:encoded><![CDATA[<p>Today I realized a huge problem with the global.asax error handling method that I provided in my last entry. The problem is that if you ever run into compilation errors you are left completely in the dark as to what page it came from.  You just have the date, logged in user and ip address which isn&#8217;t very helpful.<span id="more-17"></span></p>
<pre class="brush: vb">&lt;%@ Import Namespace="System.Web" %&gt;
&lt;%@ Import Namespace="System.IO" %&gt;

&lt;script runat="server"&gt;
  Sub Application_Error(ByVal sender As Object, ByVal e As EventArgs)
    Dim err As Exception = Server.GetLastError()
    Dim ctx As HttpContext = HttpContext.Current

    ' Collect useful data
    Dim user As String = ctx.Request.ServerVariables("AUTH_USER")
    Dim ip As String = ctx.Request.ServerVariables("REMOTE_ADDR")
    Dim filename As String = ctx.Request.PhysicalApplicationPath &amp; "errors.txt"
    Dim sw As StreamWriter = File.AppendText(filename)
    sw.WriteLine("--------------------------------- ")
    sw.WriteLine("ERROR: [ " &amp; Date.Now() &amp; " ] [ " &amp; user &amp; " ] [ " &amp; ip &amp; " ]")
    sw.WriteLine("URL: " &amp; ctx.Request.Url.AbsolutePath)
    sw.WriteLine("QUERYSTRING: " &amp; ctx.Request.QueryString.ToString)
    sw.WriteLine("FORM: " &amp; ctx.Request.Form.ToString)
    sw.WriteLine("REFERER: " &amp; ctx.Request.ServerVariables("HTTP_REFERER"))

    Dim cnt As Integer = 0   ' Avoid infinite looping (just in case)
    err = err.InnerException
    While cnt &lt; 5 And Not err Is Nothing
      If cnt = 0 Then
        sw.WriteLine("======== EXCEPTION ========")
      Else
        sw.WriteLine("----- INNER EXCEPTION -----")
      End If
      sw.WriteLine("MESSAGE: " &amp; err.Message)
      sw.WriteLine("TYPE: " &amp; err.GetType().ToString)
      sw.WriteLine("SOURCE: " &amp; err.Source)
      sw.WriteLine("TARGETSITE: " &amp; err.TargetSite.ToString)
      sw.WriteLine("STACKTRACE:" &amp; vbNewLine &amp; err.StackTrace)
      err = err.InnerException
      cnt += 1
    End While

    ' Finalize writing to file
    sw.WriteLine(vbNewLine)
    sw.Close()
  End Sub
&lt;/script&gt;</pre>
<p>Now you will get the header and the page the error occurred on in all circumstances. Additionally there is less duplication since the form string is extremely long due to the viewstate and would be repeated in the event of an inner exception.</p>
]]></content:encoded>
			<wfw:commentRss>http://devsushi.com/2006/10/11/error-handling-correction/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>ASP.Net Error Logging</title>
		<link>http://devsushi.com/2006/10/06/aspnet-error-logging/</link>
		<comments>http://devsushi.com/2006/10/06/aspnet-error-logging/#comments</comments>
		<pubDate>Fri, 06 Oct 2006 13:39:23 +0000</pubDate>
		<dc:creator>Adam</dc:creator>
				<category><![CDATA[miscellaneous]]></category>
		<category><![CDATA[asp.net]]></category>

		<guid isPermaLink="false">http://adamhewgill.com/devsushi/2006/10/06/aspnet-error-logging/</guid>
		<description><![CDATA[Like any good ASP.Net developer I have Scott Guthrie&#8217;s blog bookmarked in my GReader. Recently I was browsing through the archives and came across an entry about not using Debug=&#8221;True&#8221; in production applications. I have to admit that I am VERY guilty of this since pretty much all of my applications are production and are [...]]]></description>
			<content:encoded><![CDATA[<p></p>
<p>Like any good ASP.Net developer I have <a href="http://weblogs.asp.net/scottgu/">Scott Guthrie&#8217;s blog</a> bookmarked in my GReader. Recently I was browsing through the archives and came across an entry about not using <a href="http://weblogs.asp.net/scottgu/archive/2006/04/11/Don_1920_t-run-production-ASP.NET-Applications-with-debug_3D001D20_true_1D20_-enabled.aspx">Debug=&#8221;True&#8221; in production applications</a>. I have to admit that I am VERY guilty of this since pretty much all of my applications are production and are using Debug=&#8221;True&#8221;. The reason for this is simple, I am just me and I have to monitor/update all of these applications. I do as much testing as I can before sending it off to production and moving on to the next project but often once the users start working with it something bad happens. The ability to have the errors logged including the line number in the source code is invaluable when going back to an application to fix a bug after a length of time. However, in light of Scott&#8217;s points it stops now.<span id="more-16"></span></p>
<h3>Current Error Methods</h3>
<p>First let me outline how I look after error handling currently and then I will discuss alternatives and changes to become Debug=&#8221;False&#8221; compliant. There are a few different components to my current method but all are very simple and chances are most of you already have a much better system.</p>
<h4>Try/Catch Blocks</h4>
<p>I only use a Try/Catch block when I know exactly what might happen and how to recover from it. In fact I use them really only in three instances: Transactions, Date Conversion Checking and LDAP Authentication. The reason for this is because these cases all require (as far as I know) that you catch exceptions in order to handle a normal failure case. Lets take a quick look why. Transactions are for atomic database handling and allow you to cancel all partial queries if anything during a block of code causes an exception. So you must catch any exception so that you can rollback the transaction and keep the databases <a href="http://en.wikipedia.org/wiki/Referential_integrity">referential integrity</a>. I have never been able to find an exception free way (save by doing a lot of coding) to check if a date is in the proper format to be put into a date object thus a catch is needed. Finally, the method to check user credentials with LDAP is to try connecting to it using those credentials. When you connect with invalid credentials .Net&#8217;s LDAP module raises an exception which you must catch to provide login failed information. Every other case where an exception might occur I program my way out of it by defensive checking and failing that let the exception propagate beyond the Page.</p>
<h4>Application Error Handler</h4>
<p>ASP.Net provides you the ability to override the application wide error handler with your own code so that you can log any errors that propagate up from your pages. You do this in the global.asax file that sits in your application directory beside your web.config file. Here is mine:</p>
<pre class="brush: vb">&lt;%@ Import Namespace="System.Web" %&gt;
&lt;%@ Import Namespace="System.IO" %&gt;

&lt;script runat="server"&gt;
  Sub Application_Error(ByVal sender As Object, ByVal e As EventArgs)
    Dim err As Exception = Server.GetLastError()
    Dim ctx As HttpContext = HttpContext.Current

    ' Collect useful data
    Dim user As String = ctx.Request.ServerVariables("AUTH_USER")
    Dim ip As String = ctx.Request.ServerVariables("REMOTE_ADDR")
    Dim filename As String = ctx.Request.PhysicalApplicationPath &amp; "errors.txt"
    Dim sw As StreamWriter = File.AppendText(filename)
    sw.WriteLine("--------------------------------- ")
    sw.WriteLine("ERROR: [ " &amp; Date.Now() &amp; " ] [ " &amp; user &amp; " ] [ " &amp; ip &amp; " ]")
    sw.WriteLine("URL: " &amp; ctx.Request.Url.AbsolutePath)
    sw.WriteLine("QUERYSTRING: " &amp; ctx.Request.QueryString.ToString)
    sw.WriteLine("FORM: " &amp; ctx.Request.Form.ToString)
    sw.WriteLine("REFERER: " &amp; ctx.Request.ServerVariables("HTTP_REFERER"))

    Dim cnt As Integer = 0   ' Avoid infinite looping (just in case)
    err = err.InnerException
    While cnt &lt; 5 And Not err Is Nothing
      If cnt = 0 Then
        sw.WriteLine("======== EXCEPTION ========")
      Else
        sw.WriteLine("----- INNER EXCEPTION -----")
      End If
      sw.WriteLine("MESSAGE: " &amp; err.Message)
      sw.WriteLine("TYPE: " &amp; err.GetType().ToString)
      sw.WriteLine("SOURCE: " &amp; err.Source)
      sw.WriteLine("TARGETSITE: " &amp; err.TargetSite.ToString)
      sw.WriteLine("STACKTRACE:" &amp; vbNewLine &amp; err.StackTrace)
      err = err.InnerException
      cnt += 1
    End While

    ' Finalize writing to file
    sw.WriteLine(vbNewLine)
    sw.Close()
  End Sub
&lt;/script&gt;</pre>
<p>The gist of the code is to grab the error that causes us to be in the error handler and the current HTTP context and we&#8217;ll dump as much information as possible into errors.txt for debugging. With Debug=&#8221;True&#8221; this includes the line number that caused the exception. At this point all that is needed is to read the exception and find the bug. You can of course email the exception to yourself instead of logging it to a text file if you wish.</p>
<h3>No more Debug=&#8221;True&#8221;</h3>
<p>Now let us discuss what to do in the absence of Debug=&#8221;True&#8221;. All the above will still work exactly as before except that the line number is missing. There is no solution for this since the debug symbols that gave you the line number in the first place are now gone, compiled code has no line numbers.</p>
<h4>Try/Catch Blocks</h4>
<p>You can extend the use of your exception handling to include an error wrapper that collects the exceptions from a block of code and wraps it in another exception which then will be logged. This way you know exactly which block of code caused the error. Try not to make your Try/Catch blocks too small because the overhead might cause performance degradation.</p>
<h4>Re-Enable Debug=&#8221;True&#8221;</h4>
<p>If you have an exception happen that you can&#8217;t track down using the information provided then you can temporarily re-enable debug mode until you get the error again with the line number. This isn&#8217;t a very good solution since you are still using Debug=&#8221;True&#8221; in production.</p>
<h4>Draw it out</h4>
<p>Drawing out the relationships between the code and data is my method of choice for solving bugs I can&#8217;t find quickly. Narrow down where the error came from as best you can within the offending Page. It is almost a guarantee that the error was causes by user input so first write down all the inputs to the block of code on the left side of the page. Take a look at the controls that collect the inputs and figure out what the user can possibly enter. Next you have to consider the malicious case of page hijacking (which circumvents MaxLengths, hidden value reliability, JavaScript checks and updates, etc.). Are you dropping these inputs directly into a database that only allows a certain number of characters? Will an empty string cause problems? Take each input one at a time and walk it through its code path keeping in mind the potential inputs you calculated. Somewhere along one of the paths of one of the inputs is your exception.</p>
<p>Error handling is a very important part of programming and hopefully these tips will help you to be able to find and fix your applications bugs in a faster and more efficient way. I would really appreciate your thoughts or improvements on these methods.</p>
]]></content:encoded>
			<wfw:commentRss>http://devsushi.com/2006/10/06/aspnet-error-logging/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Downlevel Forms Authentication</title>
		<link>http://devsushi.com/2006/09/25/downlevel-forms-authentication/</link>
		<comments>http://devsushi.com/2006/09/25/downlevel-forms-authentication/#comments</comments>
		<pubDate>Mon, 25 Sep 2006 20:11:16 +0000</pubDate>
		<dc:creator>Adam</dc:creator>
				<category><![CDATA[miscellaneous]]></category>
		<category><![CDATA[asp.net]]></category>

		<guid isPermaLink="false">http://adamhewgill.com/devsushi/2006/09/25/downlevel-forms-authentication/</guid>
		<description><![CDATA[I ran into this issue a couple of weeks ago and have been itching to throw together an article about it. I initially suspected that it was a bug that was causing the problem but now I realize the truth. When you force a page into “Downlevel” mode using the ClientTarget property of the &#60;%@ [...]]]></description>
			<content:encoded><![CDATA[<p>I ran into this issue a couple of weeks ago and have been itching to throw together an article about it. I initially suspected that it was a bug that was causing the problem but now I realize the truth. When you force a page into “Downlevel” mode using the ClientTarget property of the &lt;%@ Page %&gt; tag .Net doesn&#8217;t use cookies anymore. Out of the box forms authentication is done using session tracking via cookies and thus you are unable to log in.<span id="more-14"></span></p>
<p>One option is to not use “Downlevel” on the login page so that .Net will successfully give the user a cookie and they can proceed into your application. If you try this you will notice that users can not log out if you have the sign-out page using “Downlevel” too since .Net can&#8217;t expire the cookie. A work-around for this problem is to create a sign-out link instead of having the sign-out ability on every page.  This way you can still use “Downlevel” in your application without blocking user sign-out. The following code is signout.aspx:</p>
<pre class="brush: vb">&lt;script runat="server"&gt;
  Sub Page_Load()
    Session.Abandon()
    FormsAuthentication.SignOut()
    Response.Redirect("login.aspx", True)
  End Sub
&lt;/script&gt;
</pre>
<p>Thankfully even when your page is in “Downlevel” mode it can still access the Session variables based on the Session ID in the user cookie. So reading cookies is no problem in “Downlevel” mode just writing to them. The main reason for using “Downlevel” is to stop .Net from using client side validation so what are our options? Is there a different way to achieve this? How about changing how “Downlevel” functions?</p>
<p>Upon inspection all the browser configuration information exits in C:\WINDOWS\ Microsoft .NET\ Framework\ v2.0.xxxx\ CONFIG\ Browsers in various files. The “Downlevel” configuration is a clientTarget alias that points to “Generic Downlevel” which exists in the generic.browser file. I believe that if you change the cookie setting to &#8220;true&#8221; then restart IIS you will have cookies working in “Downlevel” mode.  However, I did not test this since I don&#8217;t believe this is a very good option. The browser detection is a pretty complex hierarchy and it is best not to mess with it. Imagine that one day a user visits that actually maps to “Downlevel” on one of your other applications but then is given cookies what will happen? The browser will likely discard the cookie but the full repercussions are not simple to determine. There is more to “Downlevel” than cookies so from now on I won&#8217;t be recommending its use.</p>
<p>How about forcing server side validation? Absolutely! Although I could not find an application wide method you can set the EnableClientScript property of each validator control to &#8220;false&#8221; which will force the control into server-side validation mode.</p>
<p>What to take away from this article? Well the issue of using ClientTarget=&#8221;Downlevel&#8221; is more complex than simply causing all controls to use server-side validation in one statement so it is best not to. Take the extra time to set the EnableClientScript=&#8221;false&#8221; for each validator and save yourself the issues involved with the ClientTarget method.</p>
]]></content:encoded>
			<wfw:commentRss>http://devsushi.com/2006/09/25/downlevel-forms-authentication/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
