<?xml version="1.0" encoding="utf-8"?>
<rss xmlns:content="http://purl.org/rss/1.0/modules/content/" version="2.0">
  <channel>
    <title><![CDATA[Security Briefs]]></title>
    <link>http://securityratty.com/feed/1df878f224c46a2378494f61f41df90b</link>
    <description></description>
    <pubDate>Fri, 01 Aug 2008 09:59:01 +0000</pubDate>
    <generator>iRatty Engine</generator>
    <docs>http://blogs.law.harvard.edu/tech/rss</docs>
    <item>
      <title><![CDATA[Null Strings in ASP.NET Declarative DataSource Updates]]></title>
      <link>http://securityratty.com/article/11f8906732a7b86831292456d642b2f5</link>
      <guid>http://securityratty.com/article/11f8906732a7b86831292456d642b2f5</guid>
      <description><![CDATA[I just spent about 15 minutes debugging a problem where a document was getting unexpected nulls where empty strings should have been. Indeed controls like the TextBox have code in them that allows you...]]></description>
      <content:encoded><![CDATA[<p>I just spent about 15 minutes debugging a problem where a document was getting unexpected nulls where empty strings should have been. Indeed controls like the TextBox have code in them that allows you to set the Text property to null and the TextBox will convert that into an empty string. So it&#39;s a bit counterintuitive that <em>the declarative data source works the opposite way by default</em>.</p> <p>When you use a declarative data source to perform a parameterized update that contains string parameters, consider setting ConvertEmptyStringToNull=&#39;false&#39; on your &lt;asp:Parameter&gt; elements, because <em>it&#39;s true by default</em>! In other words, if a text field contains an empty string, it&#39;ll be sent to your declarative data source not as string.Empty, but as null.</p> <p>Now I don&#39;t know about you, but I don&#39;t like dealing with nulls if I can avoid it. Especially strings. Unless there&#39;s a clear need to have a null state, I avoid them like the plague not only in my database designs but also in my XML schema designs. Hopefully this helps somebody out!</p><div style="clear:both;"></div><img src="http://www.pluralsight.com/community/aggbug.aspx?PostID=52773" width="1" height="1">]]></content:encoded>
      <pubDate>Fri, 29 Aug 2008 11:42:47 +0000</pubDate>
      <category domain="http://securityratty.com/tag/strings">strings</category>
      <category domain="http://securityratty.com/tag/declarative data source">declarative data source</category>
      <category domain="http://securityratty.com/tag/empty strings">empty strings</category>
      <category domain="http://securityratty.com/tag/null">null</category>
      <category domain="http://securityratty.com/tag/empty">empty</category>
      <category domain="http://securityratty.com/tag/xml schema designs">xml schema designs</category>
      <category domain="http://securityratty.com/tag/textbox">textbox</category>
      <category domain="http://securityratty.com/tag/text property">text property</category>
      <category domain="http://securityratty.com/tag/nulls">nulls</category>
      <source url="http://www.pluralsight.com/community/blogs/keith/archive/2008/08/29/null-strings-in-asp-net-declarative-datasource-updates.aspx">Null Strings in ASP.NET Declarative DataSource Updates</source>
    </item>
    <item>
      <title><![CDATA[Serializable XmlDocument]]></title>
      <link>http://securityratty.com/article/94c84cd2ea7a6ea71c9712991d27722d</link>
      <guid>http://securityratty.com/article/94c84cd2ea7a6ea71c9712991d27722d</guid>
      <description><![CDATA[It's surprising that XmlDocument isn't marked [Serializable], because it's very natural to serialize one into a stream. I wanted to put an object into ASP.NET ViewState the other day, and quickly ran...]]></description>
      <content:encoded><![CDATA[<p>It&#39;s surprising that XmlDocument isn&#39;t marked [Serializable], because it&#39;s very natural to serialize one into a stream. I wanted to put an object into ASP.NET ViewState the other day, and quickly ran into this roadblock, because part of the object included an XmlDocument, which is not serializable. A quick search revealed that most people deal with this problem by storing a string instead. Indeed, that was where I started, but I quickly realized that there are multiple places in my code where I want to do this sort of thing, and I don&#39;t want to have to mess with it in each data structure that contains an XmlDocument.</p>
<p>So I put together a simple class that holds an XmlDocument and implements ISerializable and called it SerializableXmlDocument. I&#39;m sharing the source code here in the hopes that</p>
<blockquote>
<p>a) somebody will find it useful, and</p>
<p>b) somebody smarter than I am will point out how I screwed it up and help me make it better.</p>
</blockquote>
<p>SerializableXmlDocument includes implicit conversion operators to make it easy to convert to/from an XmlDocument. It holds the actual document in a property called Value. This &quot;isomorph&quot; pattern is one that I picked up from <a href="http://www.pluralsight.com/community/blogs/craig/default.aspx" target="_blank">Craig</a>.</p>
<p>While writing this code, I also wrote a helpful extension method for getting a byte array out of a MemoryStream that is exactly the length of the data written to the stream so far (CopyUpToSeekPointer). So don&#39;t go looking in the docs for MemoryStream for this method :) This is obviously not the most efficient way to consume bytes written to a MemoryStream since it copies the data into a new byte array, but it&#39;s very convenient in many scenarios.</p>
<p>Here is SerializableXmlDocument.cs:</p>
<pre class="csharpcode"><span class="kwrd">using</span> System;<br /><span class="kwrd">using</span> System.Runtime.Serialization;<br /><span class="kwrd">using</span> System.Xml;<br /><span class="kwrd">using</span> System.IO;<br /><br /><span class="kwrd">namespace</span> Pluralsight.Samples<br />{<br />    [Serializable]<br />    <span class="kwrd">public</span> <span class="kwrd">class</span> SerializableXmlDocument : ISerializable<br />    {<br />        <span class="kwrd">public</span> SerializableXmlDocument() { }<br />        <span class="kwrd">public</span> SerializableXmlDocument(XmlDocument <span class="kwrd">value</span>)<br />        {<br />            <span class="kwrd">this</span>.Value = <span class="kwrd">value</span>;<br />        }<br /><br />        <span class="kwrd">public</span> XmlDocument Value { get; set; }<br /><br />        <span class="preproc">#region</span> ISerializable implementation<br />        <span class="kwrd">public</span> SerializableXmlDocument(SerializationInfo info,<br />                                       StreamingContext context)<br />        {<br />            <span class="kwrd">byte</span>[] serializedData = (<span class="kwrd">byte</span>[])info.GetValue(<span class="str">&quot;doc&quot;</span>,<br />                <span class="kwrd">typeof</span>(<span class="kwrd">byte</span>[]));<br />            <span class="kwrd">if</span> (<span class="kwrd">null</span> != serializedData)<br />                <span class="kwrd">this</span>.Value = Deserialize(serializedData);<br />        }<br /><br />        <span class="kwrd">public</span> <span class="kwrd">void</span> GetObjectData(SerializationInfo info,<br />                                  StreamingContext context)<br />        {<br />            <span class="kwrd">byte</span>[] serializedData = <span class="kwrd">null</span>;<br />            <span class="kwrd">if</span> (<span class="kwrd">null</span> != Value)<br />                serializedData = Serialize(Value);<br />            info.AddValue(<span class="str">&quot;doc&quot;</span>, serializedData);<br />        }<br />        <span class="preproc">#endregion</span><br /><br />        <span class="preproc">#region</span> <span class="kwrd">implicit</span> conversion to/from XmlDocument<br />        <span class="kwrd">public</span> <span class="kwrd">static</span> <span class="kwrd">implicit</span> <span class="kwrd">operator</span> SerializableXmlDocument(<br />            XmlDocument doc)<br />        {<br />            <span class="kwrd">return</span> <span class="kwrd">new</span> SerializableXmlDocument(doc);<br />        }<br />        <span class="kwrd">public</span> <span class="kwrd">static</span> <span class="kwrd">implicit</span> <span class="kwrd">operator</span> XmlDocument(<br />            SerializableXmlDocument sdoc)<br />        {<br />            <span class="kwrd">return</span> sdoc.Value;<br />        }<br />        <span class="preproc">#endregion</span><br /><br />        <span class="preproc">#region</span> Xml serialization helper methods<br />        <span class="kwrd">private</span> <span class="kwrd">static</span> <span class="kwrd">byte</span>[] Serialize(XmlDocument doc)<br />        {<br />            MemoryStream stream = <span class="kwrd">new</span> MemoryStream();<br />            doc.Save(stream);<br />            <span class="kwrd">return</span> stream.CopyUpToSeekPointer();<br />        }<br />        <span class="kwrd">private</span> <span class="kwrd">static</span> XmlDocument Deserialize(<span class="kwrd">byte</span>[] serializedData)<br />        {<br />            XmlDocument doc = <span class="kwrd">new</span> XmlDocument();<br />            doc.Load(<span class="kwrd">new</span> MemoryStream(serializedData, <span class="kwrd">false</span>));<br />            <span class="kwrd">return</span> doc;<br />        }<br />        <span class="preproc">#endregion</span><br />    }<br />}</pre>
<p>...and here&#39;s the CopyUpToSeekPointer extension method for MemoryStream:</p>
<pre class="csharpcode"><span class="kwrd">using</span> System;<br /><span class="kwrd">using</span> System.IO;<br /><br /><span class="kwrd">namespace</span> Pluralsight.Samples<br />{<br />    <span class="kwrd">public</span> <span class="kwrd">static</span> <span class="kwrd">class</span> MemoryStreamExtensionMethods<br />    {<br />        <span class="kwrd">public</span> <span class="kwrd">static</span> <span class="kwrd">byte</span>[] CopyUpToSeekPointer(<br />            <span class="kwrd">this</span> MemoryStream stream)<br />        {<br />            <span class="rem">// copy only the part of the buffer</span><br />            <span class="rem">// that contains the serialized document</span><br />            <span class="kwrd">long</span> length = stream.Position;<br />            <span class="kwrd">byte</span>[] buffer = stream.GetBuffer();<br />            <span class="kwrd">byte</span>[] result = <span class="kwrd">new</span> <span class="kwrd">byte</span>[length];<br />            <span class="kwrd">for</span> (<span class="kwrd">int</span> i = 0; i &lt; length; ++i)<br />                result[i] = buffer[i];<br />            <span class="kwrd">return</span> result;<br />        }<br />    }<br />}</pre>
<p>...and here&#39;s a sample object that uses SerializableXmlDocument:</p>
<pre class="csharpcode"><span class="kwrd">using</span> System;<br /><br /><span class="kwrd">namespace</span> Pluralsight.Samples<br />{<br />    [Serializable]<br />    <span class="kwrd">public</span> <span class="kwrd">class</span> Item<br />    {<br />        <span class="kwrd">public</span> <span class="kwrd">string</span> Name { get; set; }<br />        <span class="kwrd">public</span> SerializableXmlDocument Data { get; set; }<br /><br />        <span class="kwrd">public</span> <span class="kwrd">void</span> Print()<br />        {<br />            Console.WriteLine(<span class="str">&quot;Name: {0}&quot;</span>, Name);<br />            Console.WriteLine(Data.Value.OuterXml);<br />        }<br />    }<br />}</pre>
<p>...and here&#39;s a sample program that creates an instance of Item, serializes it, then deserializes it, printing diagnostics along the way to show that it&#39;s working properly.</p>
<pre class="csharpcode"><span class="kwrd">using</span> System;<br /><span class="kwrd">using</span> System.Xml;<br /><span class="kwrd">using</span> System.Runtime.Serialization.Formatters.Binary;<br /><span class="kwrd">using</span> System.IO;<br /><span class="kwrd">using</span> Pluralsight.Samples;<br /><br /><span class="kwrd">class</span> DemoProgram<br />{<br />    <span class="kwrd">static</span> <span class="kwrd">void</span> Main(<span class="kwrd">string</span>[] args)<br />    {<br />        XmlDocument doc = <span class="kwrd">new</span> XmlDocument();<br />        doc.LoadXml(<span class="str">&quot;&lt;root&gt;&lt;child&gt;text&lt;/child&gt;&lt;/root&gt;&quot;</span>);<br /><br />        Item item = <span class="kwrd">new</span> Item<br />        {<br />            Name = <span class="str">&quot;Testing 123&quot;</span>,<br />            Data = doc,<br />        };<br /><br />        <span class="rem">// print object before serialization</span><br />        item.Print();<br /><br />        BinaryFormatter formatter = <span class="kwrd">new</span> BinaryFormatter();<br />        MemoryStream stream = <span class="kwrd">new</span> MemoryStream();<br />        formatter.Serialize(stream, item);<br /><br />        <span class="kwrd">byte</span>[] serializedItem = stream.CopyUpToSeekPointer();<br /><br />        Console.WriteLine(<span class="str">&quot;Serialized data (base64): {0}&quot;</span>,<br />            Convert.ToBase64String(serializedItem));<br /><br />        item = (Item)formatter.Deserialize(<br />            <span class="kwrd">new</span> MemoryStream(serializedItem, <span class="kwrd">false</span>));<br /><br />        <span class="rem">// print object after deserialization</span><br />        item.Print();<br />    }<br />}</pre>
<p>Here&#39;s the output of the previous sample program:</p>
<p><a href="http://www.pluralsight.com/community/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/keith/sample_2D00_output_5F00_2.jpg"><img style="border-top-width:0px;border-left-width:0px;border-bottom-width:0px;border-right-width:0px;" alt="sample-output" src="http://www.pluralsight.com/community/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/keith/sample_2D00_output_5F00_thumb.jpg" width="422" border="0" height="214" /></a>&nbsp;</p>
<p>Flame away!</p><div style="clear:both;"></div><img src="http://www.pluralsight.com/community/aggbug.aspx?PostID=52538" width="1" height="1">]]></content:encoded>
      <pubDate>Mon, 18 Aug 2008 22:58:00 +0000</pubDate>
      <category domain="http://securityratty.com/tag/public class item">public class item</category>
      <category domain="http://securityratty.com/tag/public">public</category>
      <category domain="http://securityratty.com/tag/public void getobjectdata">public void getobjectdata</category>
      <category domain="http://securityratty.com/tag/public static byte">public static byte</category>
      <category domain="http://securityratty.com/tag/xmldocument">xmldocument</category>
      <category domain="http://securityratty.com/tag/return doc">return doc</category>
      <category domain="http://securityratty.com/tag/return">return</category>
      <category domain="http://securityratty.com/tag/static byte">static byte</category>
      <category domain="http://securityratty.com/tag/public class">public class</category>
      <source url="http://www.pluralsight.com/community/blogs/keith/archive/2008/08/18/serializable-xmldocument.aspx">Serializable XmlDocument</source>
    </item>
    <item>
      <title><![CDATA[Two-way formatted data binding in ASP.NET]]></title>
      <link>http://securityratty.com/article/defaefd1679588644fb6df7a435f5f6a</link>
      <guid>http://securityratty.com/article/defaefd1679588644fb6df7a435f5f6a</guid>
      <description><![CDATA[Two way data binding in ASP.NET is easy, just use the Bind expression and data will flow between your web controls and your data source flawlessly. Until that is, you try to use a format string...]]></description>
      <content:encoded><![CDATA[<p>Two way data binding in ASP.NET is easy, just use the Bind expression and data will flow between your web controls and your data source flawlessly. Until that is, you try to use a format string:</p> <p>Bind(&quot;AmountCharged&quot;, &quot;{0:C}&quot;)</p> <p>While this displays just as you&#39;d expect (e.g., $200), it doesn&#39;t do so well when you submit an edit that includes the same value ($200):</p> <p><span style="font-weight:normal;font-size:14pt;color:maroon;font-family:&#39;Verdana&#39;;"><i>Input string was not in a correct format.</i></span></p> <p>I searched around and didn&#39;t find much in the way of a clean solution, but I did solve the problem with just a few lines of code. The trick is to handle the data-bound control&#39;s Updating event. Since I was working with a GridView, my solution looked a bit like this:</p><pre class="csharpcode"><span class="kwrd">&lt;</span><span class="html">asp:GridView</span> <span class="attr">DataSourceID</span><span class="kwrd">=&#39;myDataSource&#39;</span>
              <span class="attr">OnRowUpdating</span><span class="kwrd">=&#39;FixFormatting&#39;</span>
              <span class="attr">AutoGenerateColumns</span><span class="kwrd">=&#39;false&#39;</span>
              <span class="attr">CellPadding</span><span class="kwrd">=&quot;3&quot; ...&gt;</span></pre>
<p>Notice the OnRowUpdating handler that I&#39;ve installed in my grid view. That code looks like this:</p><pre class="csharpcode"><span class="kwrd">protected</span> <span class="kwrd">void</span> FixFormatting(<span class="kwrd">object</span> sender, GridViewUpdateEventArgs args)
{
    <span class="kwrd">decimal</span> amountPaid = ParseDecimal((<span class="kwrd">string</span>)args.NewValues[<span class="str">&quot;AmountPaid&quot;</span>]);
    args.NewValues[<span class="str">&quot;AmountPaid&quot;</span>] = amountPaid;
}</pre>
<p>When you handle this event, you&#39;re given a dictionary of old and new values, which appear to come directly from the controls (in my case, a TextBox was used to gather the updated data AmountPaid, so the type of object that I found in NewValues[&quot;AmountPaid&quot;] was a string. I wrote a little helper method called ParseDecimal that parses a string into a decimal value, allowing currency characters, decimal points, and thousands separators. I also allowed a blank value to indicate zero:</p><pre class="csharpcode"><span class="kwrd">public</span> <span class="kwrd">static</span> <span class="kwrd">decimal</span> ParseDecimal(<span class="kwrd">string</span> <span class="kwrd">value</span>)
{
    <span class="kwrd">if</span> (<span class="kwrd">string</span>.IsNullOrEmpty(<span class="kwrd">value</span>))
        <span class="kwrd">return</span> 0;
    <span class="kwrd">return</span> Decimal.Parse(<span class="kwrd">value</span>,
        NumberStyles.AllowThousands |
        NumberStyles.AllowDecimalPoint |
        NumberStyles.AllowCurrencySymbol,
        CultureInfo.InstalledUICulture);
}
</pre>
<p>This solved the problem quite nicely. Now two-way binding works with formatted data.</p><div style="clear:both;"></div><img src="http://www.pluralsight.com/community/aggbug.aspx?PostID=52504" width="1" height="1">]]></content:encoded>
      <pubDate>Fri, 15 Aug 2008 16:22:37 +0000</pubDate>
      <category domain="http://securityratty.com/tag/data">data</category>
      <category domain="http://securityratty.com/tag/data amountpaid">data amountpaid</category>
      <category domain="http://securityratty.com/tag/amountpaid">amountpaid</category>
      <category domain="http://securityratty.com/tag/data-bound control">data-bound control</category>
      <category domain="http://securityratty.com/tag/decimal amountpaid">decimal amountpaid</category>
      <category domain="http://securityratty.com/tag/return decimal">return decimal</category>
      <category domain="http://securityratty.com/tag/return">return</category>
      <category domain="http://securityratty.com/tag/data source flawlessly">data source flawlessly</category>
      <category domain="http://securityratty.com/tag/decimal">decimal</category>
      <source url="http://www.pluralsight.com/community/blogs/keith/archive/2008/08/15/two-way-formatted-data-binding-in-asp-net.aspx">Two-way formatted data binding in ASP.NET</source>
    </item>
    <item>
      <title><![CDATA[Where to get Password Minder]]></title>
      <link>http://securityratty.com/article/6fd519c118d9365baa63f9bddb0cba63</link>
      <guid>http://securityratty.com/article/6fd519c118d9365baa63f9bddb0cba63</guid>
      <description><![CDATA[We recently updated our website and some links have broken as a result. Here's the place you should go to get the latest version of Password Minder
http://mercury.pluralsight.com/tools.aspx
Sorry for...]]></description>
      <content:encoded><![CDATA[<p>We recently updated our website and some links have broken as a result. Here&#39;s the place you should go to get the latest version of Password Minder:</p>
<p><a href="http://mercury.pluralsight.com/tools.aspx">http://mercury.pluralsight.com/tools.aspx</a></p>
<p>Sorry for any inconvenience!</p><div style="clear:both;"></div><img src="http://www.pluralsight.com/community/aggbug.aspx?PostID=52369" width="1" height="1">]]></content:encoded>
      <pubDate>Tue, 05 Aug 2008 13:00:00 +0000</pubDate>
      <category domain="http://securityratty.com/tag/password minder">password minder</category>
      <category domain="http://securityratty.com/tag/website">website</category>
      <category domain="http://securityratty.com/tag/recently">recently</category>
      <category domain="http://securityratty.com/tag/version">version</category>
      <category domain="http://securityratty.com/tag/pluralsight">pluralsight</category>
      <category domain="http://securityratty.com/tag/inconvenience">inconvenience</category>
      <category domain="http://securityratty.com/tag/aspx">aspx</category>
      <category domain="http://securityratty.com/tag/mercury">mercury</category>
      <category domain="http://securityratty.com/tag/links">links</category>
      <source url="http://www.pluralsight.com/community/blogs/keith/archive/2008/08/05/where-to-get-password-minder.aspx">Where to get Password Minder</source>
    </item>
    <item>
      <title><![CDATA[Better exception reporting in ASP.NET part 2]]></title>
      <link>http://securityratty.com/article/b878f7921917b371086606df6d043229</link>
      <guid>http://securityratty.com/article/b878f7921917b371086606df6d043229</guid>
      <description><![CDATA[This is the third post in a series
The first post described the problem: ASP.NET wasn't reporting inner exception stack traces
The second post described my solution
This post shows the code I used to...]]></description>
      <content:encoded><![CDATA[<p>This is the third post in a series.</p> <p>The <a href="http://www.pluralsight.com/community/blogs/keith/archive/2008/08/01/asp-net-health-monitoring-doesn-t-log-inner-exception-stack-trace.aspx" target="_blank">first post</a> described the problem: ASP.NET wasn&#39;t reporting inner exception stack traces.</p> <p>The <a href="http://www.pluralsight.com/community/blogs/keith/archive/2008/08/01/better-exception-reporting-in-asp-net.aspx" target="_blank">second post</a> described my solution.</p> <p>This post shows the code I used to solve the problem: a custom email provider for the Health Monitoring system in ASP.NET. Enjoy!</p> <p>Here&#39;s the provider. Note that I opted *not* to build a buffering provider to keep things simple:</p><pre class="csharpcode"><span class="kwrd">public</span> <span class="kwrd">class</span> MyMailWebEventProvider : WebEventProvider
{
    <span class="kwrd">string</span> to;
    <span class="kwrd">string</span> from;
    <span class="kwrd">string</span> subjectPrefix;

    <span class="kwrd">public</span> <span class="kwrd">override</span> <span class="kwrd">void</span> Initialize(<span class="kwrd">string</span> name,
        NameValueCollection config)
    {
        <span class="kwrd">base</span>.Initialize(name, config);

        to = GetAndRemoveStringAttribute(config, <span class="str">&quot;to&quot;</span>, <span class="kwrd">true</span>);
        from = GetAndRemoveStringAttribute(config, <span class="str">&quot;from&quot;</span>, <span class="kwrd">true</span>);
        subjectPrefix = GetAndRemoveStringAttribute(config,
            <span class="str">&quot;subjectPrefix&quot;</span>, <span class="kwrd">false</span>);
    }
    <span class="kwrd">public</span> <span class="kwrd">override</span> <span class="kwrd">void</span> ProcessEvent(WebBaseEvent raisedEvent)
    {
        SendMail(raisedEvent);
    }

    <span class="kwrd">private</span> <span class="kwrd">void</span> SendMail(WebBaseEvent raisedEvent)
    {
        <span class="kwrd">string</span> subject = ComputeEmailSubject(raisedEvent);
        <span class="kwrd">string</span> body = ComputeEmailBody(raisedEvent);

        MailMessage msg = <span class="kwrd">new</span> MailMessage(from, to, subject, body);
        <span class="kwrd">new</span> SmtpClient().Send(msg);
    }

    <span class="kwrd">private</span> <span class="kwrd">string</span> ComputeEmailBody(WebBaseEvent raisedEvent)
    {
        WebRequestErrorEvent errorEvent =
            raisedEvent <span class="kwrd">as</span> WebRequestErrorEvent;
        <span class="kwrd">if</span> (<span class="kwrd">null</span> != errorEvent)
            <span class="kwrd">return</span> ErrorEventFormattingHelper.FormatRequestErrorEvent(errorEvent);
        <span class="kwrd">else</span> <span class="kwrd">return</span> raisedEvent.ToString();
    }

    <span class="kwrd">private</span> <span class="kwrd">string</span> ComputeEmailSubject(WebBaseEvent raisedEvent)
    {
        StringBuilder subjectBuilder = <span class="kwrd">new</span> StringBuilder();

        <span class="rem">// surface some details in subject about error events</span>
        WebBaseErrorEvent errorEvent = raisedEvent <span class="kwrd">as</span> WebBaseErrorEvent;
        <span class="kwrd">if</span> (<span class="kwrd">null</span> != errorEvent)
        {
            Exception unhandledException = errorEvent.ErrorException;

            <span class="rem">// drill through reflection exceptions to show the root cause</span>
            TargetInvocationException invocationException =
                unhandledException <span class="kwrd">as</span> TargetInvocationException;
            <span class="kwrd">if</span> (<span class="kwrd">null</span> != invocationException)
            {
                Exception innerException =
                    DrillIntoTargetInvocationException(invocationException);
                subjectBuilder.AppendFormat(<span class="str">&quot;{0}&quot;</span>,
                    (innerException ?? invocationException).GetType().Name);
                <span class="kwrd">if</span> (<span class="kwrd">null</span> != innerException)
                    subjectBuilder.Append(<span class="str">&quot; (via reflection)&quot;</span>);
            }
            <span class="kwrd">else</span> subjectBuilder.Append(unhandledException.GetType().Name);
        }

        <span class="rem">// if we&#39;ve not got anything better</span>
        <span class="rem">// just show the event type in the subject</span>
        <span class="kwrd">if</span> (0 == subjectBuilder.Length)
            subjectBuilder.AppendFormat(<span class="str">&quot;Event type: {0}&quot;</span>,
                raisedEvent.GetType().Name);

        <span class="kwrd">if</span> (!<span class="kwrd">string</span>.IsNullOrEmpty(subjectPrefix)) {
            subjectBuilder.Insert(0, <span class="str">&#39; &#39;</span>);
            subjectBuilder.Insert(0, subjectPrefix);
        }
        <span class="kwrd">return</span> subjectBuilder.ToString();
    }

    <span class="rem">/// &lt;summary&gt;</span>
    <span class="rem">/// Reflection often hides exception details, so we try to drill down</span>
    <span class="rem">/// through the plumbing exceptions to find a likely cause</span>
    <span class="rem">/// &lt;/summary&gt;</span>
    <span class="kwrd">private</span> Exception DrillIntoTargetInvocationException(
        TargetInvocationException outerException)
    {
        Exception innerException = outerException.InnerException;
        TargetInvocationException innerInvocationException =
            innerException <span class="kwrd">as</span> TargetInvocationException;
        <span class="kwrd">if</span> (<span class="kwrd">null</span> != innerInvocationException)
            <span class="kwrd">return</span> DrillIntoTargetInvocationException(innerInvocationException);
        <span class="kwrd">else</span> <span class="kwrd">if</span> (<span class="kwrd">null</span> != innerException)
            <span class="kwrd">return</span> innerException;
        <span class="kwrd">else</span> <span class="kwrd">return</span> <span class="kwrd">null</span>;
    }

    <span class="kwrd">private</span> <span class="kwrd">static</span> <span class="kwrd">string</span> GetAndRemoveStringAttribute(NameValueCollection config,
        <span class="kwrd">string</span> attributeName, <span class="kwrd">bool</span> required)
    {
        <span class="kwrd">string</span> <span class="kwrd">value</span> = config.Get(attributeName);
        <span class="kwrd">if</span> (required &amp;&amp; <span class="kwrd">string</span>.IsNullOrEmpty(<span class="kwrd">value</span>))
            <span class="kwrd">throw</span> <span class="kwrd">new</span> ConfigurationErrorsException(<span class="kwrd">string</span>.Format(
                <span class="str">&quot;Expected attribute {0}, which is missing or empty.&quot;</span>,
                attributeName));
        config.Remove(attributeName);
        <span class="kwrd">return</span> <span class="kwrd">value</span>;
    }

    <span class="kwrd">public</span> <span class="kwrd">override</span> <span class="kwrd">void</span> Flush()
    {
        <span class="rem">// nothing to do - this is not a buffering provider</span>
    }

    <span class="kwrd">public</span> <span class="kwrd">override</span> <span class="kwrd">void</span> Shutdown()
    {
        <span class="rem">// nothing to do here either</span>
    }
}</pre>
<p>Here&#39;s a helper class that formats the error messages the way I want to see them. Note that I&#39;ve omitted some fields that I personally didn&#39;t care about, and I&#39;ve reordered things a bit, so you might want to tweak this if you&#39;re going to use it in your own system.</p><pre class="csharpcode"><span class="kwrd">internal</span> <span class="kwrd">static</span> <span class="kwrd">class</span> ErrorEventFormattingHelper
{
    <span class="kwrd">internal</span> <span class="kwrd">static</span> <span class="kwrd">string</span> FormatRequestErrorEvent(
        WebRequestErrorEvent errorEvent)
    {
        CustomEventFormatter formatter = 
            <span class="kwrd">new</span> CustomEventFormatter();

        formatter.AppendLine(<span class="kwrd">string</span>.Format(
            <span class="str">&quot;Unhandled Exception in {0}:&quot;</span>,
            WebBaseEvent.ApplicationInformation
            .ApplicationVirtualPath));
        formatter.Indent();
        EmitExceptionAtAGlance(formatter, 
            errorEvent.ErrorException);
        formatter.RevertIndent();

        formatter.AppendLine();
        formatter.AppendLine(<span class="str">&quot;Exception stack trace(s):&quot;</span>);
        EmitExceptionStackTrace(formatter, 
            errorEvent.ErrorException);

        formatter.AppendLine();
        formatter.AppendLine(<span class="str">&quot;Event information:&quot;</span>);
        formatter.Indent();
        EmitEventInfo(formatter, errorEvent);
        formatter.RevertIndent();

        formatter.AppendLine();
        formatter.AppendLine(<span class="str">&quot;Application information:&quot;</span>);
        formatter.Indent();
        EmitApplicationInfo(formatter, 
            WebBaseEvent.ApplicationInformation);
        formatter.RevertIndent();

        formatter.AppendLine();
        formatter.AppendLine(<span class="str">&quot;Process/thread information:&quot;</span>);
        formatter.Indent();
        EmitProcessInfo(formatter, 
            errorEvent.ProcessInformation);
        formatter.RevertIndent();

        formatter.AppendLine();
        formatter.AppendLine(<span class="str">&quot;Request information:&quot;</span>);
        formatter.Indent();
        EmitRequestInfo(formatter, 
            errorEvent.RequestInformation);
        formatter.RevertIndent();

        <span class="kwrd">return</span> formatter.ToString();
    }

    <span class="kwrd">private</span> <span class="kwrd">static</span> <span class="kwrd">void</span> EmitEventInfo(
        CustomEventFormatter formatter,
        WebBaseEvent theEvent)
    {
        formatter.AppendLine(<span class="kwrd">string</span>.Format(
            <span class="str">&quot;Event code: {0}&quot;</span>,
            theEvent.EventCode.ToString(
            CultureInfo.InvariantCulture)));
        formatter.AppendLine(<span class="kwrd">string</span>.Format(
            <span class="str">&quot;Event message: {0}&quot;</span>, 
            theEvent.Message));
        formatter.AppendLine(<span class="kwrd">string</span>.Format(
            <span class="str">&quot;Event time: {0}&quot;</span>, 
            theEvent.EventTime.ToString(
            CultureInfo.InvariantCulture)));
        formatter.AppendLine(<span class="kwrd">string</span>.Format(
            <span class="str">&quot;Event ID: {0}&quot;</span>, 
            theEvent.EventID.ToString(<span class="str">&quot;N&quot;</span>, 
            CultureInfo.InvariantCulture)));
    }

    <span class="kwrd">private</span> <span class="kwrd">static</span> <span class="kwrd">void</span> EmitApplicationInfo(
        CustomEventFormatter formatter, 
        WebApplicationInformation appInfo)
    {
        formatter.AppendLine(<span class="kwrd">string</span>.Format(
            <span class="str">&quot;Application domain: {0}&quot;</span>, 
            appInfo.ApplicationDomain));
        formatter.AppendLine(<span class="kwrd">string</span>.Format(
            <span class="str">&quot;Application Virtual Path: {0}&quot;</span>, 
            appInfo.ApplicationVirtualPath));
        formatter.AppendLine(<span class="kwrd">string</span>.Format(
            <span class="str">&quot;Application Physical Path: {0}&quot;</span>, 
            appInfo.ApplicationPath));
    }

    <span class="kwrd">private</span> <span class="kwrd">static</span> <span class="kwrd">void</span> EmitProcessInfo(
        CustomEventFormatter formatter, 
        WebProcessInformation webProcessInfo)
    {
        formatter.AppendLine(<span class="kwrd">string</span>.Format(
            <span class="str">&quot;Process ID: {0}&quot;</span>, 
            webProcessInfo.ProcessID.ToString(
            CultureInfo.InvariantCulture)));
        formatter.AppendLine(<span class="kwrd">string</span>.Format(
            <span class="str">&quot;Process name: {0}&quot;</span>, 
            webProcessInfo.ProcessName));
        formatter.AppendLine(<span class="kwrd">string</span>.Format(
            <span class="str">&quot;Account name: {0}&quot;</span>, 
            webProcessInfo.AccountName));
    }

    <span class="kwrd">private</span> <span class="kwrd">static</span> <span class="kwrd">void</span> EmitRequestInfo(
        CustomEventFormatter formatter, 
        WebRequestInformation webRequestInfo)
    {
        <span class="kwrd">string</span> name = <span class="kwrd">null</span>;
        <span class="kwrd">if</span> (webRequestInfo.Principal != <span class="kwrd">null</span>)
            name = webRequestInfo.Principal.Identity.Name;

        formatter.AppendLine(<span class="kwrd">string</span>.Format(
            <span class="str">&quot;Request URL: {0}&quot;</span>, 
            webRequestInfo.RequestUrl));
        formatter.AppendLine(<span class="kwrd">string</span>.Format(
            <span class="str">&quot;Request path: {0}&quot;</span>, 
            webRequestInfo.RequestPath));
        formatter.AppendLine(<span class="kwrd">string</span>.Format(
            <span class="str">&quot;User name: {0}&quot;</span>, 
            name ?? <span class="str">&quot;[ANONYMOUS]&quot;</span>));
        formatter.AppendLine(<span class="kwrd">string</span>.Format(
            <span class="str">&quot;User host address: {0}&quot;</span>, 
            webRequestInfo.UserHostAddress));
    }

    <span class="kwrd">private</span> <span class="kwrd">static</span> <span class="kwrd">void</span> EmitExceptionAtAGlance(
        CustomEventFormatter formatter, 
        Exception exception)
    {
        formatter.AppendLine(<span class="kwrd">string</span>.Format(
            <span class="str">&quot;Type: {0}&quot;</span>, 
            exception.GetType().Name));
        formatter.AppendLine(<span class="kwrd">string</span>.Format(
            <span class="str">&quot;Message: {0}&quot;</span>, 
            exception.Message));
        <span class="kwrd">if</span> (<span class="kwrd">null</span> != exception.InnerException)
        {
            formatter.Indent();
            formatter.AppendLine(<span class="str">&quot;--&gt;Inner Exception&quot;</span>);
            EmitExceptionAtAGlance(formatter, 
                exception.InnerException);
            formatter.RevertIndent();
        }
    }

    <span class="kwrd">private</span> <span class="kwrd">static</span> <span class="kwrd">void</span> EmitExceptionStackTrace(
        CustomEventFormatter formatter, Exception exception)
    {
        formatter.AppendLine(exception.StackTrace);

        <span class="kwrd">if</span> (<span class="kwrd">null</span> != exception.InnerException)
        {
            <span class="rem">// no point indenting</span>
            <span class="rem">// since stack traces typically wrap like crazy</span>
            formatter.AppendLine();
            formatter.AppendLine(<span class="str">&quot;--&gt;Inner exception stack trace:&quot;</span>);
            EmitExceptionStackTrace(formatter, exception.InnerException);
        }
    }
}
</pre>
<p>And finally, here&#39;s a helper class that manages indentation levels for the output email message:</p><pre class="csharpcode"><span class="kwrd">public</span> <span class="kwrd">class</span> CustomEventFormatter
{
    <span class="kwrd">const</span> <span class="kwrd">int</span> TabSpaces = 4;

    StringBuilder sb = <span class="kwrd">new</span> StringBuilder();
    <span class="kwrd">private</span> <span class="kwrd">int</span> indentLevel;
    <span class="kwrd">private</span> <span class="kwrd">bool</span> startingNewLine = <span class="kwrd">true</span>;

    <span class="kwrd">public</span> <span class="kwrd">void</span> Indent()
    {
        ++indentLevel;
    }

    <span class="kwrd">public</span> <span class="kwrd">void</span> RevertIndent()
    {
        <span class="kwrd">if</span> (indentLevel &gt; 0)
            --indentLevel;
    }

    <span class="kwrd">public</span> <span class="kwrd">void</span> Append(<span class="kwrd">string</span> text)
    {
        <span class="kwrd">if</span> (startingNewLine)
            EmitIndent();
        sb.Append(text);
        startingNewLine = <span class="kwrd">false</span>;
    }

    <span class="kwrd">public</span> <span class="kwrd">void</span> AppendLine(<span class="kwrd">string</span> lineOfText)
    {
        <span class="kwrd">if</span> (startingNewLine)
            EmitIndent();
        EmitIndent();
        sb.AppendLine(lineOfText);
        startingNewLine = <span class="kwrd">true</span>;
    }

    <span class="kwrd">private</span> <span class="kwrd">void</span> EmitIndent()
    {
        sb.Append(<span class="str">&#39; &#39;</span>, TabSpaces * indentLevel);
    }

    <span class="kwrd">public</span> <span class="kwrd">void</span> AppendLine()
    {
        AppendLine(<span class="kwrd">string</span>.Empty);
    }

    <span class="kwrd">public</span> <span class="kwrd">override</span> <span class="kwrd">string</span> ToString()
    {
        <span class="kwrd">return</span> sb.ToString();
    }
}
</pre>
<p>Build this into a library application and reference it in your config file. Here&#39;s an example:</p><pre class="csharpcode"><span class="kwrd">&lt;</span><span class="html">healthMonitoring</span><span class="kwrd">&gt;</span>
  <span class="kwrd">&lt;</span><span class="html">providers</span><span class="kwrd">&gt;</span>
    <span class="kwrd">&lt;</span><span class="html">add</span> <span class="attr">name</span><span class="kwrd">=&quot;mailWebEventProvider&quot;</span>
         <span class="attr">type</span><span class="kwrd">=&quot;MyMailWebEventProvider&quot;</span>
         <span class="attr">to</span><span class="kwrd">=&quot;web-fault@fabrikam.com&quot;</span>
         <span class="attr">from</span><span class="kwrd">=&quot;website@fabrikam.com&quot;</span>
         <span class="attr">buffer</span><span class="kwrd">=&quot;false&quot;</span>
         <span class="attr">subjectPrefix</span><span class="kwrd">=&quot;[WEB-ERROR]&quot;</span>
       <span class="kwrd">/&gt;</span>
  <span class="kwrd">&lt;/</span><span class="html">providers</span><span class="kwrd">&gt;</span>
  <span class="kwrd">&lt;</span><span class="html">rules</span><span class="kwrd">&gt;</span>
    <span class="kwrd">&lt;</span><span class="html">add</span> <span class="attr">name</span><span class="kwrd">=&quot;All Errors Email&quot;</span>
         <span class="attr">eventName</span><span class="kwrd">=&quot;All Errors&quot;</span>
         <span class="attr">provider</span><span class="kwrd">=&quot;mailWebEventProvider&quot;</span>
         <span class="attr">profile</span><span class="kwrd">=&quot;Default&quot;</span>
         <span class="attr">minInstances</span><span class="kwrd">=&quot;1&quot;</span>
         <span class="attr">maxLimit</span><span class="kwrd">=&quot;Infinite&quot;</span>
         <span class="attr">minInterval</span><span class="kwrd">=&quot;00:01:00&quot;</span>
         <span class="attr">custom</span><span class="kwrd">=&quot;&quot;</span><span class="kwrd">/&gt;</span>
  <span class="kwrd">&lt;/</span><span class="html">rules</span><span class="kwrd">&gt;</span>
<span class="kwrd">&lt;/</span><span class="html">healthMonitoring</span><span class="kwrd">&gt;</span>
</pre><div style="clear:both;"></div><img src="http://www.pluralsight.com/community/aggbug.aspx?PostID=52349" width="1" height="1">]]></content:encoded>
      <pubDate>Mon, 04 Aug 2008 10:11:14 +0000</pubDate>
      <category domain="http://securityratty.com/tag/return">return</category>
      <category domain="http://securityratty.com/tag/return subjectbuilder">return subjectbuilder</category>
      <category domain="http://securityratty.com/tag/return formatter">return formatter</category>
      <category domain="http://securityratty.com/tag/exception">exception</category>
      <category domain="http://securityratty.com/tag/formatter">formatter</category>
      <category domain="http://securityratty.com/tag/crazy formatter">crazy formatter</category>
      <category domain="http://securityratty.com/tag/static void">static void</category>
      <category domain="http://securityratty.com/tag/static void emitprocessinfo">static void emitprocessinfo</category>
      <category domain="http://securityratty.com/tag/return null">return null</category>
      <source url="http://www.pluralsight.com/community/blogs/keith/archive/2008/08/04/better-exception-reporting-in-asp-net-part-2.aspx">Better exception reporting in ASP.NET part 2</source>
    </item>
    <item>
      <title><![CDATA[Twisted Coronas]]></title>
      <link>http://securityratty.com/article/7ceb9ae30eb4801d1b48db211acf0539</link>
      <guid>http://securityratty.com/article/7ceb9ae30eb4801d1b48db211acf0539</guid>
      <description><![CDATA[Okay it's Saturday, so let me share something completely nontechnical and fun
What you need to make these cocktails: Six pack of Corona Extra
Bottle of Bacardi Limon
Lime
Coctail stirrer (a chopstick...]]></description>
      <content:encoded><![CDATA[<p>Okay it&#39;s Saturday, so let me share something completely nontechnical and fun.</p> <p>What you need to make these cocktails:</p> <blockquote>Six pack of <a href="http://www.corona.com/" target="_blank">Corona Extra</a><br />Bottle of <a href="http://www.bacardi.com/us/en-us/products/additionalproducts/bacardilim%C3%B3n?accessibility=true&amp;marketlanguageid=2" target="_blank">Bacardi Limon</a><br />Lime<br />Coctail stirrer (a chopstick works fine)</blockquote> <p>Pop a slice of lime into a Corona and hand to a friend. Have them drink the neck, then refill with Bacardi Limon (putting the lime in first seems to reduce fizzing). Stir and hand back to them so they can drink it down as it fizzes up a bit.</p> <p>Mixing rum and beer may sound nasty, but this actually results in a very smooth, tasty drink. It&#39;s our favorite accompaniment when we are playing <a href="http://www.xbox.com/en-us/games/r/rockband/" target="_blank">Rock Band</a>.</p> <p>We took this recipe and applied it to one of our other favorite beers as well: <a href="http://www.epinions.com/content_369863855748" target="_blank">Honey Moon Summer Ale</a> (also works with <a href="http://en.wikipedia.org/wiki/Blue_Moon_(beer)" target="_blank">Blue Moon</a>, or any other typically orange-flavored beer). Just use <a href="http://www.bacardi.com/us/en-us/products/additionalproducts/bacardio?accessibility=true&amp;marketlanguageid=2" target="_blank">Barcardi O</a> instead of Limon.</p> <p>Enjoy!</p><div style="clear:both;"></div><img src="http://www.pluralsight.com/community/aggbug.aspx?PostID=52330" width="1" height="1">]]></content:encoded>
      <pubDate>Sat, 02 Aug 2008 13:33:51 +0000</pubDate>
      <category domain="http://securityratty.com/tag/limon">limon</category>
      <category domain="http://securityratty.com/tag/bacardi limon">bacardi limon</category>
      <category domain="http://securityratty.com/tag/drink">drink</category>
      <category domain="http://securityratty.com/tag/tasty drink">tasty drink</category>
      <category domain="http://securityratty.com/tag/lime">lime</category>
      <category domain="http://securityratty.com/tag/corona extra">corona extra</category>
      <category domain="http://securityratty.com/tag/corona">corona</category>
      <category domain="http://securityratty.com/tag/blue moon">blue moon</category>
      <category domain="http://securityratty.com/tag/favorite beers">favorite beers</category>
      <source url="http://www.pluralsight.com/community/blogs/keith/archive/2008/08/02/twisted-coronas.aspx">Twisted Coronas</source>
    </item>
    <item>
      <title><![CDATA[Comments]]></title>
      <link>http://securityratty.com/article/b7ccced1775deb1322083bebf81d24fa</link>
      <guid>http://securityratty.com/article/b7ccced1775deb1322083bebf81d24fa</guid>
      <description><![CDATA[We recently switched our blog engine out, and I'm still getting the hang of the new system. Looks like due to a misconfiguration, several comments have been waiting for moderation for days or weeks....]]></description>
      <content:encoded><![CDATA[<p>We recently switched our blog engine out, and I&#39;m still getting the hang of the new system. Looks like due to a misconfiguration, several comments have been waiting for moderation for days or weeks. If yours was one of them, please accept my apology - I didn&#39;t have email notifications turned on, so I wasn&#39;t being notified that comments were coming in.</p>
<p>I&#39;ve since fixed the problem, so your comments should show up sooner. Sorry for any confusion!</p><div style="clear:both;"></div><img src="http://www.pluralsight.com/community/aggbug.aspx?PostID=52316" width="1" height="1">]]></content:encoded>
      <pubDate>Fri, 01 Aug 2008 17:38:00 +0000</pubDate>
      <category domain="http://securityratty.com/tag/comments">comments</category>
      <category domain="http://securityratty.com/tag/email notifications">email notifications</category>
      <category domain="http://securityratty.com/tag/blog engine">blog engine</category>
      <category domain="http://securityratty.com/tag/due">due</category>
      <category domain="http://securityratty.com/tag/recently">recently</category>
      <category domain="http://securityratty.com/tag/accept">accept</category>
      <category domain="http://securityratty.com/tag/system">system</category>
      <category domain="http://securityratty.com/tag/fixed">fixed</category>
      <category domain="http://securityratty.com/tag/confusion">confusion</category>
      <source url="http://www.pluralsight.com/community/blogs/keith/archive/2008/08/01/comments.aspx">Comments</source>
    </item>
    <item>
      <title><![CDATA[Better exception reporting in ASP.NET]]></title>
      <link>http://securityratty.com/article/34119f443c0ec116d6e16efd70378528</link>
      <guid>http://securityratty.com/article/34119f443c0ec116d6e16efd70378528</guid>
      <description><![CDATA[In my last post , I commented on how ASP.NET health monitoring doesn't output stack traces for inner exceptions, which can be problematic due to its heavy reliance on reflection. I spent the morning...]]></description>
      <content:encoded><![CDATA[<p>In <a href="http://www.pluralsight.com/community/blogs/keith/archive/2008/08/01/asp-net-health-monitoring-doesn-t-log-inner-exception-stack-trace.aspx" target="_blank">my last post</a>, I commented on how ASP.NET health monitoring doesn&#39;t output stack traces for inner exceptions, which can be problematic due to its heavy reliance on reflection. I spent the morning doing some further spelunking with <a href="http://www.aisto.com/roeder/dotnet/" target="_blank">reflector</a>, and my first solution was to implement a custom WebEvent that overrides ToString() to format itself with all of the data I care about. I then overrode the Error event via global.asax and raised my custom event, instead of letting ASP.NET raise its default event. This worked reasonably well with the SimpleMailWebEventProvider, but didn&#39;t seem to change anything at all with the event log provider.</p> <p>What I found is that the two providers were using entirely different means to format the events! The email provider calls ToString(bool, bool) on the event to ask it to format itself. But the EventLogWebEventProvider does its own formatting of individual fields of the event. Indeed, its ProcessEvent method has a big list of checks:</p><pre class="csharpcode"><span class="kwrd">if</span> (eventRaised <span class="kwrd">is</span> WebBaseErrorEvent)
    AddErrorStuff();
<span class="kwrd">if</span> (eventRaised <span class="kwrd">is</span> WebAuthenticationSuccessAuditEvent)
    AddLogonStuff();
</pre>
<p>So it seemed like a better approach would be to write my own provider. I left the event log provider alone, and I wrote a custom email provider to display errors in a more useful way. This also allowed me to drop some fields from the event report that aren&#39;t useful for us. And I was able to construct a much more concise and useful subject line (the subject line that SimpleMailWebEventProvider uses is rather clunky since it assumes it might be spitting out a whole bunch of buffered events in one go).</p>
<p>Not only does my provider include the stack traces for all of the exceptions in the chain, but in the subject line, I display the type of error that is at the root of the problem. So if I am formatting a TargetInvocationException, I drill into its InnerException chain until I find a different exception type, and display that exception type instead.</p>
<p>Oh, one other benefit of building the custom provider instead of using a custom WebEvent was that I was then able to remove the Error handler from global.asax. All I had to do was replace the SimpleMailWebEventProvider with my own provider, and I got the behavior I wanted. Now my email notifications include detailed stack traces.</p>
<p>I&#39;ll post the code for this provider once it&#39;s run for a little while in production and I&#39;m satisfied that it works reasonably well.</p><div style="clear:both;"></div><img src="http://www.pluralsight.com/community/aggbug.aspx?PostID=52314" width="1" height="1">]]></content:encoded>
      <pubDate>Fri, 01 Aug 2008 16:30:05 +0000</pubDate>
      <category domain="http://securityratty.com/tag/error event">error event</category>
      <category domain="http://securityratty.com/tag/event">event</category>
      <category domain="http://securityratty.com/tag/provider">provider</category>
      <category domain="http://securityratty.com/tag/default event">default event</category>
      <category domain="http://securityratty.com/tag/email provider calls">email provider calls</category>
      <category domain="http://securityratty.com/tag/event log provider">event log provider</category>
      <category domain="http://securityratty.com/tag/provider include">provider include</category>
      <category domain="http://securityratty.com/tag/custom email provider">custom email provider</category>
      <category domain="http://securityratty.com/tag/output stack traces">output stack traces</category>
      <source url="http://www.pluralsight.com/community/blogs/keith/archive/2008/08/01/better-exception-reporting-in-asp-net.aspx">Better exception reporting in ASP.NET</source>
    </item>
    <item>
      <title><![CDATA[ASP.NET Health Monitoring doesn't log inner exception stack trace]]></title>
      <link>http://securityratty.com/article/b3299c7401f4189ad9619ab42a4a438e</link>
      <guid>http://securityratty.com/article/b3299c7401f4189ad9619ab42a4a438e</guid>
      <description><![CDATA[This can be a problem, especially when an ObjectDataSource starts throwing exceptions. The stack trace looks the same because of the way the methods are invoked (via reflection) - you end up with a...]]></description>
      <content:encoded><![CDATA[<p>This can be a problem, especially when an ObjectDataSource starts throwing exceptions. The stack trace looks the same because of the way the methods are invoked (via reflection) - you end up with a stack trace for a TargetInvocationException, which basically says, &quot;I used reflection to invoke some method, and it threw an exception. See the inner exception for details.&quot;</p>
<p>ASP.NET&#39;s health monitoring system does list the inner exceptions (apparently up to a maximum depth of two, from spelunking the code with <a href="http://www.aisto.com/roeder/dotnet/">reflector</a>), but it does not emit the stack traces for these exceptions, which would be <i>really helpful</i>. I&#39;ve spent some time this morning trying to figure out how I&#39;d customize things to emit this, and it looks like what I&#39;d have to do is catch the exception and generate a custom WebEvent that overrides ToString(bool, bool) and does everything that WebRequestErrorEvent does, but also generate the inner stack trace.</p>
<p>That seems a bit ugly. A search for &quot;ASP.NET web event inner exception stack trace&quot; yielded no interesting results, so if you&#39;ve dealt with this and have a cleaner solution, let me know. I&#39;ll post my solution once I get it worked out.</p><div style="clear:both;"></div><img src="http://www.pluralsight.com/community/aggbug.aspx?PostID=52306" width="1" height="1">]]></content:encoded>
      <pubDate>Fri, 01 Aug 2008 12:21:00 +0000</pubDate>
      <category domain="http://securityratty.com/tag/exception stack trace">exception stack trace</category>
      <category domain="http://securityratty.com/tag/exception">exception</category>
      <category domain="http://securityratty.com/tag/stack trace">stack trace</category>
      <category domain="http://securityratty.com/tag/net">net</category>
      <category domain="http://securityratty.com/tag/net web event">net web event</category>
      <category domain="http://securityratty.com/tag/asp">asp</category>
      <category domain="http://securityratty.com/tag/exceptions">exceptions</category>
      <category domain="http://securityratty.com/tag/solution">solution</category>
      <category domain="http://securityratty.com/tag/cleaner solution">cleaner solution</category>
      <source url="http://www.pluralsight.com/community/blogs/keith/archive/2008/08/01/asp-net-health-monitoring-doesn-t-log-inner-exception-stack-trace.aspx">ASP.NET Health Monitoring doesn't log inner exception stack trace</source>
    </item>
    <item>
      <title><![CDATA[Simulating Email in .NET]]></title>
      <link>http://securityratty.com/article/0c454dbe28b5b63d07ee0089e019de77</link>
      <guid>http://securityratty.com/article/0c454dbe28b5b63d07ee0089e019de77</guid>
      <description><![CDATA[I use email as a notification mechanism a lot, and often in class I'll demo sending email via a technique that I use frequently when developing code. It allows you to simulate sending an email...]]></description>
      <content:encoded><![CDATA[<p>I use email as a notification mechanism a lot, and often in class I&#39;ll demo sending email via a technique that I use frequently when developing code. It allows you to simulate sending an email message.</p> <p>The trick to doing this is not to hardcode things like host, port, etc. for your SMTP server when you use System.Net.Mail to send mail. Instead, use the default ctor for <a href="http://msdn.microsoft.com/en-us/library/system.net.mail.smtpclient.aspx" target="_blank">SmtpClient</a> as I&#39;ve done in the code below.</p> <blockquote><pre class="csharpcode"><span class="kwrd">static</span> <span class="kwrd">void</span> Main(<span class="kwrd">string</span>[] args)
{
    <span class="rem">// note the use of the MailAddress class</span>
    <span class="rem">// this allows me to specify display names as well as email addresses</span>
    MailAddress from = <span class="kwrd">new</span> MailAddress(<span class="str">&quot;admin@fabrikam.com&quot;</span>, <span class="str">&quot;Fabrikam Website&quot;</span>);
    MailAddress to = <span class="kwrd">new</span> MailAddress(<span class="str">&quot;mari@fabrikam.com&quot;</span>, <span class="str">&quot;Mari Joyce&quot;</span>);

    MailMessage msg = <span class="kwrd">new</span> MailMessage(from, to);
    msg.Subject  = <span class="str">&quot;Testing 123&quot;</span>;
    msg.Body = <span class="str">&quot;This is only a test!&quot;</span>;

    <span class="rem">// note use of default ctor</span>
    <span class="rem">// this looks in config to figure out how to send mail</span>
    <span class="kwrd">new</span> SmtpClient().Send(msg);
}</pre></blockquote>
.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, &quot;Courier New&quot;, 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; }


<p>What you&#39;re telling .NET by using the default ctor for SmtpClient is, &quot;please use my config file to figure out how to send mail&quot;. Now you can use the system.net/mailSettings/smtp section in config to specify the details of your mail server, and all of the code in your app that is written to use the default SmtpClient ctor will inherit these settings. Here&#39;s an example of what the config on a production server might look like (if you put passwords in your config files, be sure to <a href="http://msdn.microsoft.com/en-us/library/ms998283.aspx" target="_blank">encrypt those sections</a>): </p><pre class="csharpcode"><span class="kwrd">&lt;</span><span class="html">configuration</span><span class="kwrd">&gt;</span>
  <span class="kwrd">&lt;</span><span class="html">system.net</span><span class="kwrd">&gt;</span>
    <span class="kwrd">&lt;</span><span class="html">mailSettings</span><span class="kwrd">&gt;</span>
      <span class="kwrd">&lt;</span><span class="html">smtp</span> <span class="attr">deliveryMethod</span><span class="kwrd">=&quot;Network&quot;</span><span class="kwrd">&gt;</span>
        <span class="kwrd">&lt;</span><span class="html">network</span> <span class="attr">host</span><span class="kwrd">=&quot;mail.fabrikam.com&quot;</span>
                 <span class="attr">port</span><span class="kwrd">=&quot;25&quot;</span>
                 <span class="attr">userName</span><span class="kwrd">=&quot;WebsiteMailAccount&quot;</span>
                 <span class="attr">password</span><span class="kwrd">=&quot;whatever&quot;</span><span class="kwrd">/&gt;</span>
      <span class="kwrd">&lt;/</span><span class="html">smtp</span><span class="kwrd">&gt;</span>
    <span class="kwrd">&lt;/</span><span class="html">mailSettings</span><span class="kwrd">&gt;</span>
  <span class="kwrd">&lt;/</span><span class="html">system.net</span><span class="kwrd">&gt;</span>
<span class="kwrd">&lt;/</span><span class="html">configuration</span><span class="kwrd">&gt;</span></pre><pre class="csharpcode">&nbsp;</pre>
.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, &quot;Courier New&quot;, 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; }


<p>During development, I use different settings because I don&#39;t usually want to deal with the hassle of installing an SMTP server on my development box. Instead, I want email messages delivered as individual files in a directory on my hard drive (I always have a c:\mail directory on my development box for just this purpose):</p>
<blockquote><pre class="csharpcode"><span class="kwrd">&lt;</span><span class="html">configuration</span><span class="kwrd">&gt;</span>
  <span class="kwrd">&lt;</span><span class="html">system.net</span><span class="kwrd">&gt;</span>
    <span class="kwrd">&lt;</span><span class="html">mailSettings</span><span class="kwrd">&gt;</span>
      <span class="kwrd">&lt;</span><span class="html">smtp</span> <span class="attr">deliveryMethod</span><span class="kwrd">=&quot;SpecifiedPickupDirectory&quot;</span><span class="kwrd">&gt;</span>
        <span class="kwrd">&lt;</span><span class="html">specifiedPickupDirectory</span> <span class="attr">pickupDirectoryLocation</span><span class="kwrd">=&quot;c:\mail&quot;</span><span class="kwrd">/&gt;</span>
      <span class="kwrd">&lt;/</span><span class="html">smtp</span><span class="kwrd">&gt;</span>
    <span class="kwrd">&lt;/</span><span class="html">mailSettings</span><span class="kwrd">&gt;</span>
  <span class="kwrd">&lt;/</span><span class="html">system.net</span><span class="kwrd">&gt;</span>
<span class="kwrd">&lt;/</span><span class="html">configuration</span><span class="kwrd">&gt;</span></pre></blockquote>
.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, &quot;Courier New&quot;, 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; }


<p>Now when I run the program above, I get a .EML file in my c:\mail directory:</p>
<p><a href="http://www.pluralsight.com/community/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/keith/image_5F00_2.png"><img style="border-right:0px;border-top:0px;margin:0px 0px 0px 35px;border-left:0px;border-bottom:0px;" height="230" alt="image" src="http://www.pluralsight.com/community/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/keith/image_5F00_thumb.png" width="404" border="0" /></a> </p>
<p>Outlook Express is normally registered as the viewer for .EML files, so double-click the file to view it:</p>
<p><a href="http://www.pluralsight.com/community/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/keith/image_5F00_4.png"><img style="border-right:0px;border-top:0px;margin:0px 0px 0px 35px;border-left:0px;border-bottom:0px;" height="287" alt="image" src="http://www.pluralsight.com/community/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/keith/image_5F00_thumb_5F00_1.png" width="292" border="0" /></a> </p>
<p>If you&#39;ve never seen this method of simulating email before, I hope you find it as useful as I have. Happy coding!</p><div style="clear:both;"></div><img src="http://www.pluralsight.com/community/aggbug.aspx?PostID=52305" width="1" height="1">]]></content:encoded>
      <pubDate>Fri, 01 Aug 2008 09:59:01 +0000</pubDate>
      <category domain="http://securityratty.com/tag/csharpcode pre">csharpcode pre</category>
      <category domain="http://securityratty.com/tag/pre">pre</category>
      <category domain="http://securityratty.com/tag/csharpcode">csharpcode</category>
      <category domain="http://securityratty.com/tag/color">color</category>
      <category domain="http://securityratty.com/tag/email">email</category>
      <category domain="http://securityratty.com/tag/email addresses mailaddress">email addresses mailaddress</category>
      <category domain="http://securityratty.com/tag/mailaddress">mailaddress</category>
      <category domain="http://securityratty.com/tag/mail server">mail server</category>
      <category domain="http://securityratty.com/tag/mail">mail</category>
      <source url="http://www.pluralsight.com/community/blogs/keith/archive/2008/08/01/simulating-email-in-net.aspx">Simulating Email in .NET</source>
    </item>
  </channel>
</rss>
