<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://interactiveasp.net/utility/FeedStylesheets/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/"><channel><title>Nate's Stuff : Standards / Conventions</title><link>http://interactiveasp.net/blogs/natesstuff/archive/tags/Standards+_2F00_+Conventions/default.aspx</link><description>Tags: Standards / Conventions</description><dc:language>en</dc:language><generator>CommunityServer 2008 (Build: 30417.1769)</generator><item><title>Exception Handling Philosophy</title><link>http://interactiveasp.net/blogs/natesstuff/archive/2009/03/23/exception-handling-philosophy.aspx</link><pubDate>Mon, 23 Mar 2009 19:40:00 GMT</pubDate><guid isPermaLink="false">b80005ef-4071-4968-b08e-765d7d71b33e:566</guid><dc:creator>Nathan Zaugg</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://interactiveasp.net/blogs/natesstuff/rsscomments.aspx?PostID=566</wfw:commentRss><wfw:comment xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://interactiveasp.net/blogs/natesstuff/commentapi.aspx?PostID=566</wfw:comment><comments>http://interactiveasp.net/blogs/natesstuff/archive/2009/03/23/exception-handling-philosophy.aspx#comments</comments><description>&lt;div style="float:right; margin:0px; padding:0px 0px 4px 8px;" class="wlWriterHeaderFooter"&gt;
&lt;script type="text/javascript"&gt;&lt;!--
digg_url = "http://interactiveasp.net/blogs/natesstuff/archive/2009/03/23/exception-handling-philosophy.aspx";digg_title = "Exception Handling Philosophy";digg_bgcolor = "#FFFFFF";digg_skin = "normal";
// --&gt;&lt;/script&gt;
&lt;script type="text/javascript" src="http://digg.com/tools/diggthis.js"&gt;&lt;/script&gt;
&lt;script type="text/javascript"&gt;&lt;!--
digg_url = undefined;digg_title = undefined;digg_bgcolor = undefined;digg_skin = undefined;
// --&gt;&lt;/script&gt;
&lt;/div&gt;
&lt;p&gt;It's time for another episode of Good Idea / Bad Idea:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Good Idea!&lt;/strong&gt; &lt;em&gt;Catching a specific exception from a suspect numeric conversion and showing a polite input error message. &lt;br /&gt;&lt;/em&gt;&lt;strong&gt;Bad Idea!&lt;/strong&gt; &lt;em&gt;Catching all exceptions and "swallowing" the exception.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Okay, so it's not as funny as it is on &lt;em&gt;Animaniacs&lt;/em&gt;, but true none-the-less.&lt;/p&gt;
&lt;h2&gt;Exception Handling in C#&lt;/h2&gt;
&lt;p&gt;In terms of exception handling I am a big fan of "catch it only if you can do something with it" and/or "catch it only if you mean it".&amp;nbsp; Putting a try / catch around every method makes debugging very difficult and can leave your application in an unexpected state.&amp;nbsp; Besides the code is less readable, more complex, and slower performing.&lt;/p&gt;
&lt;p&gt;Before I get in to good practices, lets review some bad ones.&amp;nbsp; The first and most obvious is throwing away exceptions (without regard to what they are).&amp;nbsp; Example:&lt;/p&gt;
&lt;pre class="code"&gt;&lt;span style="color: green"&gt;// Anti-pattern #1: Throw away the exception
&lt;/span&gt;&lt;span style="color: blue"&gt;private void &lt;/span&gt;button1_Click(&lt;span style="color: blue"&gt;object &lt;/span&gt;sender, &lt;span style="color: #2b91af"&gt;EventArgs &lt;/span&gt;e) {
    &lt;span style="color: blue"&gt;try &lt;/span&gt;{
        AddPerson(&lt;span style="color: blue"&gt;new &lt;/span&gt;Person() { Name = txtName.Text });
    } &lt;span style="color: blue"&gt;catch &lt;/span&gt;{ }
}&lt;/pre&gt;
&lt;p&gt;&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Another example of what not to do is what I call the &amp;ldquo;catch just because&amp;rdquo; pattern.&amp;nbsp; Example:&lt;/p&gt;
&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;&lt;span style="color: green"&gt;// Anti-pattern #2: Needless Try / Catch
&lt;/span&gt;private void &lt;/span&gt;DoStuff(&lt;span style="color: blue"&gt;string &lt;/span&gt;shipping) {
    &lt;span style="color: blue"&gt;try &lt;/span&gt;{
        &lt;span style="color: green"&gt;// Call down to middle tier to do the shipping calculation            
        &lt;/span&gt;&lt;span style="color: blue"&gt;decimal &lt;/span&gt;ShippingCost = MyApi.Shipping.GetShippingCost(orderNum);
    } &lt;span style="color: blue"&gt;catch &lt;/span&gt;(&lt;span style="color: #2b91af"&gt;Exception &lt;/span&gt;ex) {
        &lt;span style="color: blue"&gt;throw &lt;/span&gt;ex;
    }
}&lt;/pre&gt;
&lt;pre class="code"&gt;&lt;span style="color: green"&gt;//  Needless Try / Catch
&lt;/span&gt;&lt;span style="color: blue"&gt;private void &lt;/span&gt;button2_Click(&lt;span style="color: blue"&gt;object &lt;/span&gt;sender, &lt;span style="color: #2b91af"&gt;EventArgs &lt;/span&gt;e) {
    &lt;span style="color: blue"&gt;try &lt;/span&gt;{
&lt;span style="color: green"&gt;        // CalculateShipping has it's own Try / Catch; see below.
&lt;/span&gt;        CalculateShipping();
    } &lt;span style="color: blue"&gt;catch &lt;/span&gt;(&lt;span style="color: #2b91af"&gt;Exception &lt;/span&gt;ex) {
        &lt;span style="color: #2b91af"&gt;MessageBox&lt;/span&gt;.Show(ex.Message);
    }
}
&lt;/pre&gt;
&lt;p&gt;&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;There are multiple problems with the second example.&amp;nbsp; First, there was no reason for &amp;ldquo;DoStuff&amp;rdquo; to catch the exception if all it was going to do was re-throw any exception it encountered.&amp;nbsp; Second, &amp;ldquo;DoStuff&amp;rdquo; is catching any exception rather than limiting the scope to the kinds of exceptions it might expect like &amp;ldquo;Unknown Zipcode&amp;rdquo;, &amp;ldquo;Order not found&amp;rdquo;, etc.&amp;nbsp; Next, the &amp;ldquo;button2_Click&amp;rdquo; is catching any exception and showing the raw message.&amp;nbsp; &lt;/p&gt;
&lt;p&gt;Rather than showing the exception message which is only part of the clues given in the exception object you should either show a user-friendly message indicating the kind of error that has taken place and save the exception information for later debugging.&amp;nbsp; Alternatively, you can show ex.ToString() which will show you all information in the exception class.&amp;nbsp; This is very unimpressive for end-user applications but can be acceptable with internal corporate apps and a simple screen shot will give you the information you need to find and take care of the problem.&lt;/p&gt;
&lt;p&gt;Remember, an exception doesn&amp;rsquo;t necessarily mean that there is a bug in the software.&amp;nbsp; If you do show a user an &amp;ldquo;unfriendly&amp;rdquo; exception message they will immediately think that the software has a bug when the issue could be as simple as the network is down or a database is temporarily unavailable.&amp;nbsp; I always recommend taking the time to display user-friendly messages and saving the exception information elsewhere.&lt;/p&gt;
&lt;p&gt;In the next section I will show some good examples on what "layer" to catch and/or re-throw an exception.&lt;/p&gt;
&lt;h3&gt;Presentation Layer&lt;/h3&gt;
&lt;p&gt;Personally I think that any event here should catch any/all expected exceptions and show them in a user-friendly manor.&amp;nbsp; Notice I said "expected exceptions", this could be pretty vague unless you have an design pattern in place for exceptions in your applications so I'd start with that.&amp;nbsp; One way to start is to make some "base" exceptions like "DataException", "ValidationException", "InputException", etc.&amp;nbsp; More specific types of exceptions can be derived from these.&amp;nbsp; &lt;/p&gt;
&lt;p&gt;When do you make a new type of exception?&amp;nbsp; Well, the exception should have the information needed to solve the problem.&amp;nbsp; Stack traces and exception information are like clues; leave your self a breadcrumb trail to follow later.&amp;nbsp; Throwing an ApplicationException because you couldn't connect to the database isn't very helpful.&amp;nbsp; &lt;/p&gt;
&lt;p&gt;It is also acceptable to use pre-defined / framework exception types when appropriate.&amp;nbsp; For example:&lt;/p&gt;
&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;public void &lt;/span&gt;DivideMyObjects(MyObjectType o1, MyOtherObjectType o2)
{
    &lt;span style="color: blue"&gt;if &lt;/span&gt;(o1 == &lt;span style="color: blue"&gt;null &lt;/span&gt;|| o2 == &lt;span style="color: blue"&gt;null&lt;/span&gt;)
        &lt;span style="color: blue"&gt;throw new &lt;/span&gt;&lt;span style="color: #2b91af"&gt;NullReferenceException&lt;/span&gt;(
            &lt;span style="color: #a31515"&gt;"The numerator or the denominator cannot be null!"&lt;/span&gt;);

    &lt;span style="color: blue"&gt;if &lt;/span&gt;(o2.Value == 0)
        &lt;span style="color: blue"&gt;throw new &lt;/span&gt;&lt;span style="color: #2b91af"&gt;DivideByZeroException&lt;/span&gt;(
            &lt;span style="color: #a31515"&gt;"Denominator may not be zero!"&lt;/span&gt;);

    &lt;span style="color: blue"&gt;if &lt;/span&gt;(o1.Value == &lt;span style="color: blue"&gt;null&lt;/span&gt;)
        &lt;span style="color: blue"&gt;throw new &lt;/span&gt;&lt;span style="color: #2b91af"&gt;ArgumentException&lt;/span&gt;(
            &lt;span style="color: #a31515"&gt;"There is no value for the numerator"&lt;/span&gt;);
    ...
}&lt;/pre&gt;
&lt;p&gt;&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;&lt;span style="font-family: Courier New;"&gt;&lt;/span&gt;&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;You may notice in the code example above&amp;nbsp;that a null reference may occur organically.&amp;nbsp; I am a strong believer in organic exceptions as good practice.&amp;nbsp;I define an organic exception as an error that is thrown by the&amp;nbsp;Framework.&amp;nbsp;The only exception to that rule is when there isn&amp;rsquo;t enough information from that exception to track down the problem.&amp;nbsp; Remember, you need to leave yourself enough clues that you should be able to know what is wrong from the exception information given rather than expecting users to be able to remember what steps led up to the exception.&amp;nbsp; Few, if any, end users will be able to help you reproduce any particular error.&amp;nbsp; If this can&amp;rsquo;t be accomplished by an organic exception then you may want to re-throw that exception with the appropriate information and/or change the type of the exception to be more appropriate for the callers.&amp;nbsp; &lt;/p&gt;
&lt;pre class="code"&gt;&lt;span style="color: green"&gt;// Presentation Layer Good Example
&lt;/span&gt;&lt;span style="color: blue"&gt;private void &lt;/span&gt;Calculate_Shipping(&lt;span style="color: blue"&gt;object &lt;/span&gt;sender, &lt;span style="color: #2b91af"&gt;EventArgs &lt;/span&gt;e) {
    &lt;span style="color: blue"&gt;try &lt;/span&gt;{
        &lt;span style="color: blue"&gt;decimal &lt;/span&gt;shippingCost = MyApi.Shipping.CalculateShipping(order);
        txtShippingCost.Text = shippingCost.ToString(&lt;span style="color: #a31515"&gt;"C"&lt;/span&gt;);
    } &lt;span style="color: blue"&gt;catch &lt;/span&gt;(UnknownZipcode uzipEx) {
        &lt;span style="color: green"&gt;// Specific
        &lt;/span&gt;&lt;span style="color: #2b91af"&gt;MessageBox&lt;/span&gt;.Show(
            &lt;span style="color: #a31515"&gt;"Could not locate shipping information for this zip code!"&lt;/span&gt;);
        btnSave.Enabled = &lt;span style="color: blue"&gt;false&lt;/span&gt;;
    } &lt;span style="color: blue"&gt;catch &lt;/span&gt;(ShippingException shipEx) {
        &lt;span style="color: green"&gt;// Less specific, but still helpful to the user.
        &lt;/span&gt;&lt;span style="color: #2b91af"&gt;MessageBox&lt;/span&gt;.Show(&lt;span style="color: #a31515"&gt;"Unable to calculate shipping!"
            &lt;/span&gt;+ &lt;span style="color: #2b91af"&gt;Environment&lt;/span&gt;.NewLine +
            shipEx.Message);
        MyLogging.Log(shipEx);
    } &lt;span style="color: blue"&gt;catch &lt;/span&gt;(&lt;span style="color: #2b91af"&gt;Exception &lt;/span&gt;ex) {
        &lt;span style="color: #2b91af"&gt;MessageBox&lt;/span&gt;.Show(
            &lt;span style="color: #a31515"&gt;"An unknown error has occured, Please report this error"&lt;/span&gt;);
        MyLogging.Log(ex);
        Close();
    }
}&lt;/pre&gt;
&lt;p&gt;&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;In general you are pretty safe catching exceptions in the presentation layer.&amp;nbsp; The only real thing to watch out for here is that your control states don&amp;rsquo;t become invalid because an exception is caught but the event still altered the state.&amp;nbsp; For example, if a call to &amp;ldquo;Calculate_Shipping&amp;rdquo; throws an exception you will want to be careful to invalidate the shipping cost control and disable the &amp;ldquo;save order&amp;rdquo; button.&amp;nbsp; &lt;/p&gt;
&lt;p&gt;You will notice in the code above that I did catch generic exception.&amp;nbsp; The presentation layer is usually okay doing this so long as it is taking adequate measures to protect application integrity.&amp;nbsp; You will notice that I am closing the order form if I get an exception back that that is unknown.&amp;nbsp; Of course this will give you plenty of motivation to make sure you know what kinds of exceptions are expected as end users will generally hate having their order forms close.&amp;nbsp; You may be tempted to leave the form open or take lesser action but it is very important that you keep application integrity.&amp;nbsp; Otherwise you will spend your life chasing down un-reproducible bugs.&lt;/p&gt;
&lt;h3&gt;Middle Layer&lt;/h3&gt;
&lt;p&gt;Most of your code should end up being middle layer code.&amp;nbsp; We want the presentation layer to be as light as possible!&amp;nbsp; The middle layer should act as the API of the application.&amp;nbsp; Anything that the application &amp;ldquo;does&amp;rdquo; this layer should do it either directly or indirectly. In this sense the middle layer needs to be very up front in which exceptions are possible from any given call.&amp;nbsp; &lt;/p&gt;
&lt;p&gt;Take for example a method call in the middle layer that inserts a new customer into the database.&amp;nbsp; Because you use the database objects you are exposed to any exceptions that are possible from the objects that you use such as SqlExceptions.&amp;nbsp; You will either need to publish that you are going to allow SqlExceptions to be bubble through this API or you need to catch the expected exceptions from those objects and throw your own brand of exception.&lt;/p&gt;
&lt;p&gt;Here is an example of publishing the exceptions that are known to be thrown:&lt;/p&gt;
&lt;pre class="code"&gt;&lt;span style="color: green"&gt;// Middle Layer Exceptions
&lt;/span&gt;&lt;span style="color: gray"&gt;/// &amp;lt;summary&amp;gt;
/// &lt;/span&gt;&lt;span style="color: green"&gt;Calculates shipping for a given order
&lt;/span&gt;&lt;span style="color: gray"&gt;/// &amp;lt;/summary&amp;gt;
/// &amp;lt;param name="order"&amp;gt;&lt;/span&gt;&lt;span style="color: green"&gt;The order to calculate shipping for&lt;/span&gt;&lt;span style="color: gray"&gt;&amp;lt;/param&amp;gt;
/// &amp;lt;returns&amp;gt;&lt;/span&gt;&lt;span style="color: green"&gt;the shipping amount applied to the order&lt;/span&gt;&lt;span style="color: gray"&gt;&amp;lt;/returns&amp;gt;
/// &amp;lt;exception cref="UnknownZipcode"&amp;gt;&lt;/span&gt;&lt;span style="color: green"&gt;Unknown Zip Code / Zip Not Found&lt;/span&gt;&lt;span style="color: gray"&gt;&amp;lt;/exception&amp;gt;
/// &amp;lt;exception cref="BadWeightException"&amp;gt;&lt;/span&gt;&lt;span style="color: green"&gt;The weight of the order is zero or unknown&lt;/span&gt;&lt;span style="color: gray"&gt;&amp;lt;/exception&amp;gt;
&lt;/span&gt;&lt;span style="color: blue"&gt;public decimal &lt;/span&gt;CalculateShipping(Order order) {
    ...
}&lt;/pre&gt;
&lt;p&gt;&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="http://interactiveasp.net/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/natesstuff/KnownExceptions_5F00_07D5F276.png" target="_blank"&gt;&lt;img style="border-right: 0px; border-top: 0px; display: inline; border-left: 0px; border-bottom: 0px" title="Known Exceptions" border="0" alt="Known Exceptions" src="http://interactiveasp.net/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/natesstuff/KnownExceptions_5F00_thumb_5F00_122716D6.png" width="504" height="185" /&gt;&lt;/a&gt; &lt;/p&gt;
&lt;p&gt;Simply using &lt;a class="null" title="NDoc Documentation Generator" href="http://ndoc.sourceforge.net/" target="_blank"&gt;ndoc&lt;/a&gt; XML style comments will give the consumer of the API enough information to make good decisions regarding the use of exception handling from the intellisense. &lt;/p&gt;
&lt;p&gt;Another thing you should avoid while designing your middle tier is the use of exceptions as &amp;ldquo;message handling&amp;rdquo; in non-exceptional cases.&amp;nbsp; Remember, the reason you are throwing an exception is because something happened that was catastrophic enough that you were unable to continue with the normal flow of the method.&amp;nbsp; I admit that there is still a lot of gray area here.&amp;nbsp; Some of that gray area can be demonstrated in the sample code already shown.&amp;nbsp; For example, rather than throwing an exception in the &amp;ldquo;CalculateShipping&amp;rdquo; method we could refactor so an exception wouldn't be necessary.&amp;nbsp; Anytime this can be done cleanly I usually opt for these types of changes.&amp;nbsp; &lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Refactor to return a ShippingResult class that contains information about the calculation along with the rate.&amp;nbsp; Such information could include whether it was able to successfully get a shipping rate.&lt;/li&gt;
&lt;li&gt;Create a ValidateShippingAddress method that looks up the address before the calculate shipping is run.&amp;nbsp; It could return true if we know we can get shipping information for that address.&lt;/li&gt;
&lt;li&gt;We could pass back a nullable decimal result.&amp;nbsp; A null return would indicate a failure to retrieve shipping information.&amp;nbsp; We would want to make sure it was clear in our ndoc comments that this is why the value is nullable.&lt;/li&gt;
&lt;li&gt;We could pass pack a zero or negative result.&amp;nbsp; Again, making sure this behavior is documented.&lt;/li&gt;
&lt;li&gt;We could implement the &amp;ldquo;Get Last Error&amp;rdquo; pattern; though at this point I&amp;rsquo;d rather see an exception.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Another question I am often asked is &amp;ldquo;When is it appropriate to re-throw an exception&amp;rdquo;.&amp;nbsp; The answer to that questions is, of course, it depends.&amp;nbsp; The next few sections will discuss some of these nuances of this question.&lt;/p&gt;
&lt;h3&gt;Bottom Layer&lt;/h3&gt;
&lt;p&gt;The bottom layer of an application could be a database layer, a Framework of some sort but the philosophy is very different from the middle layer.&amp;nbsp; As the bottom layers deal with primitive classes and data and as such can stick pretty well to exception handling ideals.&amp;nbsp; One of the big differences is that you won&amp;rsquo;t be using nearly as many user defined exception types.&amp;nbsp; It is not taboo to use a user defined type in a Framework layer but it&amp;rsquo;s just likely to be unnecessary.&amp;nbsp; The difficulty here is the exception message that you are going to pass along.&amp;nbsp; There could be any number of middle layer calls that call your method so by nature these messages are going to be far more generic.&amp;nbsp; Generic, however, does not mean it can&amp;rsquo;t be insightful.&amp;nbsp; You should include as much information as possible about the exception and the data that caused the exception.&amp;nbsp; Take the two following exception statements:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&amp;ldquo;Invalid DateTime&amp;rdquo;&lt;/li&gt;
&lt;li&gt;&amp;ldquo;The date &amp;lsquo;4/11/2089&amp;rsquo; is an invalid birth date!&amp;nbsp; The date cannot be in the future!&amp;rdquo;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The first exception tells us that there is an invalid date time but other than a stack trace gives us no other information.&amp;nbsp; The second exception is extremely helpful and specific, including as many clues as possible.&amp;nbsp; The user may have entered the value &amp;lsquo;4/11/89&amp;rsquo; and the computer may have just assumed the wrong century. The first error message would cause greater confusion whereas the second, if the user were to see that message, could be helpful.&lt;/p&gt;
&lt;h2&gt;Summary&lt;/h2&gt;
&lt;p&gt;Of course there are lots of different ideas and philosophies on exception handling so you need to do what makes sense for your project.&amp;nbsp; Simply avoiding the two anti-patterns on the top of this blog will improve your code a lot.&amp;nbsp; &lt;strong&gt;MY ONE LAST PEICE OF ADVIECE IS THAT SOMETIMES YOU REALLY WANT TO USE A DEBUG.ASSERT RATHER THAN AN EXCEPTION!&lt;/strong&gt; The advantage of the assertion is that only debug builds show these messages.&amp;nbsp; This is good for testing scenarios in which you want to be aware of a certain condition but it&amp;rsquo;s not necessarily an exception.&lt;/p&gt;
&lt;h5&gt;Links:&lt;/h5&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://blogs.msdn.com/jmstall/archive/2007/02/07/catch-rethrow.aspx"&gt;http://blogs.msdn.com/jmstall/archive/2007/02/07/catch-rethrow.aspx&lt;/a&gt; &lt;/li&gt;
&lt;/ul&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://interactiveasp.net/aggbug.aspx?PostID=566" width="1" height="1"&gt;</description><category domain="http://interactiveasp.net/blogs/natesstuff/archive/tags/Debugging/default.aspx">Debugging</category><category domain="http://interactiveasp.net/blogs/natesstuff/archive/tags/Tips+_2600_amp_3B00_+Tricks/default.aspx">Tips &amp;amp; Tricks</category><category domain="http://interactiveasp.net/blogs/natesstuff/archive/tags/Standards+_2F00_+Conventions/default.aspx">Standards / Conventions</category><category domain="http://interactiveasp.net/blogs/natesstuff/archive/tags/.NET/default.aspx">.NET</category><category domain="http://interactiveasp.net/blogs/natesstuff/archive/tags/Design+Patterns/default.aspx">Design Patterns</category></item><item><title>Encrypting Configuration Information for ASP.NET</title><link>http://interactiveasp.net/blogs/natesstuff/archive/2008/07/16/encrypting-configuration-information-for-asp-net.aspx</link><pubDate>Wed, 16 Jul 2008 22:11:22 GMT</pubDate><guid isPermaLink="false">b80005ef-4071-4968-b08e-765d7d71b33e:54</guid><dc:creator>Nathan Zaugg</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://interactiveasp.net/blogs/natesstuff/rsscomments.aspx?PostID=54</wfw:commentRss><wfw:comment xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://interactiveasp.net/blogs/natesstuff/commentapi.aspx?PostID=54</wfw:comment><comments>http://interactiveasp.net/blogs/natesstuff/archive/2008/07/16/encrypting-configuration-information-for-asp-net.aspx#comments</comments><description>&lt;p&gt;&lt;img style="border-right:0px;border-top:0px;margin:0px 10px 5px 0px;border-left:0px;border-bottom:0px;" height="104" alt="Encryption Block Transform Graphic" src="http://interactiveasp.net/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/natesstuff/Encryption-Block-Transform-Graphic_5F00_3.png" width="104" align="left" border="0" /&gt; Every company I consult with invariably has their own &amp;quot;security&amp;quot; assembly and they all have a hard-coded encryption key with the IV and the method to decrypt is right next to the method to encrypt.&amp;nbsp; This is what I call &lt;strong&gt;&lt;em&gt;marginal&lt;/em&gt;&lt;/strong&gt; &lt;strong&gt;&lt;em&gt;protection&lt;/em&gt;&lt;/strong&gt;.&amp;nbsp; Yes, it&amp;#39;s encrypted and will probably get a security auditor off of your back but don&amp;#39;t be fooled into thinking that you are protected!&amp;nbsp; A similar thing is done with information in the database, but I&amp;#39;ll cover how to do this on an upcoming post.&amp;nbsp; &lt;/p&gt; &lt;p&gt;Why aren&amp;#39;t you protected?&amp;nbsp; The answer to this question is actually quite simple.&amp;nbsp; If an attacker has access to download your web.config file (say, they brute forced a password on the FTP server) then there is nothing stopping them from downloading the your Security.dll which is responsible for decrypting the password.&amp;nbsp; Once they have that library it&amp;#39;s seconds, not minuets, before they have got the password.&amp;nbsp; &lt;/p&gt; &lt;p&gt;One possible work around is to encrypt configuration sections of your web.config file using DPAPI as outlined in &lt;a href="http://msdn.microsoft.com/en-us/library/ms998280.aspx" target="_blank"&gt;this MSDN How-to&lt;/a&gt;.&amp;nbsp; This is immune to the download attack because the DPAPI uses encryption that is based on a machine or a user.&amp;nbsp; Even if someone was able to download your web.config they would effectively have no way to decrypt that information.&amp;nbsp; &lt;/p&gt; &lt;p&gt;What happens, though, if the attacker has the ability to upload files?&amp;nbsp; Well, in theory, they may be able to grab that configuration in code which will, of course, be decrypted before it is returned.&amp;nbsp; Ahh, but they don&amp;#39;t even know what the name of the connection string (in the case of databases) is because the entire section was encrypted.&amp;nbsp; However, they could guess it or get it from other code. By the way, you really shouldn&amp;#39;t deploy the .cs files to production anyway; you should use the &amp;quot;publish website&amp;quot; option with the setting to not allow the site to be updated.&amp;nbsp; If you follow all of the standards pretty closely your in good shape.&amp;nbsp; Another great idea is to use Integrated Authentication for database access -- that way there is no password to steal!&lt;/p&gt; &lt;p&gt;The How to outlines 3 basic steps summarized below:&lt;/p&gt; &lt;ol&gt; &lt;li&gt;Identify the configuration sections to be encrypted&lt;/li&gt; &lt;ol&gt; &lt;li&gt;You may only encrypt the following:&lt;/li&gt; &lt;div&gt;&lt;pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;border-top-style:none;line-height:12pt;padding-top:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:#f4f4f4;border-bottom-style:none;"&gt;&lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;appSettings&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;. This section contains custom application settings. 
&lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;connectionStrings&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;. This section contains connection strings. 
&lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;identity&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;. This section can contain impersonation credentials. 
&lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;sessionState&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;. The section contains the connection string for the out-of-process session state provider.&lt;/pre&gt;&lt;/div&gt;&lt;/ol&gt;
&lt;li&gt;Choose Machine or User store&lt;/li&gt;
&lt;ol&gt;
&lt;li&gt;Use Machine store if this is a dedicated server with no other applications running on it or you want to be able to share this information with other applications running on this machine.&lt;/li&gt;
&lt;li&gt;Use User store if the above does not match your situation and in a scenario in which the user has limited access to the server.&lt;/li&gt;&lt;/ol&gt;
&lt;li&gt;Encrypt your configuration file data&lt;/li&gt;
&lt;ol&gt;
&lt;li&gt;To encrypt using Machine Store, run the following command from a .NET command prompt: &lt;br /&gt;&lt;strong&gt;aspnet_regiis.exe -pef &amp;quot;&lt;em&gt;{ConfigSectionName}&lt;/em&gt;&amp;quot; &lt;em&gt;{PhysicalDirectory}&lt;/em&gt; –prov &amp;quot;DataProtectionConfigurationProvider&amp;quot;&lt;br /&gt;&lt;/strong&gt;OR&lt;br /&gt;&lt;strong&gt;aspnet_regiis.exe -pef &amp;quot;&lt;em&gt;{ConfigSectionName}&lt;/em&gt;&amp;quot; -app &amp;quot;&lt;em&gt;/{VirtualDirectory}&amp;quot;&lt;/em&gt; –prov &amp;quot;DataProtectionConfigurationProvider&amp;quot;&lt;br /&gt;&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;To encrypt using User Store:&lt;br /&gt;Add the following section to your configuration file:&lt;br /&gt;&lt;/li&gt;
&lt;div&gt;&lt;pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;border-top-style:none;line-height:12pt;padding-top:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:#f4f4f4;border-bottom-style:none;"&gt;&lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;configProtectedData&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt; 
    &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;providers&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt; 
        &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;add&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;useMachineProtection&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;false&amp;quot;&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;keyEntropy&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;&amp;quot;&lt;/span&gt; 
                &lt;span style="color:#ff0000;"&gt;name&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;MyUserDataProtectionConfigurationProvider&amp;quot;&lt;/span&gt; 
                &lt;span style="color:#ff0000;"&gt;type&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;System.Configuration.DpapiProtectedConfigurationProvider, 
                System.Configuration, Version=2.0.0.0, Culture=neutral, 
                PublicKeyToken=b03f5f7f11d50a3a&amp;quot;&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;/&amp;gt;&lt;/span&gt; 
    &lt;span style="color:#0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;providers&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt; 
&lt;span style="color:#0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;configProtectedData&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Open a command prompt using the user you plan to encrypt the file with. To do so, Right click on the Command Prompts shortcut, right click -&amp;gt; Run As.&amp;nbsp; Or use the following command: 
&lt;div&gt;&lt;pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;border-top-style:none;line-height:12pt;padding-top:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:#f4f4f4;border-bottom-style:none;"&gt;Runas /profile /user:domain\user cmd&lt;/pre&gt;&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;Run the following command:&lt;br /&gt;&lt;strong&gt;Aspnet_regiis -pe &amp;quot;connectionStrings&amp;quot; -app &amp;quot;/{VirtualDirectory}&amp;quot; -prov &amp;quot;MyUserDataProtectionConfigurationProvider&amp;quot;&lt;/strong&gt;&lt;/div&gt;&lt;/ol&gt;&lt;/ol&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;It really is that simple!&amp;nbsp; The great thing is that we don&amp;#39;t have to do anything special in development to benefit from the encryption of the configuration sections.&amp;nbsp; &lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4&gt;References:&lt;/h4&gt;
&lt;p&gt;&lt;a title="http://msdn.microsoft.com/en-us/library/ms998280.aspx" href="http://msdn.microsoft.com/en-us/library/ms998280.aspx"&gt;http://msdn.microsoft.com/en-us/library/ms998280.aspx&lt;/a&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://interactiveasp.net/aggbug.aspx?PostID=54" width="1" height="1"&gt;</description><category domain="http://interactiveasp.net/blogs/natesstuff/archive/tags/ASP.NET/default.aspx">ASP.NET</category><category domain="http://interactiveasp.net/blogs/natesstuff/archive/tags/Tips+_2600_amp_3B00_+Tricks/default.aspx">Tips &amp;amp; Tricks</category><category domain="http://interactiveasp.net/blogs/natesstuff/archive/tags/Security/default.aspx">Security</category><category domain="http://interactiveasp.net/blogs/natesstuff/archive/tags/Standards+_2F00_+Conventions/default.aspx">Standards / Conventions</category><category domain="http://interactiveasp.net/blogs/natesstuff/archive/tags/Encryption/default.aspx">Encryption</category></item><item><title>Database Naming Conventions</title><link>http://interactiveasp.net/blogs/natesstuff/archive/2008/07/02/database-naming-conventions.aspx</link><pubDate>Wed, 02 Jul 2008 20:50:00 GMT</pubDate><guid isPermaLink="false">b80005ef-4071-4968-b08e-765d7d71b33e:45</guid><dc:creator>Nathan Zaugg</dc:creator><slash:comments>1</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://interactiveasp.net/blogs/natesstuff/rsscomments.aspx?PostID=45</wfw:commentRss><wfw:comment xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://interactiveasp.net/blogs/natesstuff/commentapi.aspx?PostID=45</wfw:comment><comments>http://interactiveasp.net/blogs/natesstuff/archive/2008/07/02/database-naming-conventions.aspx#comments</comments><description>&lt;p&gt;&lt;img style="border-right: 0px; border-top: 0px; margin: 0px 10px 5px 0px; border-left: 0px; border-bottom: 0px" alt="DatabaseServer" src="http://interactiveasp.net/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/natesstuff/DatabaseServer_5F00_3.png" width="103" align="left" border="0" height="119" /&gt; Naming conventions are like arm pits.&amp;nbsp; Everyone has them and they all stink!&amp;nbsp; Well, at least that's the perspective of pretty much every developer an DBA alike.&amp;nbsp; I will present my own personal philosophy for naming conventions on databases and hopefully spawn some discussion in the process.&lt;/p&gt;
&lt;h2&gt;Basic Principles&lt;/h2&gt;
&lt;h3&gt;Consistency&lt;/h3&gt;
&lt;p&gt;As annoying as certain standards are (such as putting tbl_ before everything) it is more annoying and more difficult when there are no conventions or mixed conventions.&amp;nbsp; Being able to reliably predict the schema once the basic relational structure is understood is key to productivity.&amp;nbsp; Therefore, even if you get stuck with standards you disagree with, so long as they are consistent they will be much better than the alternative.&amp;nbsp; Unless you get to make the decision, my guess is that there are going to be some conventions that you do not agree with. &lt;/p&gt;
&lt;h3&gt;Abbreviations&lt;/h3&gt;
&lt;p&gt;It is a good idea to abbreviate, when appropriate, in the naming of objects in your database.&amp;nbsp; It may be a good idea to have a list of abbreviations that you plan to use in the database as part of your data dictionary.&amp;nbsp; However, if there is not a good, clear abbreviation for an object, don't make one up.&amp;nbsp; &lt;i&gt;When in doubt, spell it out!&lt;/i&gt;&amp;nbsp; Especially with SQL Server where you don't have the pesky 30 char limit for tables and columns like Oracle.&lt;/p&gt;
&lt;h3&gt;Identities&lt;/h3&gt;
&lt;p&gt;Every table should have an Identity as it's primary key!&amp;nbsp; Sometime, in a future blog post I will explain why this is so critical, but suffice it to say that any table that does not have a primary key is considered by SQL Server a "heap".&amp;nbsp; If you are using something other than an Identity column for the primary key you better have a really compelling reason because it will cause major performance problems.&amp;nbsp; &lt;b&gt;&lt;i&gt;THERE IS NO SUCH THING AS A NATURAL KEY AND THEY SHOULD NEVER BE USED IN PLACE OF AN IDENTITY!&lt;/i&gt;&lt;/b&gt; So always use a surrogate key approach, even with join tables.&lt;/p&gt;
&lt;h3&gt;Security&lt;/h3&gt;
&lt;p&gt;&lt;img style="border-right: 0px; border-top: 0px; margin: 5px 0px 5px 10px; border-left: 0px; border-bottom: 0px" alt="Key" src="http://interactiveasp.net/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/natesstuff/Key_5F00_3.png" width="81" align="right" border="0" height="81" /&gt; I believe that with a good data layer like &lt;a href="http://interactiveasp.net/blogs/natesstuff/archive/2007/12/19/visual-studio-2008-rtm-changes-to-linq-to-sql.aspx" target="_blank"&gt;Linq to SQL&lt;/a&gt; there is no need for relegating all database access through stored procedures.&amp;nbsp; While it does remove some of the service area for venerability and bugs robust solutions like Linq to SQL are very limited by this approach.&amp;nbsp; You should grant specific access to tables and procs by user.&amp;nbsp; A good approach can be found on another one of my &lt;a href="http://interactiveasp.net/blogs/natesstuff/archive/2008/06/26/connection-pooling-vs-audit-logging.aspx" target="_blank"&gt;blog posts&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;Object Naming&lt;/h2&gt;
&lt;h3&gt;Table Names&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;If you are running a database that preserves case (like SQL Server) tables should have no prefixes and should not contain underscores "_" unless it is a join table.&amp;nbsp; Table names should also be Pascal Cased.&amp;nbsp; If you are running a database that makes all tables upper case (like Oracle) then you have little choice but to use underscores everywhere.&lt;/li&gt;
&lt;li&gt;Avoid pluralizing table names (User vs Users).&amp;nbsp; This is a good idea for two reasons, first it can be confusing when doing the keys.&amp;nbsp; Do we use UserID or UsersID?&amp;nbsp; Second not all tables pluralize well (Addresses) so avoiding any plural names will keep it consistent.&amp;nbsp; It you are using Linq to SQL the designer will pluralize for you automatically.&lt;/li&gt;
&lt;li&gt;Join tables should the two or three tables that they are joining together as part of the name seperated by underscores.&amp;nbsp; (ex: User_Address, User_Order). Although they are many-to-many relationship see if you can find a principle table.&amp;nbsp; Users have orders, orders do not have users, therefore the User table comes first in the name.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Column Names&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Name the Primary Key Identity column the table name with ID.&amp;nbsp; (ex: UserID) With the possible exception of join tables, in which case just name the Identity ID.&lt;/li&gt;
&lt;li&gt;Use Pascal casing (ex: EachWordsStartsCapolatized)&lt;/li&gt;
&lt;li&gt;Do not use the table name as part of the column name.&amp;nbsp; If this is a shipping table don't name your columns ShippingAddress, just name it Address.&lt;/li&gt;
&lt;li&gt;Do not prefix column names with the type (ex: strUserName).&amp;nbsp; It makes the database much more difficult to work with.&lt;/li&gt;
&lt;li&gt;Use the correct data types.&amp;nbsp; Always use nvarchar types (unicode) rather than varchar types.&amp;nbsp; This avoids substantial complexity if you are ever requried to store non latin-based data!&amp;nbsp; Trust me, you do not want to have to deal with code pages in the database!&amp;nbsp; Also, use Date fields for dates, bit fields for boolean, etc.&lt;/li&gt;
&lt;li&gt;Don't make every column nullable!&amp;nbsp; Think through what data is absolutely required.&amp;nbsp; If you want to hold "partally complete records" then I would suggest a different table or different "staging" database.&amp;nbsp; &lt;/li&gt;
&lt;li&gt;Don't make a bit field nullable unless you have a great reason!&lt;/li&gt;
&lt;li&gt;Try to include a TimeStamp column if you think you may have to worry about concurrency.&lt;/li&gt;
&lt;li&gt;Don't prefix with anything.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Constraint &amp;amp; Index Names&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Name your constraints and indexes.&amp;nbsp; With the exception of foreign key constraints they are not automatically assigned meaningful names.&lt;/li&gt;
&lt;li&gt;Don't use prefixes and make light use of underscores.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Stored Procedure Names&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Don't prefix your stored procedures!&amp;nbsp; People used to prefix them with "sp" because existing procs in the database use this convention.&amp;nbsp; It has been presumed that sp stands for system procedure and it wouldn't make any sense to use that.&amp;nbsp; Seriously, prefixes are not very helpful in the database!&lt;/li&gt;
&lt;li&gt;The first part of the name of a proc should be the table name it works upon (ex: User_Insert).&amp;nbsp; If the proc works on multiple tables try to give it the name of the portion of the database this proc deals with.&amp;nbsp; For example, if it's a proc that the invoicing system uses it would be acceptable to name it &lt;i&gt;Invoicing_Update&lt;/i&gt;, for example.&lt;/li&gt;
&lt;li&gt;Don't generate procs for simple Insert, Update, Delete, and Select unless you have a policy in place for accessing data exclusively from procs.&lt;/li&gt;
&lt;li&gt;Don't create any stored procedure you don't need or plan to immediately use.&amp;nbsp; At some point you will change the schema and you won't update procs your not using.&amp;nbsp; Someone may eventually want to use that proc later only to find it broken.&lt;/li&gt;
&lt;li&gt;The verb in the naming convention does not have to be relegated to "Insert, Update, Delete, Select".&amp;nbsp; It should say what it does.&amp;nbsp; Just be careful that if there is another procedure that does this same thing to another table that the verbs are named the same.&lt;/li&gt;
&lt;li&gt;You can add additional information to the proc name to help distinguish it from others.&amp;nbsp; (ex: User_Select_ByDate, User_Select_ByState)&lt;/li&gt;
&lt;li&gt;Don't use a prefix for arguments (ex: @ArgUserID). In my experience they don't help at all and are quite annoying!&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Tips &amp;amp; Tricks&lt;/h3&gt;
&lt;p&gt;SQL Server 2008 has a policy manager that can help create and enforce policies like naming conventions!&amp;nbsp; Regardless of using SQL 2008 be sure to keep a Data Dictionary of your database! The database is the heart and soul of your business processes and should be well documented!&amp;nbsp; There is nothing worse than an unclean database!&lt;/p&gt;
&lt;p&gt;Nathan Zaugg&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://interactiveasp.net/aggbug.aspx?PostID=45" width="1" height="1"&gt;</description><category domain="http://interactiveasp.net/blogs/natesstuff/archive/tags/SQL+Server+2005/default.aspx">SQL Server 2005</category><category domain="http://interactiveasp.net/blogs/natesstuff/archive/tags/Architecture/default.aspx">Architecture</category><category domain="http://interactiveasp.net/blogs/natesstuff/archive/tags/Tips+_2600_amp_3B00_+Tricks/default.aspx">Tips &amp;amp; Tricks</category><category domain="http://interactiveasp.net/blogs/natesstuff/archive/tags/SQL+Server+2008/default.aspx">SQL Server 2008</category><category domain="http://interactiveasp.net/blogs/natesstuff/archive/tags/Standards+_2F00_+Conventions/default.aspx">Standards / Conventions</category></item></channel></rss>