<?xml version="1.0" encoding="utf-8"?>
<rss xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:pingback="http://madskills.com/public/xml/rss/module/pingback/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:dc="http://purl.org/dc/elements/1.1/" version="2.0">
  <channel>
    <title>Joshua Flanagan - .NET</title>
    <link>http://flimflan.com/blog/</link>
    <description>A .NET Software Developer</description>
    <language>en-us</language>
    <copyright>josh</copyright>
    <lastBuildDate>Wed, 25 Jun 2008 07:05:02 GMT</lastBuildDate>
    <generator>newtelligence dasBlog 2.1.8209.14743</generator>
    <managingEditor>josh@flimflan.com</managingEditor>
    <webMaster>josh@flimflan.com</webMaster>
    <item>
      <trackback:ping>http://flimflan.com/blog/Trackback.aspx?guid=354870db-1c4e-42f5-8919-6a1f95767846</trackback:ping>
      <pingback:server>http://flimflan.com/blog/pingback.aspx</pingback:server>
      <pingback:target>http://flimflan.com/blog/PermaLink,guid,354870db-1c4e-42f5-8919-6a1f95767846.aspx</pingback:target>
      <dc:creator>
      </dc:creator>
      <wfw:comment>http://flimflan.com/blog/CommentView,guid,354870db-1c4e-42f5-8919-6a1f95767846.aspx</wfw:comment>
      <wfw:commentRss>http://flimflan.com/blog/SyndicationService.asmx/GetEntryCommentsRss?guid=354870db-1c4e-42f5-8919-6a1f95767846</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
As I stated in my <a href="http://flimflan.com/blog/ToVar.aspx" target="_blank">last
post</a>, the var keyword is an acknowledgement that I do not care what the type of
the variable is - I only care what it can do.
</p>
        <h3>Into the IUknown
</h3>
        <p>
Most developer start on the path to this revelation when they discover interface-based
programming. 
</p>
        <p>
Consider: we need to write a method that returns a collection of strings. Callers
of the method will only need to loop over the items and perform some action. The number
of elements to return is not known at compile time, so we'll declare a generic List&lt;string&gt;,
populate it within a loop, and then return it to the caller. 
</p>
        <p>
The junior developer will declare the return type of the method as List&lt;string&gt;:
</p>
        <p>
          <font face="Courier New">List&lt;string&gt; GetNames(){}</font>
        </p>
        <p>
Acknowledging that callers should not be bothered with having to know an implementation
detail (the fact that a List was used instead of a fixed-sized array), and knowing
that they only need to loop over the returned items, a more experienced developer
might declare the method:
</p>
        <p>
          <font face="Courier New">IEnumerable&lt;string&gt; GetNames() {}</font>
        </p>
        <p>
Which means any variable the receives the return value will also be typed as IEnumerable&lt;string&gt;:
</p>
        <p>
          <font face="Courier New">IEnumerable&lt;string&gt; names = GetNames();</font>
        </p>
        <p>
Here's the kicker - in <em>both</em> scenarios, the GetNames method is really returning
an object of type List&lt;string&gt;! When the supposedly more experienced developer
chooses to return a more abstract type like IEnumerable&lt;string&gt;, type information
is lost. Yikes! The <em>names</em> local variable above holds a List&lt;string&gt;
instance, but you (the client developer) don't know it. As scary as that might sound,
you probably realize that you don't care. As long as you can do the things you need
to do with <em>names</em> (loop over it), you are happy.
</p>
        <h3>Walking like a duck
</h3>
        <p>
Now let's take that train of thought and consider <a href="http://en.wikipedia.org/wiki/Duck_typing" target="_blank">duck
typing</a> in a dynamic language like Python. I can declare the following method:
</p>
        <p>
          <font face="Courier New">def Recycle(service):<br />
    service.Stop()<br />
    service.Start()</font>
          <br />
        </p>
        <p>
It takes a single parameter named <em>service</em>. What is the type of the parameter
that is expected? I don't know. And after the initial anxiety settles, there is the
liberating realization that I don't have to care! All I know, or care, is that any
object instance that is passed to this method must implement a Start() and a Stop()
method. The same method can be used with instances of a Lawnmower, AuditLogger, or
SongPlayer class (assuming they all have Start and Stop methods). 
</p>
        <h3>Getting closer to the goal
</h3>
        <p>
Let me be clear - I am not suggesting that implicit typing in C# 3.0 is the same as
duck typing. What I am suggesting is that the 2 examples above are points along the
"progression of understanding" of the same concept: it is the behavior of an object
that really matters, as opposed to the type name that is attached to it. Interface-based
programming is near the start. Implicit typing is further along the progression. Duck
typing is closer to the end.
</p>
        <p>
I think we will find that programmers who have been exposed to and understand languages
which support duck typing will be more likely to be comfortable with and embrace the
var keyword. They have already made the mental leap that type information serves the
computer more than it serves the human. If you haven't yet, do yourself a favor and
learn a dynamic programming language, even if you know you will continue to spend
your days with static typing.
</p>
        <img width="0" height="0" src="http://flimflan.com/blog/aggbug.ashx?id=354870db-1c4e-42f5-8919-6a1f95767846" />
      </body>
      <title>Losing your (type) religion</title>
      <guid isPermaLink="false">http://flimflan.com/blog/PermaLink,guid,354870db-1c4e-42f5-8919-6a1f95767846.aspx</guid>
      <link>http://flimflan.com/blog/LosingYourTypeReligion.aspx</link>
      <pubDate>Wed, 25 Jun 2008 07:05:02 GMT</pubDate>
      <description>&lt;p&gt;
As I stated in my &lt;a href="http://flimflan.com/blog/ToVar.aspx" target="_blank"&gt;last
post&lt;/a&gt;, the var keyword is an acknowledgement that I do not care what the type of
the variable is - I only care what it can do.
&lt;/p&gt;
&lt;h3&gt;Into the IUknown
&lt;/h3&gt;
&lt;p&gt;
Most developer start on the path to this revelation when they discover interface-based
programming. 
&lt;/p&gt;
&lt;p&gt;
Consider: we need to write a method that returns a collection of strings. Callers
of the method will only need to loop over the items and perform some action. The number
of elements to return is not known at compile time, so we'll declare a generic List&amp;lt;string&amp;gt;,
populate it within a loop, and then return it to the caller. 
&lt;/p&gt;
&lt;p&gt;
The junior developer will declare the return type of the method as List&amp;lt;string&amp;gt;:
&lt;/p&gt;
&lt;p&gt;
&lt;font face="Courier New"&gt;List&amp;lt;string&amp;gt; GetNames(){}&lt;/font&gt;
&lt;/p&gt;
&lt;p&gt;
Acknowledging that callers should not be bothered with having to know an implementation
detail (the fact that a List was used instead of a fixed-sized array), and knowing
that they only need to loop over the returned items, a more experienced developer
might declare the method:
&lt;/p&gt;
&lt;p&gt;
&lt;font face="Courier New"&gt;IEnumerable&amp;lt;string&amp;gt; GetNames() {}&lt;/font&gt;
&lt;/p&gt;
&lt;p&gt;
Which means any variable the receives the return value will also be typed as IEnumerable&amp;lt;string&amp;gt;:
&lt;/p&gt;
&lt;p&gt;
&lt;font face="Courier New"&gt;IEnumerable&amp;lt;string&amp;gt; names = GetNames();&lt;/font&gt;
&lt;/p&gt;
&lt;p&gt;
Here's the kicker - in &lt;em&gt;both&lt;/em&gt; scenarios, the GetNames method is really returning
an object of type List&amp;lt;string&amp;gt;! When the supposedly more experienced developer
chooses to return a more abstract type like IEnumerable&amp;lt;string&amp;gt;, type information
is lost. Yikes! The &lt;em&gt;names&lt;/em&gt; local variable above holds a List&amp;lt;string&amp;gt;
instance, but you (the client developer) don't know it. As scary as that might sound,
you probably realize that you don't care. As long as you can do the things you need
to do with &lt;em&gt;names&lt;/em&gt; (loop over it), you are happy.
&lt;/p&gt;
&lt;h3&gt;Walking like a duck
&lt;/h3&gt;
&lt;p&gt;
Now let's take that train of thought and consider &lt;a href="http://en.wikipedia.org/wiki/Duck_typing" target="_blank"&gt;duck
typing&lt;/a&gt; in a dynamic language like Python. I can declare the following method:
&lt;/p&gt;
&lt;p&gt;
&lt;font face="Courier New"&gt;def Recycle(service):&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; service.Stop()&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; service.Start()&lt;/font&gt;
&lt;br&gt;
&lt;/p&gt;
&lt;p&gt;
It takes a single parameter named &lt;em&gt;service&lt;/em&gt;. What is the type of the parameter
that is expected? I don't know. And after the initial anxiety settles, there is the
liberating realization that I don't have to care! All I know, or care, is that any
object instance that is passed to this method must implement a Start() and a Stop()
method. The same method can be used with instances of a Lawnmower, AuditLogger, or
SongPlayer class (assuming they all have Start and Stop methods). 
&lt;/p&gt;
&lt;h3&gt;Getting closer to the goal
&lt;/h3&gt;
&lt;p&gt;
Let me be clear - I am not suggesting that implicit typing in C# 3.0 is the same as
duck typing. What I am suggesting is that the 2 examples above are points along the
"progression of understanding" of the same concept: it is the behavior of an object
that really matters, as opposed to the type name that is attached to it. Interface-based
programming is near the start. Implicit typing is further along the progression. Duck
typing is closer to the end.
&lt;/p&gt;
&lt;p&gt;
I think we will find that programmers who have been exposed to and understand languages
which support duck typing will be more likely to be comfortable with and embrace the
var keyword. They have already made the mental leap that type information serves the
computer more than it serves the human. If you haven't yet, do yourself a favor and
learn a dynamic programming language, even if you know you will continue to spend
your days with static typing.
&lt;/p&gt;
&lt;img width="0" height="0" src="http://flimflan.com/blog/aggbug.ashx?id=354870db-1c4e-42f5-8919-6a1f95767846" /&gt;</description>
      <comments>http://flimflan.com/blog/CommentView,guid,354870db-1c4e-42f5-8919-6a1f95767846.aspx</comments>
      <category>.NET</category>
    </item>
    <item>
      <trackback:ping>http://flimflan.com/blog/Trackback.aspx?guid=a6e5885a-d75e-4365-a78f-d6fbba6c57de</trackback:ping>
      <pingback:server>http://flimflan.com/blog/pingback.aspx</pingback:server>
      <pingback:target>http://flimflan.com/blog/PermaLink,guid,a6e5885a-d75e-4365-a78f-d6fbba6c57de.aspx</pingback:target>
      <dc:creator>
      </dc:creator>
      <wfw:comment>http://flimflan.com/blog/CommentView,guid,a6e5885a-d75e-4365-a78f-d6fbba6c57de.aspx</wfw:comment>
      <wfw:commentRss>http://flimflan.com/blog/SyndicationService.asmx/GetEntryCommentsRss?guid=a6e5885a-d75e-4365-a78f-d6fbba6c57de</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
Dare Obsanjo asked the question <a href="http://www.25hoursaday.com/weblog/2008/05/21/C30ImplicitTypeDeclarationsToVarOrNotToVar.aspx" target="_blank">To
var or not to var</a>? He asserted "case closed" at the end of his post, and closed
it to further comments, but I would like to continue the conversation.
</p>
        <p>
He pulls out the common straw man argument that the anti-<strong>var</strong> (C#
3.0's implicity type keyword) crowd likes to attack. They assume that fans of implicit
typing just want to save a few keystrokes. It isn't about less keystrokes. For me,
its about thinking a little bit less like a computer and a little bit more like a
human. I prefer to think less about Types and more about behaviors. The var keyword
is an acknowledgement that I do not care what the type of the variable is - I only
care what it can do.
</p>
        <p>
I'll address a few specific quotes from his post (emphasis is mine).
</p>
        <blockquote>
          <p>
[Referring to ReSharper] So it seems there are two suggestion modes. The first suggests
using the <code>var</code> keyword when the name of the type is obvious from the right
hand side expression being evaluated such as casts or new object creation. The second
mode suggests replacing type declarations with the <code>var</code> keyword anywhere
the compiler can infer the type... The first suggestion mode makes sense to me since
the code doesn't lose any clarity and <strong>it makes for shorter code</strong>.
The second mode is the one I find problematic it takes information out of the equation <strong>to
save a couple of characters per line of code</strong>.
</p>
        </blockquote>
        <p>
In both situations, it is about removing compiler noise. I have already given the
compiler enough information for it to do its job. I don't care about a couple characters.
</p>
        <blockquote>
          <p>
For example, the claim that it leads to "better naming for local variables" really
means it compels developers to use LONGER HUNGARIAN STYLE VARIABLE NAMES.
</p>
        </blockquote>
        <p>
Longer, more descriptive variable names? Yes, please. Hungarian style? That assumes
I care about the type (which I don't <a href="LosingYourTypeReligion.aspx" target="_blank">see
my follow-up post</a>).
</p>
        <blockquote>
          <p>
...these long variable names add more <strong>noise</strong> to the code overall since
they show up everywhere the variable is used compared to a single type name showing
up when the variable is declared.
</p>
        </blockquote>
        <p>
This is completely different understanding of the term "noise" as it relates to code.
To me, "noise" in a computer language is all of the stuff that makes code look like
something that needs to be decoded. It is all of the stuff that normal humans would
not use when communicating with each other. Your source code is a communication medium
- it communicates intent to the computer, and to the humans that need to maintain
it. Anything that is added purely for the computer's benefit is noise to the human.
It commonly takes the form of angle brackets, parentheses, semi-colons, etc. Sometimes
it takes the form of redundant or extraneous type information. But I would never consider
a descriptive variable name "noise", just because it takes up a little more screen
real-estate.
</p>
        <p>
It is interesting that Dare seems to reject the argument that var helps promote use
of better variable names, and yet the example which spurred his post illustrates it
perfectly:
</p>
        <blockquote>
          <p>
I found this change to be somewhat puzzling since while it may have shortened the
code by a couple of characters [There he goes counting characters again] on each line
but <em>at the cost of making the code less readable</em>. For example, I can't tell
what the type of the variable named <strong>lvi</strong> is just by looking at the
code.
</p>
        </blockquote>
        <p>
The var keyword did not make the code less readable, it just made the poor choice
of variable names more apparent. Might listItem or feedItem be a little more readable
than <em><strong>lvi</strong></em>?
</p>
        <p>
It seems his primary argument against var is that always knowing the type of a variable
is of utmost importance. Why? When you are writing code, doesn't your IDE let you
know what behaviors are available to your object instances? When you are reading code,
can you not assume that the compiler has already checked it for invalid code?
</p>
        <img width="0" height="0" src="http://flimflan.com/blog/aggbug.ashx?id=a6e5885a-d75e-4365-a78f-d6fbba6c57de" />
      </body>
      <title>To var</title>
      <guid isPermaLink="false">http://flimflan.com/blog/PermaLink,guid,a6e5885a-d75e-4365-a78f-d6fbba6c57de.aspx</guid>
      <link>http://flimflan.com/blog/ToVar.aspx</link>
      <pubDate>Wed, 25 Jun 2008 06:11:04 GMT</pubDate>
      <description>&lt;p&gt;
Dare Obsanjo asked the question &lt;a href="http://www.25hoursaday.com/weblog/2008/05/21/C30ImplicitTypeDeclarationsToVarOrNotToVar.aspx" target="_blank"&gt;To
var or not to var&lt;/a&gt;? He asserted "case closed" at the end of his post, and closed
it to further comments, but I would like to continue the conversation.
&lt;/p&gt;
&lt;p&gt;
He pulls out the common straw man argument that the anti-&lt;strong&gt;var&lt;/strong&gt; (C#
3.0's implicity type keyword) crowd likes to attack. They assume that fans of implicit
typing just want to save a few keystrokes. It isn't about less keystrokes. For me,
its about thinking a little bit less like a computer and a little bit more like a
human. I prefer to think less about Types and more about behaviors. The var keyword
is an acknowledgement that I do not care what the type of the variable is - I only
care what it can do.
&lt;/p&gt;
&lt;p&gt;
I'll address a few specific quotes from his post (emphasis is mine).
&lt;/p&gt;
&lt;blockquote&gt; 
&lt;p&gt;
[Referring to ReSharper] So it seems there are two suggestion modes. The first suggests
using the &lt;code&gt;var&lt;/code&gt; keyword when the name of the type is obvious from the right
hand side expression being evaluated such as casts or new object creation. The second
mode suggests replacing type declarations with the &lt;code&gt;var&lt;/code&gt; keyword anywhere
the compiler can infer the type... The first suggestion mode makes sense to me since
the code doesn't lose any clarity and &lt;strong&gt;it makes for shorter code&lt;/strong&gt;.
The second mode is the one I find problematic it takes information out of the equation &lt;strong&gt;to
save a couple of characters per line of code&lt;/strong&gt;.
&lt;/p&gt;
&lt;/blockquote&gt; 
&lt;p&gt;
In both situations, it is about removing compiler noise. I have already given the
compiler enough information for it to do its job. I don't care about a couple characters.
&lt;/p&gt;
&lt;blockquote&gt; 
&lt;p&gt;
For example, the claim that it leads to "better naming for local variables" really
means it compels developers to use LONGER HUNGARIAN STYLE VARIABLE NAMES.
&lt;/p&gt;
&lt;/blockquote&gt; 
&lt;p&gt;
Longer, more descriptive variable names? Yes, please. Hungarian style? That assumes
I care about the type (which I don't &lt;a href="LosingYourTypeReligion.aspx" target="_blank"&gt;see
my follow-up post&lt;/a&gt;).
&lt;/p&gt;
&lt;blockquote&gt; 
&lt;p&gt;
...these long variable names add more &lt;strong&gt;noise&lt;/strong&gt; to the code overall since
they show up everywhere the variable is used compared to a single type name showing
up when the variable is declared.
&lt;/p&gt;
&lt;/blockquote&gt; 
&lt;p&gt;
This is completely different understanding of the term "noise" as it relates to code.
To me, "noise" in a computer language is all of the stuff that makes code look like
something that needs to be decoded. It is all of the stuff that normal humans would
not use when communicating with each other. Your source code is a communication medium
- it communicates intent to the computer, and to the humans that need to maintain
it. Anything that is added purely for the computer's benefit is noise to the human.
It commonly takes the form of angle brackets, parentheses, semi-colons, etc. Sometimes
it takes the form of redundant or extraneous type information. But I would never consider
a descriptive variable name "noise", just because it takes up a little more screen
real-estate.
&lt;/p&gt;
&lt;p&gt;
It is interesting that Dare seems to reject the argument that var helps promote use
of better variable names, and yet the example which spurred his post illustrates it
perfectly:
&lt;/p&gt;
&lt;blockquote&gt; 
&lt;p&gt;
I found this change to be somewhat puzzling since while it may have shortened the
code by a couple of characters [There he goes counting characters again] on each line
but &lt;em&gt;at the cost of making the code less readable&lt;/em&gt;. For example, I can't tell
what the type of the variable named &lt;strong&gt;lvi&lt;/strong&gt; is just by looking at the
code.
&lt;/p&gt;
&lt;/blockquote&gt; 
&lt;p&gt;
The var keyword did not make the code less readable, it just made the poor choice
of variable names more apparent. Might listItem or feedItem be a little more readable
than &lt;em&gt;&lt;strong&gt;lvi&lt;/strong&gt;&lt;/em&gt;?
&lt;/p&gt;
&lt;p&gt;
It seems his primary argument against var is that always knowing the type of a variable
is of utmost importance. Why? When you are writing code, doesn't your IDE let you
know what behaviors are available to your object instances? When you are reading code,
can you not assume that the compiler has already checked it for invalid code?
&lt;/p&gt;
&lt;img width="0" height="0" src="http://flimflan.com/blog/aggbug.ashx?id=a6e5885a-d75e-4365-a78f-d6fbba6c57de" /&gt;</description>
      <comments>http://flimflan.com/blog/CommentView,guid,a6e5885a-d75e-4365-a78f-d6fbba6c57de.aspx</comments>
      <category>.NET</category>
    </item>
    <item>
      <trackback:ping>http://flimflan.com/blog/Trackback.aspx?guid=6878c8f0-d143-4ca7-ac48-dde254ed78b4</trackback:ping>
      <pingback:server>http://flimflan.com/blog/pingback.aspx</pingback:server>
      <pingback:target>http://flimflan.com/blog/PermaLink,guid,6878c8f0-d143-4ca7-ac48-dde254ed78b4.aspx</pingback:target>
      <dc:creator>
      </dc:creator>
      <wfw:comment>http://flimflan.com/blog/CommentView,guid,6878c8f0-d143-4ca7-ac48-dde254ed78b4.aspx</wfw:comment>
      <wfw:commentRss>http://flimflan.com/blog/SyndicationService.asmx/GetEntryCommentsRss?guid=6878c8f0-d143-4ca7-ac48-dde254ed78b4</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
Ayende Rahien will be <a href="http://www.ayende.com/Blog/archive/2008/05/06/Course-Building-Domain-Specific-Languages-in-BooCourse-Building-Domain-Specific.aspx" target="_blank">giving
a course on buliding DSLs with Boo</a> in Austin on May 19-20. I'm a closet fan of
Boo, having lurked on the mailing list for about 6 months, and really looking forward
to getting a stronger grasp of the language, and the benefits of building your own
domain specific languages. This is a great opportunity to learn from the preeminent
creator of Boo DSLs. 
</p>
        <p>
Scott Bellware sent a good writeup to the AgileATX mailing list: 
</p>
        <blockquote>
          <p>
This class takes you deeper into the reasoning and power of dynamic<br />
programming on the CLR.  It will show you how to build and take<br />
advantage of DSL's for your own CLR applications, and why DSL's and<br />
language-oriented programming are such a valuable practice at this<br />
point on the programming timeline.  
<br />
You'll leave this class having been jump-started on a new, powerful<br />
language and paradigm, and be connected to other motivated .NET folks<br />
who are working toward bringing some of successes of dynamic<br />
programming communities into the .NET community.
</p>
          <p>
The class will also give you the opportunity to check out a town that<br />
folks are starting to recognize as a progressive and leading .NET<br />
competency in North America, and to have some fun with Austin's<br />
developer community folks in lush green and sunshine of Central Texas.
</p>
        </blockquote>
        <p>
There are still some spots open, if you are interested you can <a href="http://ayende.eventbrite.com/" target="_blank">register
here</a>.
</p>
        <img width="0" height="0" src="http://flimflan.com/blog/aggbug.ashx?id=6878c8f0-d143-4ca7-ac48-dde254ed78b4" />
      </body>
      <title>Building Domain Specific Languages in Boo on the .NET Platform</title>
      <guid isPermaLink="false">http://flimflan.com/blog/PermaLink,guid,6878c8f0-d143-4ca7-ac48-dde254ed78b4.aspx</guid>
      <link>http://flimflan.com/blog/BuildingDomainSpecificLanguagesInBooOnTheNETPlatform.aspx</link>
      <pubDate>Sun, 11 May 2008 03:45:43 GMT</pubDate>
      <description>&lt;p&gt;
Ayende Rahien will be &lt;a href="http://www.ayende.com/Blog/archive/2008/05/06/Course-Building-Domain-Specific-Languages-in-BooCourse-Building-Domain-Specific.aspx" target="_blank"&gt;giving
a course on buliding DSLs with Boo&lt;/a&gt; in Austin on May 19-20. I'm a closet fan of
Boo, having lurked on the mailing list for about 6 months, and really looking forward
to getting a stronger grasp of the language, and the benefits of building your own
domain specific languages. This is a great opportunity to learn from the preeminent
creator of Boo DSLs. 
&lt;p&gt;
Scott Bellware sent a good writeup to the AgileATX mailing list: &lt;blockquote&gt; 
&lt;p&gt;
This class takes you deeper into the reasoning and power of dynamic&lt;br&gt;
programming on the CLR.&amp;nbsp; It will show you how to build and take&lt;br&gt;
advantage of DSL's for your own CLR applications, and why DSL's and&lt;br&gt;
language-oriented programming are such a valuable practice at this&lt;br&gt;
point on the programming timeline.&amp;nbsp; 
&lt;br&gt;
You'll leave this class having been jump-started on a new, powerful&lt;br&gt;
language and paradigm, and be connected to other motivated .NET folks&lt;br&gt;
who are working toward bringing some of successes of dynamic&lt;br&gt;
programming communities into the .NET community.
&lt;/p&gt;
&lt;p&gt;
The class will also give you the opportunity to check out a town that&lt;br&gt;
folks are starting to recognize as a progressive and leading .NET&lt;br&gt;
competency in North America, and to have some fun with Austin's&lt;br&gt;
developer community folks in lush green and sunshine of Central Texas.
&lt;/p&gt;
&lt;/blockquote&gt; 
&lt;p&gt;
There are still some spots open, if you are interested you can &lt;a href="http://ayende.eventbrite.com/" target="_blank"&gt;register
here&lt;/a&gt;.
&lt;/p&gt;
&lt;img width="0" height="0" src="http://flimflan.com/blog/aggbug.ashx?id=6878c8f0-d143-4ca7-ac48-dde254ed78b4" /&gt;</description>
      <comments>http://flimflan.com/blog/CommentView,guid,6878c8f0-d143-4ca7-ac48-dde254ed78b4.aspx</comments>
      <category>.NET</category>
      <category>Boo</category>
    </item>
    <item>
      <trackback:ping>http://flimflan.com/blog/Trackback.aspx?guid=a6ec56ad-932a-453d-bdf9-094a3a4f531c</trackback:ping>
      <pingback:server>http://flimflan.com/blog/pingback.aspx</pingback:server>
      <pingback:target>http://flimflan.com/blog/PermaLink,guid,a6ec56ad-932a-453d-bdf9-094a3a4f531c.aspx</pingback:target>
      <dc:creator>
      </dc:creator>
      <wfw:comment>http://flimflan.com/blog/CommentView,guid,a6ec56ad-932a-453d-bdf9-094a3a4f531c.aspx</wfw:comment>
      <wfw:commentRss>http://flimflan.com/blog/SyndicationService.asmx/GetEntryCommentsRss?guid=a6ec56ad-932a-453d-bdf9-094a3a4f531c</wfw:commentRss>
      <slash:comments>1</slash:comments>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
So a high profile ALT.NETter, who is not in attendance at this weekend's <a href="http://www.altnetconf.com/" target="_blank">altnetconf</a>,
has decided he no longer wants to be associated with the group because of its perceived
negativity. It is a shame he wasn't here in person to experience the bizarro-world
like ending to Day 2. The closing remarks, which is a chance for anyone in attendance
to stand and share their thoughts on the day, were composed entirely of expressions
of excitement around the just demonstrated System.Web.MVC framework, and thanks and
appreciation to the Microsoft ASP.NET team that created it. This is not an easy crowd
to please, but mostly because we all want to be able to assert our preference of tools
and practices individually. NOT because we want to use "anything but Microsoft", but
because we want to be able to choose "some things that are not from Microsoft". When
Microsoft does provide a great tool (as they did with the .NET Framework, and potentially
the MVC framework) members of the crowd are willing embrace it. Now, we
are not a hive mind (a fact which seems to be frustrating some people that want us
to come to some kind of consensus... on anything), so I won't say everyone is excited
about it. But unlike the earlier opening remarks, at the end nobody stood up to air
their grievances with Microsoft. It was all smiles and love for Scott Guthrie (who
was there demonstrating the framework and representing the ASP.NET team). Yes, even
from Scott Bellware.
</p>
        <p style="font-size: 0.8em">
(Of course, it may all be a side effect of ScottGu's super-hero power of being
able to <a href="http://flimflan.com/blog/ScottGuIsMyHero.aspx" target="_blank">foster
man-crush's</a> from entire rooms of ornery, cynical developers.)
</p>
        <div class="wlWriterSmartContent" id="0767317B-992E-4b12-91E0-4F059A8CECA8:54e93858-dcd2-4f2a-afe0-ba4b82e051d0" contenteditable="false" style="padding-right: 0px; display: inline; padding-left: 0px; padding-bottom: 0px; margin: 0px; padding-top: 0px">Technorati
Tags: <a href="http://technorati.com/tags/altnetconf" rel="tag">altnetconf</a></div>
        <img width="0" height="0" src="http://flimflan.com/blog/aggbug.ashx?id=a6ec56ad-932a-453d-bdf9-094a3a4f531c" />
      </body>
      <title>ALT.NET heart Microsoft</title>
      <guid isPermaLink="false">http://flimflan.com/blog/PermaLink,guid,a6ec56ad-932a-453d-bdf9-094a3a4f531c.aspx</guid>
      <link>http://flimflan.com/blog/ALTNETHeartMicrosoft.aspx</link>
      <pubDate>Sun, 07 Oct 2007 02:13:13 GMT</pubDate>
      <description>&lt;p&gt;
So a high profile&amp;nbsp;ALT.NETter, who is not in attendance at this weekend's &lt;a href="http://www.altnetconf.com/" target="_blank"&gt;altnetconf&lt;/a&gt;,
has decided he no longer wants to be associated with the group because of its perceived
negativity. It is a shame he wasn't here in person to experience the bizarro-world
like ending to Day 2. The closing remarks, which is a chance for anyone in attendance
to stand and share their thoughts on the day,&amp;nbsp;were composed entirely of expressions
of excitement around the just demonstrated System.Web.MVC framework, and thanks and
appreciation to the Microsoft ASP.NET team that created it. This is not an easy crowd
to please, but mostly because we all want to be able to assert our preference of tools
and practices individually. NOT because we want to use "anything but Microsoft", but
because we want to be able to choose "some things that are not from Microsoft".&amp;nbsp;When
Microsoft does provide a great tool (as they did with the .NET Framework, and potentially
the MVC framework) members of the&amp;nbsp;crowd&amp;nbsp;are willing embrace it. Now, we
are not a hive mind (a fact which seems to be frustrating some people that want us
to come to some kind of consensus... on anything), so I won't say everyone is excited
about it. But unlike the earlier opening remarks, at the end nobody stood up to air
their grievances with Microsoft. It was all smiles and love for Scott Guthrie (who
was there demonstrating the framework and representing the ASP.NET team). Yes, even
from Scott Bellware.
&lt;/p&gt;
&lt;p style="font-size: 0.8em"&gt;
(Of course, it may&amp;nbsp;all be a side effect of ScottGu's super-hero power of being
able to&amp;nbsp;&gt;&lt;a href="http://flimflan.com/blog/ScottGuIsMyHero.aspx" target="_blank"&gt;foster
man-crush's&lt;/a&gt;&amp;nbsp;from entire rooms of ornery, cynical&amp;nbsp;developers.)
&lt;/p&gt;
&lt;div class="wlWriterSmartContent" id="0767317B-992E-4b12-91E0-4F059A8CECA8:54e93858-dcd2-4f2a-afe0-ba4b82e051d0" contenteditable="false" style="padding-right: 0px; display: inline; padding-left: 0px; padding-bottom: 0px; margin: 0px; padding-top: 0px"&gt;Technorati
Tags: &lt;a href="http://technorati.com/tags/altnetconf" rel="tag"&gt;altnetconf&lt;/a&gt;
&lt;/div&gt;
&lt;img width="0" height="0" src="http://flimflan.com/blog/aggbug.ashx?id=a6ec56ad-932a-453d-bdf9-094a3a4f531c" /&gt;</description>
      <comments>http://flimflan.com/blog/CommentView,guid,a6ec56ad-932a-453d-bdf9-094a3a4f531c.aspx</comments>
      <category>.NET</category>
      <category>altnetconf</category>
    </item>
    <item>
      <trackback:ping>http://flimflan.com/blog/Trackback.aspx?guid=f110c144-dfdd-4f93-aa9c-8f27d9c05726</trackback:ping>
      <pingback:server>http://flimflan.com/blog/pingback.aspx</pingback:server>
      <pingback:target>http://flimflan.com/blog/PermaLink,guid,f110c144-dfdd-4f93-aa9c-8f27d9c05726.aspx</pingback:target>
      <dc:creator>
      </dc:creator>
      <wfw:comment>http://flimflan.com/blog/CommentView,guid,f110c144-dfdd-4f93-aa9c-8f27d9c05726.aspx</wfw:comment>
      <wfw:commentRss>http://flimflan.com/blog/SyndicationService.asmx/GetEntryCommentsRss?guid=f110c144-dfdd-4f93-aa9c-8f27d9c05726</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
          <a href="http://codebetter.com/blogs/jeremy.miller">Jeremy D. Miller</a> recently
wrote about <a href="http://codebetter.com/blogs/jeremy.miller/archive/2006/09/11/Machine-specific-tasks-with-NAnt.aspx">how
to make a NAnt script branch based on the machine</a> it's runnig on. Since I've been
working almost exclusively with MSBuild, I figured it might be educational to post
the equivalent script.
</p>
        <p>
First, in Jeremy's example, he is really only changing the values of a property based
on the machine name. If that is all you need to do, the MSBuild solution is fairly
straightforward. I'll include the entire file contents so that you can easily copy/paste
and test, and verify their are no hidden tricks.
</p>
        <div style="background: white none repeat scroll 0% 50%; font-size: 10pt; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial; color: black; font-family: consolas;">
          <p style="margin: 0px;">
            <span style="color: blue;">&lt;?</span>
            <span style="color: maroon;">xml</span>
            <span style="color: blue;">
            </span>
            <span style="color: red;">version</span>
            <span style="color: blue;">=</span>"<span style="color: blue;">1.0</span>"<span style="color: blue;"></span><span style="color: red;">encoding</span><span style="color: blue;">=</span>"<span style="color: blue;">utf-8</span>"<span style="color: blue;">?&gt;</span></p>
          <p style="margin: 0px;">
            <span style="color: blue;">&lt;</span>
            <span style="color: maroon;">Project</span>
            <span style="color: blue;">
            </span>
            <span style="color: red;">DefaultTargets</span>
            <span style="color: blue;">=</span>"<span style="color: blue;">Build</span>"<span style="color: blue;"></span><span style="color: red;">xmlns</span><span style="color: blue;">=</span>"<span style="color: blue;">http://schemas.microsoft.com/developer/msbuild/2003</span>"<span style="color: blue;">&gt;</span></p>
          <p style="margin: 0px;">
            <span style="color: blue;">  &lt;</span>
            <span style="color: maroon;">PropertyGroup</span>
            <span style="color: blue;">&gt;</span>
          </p>
          <p style="margin: 0px;">
            <span style="color: blue;">  &lt;</span>
            <span style="color: maroon;">Database</span>
            <span style="color: blue;">&gt;</span>invoice_dev<span style="color: blue;">&lt;/</span><span style="color: maroon;">Database</span><span style="color: blue;">&gt;</span></p>
          <p style="margin: 0px;">
            <span style="color: blue;">  &lt;</span>
            <span style="color: maroon;">Database</span>
            <span style="color: blue;">
            </span>
            <span style="color: red;">Condition</span>
            <span style="color: blue;">=</span>"<span style="color: blue;">'$(Computername)'=='TEST-SERVER'</span>"<span style="color: blue;">&gt;</span>invoice_test<span style="color: blue;">&lt;/</span><span style="color: maroon;">Database</span><span style="color: blue;">&gt;</span></p>
          <p style="margin: 0px;">
            <span style="color: blue;">  &lt;</span>
            <span style="color: maroon;">Database</span>
            <span style="color: blue;">
            </span>
            <span style="color: red;">Condition</span>
            <span style="color: blue;">=</span>"<span style="color: blue;">'$(Computername)'=='PRODUCTION-SERVER'</span>"<span style="color: blue;">&gt;</span>invoice_prod<span style="color: blue;">&lt;/</span><span style="color: maroon;">Database</span><span style="color: blue;">&gt;</span></p>
          <p style="margin: 0px;">
            <span style="color: blue;">  &lt;/</span>
            <span style="color: maroon;">PropertyGroup</span>
            <span style="color: blue;">&gt;</span>
          </p>
          <p style="margin: 0px;">
 
</p>
          <p style="margin: 0px;">
            <span style="color: blue;">  &lt;</span>
            <span style="color: maroon;">Target</span>
            <span style="color: blue;">
            </span>
            <span style="color: red;">Name</span>
            <span style="color: blue;">=</span>"<span style="color: blue;">Build</span>"<span style="color: blue;"> &gt;</span></p>
          <p style="margin: 0px;">
            <span style="color: blue;">  &lt;</span>
            <span style="color: maroon;">Message</span>
            <span style="color: blue;">
            </span>
            <span style="color: red;">Text</span>
            <span style="color: blue;">=</span>"<span style="color: blue;">Connect
to database $(Database)</span>"<span style="color: blue;"> /&gt;</span></p>
          <p style="margin: 0px;">
            <span style="color: blue;">  &lt;/</span>
            <span style="color: maroon;">Target</span>
            <span style="color: blue;">&gt;</span>
          </p>
          <p style="margin: 0px;">
            <span style="color: blue;">&lt;/</span>
            <span style="color: maroon;">Project</span>
            <span style="color: blue;">&gt;</span>
          </p>
        </div>
        <p>
This takes advantage of the fact that all environment variables are immediately available
as properties in an MSBuild script; and that all Windows machines (that I've worked
on recently) have the COMPUTERNAME environment variable set.
</p>
        <p>
However, if you actually needed to run different tasks (as opposed to just setting
properties), things would look a little different. One way I might approach it would
be:
</p>
        <div style="background: white none repeat scroll 0% 50%; font-size: 10pt; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial; color: black; font-family: consolas;">
          <p style="margin: 0px;">
            <span style="color: blue;">&lt;?</span>
            <span style="color: maroon;">xml</span>
            <span style="color: blue;">
            </span>
            <span style="color: red;">version</span>
            <span style="color: blue;">=</span>"<span style="color: blue;">1.0</span>"<span style="color: blue;"></span><span style="color: red;">encoding</span><span style="color: blue;">=</span>"<span style="color: blue;">utf-8</span>"<span style="color: blue;">?&gt;</span></p>
          <p style="margin: 0px;">
            <span style="color: blue;">&lt;</span>
            <span style="color: maroon;">Project</span>
            <span style="color: blue;">
            </span>
            <span style="color: red;">DefaultTargets</span>
            <span style="color: blue;">=</span>"<span style="color: blue;">Build</span>"<span style="color: blue;"></span><span style="color: red;">xmlns</span><span style="color: blue;">=</span>"<span style="color: blue;">http://schemas.microsoft.com/developer/msbuild/2003</span>"<span style="color: blue;">&gt;</span></p>
          <p style="margin: 0px;">
 
</p>
          <p style="margin: 0px;">
            <span style="color: blue;">  &lt;</span>
            <span style="color: maroon;">Target</span>
            <span style="color: blue;">
            </span>
            <span style="color: red;">Name</span>
            <span style="color: blue;">=</span>"<span style="color: blue;">Build</span>"<span style="color: blue;"></span><span style="color: red;">DependsOnTargets</span><span style="color: blue;">=</span>"<span style="color: blue;">MachineSpecificTasks</span>"<span style="color: blue;">&gt;</span></p>
          <p style="margin: 0px;">
            <span style="color: blue;">  &lt;</span>
            <span style="color: maroon;">Message</span>
            <span style="color: blue;">
            </span>
            <span style="color: red;">Text</span>
            <span style="color: blue;">=</span>"<span style="color: blue;">Start
Build</span>"<span style="color: blue;"> /&gt;</span></p>
          <p style="margin: 0px;">
            <span style="color: blue;">  &lt;/</span>
            <span style="color: maroon;">Target</span>
            <span style="color: blue;">&gt;</span>
          </p>
          <p style="margin: 0px;">
 
</p>
          <p style="margin: 0px;">
            <span style="color: blue;">  &lt;</span>
            <span style="color: maroon;">Target</span>
            <span style="color: blue;">
            </span>
            <span style="color: red;">Name</span>
            <span style="color: blue;">=</span>"<span style="color: blue;">MachineSpecificTasks</span>"<span style="color: blue;"></span></p>
          <p style="margin: 0px;">
            <span style="color: blue;">  </span>
            <span style="color: red;">DependsOnTargets</span>
            <span style="color: blue;">=</span>"<span style="color: blue;">TestServers;</span></p>
          <p style="margin: 0px;">
            <span style="color: blue;">               
      ProductionServers</span>"<span style="color: blue;"> /&gt;</span></p>
          <p style="margin: 0px;">
 
</p>
          <p style="margin: 0px;">
            <span style="color: blue;">  &lt;</span>
            <span style="color: maroon;">Target</span>
            <span style="color: blue;">
            </span>
            <span style="color: red;">Name</span>
            <span style="color: blue;">=</span>"<span style="color: blue;">TestServers</span>"<span style="color: blue;"></span><span style="color: red;">Condition</span><span style="color: blue;">=</span>"<span style="color: blue;">'$(Computername)'=='TEST-SERVER1'</span>"<span style="color: blue;">&gt;</span></p>
          <p style="margin: 0px;">
            <span style="color: blue;">  &lt;</span>
            <span style="color: maroon;">Message</span>
            <span style="color: blue;">
            </span>
            <span style="color: red;">Text</span>
            <span style="color: blue;">=</span>"<span style="color: blue;">Building
on test server.</span>"<span style="color: blue;"> /&gt;</span></p>
          <p style="margin: 0px;">
            <span style="color: blue;">  &lt;/</span>
            <span style="color: maroon;">Target</span>
            <span style="color: blue;">&gt;</span>
          </p>
          <p style="margin: 0px;">
 
</p>
          <p style="margin: 0px;">
            <span style="color: blue;">  &lt;</span>
            <span style="color: maroon;">Target</span>
            <span style="color: blue;">
            </span>
            <span style="color: red;">Name</span>
            <span style="color: blue;">=</span>"<span style="color: blue;">ProductionServers</span>"<span style="color: blue;"></span><span style="color: red;">Condition</span><span style="color: blue;">=</span>"<span style="color: blue;">'$(Computername)'=='PRODUCTION-SERVER1'</span></p>
          <p style="margin: 0px;">
            <span style="color: blue;">               
                    OR '$(Computername)'=='PRODUCTION-SERVER2'</span>"<span style="color: blue;">&gt;</span></p>
          <p style="margin: 0px;">
            <span style="color: blue;">  &lt;</span>
            <span style="color: maroon;">Message</span>
            <span style="color: blue;">
            </span>
            <span style="color: red;">Text</span>
            <span style="color: blue;">=</span>"<span style="color: blue;">Building
on production server.</span>"<span style="color: blue;"> /&gt;</span></p>
          <p style="margin: 0px;">
            <span style="color: blue;">  &lt;/</span>
            <span style="color: maroon;">Target</span>
            <span style="color: blue;">&gt;</span>
          </p>
          <p style="margin: 0px;">
            <span style="color: blue;">&lt;/</span>
            <span style="color: maroon;">Project</span>
            <span style="color: blue;">&gt;</span>
          </p>
        </div>
        <p>
I created a separate dummy target called MachineSpecificTasks. It is just used to
define the different targets that you make available for each environment. I
make all of the machine specific targets as dependencies on this target, so that the
script will attempt to execute each of them. I could have just as easily
skipped the MachineSpecificTasks target and put the dependencies on my Build
target, but I felt that list might get large and get confusing. Better to
hide it away. I then set a condition on each target so that it is only run if
the computername environment variable matches the given computer name. I went
a little further and showed how you could associate multiple computer names (PRODUCTION-SERVER1
and PRODUCTION-SERVER2) with the same set of tasks (collectively called ProductionServers).
</p>
        <p>
There is probably a way to use the CallTarget task to more closely match the look
of the NAnt solution, but I'm not sure if it would buy you anything.
</p>
        <p>
Hope that helps.
</p>
        <img width="0" height="0" src="http://flimflan.com/blog/aggbug.ashx?id=f110c144-dfdd-4f93-aa9c-8f27d9c05726" />
      </body>
      <title>Machine specific tasks with MSBuild</title>
      <guid isPermaLink="false">http://flimflan.com/blog/PermaLink,guid,f110c144-dfdd-4f93-aa9c-8f27d9c05726.aspx</guid>
      <link>http://flimflan.com/blog/MachineSpecificTasksWithMSBuild.aspx</link>
      <pubDate>Wed, 13 Sep 2006 03:24:33 GMT</pubDate>
      <description>&lt;p&gt;
&lt;a href="http://codebetter.com/blogs/jeremy.miller"&gt;Jeremy D. Miller&lt;/a&gt; recently
wrote about &lt;a href="http://codebetter.com/blogs/jeremy.miller/archive/2006/09/11/Machine-specific-tasks-with-NAnt.aspx"&gt;how
to make a NAnt script branch based on the machine&lt;/a&gt; it's runnig on. Since I've been
working almost exclusively with MSBuild, I figured it might be educational to post
the equivalent script.
&lt;/p&gt;
&lt;p&gt;
First, in Jeremy's example, he is really only changing the values of a property based
on the machine name. If that is all you need to do, the MSBuild solution is fairly
straightforward. I'll include the entire file contents so that you can easily copy/paste
and test, and verify their are no hidden tricks.
&lt;/p&gt;
&lt;div style="background: white none repeat scroll 0% 50%; font-size: 10pt; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial; color: black; font-family: consolas;"&gt;
&lt;p style="margin: 0px;"&gt;
&lt;span style="color: blue;"&gt;&amp;lt;?&lt;/span&gt;&lt;span style="color: maroon;"&gt;xml&lt;/span&gt;&lt;span style="color: blue;"&gt; &lt;/span&gt;&lt;span style="color: red;"&gt;version&lt;/span&gt;&lt;span style="color: blue;"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue;"&gt;1.0&lt;/span&gt;&amp;quot;&lt;span style="color: blue;"&gt; &lt;/span&gt;&lt;span style="color: red;"&gt;encoding&lt;/span&gt;&lt;span style="color: blue;"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue;"&gt;utf-8&lt;/span&gt;&amp;quot;&lt;span style="color: blue;"&gt;?&amp;gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;
&lt;span style="color: blue;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: maroon;"&gt;Project&lt;/span&gt;&lt;span style="color: blue;"&gt; &lt;/span&gt;&lt;span style="color: red;"&gt;DefaultTargets&lt;/span&gt;&lt;span style="color: blue;"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue;"&gt;Build&lt;/span&gt;&amp;quot;&lt;span style="color: blue;"&gt; &lt;/span&gt;&lt;span style="color: red;"&gt;xmlns&lt;/span&gt;&lt;span style="color: blue;"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue;"&gt;http://schemas.microsoft.com/developer/msbuild/2003&lt;/span&gt;&amp;quot;&lt;span style="color: blue;"&gt;&amp;gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;
&lt;span style="color: blue;"&gt;&amp;nbsp; &amp;lt;&lt;/span&gt;&lt;span style="color: maroon;"&gt;PropertyGroup&lt;/span&gt;&lt;span style="color: blue;"&gt;&amp;gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;
&lt;span style="color: blue;"&gt;&amp;nbsp; &amp;lt;&lt;/span&gt;&lt;span style="color: maroon;"&gt;Database&lt;/span&gt;&lt;span style="color: blue;"&gt;&amp;gt;&lt;/span&gt;invoice_dev&lt;span style="color: blue;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: maroon;"&gt;Database&lt;/span&gt;&lt;span style="color: blue;"&gt;&amp;gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;
&lt;span style="color: blue;"&gt;&amp;nbsp; &amp;lt;&lt;/span&gt;&lt;span style="color: maroon;"&gt;Database&lt;/span&gt;&lt;span style="color: blue;"&gt; &lt;/span&gt;&lt;span style="color: red;"&gt;Condition&lt;/span&gt;&lt;span style="color: blue;"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue;"&gt;'$(Computername)'=='TEST-SERVER'&lt;/span&gt;&amp;quot;&lt;span style="color: blue;"&gt;&amp;gt;&lt;/span&gt;invoice_test&lt;span style="color: blue;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: maroon;"&gt;Database&lt;/span&gt;&lt;span style="color: blue;"&gt;&amp;gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;
&lt;span style="color: blue;"&gt;&amp;nbsp; &amp;lt;&lt;/span&gt;&lt;span style="color: maroon;"&gt;Database&lt;/span&gt;&lt;span style="color: blue;"&gt; &lt;/span&gt;&lt;span style="color: red;"&gt;Condition&lt;/span&gt;&lt;span style="color: blue;"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue;"&gt;'$(Computername)'=='PRODUCTION-SERVER'&lt;/span&gt;&amp;quot;&lt;span style="color: blue;"&gt;&amp;gt;&lt;/span&gt;invoice_prod&lt;span style="color: blue;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: maroon;"&gt;Database&lt;/span&gt;&lt;span style="color: blue;"&gt;&amp;gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;
&lt;span style="color: blue;"&gt;&amp;nbsp; &amp;lt;/&lt;/span&gt;&lt;span style="color: maroon;"&gt;PropertyGroup&lt;/span&gt;&lt;span style="color: blue;"&gt;&amp;gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;
&amp;nbsp;
&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;
&lt;span style="color: blue;"&gt;&amp;nbsp; &amp;lt;&lt;/span&gt;&lt;span style="color: maroon;"&gt;Target&lt;/span&gt;&lt;span style="color: blue;"&gt; &lt;/span&gt;&lt;span style="color: red;"&gt;Name&lt;/span&gt;&lt;span style="color: blue;"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue;"&gt;Build&lt;/span&gt;&amp;quot;&lt;span style="color: blue;"&gt; &amp;gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;
&lt;span style="color: blue;"&gt;&amp;nbsp; &amp;lt;&lt;/span&gt;&lt;span style="color: maroon;"&gt;Message&lt;/span&gt;&lt;span style="color: blue;"&gt; &lt;/span&gt;&lt;span style="color: red;"&gt;Text&lt;/span&gt;&lt;span style="color: blue;"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue;"&gt;Connect
to database $(Database)&lt;/span&gt;&amp;quot;&lt;span style="color: blue;"&gt; /&amp;gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;
&lt;span style="color: blue;"&gt;&amp;nbsp; &amp;lt;/&lt;/span&gt;&lt;span style="color: maroon;"&gt;Target&lt;/span&gt;&lt;span style="color: blue;"&gt;&amp;gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;
&lt;span style="color: blue;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: maroon;"&gt;Project&lt;/span&gt;&lt;span style="color: blue;"&gt;&amp;gt;&lt;/span&gt;
&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;
This takes advantage of the fact that all environment variables are immediately available
as properties in an MSBuild script; and that all Windows machines (that I've worked
on recently) have the COMPUTERNAME environment variable set.
&lt;/p&gt;
&lt;p&gt;
However, if you actually needed to run different tasks (as opposed to just setting
properties), things would look a little different. One way I might approach it would
be:
&lt;/p&gt;
&lt;div style="background: white none repeat scroll 0% 50%; font-size: 10pt; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial; color: black; font-family: consolas;"&gt;
&lt;p style="margin: 0px;"&gt;
&lt;span style="color: blue;"&gt;&amp;lt;?&lt;/span&gt;&lt;span style="color: maroon;"&gt;xml&lt;/span&gt;&lt;span style="color: blue;"&gt; &lt;/span&gt;&lt;span style="color: red;"&gt;version&lt;/span&gt;&lt;span style="color: blue;"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue;"&gt;1.0&lt;/span&gt;&amp;quot;&lt;span style="color: blue;"&gt; &lt;/span&gt;&lt;span style="color: red;"&gt;encoding&lt;/span&gt;&lt;span style="color: blue;"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue;"&gt;utf-8&lt;/span&gt;&amp;quot;&lt;span style="color: blue;"&gt;?&amp;gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;
&lt;span style="color: blue;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: maroon;"&gt;Project&lt;/span&gt;&lt;span style="color: blue;"&gt; &lt;/span&gt;&lt;span style="color: red;"&gt;DefaultTargets&lt;/span&gt;&lt;span style="color: blue;"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue;"&gt;Build&lt;/span&gt;&amp;quot;&lt;span style="color: blue;"&gt; &lt;/span&gt;&lt;span style="color: red;"&gt;xmlns&lt;/span&gt;&lt;span style="color: blue;"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue;"&gt;http://schemas.microsoft.com/developer/msbuild/2003&lt;/span&gt;&amp;quot;&lt;span style="color: blue;"&gt;&amp;gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;
&amp;nbsp;
&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;
&lt;span style="color: blue;"&gt;&amp;nbsp; &amp;lt;&lt;/span&gt;&lt;span style="color: maroon;"&gt;Target&lt;/span&gt;&lt;span style="color: blue;"&gt; &lt;/span&gt;&lt;span style="color: red;"&gt;Name&lt;/span&gt;&lt;span style="color: blue;"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue;"&gt;Build&lt;/span&gt;&amp;quot;&lt;span style="color: blue;"&gt; &lt;/span&gt;&lt;span style="color: red;"&gt;DependsOnTargets&lt;/span&gt;&lt;span style="color: blue;"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue;"&gt;MachineSpecificTasks&lt;/span&gt;&amp;quot;&lt;span style="color: blue;"&gt;&amp;gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;
&lt;span style="color: blue;"&gt;&amp;nbsp; &amp;lt;&lt;/span&gt;&lt;span style="color: maroon;"&gt;Message&lt;/span&gt;&lt;span style="color: blue;"&gt; &lt;/span&gt;&lt;span style="color: red;"&gt;Text&lt;/span&gt;&lt;span style="color: blue;"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue;"&gt;Start
Build&lt;/span&gt;&amp;quot;&lt;span style="color: blue;"&gt; /&amp;gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;
&lt;span style="color: blue;"&gt;&amp;nbsp; &amp;lt;/&lt;/span&gt;&lt;span style="color: maroon;"&gt;Target&lt;/span&gt;&lt;span style="color: blue;"&gt;&amp;gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;
&amp;nbsp;
&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;
&lt;span style="color: blue;"&gt;&amp;nbsp; &amp;lt;&lt;/span&gt;&lt;span style="color: maroon;"&gt;Target&lt;/span&gt;&lt;span style="color: blue;"&gt; &lt;/span&gt;&lt;span style="color: red;"&gt;Name&lt;/span&gt;&lt;span style="color: blue;"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue;"&gt;MachineSpecificTasks&lt;/span&gt;&amp;quot;&lt;span style="color: blue;"&gt; &lt;/span&gt;
&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;
&lt;span style="color: blue;"&gt;&amp;nbsp; &lt;/span&gt;&lt;span style="color: red;"&gt;DependsOnTargets&lt;/span&gt;&lt;span style="color: blue;"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue;"&gt;TestServers;&lt;/span&gt;
&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;
&lt;span style="color: blue;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;
&amp;nbsp; &amp;nbsp; &amp;nbsp; ProductionServers&lt;/span&gt;&amp;quot;&lt;span style="color: blue;"&gt; /&amp;gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;
&amp;nbsp;
&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;
&lt;span style="color: blue;"&gt;&amp;nbsp; &amp;lt;&lt;/span&gt;&lt;span style="color: maroon;"&gt;Target&lt;/span&gt;&lt;span style="color: blue;"&gt; &lt;/span&gt;&lt;span style="color: red;"&gt;Name&lt;/span&gt;&lt;span style="color: blue;"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue;"&gt;TestServers&lt;/span&gt;&amp;quot;&lt;span style="color: blue;"&gt; &lt;/span&gt;&lt;span style="color: red;"&gt;Condition&lt;/span&gt;&lt;span style="color: blue;"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue;"&gt;'$(Computername)'=='TEST-SERVER1'&lt;/span&gt;&amp;quot;&lt;span style="color: blue;"&gt;&amp;gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;
&lt;span style="color: blue;"&gt;&amp;nbsp; &amp;lt;&lt;/span&gt;&lt;span style="color: maroon;"&gt;Message&lt;/span&gt;&lt;span style="color: blue;"&gt; &lt;/span&gt;&lt;span style="color: red;"&gt;Text&lt;/span&gt;&lt;span style="color: blue;"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue;"&gt;Building
on test server.&lt;/span&gt;&amp;quot;&lt;span style="color: blue;"&gt; /&amp;gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;
&lt;span style="color: blue;"&gt;&amp;nbsp; &amp;lt;/&lt;/span&gt;&lt;span style="color: maroon;"&gt;Target&lt;/span&gt;&lt;span style="color: blue;"&gt;&amp;gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;
&amp;nbsp;
&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;
&lt;span style="color: blue;"&gt;&amp;nbsp; &amp;lt;&lt;/span&gt;&lt;span style="color: maroon;"&gt;Target&lt;/span&gt;&lt;span style="color: blue;"&gt; &lt;/span&gt;&lt;span style="color: red;"&gt;Name&lt;/span&gt;&lt;span style="color: blue;"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue;"&gt;ProductionServers&lt;/span&gt;&amp;quot;&lt;span style="color: blue;"&gt; &lt;/span&gt;&lt;span style="color: red;"&gt;Condition&lt;/span&gt;&lt;span style="color: blue;"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue;"&gt;'$(Computername)'=='PRODUCTION-SERVER1'&lt;/span&gt;
&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;
&lt;span style="color: blue;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; OR '$(Computername)'=='PRODUCTION-SERVER2'&lt;/span&gt;&amp;quot;&lt;span style="color: blue;"&gt;&amp;gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;
&lt;span style="color: blue;"&gt;&amp;nbsp; &amp;lt;&lt;/span&gt;&lt;span style="color: maroon;"&gt;Message&lt;/span&gt;&lt;span style="color: blue;"&gt; &lt;/span&gt;&lt;span style="color: red;"&gt;Text&lt;/span&gt;&lt;span style="color: blue;"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue;"&gt;Building
on production server.&lt;/span&gt;&amp;quot;&lt;span style="color: blue;"&gt; /&amp;gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;
&lt;span style="color: blue;"&gt;&amp;nbsp; &amp;lt;/&lt;/span&gt;&lt;span style="color: maroon;"&gt;Target&lt;/span&gt;&lt;span style="color: blue;"&gt;&amp;gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;
&lt;span style="color: blue;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: maroon;"&gt;Project&lt;/span&gt;&lt;span style="color: blue;"&gt;&amp;gt;&lt;/span&gt;
&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;
I created a separate dummy target called MachineSpecificTasks. It is just used to
define the different targets that you make available for each environment.&amp;nbsp;I
make all of the machine specific targets as dependencies on this target, so that the
script will attempt to execute each of them. I&amp;nbsp;could have just&amp;nbsp;as easily
skipped the MachineSpecificTasks target and&amp;nbsp;put the dependencies on my Build
target, but I felt that&amp;nbsp;list might get large and&amp;nbsp;get confusing. Better to
hide it away.&amp;nbsp;I then set a condition on each target so that it is only run if
the computername environment variable&amp;nbsp;matches the given computer name. I went
a little further and showed how you could associate multiple computer names (PRODUCTION-SERVER1
and PRODUCTION-SERVER2) with the same set of tasks (collectively called ProductionServers).
&lt;/p&gt;
&lt;p&gt;
There is probably a way to use the CallTarget task to more closely match the look
of the NAnt solution, but I'm not sure if it would buy you anything.
&lt;/p&gt;
&lt;p&gt;
Hope that helps.
&lt;/p&gt;
&lt;img width="0" height="0" src="http://flimflan.com/blog/aggbug.ashx?id=f110c144-dfdd-4f93-aa9c-8f27d9c05726" /&gt;</description>
      <comments>http://flimflan.com/blog/CommentView,guid,f110c144-dfdd-4f93-aa9c-8f27d9c05726.aspx</comments>
      <category>.NET</category>
    </item>
    <item>
      <trackback:ping>http://flimflan.com/blog/Trackback.aspx?guid=2cdfac61-ed63-4e65-82bd-7c47edc7a1dc</trackback:ping>
      <pingback:server>http://flimflan.com/blog/pingback.aspx</pingback:server>
      <pingback:target>http://flimflan.com/blog/PermaLink,guid,2cdfac61-ed63-4e65-82bd-7c47edc7a1dc.aspx</pingback:target>
      <dc:creator>
      </dc:creator>
      <wfw:comment>http://flimflan.com/blog/CommentView,guid,2cdfac61-ed63-4e65-82bd-7c47edc7a1dc.aspx</wfw:comment>
      <wfw:commentRss>http://flimflan.com/blog/SyndicationService.asmx/GetEntryCommentsRss?guid=2cdfac61-ed63-4e65-82bd-7c47edc7a1dc</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
It's <a href="http://weblogs.asp.net/scottgu/archive/2006/09/11/_2200_Atlas_2200_-1.0-Naming-and-Roadmap.aspx">official</a>,
the technology formerly known as Atlas will be called...  Microsoft AJAX Library,
ASP.NET 2.0 AJAX Extensions, and ASP.NET AJAX Control Toolkit!
</p>
        <p>
Wow, those names are actually intuitive and descriptive. This is such a relief, considering
what COULD have been... I had my bets on the dry, but .NET 3.0 compliant "Windows
Dynamic Web Foundation"? Or the completely absurd "<a href="http://flimflan.com/blog/FormerlyKnownAsAtlas.aspx">ASP.NET
7.0</a>" ;-)
</p>
        <p>
Yeah, about that... I completely made it up. It wasn't a hoax; no, I wasn't trying
to fool anyone or make anyone believe it so that I could secretly laugh at them. It
was a satire, so that I could publicly laugh at the madness of Microsoft naming
schemes. I wanted to try and draw some attention to the issue, and hopefully motivate
some people to go sign the <a href="http://www.petitiononline.com/winfx/petition.html">Reverse
WinFX Petition</a>. Not because I thought Microsoft would change their mind, but because
I wanted them to get the message that we don't want marketing decisions obfuscating
and hijacking the terminology that we developers use to communicate. Its a version
number - it has a very specific meaning, it is not a brand. Of all the things to lift
from the Java camp, why did we want the <a href="http://www.particle.kth.se/~lindsey/JavaCourse/Book/Part1/Java/Chapter01/versions.html">version
number confusion</a>?
</p>
        <p>
If you believed my post regarding Atlas =&gt; ASP.NET 7.0, I'm sorry, it wasn't my
intention to deceive. But the fact that a number of people <em>did</em> believe it
just demonstrates the levels of absurdity we've come to expect and accept from Microsoft
when it comes to branding. I <em>tried </em>to make it absurd. I tried to make it
so ridiculous, and so obvious that it was fake (the quotes were almost word for word
cut from one of the linked articles about the .NET 3.0 naming), but people still believed
it. Apparently I need to work on my comedic writing and satirical wit.
</p>
        <p>
Thanks to the Microsoft Web Platform team for the sane naming and their ability to
continue delivering technology without waiting for a large release vehicle (and sorry
for any confusion the last post may have caused).<br /></p>
        <img width="0" height="0" src="http://flimflan.com/blog/aggbug.ashx?id=2cdfac61-ed63-4e65-82bd-7c47edc7a1dc" />
      </body>
      <title>Formerly Known As Atlas, for real</title>
      <guid isPermaLink="false">http://flimflan.com/blog/PermaLink,guid,2cdfac61-ed63-4e65-82bd-7c47edc7a1dc.aspx</guid>
      <link>http://flimflan.com/blog/FormerlyKnownAsAtlasForReal.aspx</link>
      <pubDate>Tue, 12 Sep 2006 02:29:10 GMT</pubDate>
      <description>&lt;p&gt;
It's &lt;a href="http://weblogs.asp.net/scottgu/archive/2006/09/11/_2200_Atlas_2200_-1.0-Naming-and-Roadmap.aspx"&gt;official&lt;/a&gt;,
the technology formerly known as Atlas will be called...&amp;nbsp; Microsoft AJAX Library,
ASP.NET 2.0 AJAX Extensions, and ASP.NET AJAX Control Toolkit!
&lt;/p&gt;
&lt;p&gt;
Wow, those names are actually intuitive and descriptive. This is such a relief, considering
what COULD have been... I had my bets on the dry, but .NET 3.0 compliant &amp;quot;Windows
Dynamic Web Foundation&amp;quot;? Or the completely&amp;nbsp;absurd &amp;quot;&lt;a href="http://flimflan.com/blog/FormerlyKnownAsAtlas.aspx"&gt;ASP.NET
7.0&lt;/a&gt;&amp;quot; ;-)
&lt;/p&gt;
&lt;p&gt;
Yeah, about that... I completely made it up. It wasn't a hoax; no, I wasn't trying
to fool anyone or make anyone believe it so that I could secretly laugh at them.&amp;nbsp;It
was a satire, so that&amp;nbsp;I could publicly laugh at the madness of Microsoft naming
schemes. I wanted to try and draw some attention to the issue, and hopefully motivate
some people to go sign the &lt;a href="http://www.petitiononline.com/winfx/petition.html"&gt;Reverse
WinFX Petition&lt;/a&gt;. Not because I thought Microsoft would change their mind, but because
I wanted them to get the message that we don't want marketing decisions obfuscating
and hijacking the terminology that we developers use to communicate. Its a version
number - it has a very specific meaning, it is not a brand. Of all the things to lift
from the Java camp, why did we want the &lt;a href="http://www.particle.kth.se/~lindsey/JavaCourse/Book/Part1/Java/Chapter01/versions.html"&gt;version
number confusion&lt;/a&gt;?
&lt;/p&gt;
&lt;p&gt;
If you believed my post regarding Atlas =&amp;gt; ASP.NET 7.0, I'm sorry, it wasn't my
intention to deceive. But the fact that a number of people &lt;em&gt;did&lt;/em&gt; believe it
just demonstrates the levels of absurdity we've come to expect and accept from Microsoft
when it comes to branding. I &lt;em&gt;tried &lt;/em&gt;to make it absurd. I tried to make it
so ridiculous, and so obvious that it was fake (the quotes were almost word for word
cut from one of the linked articles about the .NET 3.0 naming), but people still believed
it. Apparently I need to work on my comedic writing and satirical wit.
&lt;/p&gt;
&lt;p&gt;
Thanks to the Microsoft Web Platform team for the sane naming and their ability to
continue delivering technology without waiting for a large release vehicle (and sorry
for any confusion the last post may have caused).&lt;br /&gt;
&lt;/p&gt;
&lt;img width="0" height="0" src="http://flimflan.com/blog/aggbug.ashx?id=2cdfac61-ed63-4e65-82bd-7c47edc7a1dc" /&gt;</description>
      <comments>http://flimflan.com/blog/CommentView,guid,2cdfac61-ed63-4e65-82bd-7c47edc7a1dc.aspx</comments>
      <category>.NET</category>
    </item>
    <item>
      <trackback:ping>http://flimflan.com/blog/Trackback.aspx?guid=91f4f305-8462-42e6-8491-22d4be189070</trackback:ping>
      <pingback:server>http://flimflan.com/blog/pingback.aspx</pingback:server>
      <pingback:target>http://flimflan.com/blog/PermaLink,guid,91f4f305-8462-42e6-8491-22d4be189070.aspx</pingback:target>
      <dc:creator>
      </dc:creator>
      <wfw:comment>http://flimflan.com/blog/CommentView,guid,91f4f305-8462-42e6-8491-22d4be189070.aspx</wfw:comment>
      <wfw:commentRss>http://flimflan.com/blog/SyndicationService.asmx/GetEntryCommentsRss?guid=91f4f305-8462-42e6-8491-22d4be189070</wfw:commentRss>
      <slash:comments>6</slash:comments>
      <title>Formerly known as Atlas</title>
      <guid isPermaLink="false">http://flimflan.com/blog/PermaLink,guid,91f4f305-8462-42e6-8491-22d4be189070.aspx</guid>
      <link>http://flimflan.com/blog/FormerlyKnownAsAtlas.aspx</link>
      <pubDate>Fri, 25 Aug 2006 02:27:48 GMT</pubDate>
      <description>&lt;p&gt;
You've probably read the news a hundred times around the blogosphere already, but
that won't stop me from joining the chorus and adding my 2 cents.&lt;br /&gt;
&lt;br /&gt;
The &lt;a target="_blank" href="http://atlas.asp.net/Default.aspx?tabid=47"&gt;Microsoft
AJAX (formerly known as DHTML) technology, codename Atlas&lt;/a&gt;, will be officially
named... ASP.NET 7.0!
&lt;/p&gt;
&lt;p&gt;
I was very skeptical at first... this is the explanation:
&lt;/p&gt;
&lt;blockquote&gt; 
&lt;p&gt;
&amp;quot;ASP.NET 7.0 aptly identifies the technology for exactly what it is &amp;ndash; the
next version of our web developer framework.&amp;quot;
&lt;/p&gt;
&lt;p&gt;
&amp;quot;...The change is in name only and will not affect the technologies being delivered
as part of the product.&amp;nbsp;ASP.NET 7.0&amp;nbsp;is still comprised of the existing ASP.NET
2.0 components, including DataSource controls, the Provider model, and Master Pages
&amp;amp; Themes,&amp;nbsp;as well as new web 2.0 developer-focused innovative technologies
like UpdatePanels and JSON serialization.&amp;quot;
&lt;/p&gt;
&lt;p&gt;
&amp;quot;...The ASP.NET platform has always been at the core of Atlas, but the Atlas
brand didn&amp;rsquo;t convey this&amp;quot;
&lt;/p&gt;
&lt;p&gt;
&amp;quot;...The name conveys the maturity of the platform by emphasizing that it has
evolved from proven technology in production for over a decade, while also aligning
it with the rest of the Web Tools Platform (IIS 7 + IE 7).&amp;quot;
&lt;/p&gt;
&lt;/blockquote&gt; 
&lt;p&gt;
&lt;em&gt;Over a decade you ask?&lt;/em&gt; Follow along - it started with Active Server Pages
1, 2, &amp;amp; 3.0, changed the brand slightly to ASP.NET (4.0), ASP.NET 1.1 (5.0), and
then most recently ASP.NET 2.0 (6.0). The next logical name of the development platform,
ASP.NET 7.0, more accurately reflects this heritage.
&lt;/p&gt;
&lt;p&gt;
(I can't help but suspect a little marketeering &amp;quot;two-upmanship&amp;quot;&amp;nbsp;over
the PHP 5 competition).
&lt;/p&gt;
&lt;blockquote&gt; 
&lt;p&gt;
&amp;quot;In the specific example of ASP.NET 7.0, there is a lot of new compelling improvements
to the technology that warrant a major version number for the redist&amp;quot;
&lt;/p&gt;
&lt;p&gt;
&amp;quot;...We are confident that this change will go a long way towards reducing confusion
people may have about our web developer platform and the technologies in which they
should invest.&amp;quot;
&lt;/p&gt;
&lt;/blockquote&gt; 
&lt;p&gt;
Reducing confusion? Ok, never mind what I said earlier about coming around.. this
is ridiculous. If &lt;a href="http://blogs.msdn.com/somasegar/archive/2006/06/09/624300.aspx"&gt;any
of this&lt;/a&gt; bugs you like &lt;a href="http://blogs.msdn.com/jasonz/archive/2006/06/13/630066.aspx"&gt;it
bugs me&lt;/a&gt;, go sign the &lt;a href="http://www.petitiononline.com/winfx/petition.html"&gt;Reverse
WinFX Petition&lt;/a&gt;.
&lt;/p&gt;
&lt;p&gt;
&lt;em&gt;This post was written using Windows Live Writer Beta. My source tells me that
when it comes out of Beta, it will be renamed Word 13.&lt;/em&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;span style="font-weight: bold; color: rgb(51, 153, 102);"&gt;Update&lt;/span&gt;: You should
probably read the &lt;a href="http://flimflan.com/blog/FormerlyKnownAsAtlasForReal.aspx"&gt;follow
up post regarding the naming of the Atlas framework.&lt;/a&gt;&lt;em&gt;
&lt;br /&gt;
&lt;/em&gt;
&lt;/p&gt;
&lt;img width="0" height="0" src="http://flimflan.com/blog/aggbug.ashx?id=91f4f305-8462-42e6-8491-22d4be189070" /&gt;</description>
      <comments>http://flimflan.com/blog/CommentView,guid,91f4f305-8462-42e6-8491-22d4be189070.aspx</comments>
      <category>.NET</category>
    </item>
    <item>
      <trackback:ping>http://flimflan.com/blog/Trackback.aspx?guid=ba11f114-6da4-4e79-9a0d-57402643baaf</trackback:ping>
      <pingback:server>http://flimflan.com/blog/pingback.aspx</pingback:server>
      <pingback:target>http://flimflan.com/blog/PermaLink,guid,ba11f114-6da4-4e79-9a0d-57402643baaf.aspx</pingback:target>
      <dc:creator>
      </dc:creator>
      <wfw:comment>http://flimflan.com/blog/CommentView,guid,ba11f114-6da4-4e79-9a0d-57402643baaf.aspx</wfw:comment>
      <wfw:commentRss>http://flimflan.com/blog/SyndicationService.asmx/GetEntryCommentsRss?guid=ba11f114-6da4-4e79-9a0d-57402643baaf</wfw:commentRss>
      <slash:comments>9</slash:comments>
      <body xmlns="http://www.w3.org/1999/xhtml">As you know, the customErrors section of
web.config allows you to define your own pages to display to the user when an error
occurs. It allows for a default page to display when any unhandled error occurs, and
it also allows you to specify different pages to display depending on the HTTP status
code.<br /><br />
I like to take advantage of ASP.NET's declarative security model by defining the users
and roles that are authorized to execute different parts of my website. For example,
I can limit access to a page named Protected.aspx by declaring that all users must
be a meber of the VerySpecialUsers group. This can be accomplished by adding the following
section to my web.config:<br /><br /><div style="background: white none repeat scroll 0% 50%; font-family: Consolas; font-size: 10pt; color: black; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial;"><p style="margin: 0px;"><span style="color: blue;">  &lt;</span><span style="color: maroon;">location</span><span style="color: blue;"></span><span style="color: red;">path</span><span style="color: blue;">=</span>"<span style="color: blue;">Protected.aspx</span>"<span style="color: blue;">&gt;</span></p><p style="margin: 0px;"><span style="color: blue;">    &lt;</span><span style="color: maroon;">system.web</span><span style="color: blue;">&gt;</span></p><p style="margin: 0px;"><span style="color: blue;">      &lt;</span><span style="color: maroon;">authorization</span><span style="color: blue;">&gt;</span></p><p style="margin: 0px;"><span style="color: blue;">        &lt;</span><span style="color: maroon;">allow</span><span style="color: blue;"></span><span style="color: red;">roles</span><span style="color: blue;">=</span>"<span style="color: blue;">VerySpecialUsers</span>"<span style="color: blue;">/&gt;</span></p><p style="margin: 0px;"><span style="color: blue;">        &lt;</span><span style="color: maroon;">deny</span><span style="color: blue;"></span><span style="color: red;">users</span><span style="color: blue;">=</span>"<span style="color: blue;">*</span>"<span style="color: blue;">/&gt;</span></p><p style="margin: 0px;"><span style="color: blue;">      &lt;/</span><span style="color: maroon;">authorization</span><span style="color: blue;">&gt;</span></p><p style="margin: 0px;"><span style="color: blue;">    &lt;/</span><span style="color: maroon;">system.web</span><span style="color: blue;">&gt;</span></p><p style="margin: 0px;"><span style="color: blue;">  &lt;/</span><span style="color: maroon;">location</span><span style="color: blue;">&gt;</span></p></div><br />
I like this model as it allows me to easily modify the access restrictions for a page,
and since it uses ASP.NET's Role Provider framework, it is not tied to any implementation
about how role membership is determined. By default in a Windows Authentication/NTLM
scenario, the roles map to the group memberships of your Windows login account (Administrators,
Power Users, Users, etc). But you can <a href="http://flimflan.com/blog/ASPNETRoleProviderVisualStudioTemplate.aspx">very
easily create your own Role Provider</a> that retrieves group membership information
from your own data store.<br /><br />
When a user does not meet the authorization requirements to visit a certain page,
ASP.NET will return a 401.2 Access Denied error. The page looks like the standard <a href="http://en.wikipedia.org/wiki/Yellow_Screen_of_Death">yellow
screen of death</a> (YSOD) that ASP.NET returns for all errors.The customErrors section
of web.config is supposed to let you provide a friendlier response to your users so
they never have to see the YSOD. You would think that all you need to do is define
a page for the 401 status code in customErrors and all would be good. You would be
wrong. You can even try changing the custom error page defined in your IIS settings,
and it still won't work.<br /><br />
The newsgroups have countless unanswered posts about this issue. Fortunately, my most
recent attempt to solve this problem finally found some answers. The first one I found,
and the one I use for my solution, was <a href="http://forums.aspfree.com/showpost.php?p=100206&amp;postcount=5">posted
by John "iSpeakGeek" on ASPFree forums</a>. I have since discovered a <a href="http://www.codeproject.com/aspnet/Custon401Page.asp">CodeProject
article by George Mamaladze</a>, and even a (somewhat related) <a href="http://support.microsoft.com/default.aspx?scid=kb;en-us;902239">Microsoft
KB article</a>. Hopefully this post will help improve the search results for other
people struggling with this issue.<br /><br />
The key to the solution is to intercept the EndRequest event of the page lifecycle,
check for a 401 status code, and then execute your custom page. The Microsoft article
suggests intercepting the Error event and checking for an UnauthroizedAccessException,
but that didn't work for my scenario. It may only apply when using impersonation,
as the article describes. I need to do more testing and will possibly modify my solution
to cover more scenarios.<br /><br />
Since I need this functionality on pretty much every website I make, I created an
HttpModule to encapsulate the logic. The nice thing about my module approach is that
you simply register the module in your web.config, and it will automatically respect
the settings you define in your customErrors section. There is no hardcoded dependence
on a specific error page or need for a custom configuration section.<br /><br /><div style="background: white none repeat scroll 0% 50%; font-family: Consolas; font-size: 10pt; color: black; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial;"><p style="margin: 0px;"><span style="color: blue;">&lt;</span><span style="color: maroon;">httpModules</span><span style="color: blue;">&gt;</span></p><p style="margin: 0px;"><span style="color: blue;">  &lt;</span><span style="color: maroon;">add</span><span style="color: blue;"></span><span style="color: red;">name</span><span style="color: blue;">=</span>"<span style="color: blue;">CustomAccessDenied</span>"<span style="color: blue;"></span><span style="color: red;">type</span><span style="color: blue;">=</span>"<span style="color: blue;">FlimFlan.CustomAccessDenied,
FlimFlan.CustomAccessDenied</span>"<span style="color: blue;">/&gt;</span></p><p style="margin: 0px;"><span style="color: blue;">&lt;/</span><span style="color: maroon;">httpModules</span><span style="color: blue;">&gt;</span></p><p style="margin: 0px;"><span style="color: blue;">&lt;</span><span style="color: maroon;">customErrors</span><span style="color: blue;"></span><span style="color: red;">mode</span><span style="color: blue;">=</span>"<span style="color: blue;">On</span>"<span style="color: blue;"></span><span style="color: red;">defaultRedirect</span><span style="color: blue;">=</span>"<span style="color: blue;">Error.htm</span>"<span style="color: blue;">&gt;</span></p><p style="margin: 0px;"><span style="color: blue;">  &lt;</span><span style="color: maroon;">error</span><span style="color: blue;"></span><span style="color: red;">statusCode</span><span style="color: blue;">=</span>"<span style="color: blue;">401</span>"<span style="color: blue;"></span><span style="color: red;">redirect</span><span style="color: blue;">=</span>"<span style="color: blue;">AccessDenied.aspx</span>"<span style="color: blue;">/&gt;</span></p><p style="margin: 0px;"><span style="color: blue;">&lt;/</span><span style="color: maroon;">customErrors</span><span style="color: blue;">&gt;</span></p></div><br />
I've packaged up the full source and a sample website. Use it and change it as you
wish. If you don't care about the source, just grab the DLL from the DemoWeb\Bin folder
and put it in your own website's Bin folder.<br /><br />
I can't claim it is a general purpose solution yet, as I have not tested it with all
possible authentication/authorization settings. If you find a scenario that doesn't
work, please let me know and I'll see if I can address it.<br /><br />
Download <a href="http://flimflan.com/files/FlimFlan_CustomAccessDenied.zip">FlimFlan.CustomAccessDenied</a><img width="0" height="0" src="http://flimflan.com/blog/aggbug.ashx?id=ba11f114-6da4-4e79-9a0d-57402643baaf" /></body>
      <title>HttpModule to allow a custom error page for 401.2 Access Denied in ASP.NET</title>
      <guid isPermaLink="false">http://flimflan.com/blog/PermaLink,guid,ba11f114-6da4-4e79-9a0d-57402643baaf.aspx</guid>
      <link>http://flimflan.com/blog/HttpModuleToAllowACustomErrorPageFor4012AccessDeniedInASPNET.aspx</link>
      <pubDate>Sat, 05 Aug 2006 17:02:52 GMT</pubDate>
      <description>As you know, the customErrors section of web.config allows you to define your own pages to display to the user when an error occurs. It allows for a default page to display when any unhandled error occurs, and it also allows you to specify different pages to display depending on the HTTP status code.&lt;br /&gt;
&lt;br /&gt;
I like to take advantage of ASP.NET's declarative security model by defining the users
and roles that are authorized to execute different parts of my website. For example,
I can limit access to a page named Protected.aspx by declaring that all users must
be a meber of the VerySpecialUsers group. This can be accomplished by adding the following
section to my web.config:&lt;br /&gt;
&lt;br /&gt;
&lt;div style="background: white none repeat scroll 0% 50%; font-family: Consolas; font-size: 10pt; color: black; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial;"&gt;
&lt;p style="margin: 0px;"&gt;
&lt;span style="color: blue;"&gt;&amp;nbsp; &amp;lt;&lt;/span&gt;&lt;span style="color: maroon;"&gt;location&lt;/span&gt;&lt;span style="color: blue;"&gt; &lt;/span&gt;&lt;span style="color: red;"&gt;path&lt;/span&gt;&lt;span style="color: blue;"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue;"&gt;Protected.aspx&lt;/span&gt;&amp;quot;&lt;span style="color: blue;"&gt;&amp;gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;
&lt;span style="color: blue;"&gt;&amp;nbsp; &amp;nbsp; &amp;lt;&lt;/span&gt;&lt;span style="color: maroon;"&gt;system.web&lt;/span&gt;&lt;span style="color: blue;"&gt;&amp;gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;
&lt;span style="color: blue;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;lt;&lt;/span&gt;&lt;span style="color: maroon;"&gt;authorization&lt;/span&gt;&lt;span style="color: blue;"&gt;&amp;gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;
&lt;span style="color: blue;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;lt;&lt;/span&gt;&lt;span style="color: maroon;"&gt;allow&lt;/span&gt;&lt;span style="color: blue;"&gt; &lt;/span&gt;&lt;span style="color: red;"&gt;roles&lt;/span&gt;&lt;span style="color: blue;"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue;"&gt;VerySpecialUsers&lt;/span&gt;&amp;quot;&lt;span style="color: blue;"&gt;/&amp;gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;
&lt;span style="color: blue;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;lt;&lt;/span&gt;&lt;span style="color: maroon;"&gt;deny&lt;/span&gt;&lt;span style="color: blue;"&gt; &lt;/span&gt;&lt;span style="color: red;"&gt;users&lt;/span&gt;&lt;span style="color: blue;"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue;"&gt;*&lt;/span&gt;&amp;quot;&lt;span style="color: blue;"&gt;/&amp;gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;
&lt;span style="color: blue;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;lt;/&lt;/span&gt;&lt;span style="color: maroon;"&gt;authorization&lt;/span&gt;&lt;span style="color: blue;"&gt;&amp;gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;
&lt;span style="color: blue;"&gt;&amp;nbsp; &amp;nbsp; &amp;lt;/&lt;/span&gt;&lt;span style="color: maroon;"&gt;system.web&lt;/span&gt;&lt;span style="color: blue;"&gt;&amp;gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;
&lt;span style="color: blue;"&gt;&amp;nbsp; &amp;lt;/&lt;/span&gt;&lt;span style="color: maroon;"&gt;location&lt;/span&gt;&lt;span style="color: blue;"&gt;&amp;gt;&lt;/span&gt;
&lt;/p&gt;
&lt;/div&gt;
&lt;br /&gt;
I like this model as it allows me to easily modify the access restrictions for a page,
and since it uses ASP.NET's Role Provider framework, it is not tied to any implementation
about how role membership is determined. By default in a Windows Authentication/NTLM
scenario, the roles map to the group memberships of your Windows login account (Administrators,
Power Users, Users, etc). But you can &lt;a href="http://flimflan.com/blog/ASPNETRoleProviderVisualStudioTemplate.aspx"&gt;very
easily create your own Role Provider&lt;/a&gt; that retrieves group membership information
from your own data store.&lt;br /&gt;
&lt;br /&gt;
When a user does not meet the authorization requirements to visit a certain page,
ASP.NET will return a 401.2 Access Denied error. The page looks like the standard &lt;a href="http://en.wikipedia.org/wiki/Yellow_Screen_of_Death"&gt;yellow
screen of death&lt;/a&gt; (YSOD) that ASP.NET returns for all errors.The customErrors section
of web.config is supposed to let you provide a friendlier response to your users so
they never have to see the YSOD. You would think that all you need to do is define
a page for the 401 status code in customErrors and all would be good. You would be
wrong. You can even try changing the custom error page defined in your IIS settings,
and it still won't work.&lt;br /&gt;
&lt;br /&gt;
The newsgroups have countless unanswered posts about this issue. Fortunately, my most
recent attempt to solve this problem finally found some answers. The first one I found,
and the one I use for my solution, was &lt;a href="http://forums.aspfree.com/showpost.php?p=100206&amp;amp;postcount=5"&gt;posted
by John &amp;quot;iSpeakGeek&amp;quot; on ASPFree forums&lt;/a&gt;. I have since discovered a &lt;a href="http://www.codeproject.com/aspnet/Custon401Page.asp"&gt;CodeProject
article by George Mamaladze&lt;/a&gt;, and even a (somewhat related) &lt;a href="http://support.microsoft.com/default.aspx?scid=kb;en-us;902239"&gt;Microsoft
KB article&lt;/a&gt;. Hopefully this post will help improve the search results for other
people struggling with this issue.&lt;br /&gt;
&lt;br /&gt;
The key to the solution is to intercept the EndRequest event of the page lifecycle,
check for a 401 status code, and then execute your custom page. The Microsoft article
suggests intercepting the Error event and checking for an UnauthroizedAccessException,
but that didn't work for my scenario. It may only apply when using impersonation,
as the article describes. I need to do more testing and will possibly modify my solution
to cover more scenarios.&lt;br /&gt;
&lt;br /&gt;
Since I need this functionality on pretty much every website I make, I created an
HttpModule to encapsulate the logic. The nice thing about my module approach is that
you simply register the module in your web.config, and it will automatically respect
the settings you define in your customErrors section. There is no hardcoded dependence
on a specific error page or need for a custom configuration section.&lt;br /&gt;
&lt;br /&gt;
&lt;div style="background: white none repeat scroll 0% 50%; font-family: Consolas; font-size: 10pt; color: black; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial;"&gt;
&lt;p style="margin: 0px;"&gt;
&lt;span style="color: blue;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: maroon;"&gt;httpModules&lt;/span&gt;&lt;span style="color: blue;"&gt;&amp;gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;
&lt;span style="color: blue;"&gt;&amp;nbsp; &amp;lt;&lt;/span&gt;&lt;span style="color: maroon;"&gt;add&lt;/span&gt;&lt;span style="color: blue;"&gt; &lt;/span&gt;&lt;span style="color: red;"&gt;name&lt;/span&gt;&lt;span style="color: blue;"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue;"&gt;CustomAccessDenied&lt;/span&gt;&amp;quot;&lt;span style="color: blue;"&gt; &lt;/span&gt;&lt;span style="color: red;"&gt;type&lt;/span&gt;&lt;span style="color: blue;"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue;"&gt;FlimFlan.CustomAccessDenied,
FlimFlan.CustomAccessDenied&lt;/span&gt;&amp;quot;&lt;span style="color: blue;"&gt;/&amp;gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;
&lt;span style="color: blue;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: maroon;"&gt;httpModules&lt;/span&gt;&lt;span style="color: blue;"&gt;&amp;gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;
&lt;span style="color: blue;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: maroon;"&gt;customErrors&lt;/span&gt;&lt;span style="color: blue;"&gt; &lt;/span&gt;&lt;span style="color: red;"&gt;mode&lt;/span&gt;&lt;span style="color: blue;"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue;"&gt;On&lt;/span&gt;&amp;quot;&lt;span style="color: blue;"&gt; &lt;/span&gt;&lt;span style="color: red;"&gt;defaultRedirect&lt;/span&gt;&lt;span style="color: blue;"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue;"&gt;Error.htm&lt;/span&gt;&amp;quot;&lt;span style="color: blue;"&gt;&amp;gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;
&lt;span style="color: blue;"&gt;&amp;nbsp; &amp;lt;&lt;/span&gt;&lt;span style="color: maroon;"&gt;error&lt;/span&gt;&lt;span style="color: blue;"&gt; &lt;/span&gt;&lt;span style="color: red;"&gt;statusCode&lt;/span&gt;&lt;span style="color: blue;"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue;"&gt;401&lt;/span&gt;&amp;quot;&lt;span style="color: blue;"&gt; &lt;/span&gt;&lt;span style="color: red;"&gt;redirect&lt;/span&gt;&lt;span style="color: blue;"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue;"&gt;AccessDenied.aspx&lt;/span&gt;&amp;quot;&lt;span style="color: blue;"&gt;/&amp;gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;
&lt;span style="color: blue;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: maroon;"&gt;customErrors&lt;/span&gt;&lt;span style="color: blue;"&gt;&amp;gt;&lt;/span&gt;
&lt;/p&gt;
&lt;/div&gt;
&lt;br /&gt;
I've packaged up the full source and a sample website. Use it and change it as you
wish. If you don't care about the source, just grab the DLL from the DemoWeb\Bin folder
and put it in your own website's Bin folder.&lt;br /&gt;
&lt;br /&gt;
I can't claim it is a general purpose solution yet, as I have not tested it with all
possible authentication/authorization settings. If you find a scenario that doesn't
work, please let me know and I'll see if I can address it.&lt;br /&gt;
&lt;br /&gt;
Download &lt;a href="http://flimflan.com/files/FlimFlan_CustomAccessDenied.zip"&gt;FlimFlan.CustomAccessDenied&lt;/a&gt;&lt;img width="0" height="0" src="http://flimflan.com/blog/aggbug.ashx?id=ba11f114-6da4-4e79-9a0d-57402643baaf" /&gt;</description>
      <comments>http://flimflan.com/blog/CommentView,guid,ba11f114-6da4-4e79-9a0d-57402643baaf.aspx</comments>
      <category>.NET</category>
    </item>
    <item>
      <trackback:ping>http://flimflan.com/blog/Trackback.aspx?guid=e7597cd9-6f4c-4ca5-bf15-fd4223fe5ab0</trackback:ping>
      <pingback:server>http://flimflan.com/blog/pingback.aspx</pingback:server>
      <pingback:target>http://flimflan.com/blog/PermaLink,guid,e7597cd9-6f4c-4ca5-bf15-fd4223fe5ab0.aspx</pingback:target>
      <dc:creator>
      </dc:creator>
      <wfw:comment>http://flimflan.com/blog/CommentView,guid,e7597cd9-6f4c-4ca5-bf15-fd4223fe5ab0.aspx</wfw:comment>
      <wfw:commentRss>http://flimflan.com/blog/SyndicationService.asmx/GetEntryCommentsRss?guid=e7597cd9-6f4c-4ca5-bf15-fd4223fe5ab0</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">Considering how many pre-release Whidbey
demos I saw showing off the new color support in Console applications, I'm surprised
this wasn't include in the box. I use a System.Diagnostics.TraceSource coupled with
the ConsoleTraceListener for output in console apps. Of course, when you have verbose
logging enabled, you see a LOT of gray text scroll across the screen, and nothing
really stands out. Reminds me of trying to decode <span style="color: rgb(192, 192, 192);">NAnt </span>output
after living with <span style="color: rgb(255, 0, 0);">M</span><span style="color: rgb(128, 128, 128);">S</span><span style="color: rgb(0, 0, 255);">Build</span> for
a while. I did a quick search for "color consoletracelistener" and came
across <a href="http://blogs.artinsoft.net/mrojas/archive/2006/05/29/1069.aspx">this
offering</a> from Mauricio Rojas. I (probably unfairly) dimissed it because it looked
much more complicated than I would expect (ok, and because it was in VB). 
<br />
So I spent 10 minutes throwing this together. It works for every scenario that I need.
In other words, I make no claims that it is general purpose solution for you - it
may not add color to every type of trace message (depending on which methods you use
to write messages). If this doesn't work for you, Mauricio's may be a better bet.<br /><br /><!--
{\rtf1\ansi\ansicpg\lang1024\noproof1252\uc1 \deff0{\fonttbl{\f0\fnil\fcharset0\fprq1 Consolas;}}{\colortbl;\red0\green0\blue0;\red0\green0\blue255;\red0\green255\blue255;\red0\green255\blue0??;\red255\green0\blue255;\red255\green0\blue0;\red255\green255\blue0;\red255\green255\blue255;??\red0\green0\blue128;\red0\green128\blue128;\red0\green128\blue0;??\red128\green0\blue128;\red128\green0\blue0;\red128\green128\blue0;\red128\green128\blue128;??\red192\green192\blue192;}??\fs20 \cf2 using\cf0  System;\par ??\cf2 using\cf0  System.Diagnostics;\par ??\cf2 using\cf0  System.Collections.Generic;\par ??\par ??\cf2 namespace\cf0  FlimFlan.Diagnostics\par ??\{\par ??    \cf2 public\cf0  \cf2 class\cf0  \cf10 ColorConsoleTraceListener\cf0  : \cf10 ConsoleTraceListener\par ??\cf0     \{\par ??        \cf10 Dictionary\cf0 &lt;\cf10 TraceEventType\cf0 , \cf10 ConsoleColor\cf0 &gt; eventColor = \cf2 new\cf0  \cf10 Dictionary\cf0 &lt;\cf10 TraceEventType\cf0 , \cf10 ConsoleColor\cf0 &gt;();\par ??\par ??        \cf2 public\cf0  ColorConsoleTraceListener()\par ??        \{\par ??            eventColor.Add(\cf10 TraceEventType\cf0 .Verbose, \cf10 ConsoleColor\cf0 .DarkGray);\par ??            eventColor.Add(\cf10 TraceEventType\cf0 .Information, \cf10 ConsoleColor\cf0 .Gray);\par ??            eventColor.Add(\cf10 TraceEventType\cf0 .Warning, \cf10 ConsoleColor\cf0 .Yellow);\par ??            eventColor.Add(\cf10 TraceEventType\cf0 .Error, \cf10 ConsoleColor\cf0 .DarkRed);\par ??            eventColor.Add(\cf10 TraceEventType\cf0 .Critical, \cf10 ConsoleColor\cf0 .Red);\par ??            eventColor.Add(\cf10 TraceEventType\cf0 .Start, \cf10 ConsoleColor\cf0 .DarkCyan);\par ??            eventColor.Add(\cf10 TraceEventType\cf0 .Stop, \cf10 ConsoleColor\cf0 .DarkCyan);\par ??        \}\par ??\par ??        \cf2 public\cf0  \cf2 override\cf0  \cf2 void\cf0  TraceEvent(\cf10 TraceEventCache\cf0  eventCache, \cf2 string\cf0  source, \cf10 TraceEventType\cf0  eventType, \cf2 int\cf0  id, \cf2 string\cf0  message)\par ??        \{\par ??            TraceEvent(eventCache, source, eventType, id, \cf13 "\{0\}"\cf0 , message);\par ??        \}\par ??\par ??        \cf2 public\cf0  \cf2 override\cf0  \cf2 void\cf0  TraceEvent(\cf10 TraceEventCache\cf0  eventCache, \cf2 string\cf0  source, \cf10 TraceEventType\cf0  eventType, \cf2 int\cf0  id, \cf2 string\cf0  format, \cf2 params\cf0  \cf2 object\cf0 [] args)\par ??        \{\par ??            \cf10 ConsoleColor\cf0  originalColor = \cf10 Console\cf0 .ForegroundColor;\par ??            \cf10 Console\cf0 .ForegroundColor = getEventColor(eventType, originalColor);\par ??            \cf2 base\cf0 .TraceEvent(eventCache, source, eventType, id, format, args);\par ??            \cf10 Console\cf0 .ForegroundColor = originalColor;\par ??        \}\par ??\par ??        \cf2 private\cf0  \cf10 ConsoleColor\cf0  getEventColor(\cf10 TraceEventType\cf0  eventType, \cf10 ConsoleColor\cf0  defaultColor)\par ??        \{\par ??            \cf2 if\cf0  (eventColor.ContainsKey(eventType))\par ??            \{\par ??                \cf2 return\cf0  eventColor[eventType];\par ??            \}\par ??            \cf2 return\cf0  defaultColor;\par ??        \}\par ??    \}\par ??\}\par ??}
--><div style="background: white none repeat scroll 0% 50%; font-family: Consolas; font-size: 10pt; color: black; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial;"><p style="margin: 0px;"><span style="color: blue;">using</span> System;
</p><p style="margin: 0px;"><span style="color: blue;">using</span> System.Diagnostics;
</p><p style="margin: 0px;"><span style="color: blue;">using</span> System.Collections.Generic;
</p><p style="margin: 0px;">
 
</p><p style="margin: 0px;"><span style="color: blue;">namespace</span> FlimFlan.Diagnostics
</p><p style="margin: 0px;">
{
</p><p style="margin: 0px;">
    <span style="color: blue;">public</span><span style="color: blue;">class</span><span style="color: teal;">ColorConsoleTraceListener</span> : <span style="color: teal;">ConsoleTraceListener</span></p><p style="margin: 0px;">
    {
</p><p style="margin: 0px;">
        <span style="color: teal;">Dictionary</span>&lt;<span style="color: teal;">TraceEventType</span>, <span style="color: teal;">ConsoleColor</span>&gt;
eventColor = <span style="color: blue;">new</span><span style="color: teal;">Dictionary</span>&lt;<span style="color: teal;">TraceEventType</span>, <span style="color: teal;">ConsoleColor</span>&gt;();
</p><p style="margin: 0px;">
 
</p><p style="margin: 0px;">
        <span style="color: blue;">public</span> ColorConsoleTraceListener()
</p><p style="margin: 0px;">
        {
</p><p style="margin: 0px;">
            eventColor.Add(<span style="color: teal;">TraceEventType</span>.Verbose, <span style="color: teal;">ConsoleColor</span>.DarkGray);
</p><p style="margin: 0px;">
            eventColor.Add(<span style="color: teal;">TraceEventType</span>.Information, <span style="color: teal;">ConsoleColor</span>.Gray);
</p><p style="margin: 0px;">
            eventColor.Add(<span style="color: teal;">TraceEventType</span>.Warning, <span style="color: teal;">ConsoleColor</span>.Yellow);
</p><p style="margin: 0px;">
            eventColor.Add(<span style="color: teal;">TraceEventType</span>.Error, <span style="color: teal;">ConsoleColor</span>.DarkRed);
</p><p style="margin: 0px;">
            eventColor.Add(<span style="color: teal;">TraceEventType</span>.Critical, <span style="color: teal;">ConsoleColor</span>.Red);
</p><p style="margin: 0px;">
            eventColor.Add(<span style="color: teal;">TraceEventType</span>.Start, <span style="color: teal;">ConsoleColor</span>.DarkCyan);
</p><p style="margin: 0px;">
            eventColor.Add(<span style="color: teal;">TraceEventType</span>.Stop, <span style="color: teal;">ConsoleColor</span>.DarkCyan);
</p><p style="margin: 0px;">
        }
</p><p style="margin: 0px;">
 
</p><p style="margin: 0px;">
        <span style="color: blue;">public</span><span style="color: blue;">override</span><span style="color: blue;">void</span> TraceEvent(<span style="color: teal;">TraceEventCache</span> eventCache, <span style="color: blue;">string</span> source, <span style="color: teal;">TraceEventType</span> eventType, <span style="color: blue;">int</span> id, <span style="color: blue;">string</span> message)
</p><p style="margin: 0px;">
        {
</p><p style="margin: 0px;">
            TraceEvent(eventCache, source, eventType,
id, <span style="color: maroon;">"{0}"</span>, message);
</p><p style="margin: 0px;">
        }
</p><p style="margin: 0px;">
 
</p><p style="margin: 0px;">
        <span style="color: blue;">public</span><span style="color: blue;">override</span><span style="color: blue;">void</span> TraceEvent(<span style="color: teal;">TraceEventCache</span> eventCache, <span style="color: blue;">string</span> source, <span style="color: teal;">TraceEventType</span> eventType, <span style="color: blue;">int</span> id, <span style="color: blue;">string</span> format, <span style="color: blue;">params</span><span style="color: blue;">object</span>[]
args)
</p><p style="margin: 0px;">
        {
</p><p style="margin: 0px;">
            <span style="color: teal;">ConsoleColor</span> originalColor
= <span style="color: teal;">Console</span>.ForegroundColor;
</p><p style="margin: 0px;">
            <span style="color: teal;">Console</span>.ForegroundColor
= getEventColor(eventType, originalColor);
</p><p style="margin: 0px;">
            <span style="color: blue;">base</span>.TraceEvent(eventCache,
source, eventType, id, format, args);
</p><p style="margin: 0px;">
            <span style="color: teal;">Console</span>.ForegroundColor
= originalColor;
</p><p style="margin: 0px;">
        }
</p><p style="margin: 0px;">
 
</p><p style="margin: 0px;">
        <span style="color: blue;">private</span><span style="color: teal;">ConsoleColor</span> getEventColor(<span style="color: teal;">TraceEventType</span> eventType, <span style="color: teal;">ConsoleColor</span> defaultColor)
</p><p style="margin: 0px;">
        {
</p><p style="margin: 0px;">
            <span style="color: blue;">if</span> (!eventColor.ContainsKey(eventType))
</p><p style="margin: 0px;">
            {
</p><p style="margin: 0px;">
                <span style="color: blue;">return</span> defaultColor;
</p><p style="margin: 0px;">
            }
</p><p style="margin: 0px;">
            <span style="color: blue;">return</span> eventColor[eventType];
</p><p style="margin: 0px;">
        }
</p><p style="margin: 0px;">
    }
</p><p style="margin: 0px;">
}
</p></div><br />
You can see it in action using the following app:<br /><br /><div style="background: white none repeat scroll 0%; font-family: Consolas; font-size: 10pt; color: black; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial;"><p style="margin: 0px;"><span style="color: blue;">using</span> System.Diagnostics;
</p><p style="margin: 0px;"><span style="color: blue;">namespace</span> ConsoleApplication1
</p><p style="margin: 0px;">
{
</p><p style="margin: 0px;">
    <span style="color: blue;">class</span><span style="color: teal;">Program</span></p><p style="margin: 0px;">
    {
</p><p style="margin: 0px;">
        <span style="color: blue;">static</span><span style="color: blue;">void</span> Main(<span style="color: blue;">string</span>[]
args)
</p><p style="margin: 0px;">
        {
</p><p style="margin: 0px;">
            <span style="color: teal;">TraceSource</span> trace
= <span style="color: blue;">new</span><span style="color: teal;">TraceSource</span>(<span style="color: maroon;">"log"</span>);
</p><p style="margin: 0px;">
            trace.TraceEvent(<span style="color: teal;">TraceEventType</span>.Start,
0);
</p><p style="margin: 0px;">
            trace.TraceInformation(<span style="color: maroon;">"Hello
World"</span>);
</p><p style="margin: 0px;">
            trace.TraceEvent(<span style="color: teal;">TraceEventType</span>.Error,
0, <span style="color: maroon;">"Something failed."</span>);
</p><p style="margin: 0px;">
            trace.TraceEvent(<span style="color: teal;">TraceEventType</span>.Verbose,
0, <span style="color: maroon;">"I like ice cream."</span>);
</p><p style="margin: 0px;">
            trace.TraceEvent(<span style="color: teal;">TraceEventType</span>.Critical,
0, <span style="color: maroon;">"Something went horribly wrong!"</span>);
</p><p style="margin: 0px;">
            trace.TraceEvent(<span style="color: teal;">TraceEventType</span>.Verbose,
0, <span style="color: maroon;">"I like cherries."</span>);
</p><p style="margin: 0px;">
            trace.TraceEvent(<span style="color: teal;">TraceEventType</span>.Warning,
0, <span style="color: maroon;">"This program will end soon..."</span>);
</p><p style="margin: 0px;">
            trace.TraceEvent(<span style="color: teal;">TraceEventType</span>.Information,
0, <span style="color: maroon;">"Ending program."</span>);
</p><p style="margin: 0px;">
            trace.TraceEvent(<span style="color: teal;">TraceEventType</span>.Stop,
0);
</p><p style="margin: 0px;">
        }
</p><p style="margin: 0px;">
    }
</p><p style="margin: 0px;">
}
</p></div><br />
Add these settings to the configuration section of your app.config:<br /><br /><div style="background: white none repeat scroll 0%; font-family: Consolas; font-size: 10pt; color: black; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial;"><p style="margin: 0px;"><span style="color: blue;">  &lt;</span><span style="color: maroon;">system.diagnostics</span><span style="color: blue;">&gt;</span></p><p style="margin: 0px;"><span style="color: blue;">    &lt;</span><span style="color: maroon;">sources</span><span style="color: blue;">&gt;</span></p><p style="margin: 0px;"><span style="color: blue;">      &lt;</span><span style="color: maroon;">source</span><span style="color: blue;"></span><span style="color: red;">name</span><span style="color: blue;">=</span>"<span style="color: blue;">log</span>"<span style="color: blue;"></span><span style="color: red;">switchValue</span><span style="color: blue;">=</span>"<span style="color: blue;">All</span>"<span style="color: blue;">&gt;</span></p><p style="margin: 0px;"><span style="color: blue;">        &lt;</span><span style="color: maroon;">listeners</span><span style="color: blue;">&gt;</span></p><p style="margin: 0px;"><span style="color: blue;">          &lt;</span><span style="color: maroon;">add</span><span style="color: blue;"></span><span style="color: red;">name</span><span style="color: blue;">=</span>"<span style="color: blue;">Console</span>"<span style="color: blue;"></span><span style="color: red;">type</span><span style="color: blue;">=</span>"<span style="color: blue;">FlimFlan.Diagnostics.ColorConsoleTraceListener,
ConsoleApplication1</span>"<span style="color: blue;"> /&gt;</span></p><p style="margin: 0px;"><span style="color: blue;">        &lt;/</span><span style="color: maroon;">listeners</span><span style="color: blue;">&gt;</span></p><p style="margin: 0px;"><span style="color: blue;">      &lt;/</span><span style="color: maroon;">source</span><span style="color: blue;">&gt;</span></p><p style="margin: 0px;"><span style="color: blue;">    &lt;/</span><span style="color: maroon;">sources</span><span style="color: blue;">&gt;</span></p><p style="margin: 0px;"><span style="color: blue;">  &lt;/</span><span style="color: maroon;">system.diagnostics</span><span style="color: blue;">&gt;</span></p></div><br />
And you should see something like this:<br /><br /><img src="file:///C:/DOCUME~1/Josh/LOCALS~1/Temp/moz-screenshot.jpg" alt="" /><img border="0" src="http://flimflan.com/blog/content/binary/ColorConsoleTraceListenerOutput.png" alt="" /><img width="0" height="0" src="http://flimflan.com/blog/aggbug.ashx?id=e7597cd9-6f4c-4ca5-bf15-fd4223fe5ab0" /></body>
      <title>A simple color ConsoleTraceListener</title>
      <guid isPermaLink="false">http://flimflan.com/blog/PermaLink,guid,e7597cd9-6f4c-4ca5-bf15-fd4223fe5ab0.aspx</guid>
      <link>http://flimflan.com/blog/ASimpleColorConsoleTraceListener.aspx</link>
      <pubDate>Fri, 04 Aug 2006 03:02:45 GMT</pubDate>
      <description>Considering how many pre-release Whidbey demos I saw showing off the new color support in Console applications, I'm surprised this wasn't include in the box. I use a System.Diagnostics.TraceSource coupled with the ConsoleTraceListener for output in console apps. Of course, when you have verbose logging enabled, you see a LOT of gray text scroll across the screen, and nothing really stands out. Reminds me of trying to decode &lt;span style="color: rgb(192, 192, 192);"&gt;NAnt &lt;/span&gt;output
after living with &lt;span style="color: rgb(255, 0, 0);"&gt;M&lt;/span&gt;&lt;span style="color: rgb(128, 128, 128);"&gt;S&lt;/span&gt;&lt;span style="color: rgb(0, 0, 255);"&gt;Build&lt;/span&gt; for
a while. I did a quick search for &amp;quot;color consoletracelistener&amp;quot; and came
across &lt;a href="http://blogs.artinsoft.net/mrojas/archive/2006/05/29/1069.aspx"&gt;this
offering&lt;/a&gt; from Mauricio Rojas. I (probably unfairly) dimissed it because it looked
much more complicated than I would expect (ok, and because it was in VB). 
&lt;br /&gt;
So I spent 10 minutes throwing this together. It works for every scenario that I need.
In other words, I make no claims that it is general purpose solution for you - it
may not add color to every type of trace message (depending on which methods you use
to write messages). If this doesn't work for you, Mauricio's may be a better bet.&lt;br /&gt;
&lt;br /&gt;
&lt;!--
{\rtf1\ansi\ansicpg\lang1024\noproof1252\uc1 \deff0{\fonttbl{\f0\fnil\fcharset0\fprq1 Consolas;}}{\colortbl;\red0\green0\blue0;\red0\green0\blue255;\red0\green255\blue255;\red0\green255\blue0??;\red255\green0\blue255;\red255\green0\blue0;\red255\green255\blue0;\red255\green255\blue255;??\red0\green0\blue128;\red0\green128\blue128;\red0\green128\blue0;??\red128\green0\blue128;\red128\green0\blue0;\red128\green128\blue0;\red128\green128\blue128;??\red192\green192\blue192;}??\fs20 \cf2 using\cf0  System;\par ??\cf2 using\cf0  System.Diagnostics;\par ??\cf2 using\cf0  System.Collections.Generic;\par ??\par ??\cf2 namespace\cf0  FlimFlan.Diagnostics\par ??\{\par ??    \cf2 public\cf0  \cf2 class\cf0  \cf10 ColorConsoleTraceListener\cf0  : \cf10 ConsoleTraceListener\par ??\cf0     \{\par ??        \cf10 Dictionary\cf0 &amp;lt;\cf10 TraceEventType\cf0 , \cf10 ConsoleColor\cf0 &amp;gt; eventColor = \cf2 new\cf0  \cf10 Dictionary\cf0 &amp;lt;\cf10 TraceEventType\cf0 , \cf10 ConsoleColor\cf0 &amp;gt;();\par ??\par ??        \cf2 public\cf0  ColorConsoleTraceListener()\par ??        \{\par ??            eventColor.Add(\cf10 TraceEventType\cf0 .Verbose, \cf10 ConsoleColor\cf0 .DarkGray);\par ??            eventColor.Add(\cf10 TraceEventType\cf0 .Information, \cf10 ConsoleColor\cf0 .Gray);\par ??            eventColor.Add(\cf10 TraceEventType\cf0 .Warning, \cf10 ConsoleColor\cf0 .Yellow);\par ??            eventColor.Add(\cf10 TraceEventType\cf0 .Error, \cf10 ConsoleColor\cf0 .DarkRed);\par ??            eventColor.Add(\cf10 TraceEventType\cf0 .Critical, \cf10 ConsoleColor\cf0 .Red);\par ??            eventColor.Add(\cf10 TraceEventType\cf0 .Start, \cf10 ConsoleColor\cf0 .DarkCyan);\par ??            eventColor.Add(\cf10 TraceEventType\cf0 .Stop, \cf10 ConsoleColor\cf0 .DarkCyan);\par ??        \}\par ??\par ??        \cf2 public\cf0  \cf2 override\cf0  \cf2 void\cf0  TraceEvent(\cf10 TraceEventCache\cf0  eventCache, \cf2 string\cf0  source, \cf10 TraceEventType\cf0  eventType, \cf2 int\cf0  id, \cf2 string\cf0  message)\par ??        \{\par ??            TraceEvent(eventCache, source, eventType, id, \cf13 "\{0\}"\cf0 , message);\par ??        \}\par ??\par ??        \cf2 public\cf0  \cf2 override\cf0  \cf2 void\cf0  TraceEvent(\cf10 TraceEventCache\cf0  eventCache, \cf2 string\cf0  source, \cf10 TraceEventType\cf0  eventType, \cf2 int\cf0  id, \cf2 string\cf0  format, \cf2 params\cf0  \cf2 object\cf0 [] args)\par ??        \{\par ??            \cf10 ConsoleColor\cf0  originalColor = \cf10 Console\cf0 .ForegroundColor;\par ??            \cf10 Console\cf0 .ForegroundColor = getEventColor(eventType, originalColor);\par ??            \cf2 base\cf0 .TraceEvent(eventCache, source, eventType, id, format, args);\par ??            \cf10 Console\cf0 .ForegroundColor = originalColor;\par ??        \}\par ??\par ??        \cf2 private\cf0  \cf10 ConsoleColor\cf0  getEventColor(\cf10 TraceEventType\cf0  eventType, \cf10 ConsoleColor\cf0  defaultColor)\par ??        \{\par ??            \cf2 if\cf0  (eventColor.ContainsKey(eventType))\par ??            \{\par ??                \cf2 return\cf0  eventColor[eventType];\par ??            \}\par ??            \cf2 return\cf0  defaultColor;\par ??        \}\par ??    \}\par ??\}\par ??}
--&gt;
&lt;div style="background: white none repeat scroll 0% 50%; font-family: Consolas; font-size: 10pt; color: black; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial;"&gt;
&lt;p style="margin: 0px;"&gt;
&lt;span style="color: blue;"&gt;using&lt;/span&gt; System;
&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;
&lt;span style="color: blue;"&gt;using&lt;/span&gt; System.Diagnostics;
&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;
&lt;span style="color: blue;"&gt;using&lt;/span&gt; System.Collections.Generic;
&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;
&amp;nbsp;
&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;
&lt;span style="color: blue;"&gt;namespace&lt;/span&gt; FlimFlan.Diagnostics
&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;
{
&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;
&amp;nbsp; &amp;nbsp; &lt;span style="color: blue;"&gt;public&lt;/span&gt; &lt;span style="color: blue;"&gt;class&lt;/span&gt; &lt;span style="color: teal;"&gt;ColorConsoleTraceListener&lt;/span&gt; : &lt;span style="color: teal;"&gt;ConsoleTraceListener&lt;/span&gt;
&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;
&amp;nbsp; &amp;nbsp; {
&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="color: teal;"&gt;Dictionary&lt;/span&gt;&amp;lt;&lt;span style="color: teal;"&gt;TraceEventType&lt;/span&gt;, &lt;span style="color: teal;"&gt;ConsoleColor&lt;/span&gt;&amp;gt;
eventColor = &lt;span style="color: blue;"&gt;new&lt;/span&gt; &lt;span style="color: teal;"&gt;Dictionary&lt;/span&gt;&amp;lt;&lt;span style="color: teal;"&gt;TraceEventType&lt;/span&gt;, &lt;span style="color: teal;"&gt;ConsoleColor&lt;/span&gt;&amp;gt;();
&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;
&amp;nbsp;
&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="color: blue;"&gt;public&lt;/span&gt; ColorConsoleTraceListener()
&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; {
&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; eventColor.Add(&lt;span style="color: teal;"&gt;TraceEventType&lt;/span&gt;.Verbose, &lt;span style="color: teal;"&gt;ConsoleColor&lt;/span&gt;.DarkGray);
&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; eventColor.Add(&lt;span style="color: teal;"&gt;TraceEventType&lt;/span&gt;.Information, &lt;span style="color: teal;"&gt;ConsoleColor&lt;/span&gt;.Gray);
&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; eventColor.Add(&lt;span style="color: teal;"&gt;TraceEventType&lt;/span&gt;.Warning, &lt;span style="color: teal;"&gt;ConsoleColor&lt;/span&gt;.Yellow);
&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; eventColor.Add(&lt;span style="color: teal;"&gt;TraceEventType&lt;/span&gt;.Error, &lt;span style="color: teal;"&gt;ConsoleColor&lt;/span&gt;.DarkRed);
&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; eventColor.Add(&lt;span style="color: teal;"&gt;TraceEventType&lt;/span&gt;.Critical, &lt;span style="color: teal;"&gt;ConsoleColor&lt;/span&gt;.Red);
&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; eventColor.Add(&lt;span style="color: teal;"&gt;TraceEventType&lt;/span&gt;.Start, &lt;span style="color: teal;"&gt;ConsoleColor&lt;/span&gt;.DarkCyan);
&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; eventColor.Add(&lt;span style="color: teal;"&gt;TraceEventType&lt;/span&gt;.Stop, &lt;span style="color: teal;"&gt;ConsoleColor&lt;/span&gt;.DarkCyan);
&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; }
&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;
&amp;nbsp;
&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="color: blue;"&gt;public&lt;/span&gt; &lt;span style="color: blue;"&gt;override&lt;/span&gt; &lt;span style="color: blue;"&gt;void&lt;/span&gt; TraceEvent(&lt;span style="color: teal;"&gt;TraceEventCache&lt;/span&gt; eventCache, &lt;span style="color: blue;"&gt;string&lt;/span&gt; source, &lt;span style="color: teal;"&gt;TraceEventType&lt;/span&gt; eventType, &lt;span style="color: blue;"&gt;int&lt;/span&gt; id, &lt;span style="color: blue;"&gt;string&lt;/span&gt; message)
&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; {
&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; TraceEvent(eventCache, source, eventType,
id, &lt;span style="color: maroon;"&gt;&amp;quot;{0}&amp;quot;&lt;/span&gt;, message);
&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; }
&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;
&amp;nbsp;
&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="color: blue;"&gt;public&lt;/span&gt; &lt;span style="color: blue;"&gt;override&lt;/span&gt; &lt;span style="color: blue;"&gt;void&lt;/span&gt; TraceEvent(&lt;span style="color: teal;"&gt;TraceEventCache&lt;/span&gt; eventCache, &lt;span style="color: blue;"&gt;string&lt;/span&gt; source, &lt;span style="color: teal;"&gt;TraceEventType&lt;/span&gt; eventType, &lt;span style="color: blue;"&gt;int&lt;/span&gt; id, &lt;span style="color: blue;"&gt;string&lt;/span&gt; format, &lt;span style="color: blue;"&gt;params&lt;/span&gt; &lt;span style="color: blue;"&gt;object&lt;/span&gt;[]
args)
&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; {
&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="color: teal;"&gt;ConsoleColor&lt;/span&gt; originalColor
= &lt;span style="color: teal;"&gt;Console&lt;/span&gt;.ForegroundColor;
&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="color: teal;"&gt;Console&lt;/span&gt;.ForegroundColor
= getEventColor(eventType, originalColor);
&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="color: blue;"&gt;base&lt;/span&gt;.TraceEvent(eventCache,
source, eventType, id, format, args);
&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="color: teal;"&gt;Console&lt;/span&gt;.ForegroundColor
= originalColor;
&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; }
&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;
&amp;nbsp;
&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="color: blue;"&gt;private&lt;/span&gt; &lt;span style="color: teal;"&gt;ConsoleColor&lt;/span&gt; getEventColor(&lt;span style="color: teal;"&gt;TraceEventType&lt;/span&gt; eventType, &lt;span style="color: teal;"&gt;ConsoleColor&lt;/span&gt; defaultColor)
&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; {
&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="color: blue;"&gt;if&lt;/span&gt; (!eventColor.ContainsKey(eventType))
&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; {
&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="color: blue;"&gt;return&lt;/span&gt; defaultColor;
&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; }
&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="color: blue;"&gt;return&lt;/span&gt; eventColor[eventType];
&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; }
&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;
&amp;nbsp; &amp;nbsp; }
&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;
}
&lt;/p&gt;
&lt;/div&gt;
&lt;br /&gt;
You can see it in action using the following app:&lt;br /&gt;
&lt;br /&gt;
&lt;div style="background: white none repeat scroll 0%; font-family: Consolas; font-size: 10pt; color: black; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial;"&gt;
&lt;p style="margin: 0px;"&gt;
&lt;span style="color: blue;"&gt;using&lt;/span&gt; System.Diagnostics;
&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;
&lt;span style="color: blue;"&gt;namespace&lt;/span&gt; ConsoleApplication1
&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;
{
&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;
&amp;nbsp; &amp;nbsp; &lt;span style="color: blue;"&gt;class&lt;/span&gt; &lt;span style="color: teal;"&gt;Program&lt;/span&gt;
&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;
&amp;nbsp; &amp;nbsp; {
&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="color: blue;"&gt;static&lt;/span&gt; &lt;span style="color: blue;"&gt;void&lt;/span&gt; Main(&lt;span style="color: blue;"&gt;string&lt;/span&gt;[]
args)
&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; {
&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="color: teal;"&gt;TraceSource&lt;/span&gt; trace
= &lt;span style="color: blue;"&gt;new&lt;/span&gt; &lt;span style="color: teal;"&gt;TraceSource&lt;/span&gt;(&lt;span style="color: maroon;"&gt;&amp;quot;log&amp;quot;&lt;/span&gt;);
&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; trace.TraceEvent(&lt;span style="color: teal;"&gt;TraceEventType&lt;/span&gt;.Start,
0);
&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; trace.TraceInformation(&lt;span style="color: maroon;"&gt;&amp;quot;Hello
World&amp;quot;&lt;/span&gt;);
&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; trace.TraceEvent(&lt;span style="color: teal;"&gt;TraceEventType&lt;/span&gt;.Error,
0, &lt;span style="color: maroon;"&gt;&amp;quot;Something failed.&amp;quot;&lt;/span&gt;);
&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; trace.TraceEvent(&lt;span style="color: teal;"&gt;TraceEventType&lt;/span&gt;.Verbose,
0, &lt;span style="color: maroon;"&gt;&amp;quot;I like ice cream.&amp;quot;&lt;/span&gt;);
&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; trace.TraceEvent(&lt;span style="color: teal;"&gt;TraceEventType&lt;/span&gt;.Critical,
0, &lt;span style="color: maroon;"&gt;&amp;quot;Something went horribly wrong!&amp;quot;&lt;/span&gt;);
&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; trace.TraceEvent(&lt;span style="color: teal;"&gt;TraceEventType&lt;/span&gt;.Verbose,
0, &lt;span style="color: maroon;"&gt;&amp;quot;I like cherries.&amp;quot;&lt;/span&gt;);
&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; trace.TraceEvent(&lt;span style="color: teal;"&gt;TraceEventType&lt;/span&gt;.Warning,
0, &lt;span style="color: maroon;"&gt;&amp;quot;This program will end soon...&amp;quot;&lt;/span&gt;);
&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; trace.TraceEvent(&lt;span style="color: teal;"&gt;TraceEventType&lt;/span&gt;.Information,
0, &lt;span style="color: maroon;"&gt;&amp;quot;Ending program.&amp;quot;&lt;/span&gt;);
&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; trace.TraceEvent(&lt;span style="color: teal;"&gt;TraceEventType&lt;/span&gt;.Stop,
0);
&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; }
&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;
&amp;nbsp; &amp;nbsp; }
&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;
}
&lt;/p&gt;
&lt;/div&gt;
&lt;br /&gt;
Add these settings to the configuration section of your app.config:&lt;br /&gt;
&lt;br /&gt;
&lt;div style="background: white none repeat scroll 0%; font-family: Consolas; font-size: 10pt; color: black; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial;"&gt;
&lt;p style="margin: 0px;"&gt;
&lt;span style="color: blue;"&gt;&amp;nbsp; &amp;lt;&lt;/span&gt;&lt;span style="color: maroon;"&gt;system.diagnostics&lt;/span&gt;&lt;span style="color: blue;"&gt;&amp;gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;
&lt;span style="color: blue;"&gt;&amp;nbsp; &amp;nbsp; &amp;lt;&lt;/span&gt;&lt;span style="color: maroon;"&gt;sources&lt;/span&gt;&lt;span style="color: blue;"&gt;&amp;gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;
&lt;span style="color: blue;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;lt;&lt;/span&gt;&lt;span style="color: maroon;"&gt;source&lt;/span&gt;&lt;span style="color: blue;"&gt; &lt;/span&gt;&lt;span style="color: red;"&gt;name&lt;/span&gt;&lt;span style="color: blue;"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue;"&gt;log&lt;/span&gt;&amp;quot;&lt;span style="color: blue;"&gt; &lt;/span&gt;&lt;span style="color: red;"&gt;switchValue&lt;/span&gt;&lt;span style="color: blue;"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue;"&gt;All&lt;/span&gt;&amp;quot;&lt;span style="color: blue;"&gt;&amp;gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;
&lt;span style="color: blue;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;lt;&lt;/span&gt;&lt;span style="color: maroon;"&gt;listeners&lt;/span&gt;&lt;span style="color: blue;"&gt;&amp;gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;
&lt;span style="color: blue;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;lt;&lt;/span&gt;&lt;span style="color: maroon;"&gt;add&lt;/span&gt;&lt;span style="color: blue;"&gt; &lt;/span&gt;&lt;span style="color: red;"&gt;name&lt;/span&gt;&lt;span style="color: blue;"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue;"&gt;Console&lt;/span&gt;&amp;quot;&lt;span style="color: blue;"&gt; &lt;/span&gt;&lt;span style="color: red;"&gt;type&lt;/span&gt;&lt;span style="color: blue;"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue;"&gt;FlimFlan.Diagnostics.ColorConsoleTraceListener,
ConsoleApplication1&lt;/span&gt;&amp;quot;&lt;span style="color: blue;"&gt; /&amp;gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;
&lt;span style="color: blue;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;lt;/&lt;/span&gt;&lt;span style="color: maroon;"&gt;listeners&lt;/span&gt;&lt;span style="color: blue;"&gt;&amp;gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;
&lt;span style="color: blue;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;lt;/&lt;/span&gt;&lt;span style="color: maroon;"&gt;source&lt;/span&gt;&lt;span style="color: blue;"&gt;&amp;gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;
&lt;span style="color: blue;"&gt;&amp;nbsp; &amp;nbsp; &amp;lt;/&lt;/span&gt;&lt;span style="color: maroon;"&gt;sources&lt;/span&gt;&lt;span style="color: blue;"&gt;&amp;gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;
&lt;span style="color: blue;"&gt;&amp;nbsp; &amp;lt;/&lt;/span&gt;&lt;span style="color: maroon;"&gt;system.diagnostics&lt;/span&gt;&lt;span style="color: blue;"&gt;&amp;gt;&lt;/span&gt;
&lt;/p&gt;
&lt;/div&gt;
&lt;br /&gt;
And you should see something like this:&lt;br /&gt;
&lt;br /&gt;
&lt;img src="file:///C:/DOCUME~1/Josh/LOCALS~1/Temp/moz-screenshot.jpg" alt="" /&gt;&lt;img border="0" src="http://flimflan.com/blog/content/binary/ColorConsoleTraceListenerOutput.png" alt="" /&gt;&lt;img width="0" height="0" src="http://flimflan.com/blog/aggbug.ashx?id=e7597cd9-6f4c-4ca5-bf15-fd4223fe5ab0" /&gt;</description>
      <comments>http://flimflan.com/blog/CommentView,guid,e7597cd9-6f4c-4ca5-bf15-fd4223fe5ab0.aspx</comments>
      <category>.NET</category>
    </item>
    <item>
      <trackback:ping>http://flimflan.com/blog/Trackback.aspx?guid=f7354ebb-9d2f-43a4-8b5d-4795e3046f4c</trackback:ping>
      <pingback:server>http://flimflan.com/blog/pingback.aspx</pingback:server>
      <pingback:target>http://flimflan.com/blog/PermaLink,guid,f7354ebb-9d2f-43a4-8b5d-4795e3046f4c.aspx</pingback:target>
      <dc:creator>
      </dc:creator>
      <wfw:comment>http://flimflan.com/blog/CommentView,guid,f7354ebb-9d2f-43a4-8b5d-4795e3046f4c.aspx</wfw:comment>
      <wfw:commentRss>http://flimflan.com/blog/SyndicationService.asmx/GetEntryCommentsRss?guid=f7354ebb-9d2f-43a4-8b5d-4795e3046f4c</wfw:commentRss>
      <slash:comments>1</slash:comments>
      <body xmlns="http://www.w3.org/1999/xhtml">By far, the most common feature request
for my <a href="http://flimflan.com/blog/ProfileView.aspx">ProfileView</a> control
was the ability to edit the profile of any user in the system. Until now, the control
could only be used by the current user to edit their own profile. I thought it was
a limitation of the Profile provider framework, until I discovered ProfileBase.Create().
I apologize to everyone that has been waiting for this much needed feature for so
long.<br /><br />
Just set the UserName property on the control to edit a different user. The property
is null by default, which loads the current user.<br /><br />
Example usage in a WebForm used to edit a profile:<br /><br /><!--
{\rtf1\ansi\ansicpg\lang1024\noproof1252\uc1 \deff0{\fonttbl{\f0\fnil\fcharset0\fprq1 Consolas;}}{\colortbl;\red0\green0\blue0;\red0\green0\blue255;\red0\green255\blue255;\red0\green255\blue0??;\red255\green0\blue255;\red255\green0\blue0;\red255\green255\blue0;\red255\green255\blue255;??\red0\green0\blue128;\red0\green128\blue128;\red0\green128\blue0;??\red128\green0\blue128;\red128\green0\blue0;\red128\green128\blue0;\red128\green128\blue128;??\red192\green192\blue192;}??\fs20     \cf2 protected\cf0  \cf2 void\cf0  Page_Load(\cf2 object\cf0  sender, \cf10 EventArgs\cf0  e)\par ??    \{\par ??        \cf2 if\cf0  (!Page.IsPostBack)\par ??        \{\par ??            \cf2 string\cf0  userName = Request.QueryString[\cf13 "username"\cf0 ];\par ??            \cf2 if\cf0  (!\cf10 String\cf0 .IsNullOrEmpty(userName))\par ??            \{\par ??                ProfileView1.UserName = userName;\par ??            \}\par ??        \}\par ??    \}}
--><div style="background: white none repeat scroll 0%; font-family: Consolas; font-size: 10pt; color: black; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial;"><p style="margin: 0px;">
    <span style="color: blue;">protected</span><span style="color: blue;">void</span> Page_Load(<span style="color: blue;">object</span> sender, <span style="color: teal;">EventArgs</span> e)
</p><p style="margin: 0px;">
    {
</p><p style="margin: 0px;">
        <span style="color: blue;">if</span> (!Page.IsPostBack)
</p><p style="margin: 0px;">
        {
</p><p style="margin: 0px;">
            <span style="color: blue;">string</span> userName
= Request.QueryString[<span style="color: maroon;">"username"</span>];
</p><p style="margin: 0px;">
            <span style="color: blue;">if</span> (!<span style="color: teal;">String</span>.IsNullOrEmpty(userName))
</p><p style="margin: 0px;">
            {
</p><p style="margin: 0px;">
                ProfileView1.UserName = userName;
</p><p style="margin: 0px;">
            }
</p><p style="margin: 0px;">
        }
</p><p style="margin: 0px;">
    }
</p></div><br /><br />
Download the latest code from the <a href="http://flimflan.com/blog/ProfileView.aspx">ProfileView</a> project
page.<img width="0" height="0" src="http://flimflan.com/blog/aggbug.ashx?id=f7354ebb-9d2f-43a4-8b5d-4795e3046f4c" /></body>
      <title>ProfileView can now be used for user administration</title>
      <guid isPermaLink="false">http://flimflan.com/blog/PermaLink,guid,f7354ebb-9d2f-43a4-8b5d-4795e3046f4c.aspx</guid>
      <link>http://flimflan.com/blog/ProfileViewCanNowBeUsedForUserAdministration.aspx</link>
      <pubDate>Sat, 24 Jun 2006 16:47:41 GMT</pubDate>
      <description>By far, the most common feature request for my &lt;a href="http://flimflan.com/blog/ProfileView.aspx"&gt;ProfileView&lt;/a&gt; control
was the ability to edit the profile of any user in the system. Until now, the control
could only be used by the current user to edit their own profile. I thought it was
a limitation of the Profile provider framework, until I discovered ProfileBase.Create().
I apologize to everyone that has been waiting for this much needed feature for so
long.&lt;br /&gt;
&lt;br /&gt;
Just set the UserName property on the control to edit a different user. The property
is null by default, which loads the current user.&lt;br /&gt;
&lt;br /&gt;
Example usage in a WebForm used to edit a profile:&lt;br /&gt;
&lt;br /&gt;
&lt;!--
{\rtf1\ansi\ansicpg\lang1024\noproof1252\uc1 \deff0{\fonttbl{\f0\fnil\fcharset0\fprq1 Consolas;}}{\colortbl;\red0\green0\blue0;\red0\green0\blue255;\red0\green255\blue255;\red0\green255\blue0??;\red255\green0\blue255;\red255\green0\blue0;\red255\green255\blue0;\red255\green255\blue255;??\red0\green0\blue128;\red0\green128\blue128;\red0\green128\blue0;??\red128\green0\blue128;\red128\green0\blue0;\red128\green128\blue0;\red128\green128\blue128;??\red192\green192\blue192;}??\fs20     \cf2 protected\cf0  \cf2 void\cf0  Page_Load(\cf2 object\cf0  sender, \cf10 EventArgs\cf0  e)\par ??    \{\par ??        \cf2 if\cf0  (!Page.IsPostBack)\par ??        \{\par ??            \cf2 string\cf0  userName = Request.QueryString[\cf13 "username"\cf0 ];\par ??            \cf2 if\cf0  (!\cf10 String\cf0 .IsNullOrEmpty(userName))\par ??            \{\par ??                ProfileView1.UserName = userName;\par ??            \}\par ??        \}\par ??    \}}
--&gt;
&lt;div style="background: white none repeat scroll 0%; font-family: Consolas; font-size: 10pt; color: black; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial;"&gt;
&lt;p style="margin: 0px;"&gt;
&amp;nbsp; &amp;nbsp; &lt;span style="color: blue;"&gt;protected&lt;/span&gt; &lt;span style="color: blue;"&gt;void&lt;/span&gt; Page_Load(&lt;span style="color: blue;"&gt;object&lt;/span&gt; sender, &lt;span style="color: teal;"&gt;EventArgs&lt;/span&gt; e)
&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;
&amp;nbsp; &amp;nbsp; {
&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="color: blue;"&gt;if&lt;/span&gt; (!Page.IsPostBack)
&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; {
&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="color: blue;"&gt;string&lt;/span&gt; userName
= Request.QueryString[&lt;span style="color: maroon;"&gt;&amp;quot;username&amp;quot;&lt;/span&gt;];
&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="color: blue;"&gt;if&lt;/span&gt; (!&lt;span style="color: teal;"&gt;String&lt;/span&gt;.IsNullOrEmpty(userName))
&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; {
&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; ProfileView1.UserName = userName;
&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; }
&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; }
&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;
&amp;nbsp; &amp;nbsp; }
&lt;/p&gt;
&lt;/div&gt;
&lt;br /&gt;
&lt;br /&gt;
Download the latest code from the &lt;a href="http://flimflan.com/blog/ProfileView.aspx"&gt;ProfileView&lt;/a&gt; project
page.&lt;img width="0" height="0" src="http://flimflan.com/blog/aggbug.ashx?id=f7354ebb-9d2f-43a4-8b5d-4795e3046f4c" /&gt;</description>
      <comments>http://flimflan.com/blog/CommentView,guid,f7354ebb-9d2f-43a4-8b5d-4795e3046f4c.aspx</comments>
      <category>.NET</category>
      <category>ProfileView</category>
    </item>
    <item>
      <trackback:ping>http://flimflan.com/blog/Trackback.aspx?guid=b50b7d3a-d81d-462e-aece-72298bce00e2</trackback:ping>
      <pingback:server>http://flimflan.com/blog/pingback.aspx</pingback:server>
      <pingback:target>http://flimflan.com/blog/PermaLink,guid,b50b7d3a-d81d-462e-aece-72298bce00e2.aspx</pingback:target>
      <dc:creator>
      </dc:creator>
      <wfw:comment>http://flimflan.com/blog/CommentView,guid,b50b7d3a-d81d-462e-aece-72298bce00e2.aspx</wfw:comment>
      <wfw:commentRss>http://flimflan.com/blog/SyndicationService.asmx/GetEntryCommentsRss?guid=b50b7d3a-d81d-462e-aece-72298bce00e2</wfw:commentRss>
      <slash:comments>3</slash:comments>
      <body xmlns="http://www.w3.org/1999/xhtml">The .NET Framework 2.0 no longer allows
background threads to die silently when an unhandled exception is thrown. I'm not
going to dive into the details of the change, as it is already well-documented on
the web (<a href="http://www.julmar.com/blog/mark/PermaLink,guid,f733e261-5d39-4ca1-be1a-c422f3cf1f1b.aspx">this
post describes the behavior for different application types</a> &amp; <a href="http://odetocode.com/Blogs/scott/archive/2005/12/14/2618.aspx">Scott
Allen focuses on the ASP.NET impact</a>).<br /><br /><span style="font-weight: bold;">The impact is more significant for ASP.NET applications</span><br />
I think this is actually a bigger change for ASP.NET apps, because it has always had
a "safety net". In console/WinForms applications, if there is an unhandled
exception on the <span style="font-style: italic;">primary </span>thread, the application
dies. Having your application die now because of an unhandled exception on a <span style="font-style: italic;">background </span>thread
is not that big of a difference. You have an unhandled exception in your application,
the application dies. Consistent.<br /><br />
However, in ASP.NET, exceptions that you did not handle in your own code on the <span style="font-style: italic;">primary </span>thread
were always caught by a default handler (affectionately known as the "<a href="http://en.wikipedia.org/wiki/Yellow_screen_of_death">yellow
screen of death</a>"). Your application did not die. You could add a handler
for the HttpApplication.Error event (Application_Error in global.asax) to centralize
your exception handling and logging logic. In 1.x, exceptions that occurred on a background
thread would die silently. Your application did not die. Consistent. But now, in 2.0,
exceptions on your primary thread still do not kill your application, and can be logged
by your global handler. But exceptions on your background threads will kill your application,
and will not be logged.<br /><br /><span style="font-weight: bold;">My approach to exception handling and how it is now
more difficult to implement</span><br />
My philosophy is to never catch exceptions unless there is something I can do to address
the issue. I prefer not to catch all possible exceptions throughout the internals
of my code, and instead rely on try...finally blocks to clean up in case of an exception,
and allow the exception to bubble up to a top-level handler where it can be logged
(of course I catch exceptions when there is something the code can do to resolve the
issue or continue in a known state).<br /><br />
The new background thread exception behavior forces me to create "top level handler
and logging" code for the application (global.asax) AND within every method that
I run on a background thread. I end up with a lot of duplicate code, and explicit
exception handling and logging that I would prefer to be hidden behind the scenes
instead of cluttering up my application logic.<br /><br /><span style="font-weight: bold;">A proposed solution</span><br />
My goals:<br /><ul><li>
Allow unexpected exceptions on all threads to be logged by a top level exception handler</li><li>
Do not let the application die because of an exception, no matter which thread it
is running on (at least not before I get a chance to log it).</li><li>
Do not clutter the application logic with repeated try..catch and logging code.</li></ul>
To satisfy the top level exception handler goal, I would like to make use of the existing
HttpApplication.Error / Application_Error mechanism. That means I need to somehow
transfer the exception that occurred on a background thread to a primary ASP.NET thread.
To satisfy the "do not die" and "do not clutter" goals, I need
to wrap all calls to background thread methods with a single piece of code.<br /><br />
I've created the <span style="font-family: 'courier new',courier; font-size: x-small;">SafeWaitCallback </span>class.
It's <span style="font-family: 'courier new',courier; font-size: x-small;">Call </span>method
is used in place of a <span style="font-family: 'courier new',courier; font-size: x-small;">WaitCallback </span>delegate.
For example, if I want to execute the method <span style="font-family: 'courier new',courier; font-size: x-small;">DoTask </span>on
a background thread, I would call it like this:<br /><p><span style="color: Black; background-color: transparent; font-family: Courier New; font-size: 11px;">System.Threading.ThreadPool.QueueUserWorkItem(<span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;">new</span> SafeWaitCallback().Call(DoTask));</span></p>
SafeWaitCallback does two things: it wraps calls to the target method in a try...catch
block, and it forwards the caught exception to a custom HttpHandler. It forwards the
exception by serializing it to a byte array, and then POSTing it to the handler, which
will receive the bytes and deserialize back to an Exception object.<br /><br /><p><span style="color: Black; background-color: transparent; font-family: Courier New; font-size: 11px;"><span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;">using</span> System;<br /><span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;">using</span> System.Net;<br /><span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;">using</span> System.IO;<br /><span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;">using</span> System.Runtime.Serialization.Formatters.Binary;<br /><span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;">using</span> System.Runtime.Serialization;<br /><br /><span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;">public</span><span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;">class</span> SafeWaitCallback
{<br />
  <span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;">public</span><span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;">static</span> Uri
ApplicationUri;<br />
  System.Threading.WaitCallback callback;<br /><br />
  <span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;">public</span> System.Threading.WaitCallback
Call(System.Threading.WaitCallback callback) {<br />
    <span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;">this</span>.callback <span style="color: Red; background-color: transparent; font-family: Courier New; font-size: 11px;">=</span> callback;<br />
    <span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;">return</span> CallbackWrapper;<br />
  }<br /><br />
  <span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;">private</span><span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;">void</span> CallbackWrapper(<span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;">object</span> state)
{<br />
    <span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;">try</span><br />
    {<br />
      callback(state);<br />
    }<br />
    <span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;">catch</span> (Exception
e)<br />
    {<br />
      <span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;">byte</span>[]
exceptionData;<br /><br />
      MemoryStream stream <span style="color: Red; background-color: transparent; font-family: Courier New; font-size: 11px;">=</span><span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;">new</span> MemoryStream();<br />
      BinaryFormatter formatter <span style="color: Red; background-color: transparent; font-family: Courier New; font-size: 11px;">=</span><span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;">new</span> BinaryFormatter(<span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;">null</span>, <span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;">new</span> StreamingContext(StreamingContextStates.Persistence));<br />
      formatter.Serialize(stream, e);<br />
      exceptionData <span style="color: Red; background-color: transparent; font-family: Courier New; font-size: 11px;">=</span> stream.ToArray();<br /><br />
      WebClient client <span style="color: Red; background-color: transparent; font-family: Courier New; font-size: 11px;">=</span><span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;">new</span> WebClient();<br />
      Uri handler <span style="color: Red; background-color: transparent; font-family: Courier New; font-size: 11px;">=</span><span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;">new</span> Uri(ApplicationUri, <span style="color: rgb(102, 102, 102); background-color: rgb(228, 228, 228); font-family: Courier New; font-size: 11px;">"TransferException.axd"</span>);<br />
      <span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;">try</span><br />
      {<br />
        client.UploadData(handler, exceptionData);<br />
      }<br />
      <span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;">catch</span> (WebException)
{ }<br />
    }<br />
  }<br />
}<br /></span></p>
By forwarding the exception to the custom HttpHandler, I can re-raise the exception,
and since the handler will be running on a primary ASP.NET thread (not in the background),
the exception will be caught by my global handler, and logged just like any other
exception.<br /><p><span style="color: Black; background-color: transparent; font-family: Courier New; font-size: 11px;"><span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;">using</span> System;<br /><span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;">using</span> System.Web;<br /><span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;">using</span> System.IO;<br /><span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;">using</span> System.Runtime.Serialization.Formatters.Binary;<br /><span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;">using</span> System.Runtime.Serialization;<br /><br /><span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;">public</span><span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;">class</span> TransferredExceptionHandler
: IHttpHandler {<br />
  <span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;">public</span><span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;">bool</span> IsReusable
{ get { <span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;">return</span><span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;">true</span>;
}}<br /><br />
  <span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;">public</span><span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;">void</span> ProcessRequest(HttpContext
context) {<br />
    <span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;">byte</span>[]
exceptionData <span style="color: Red; background-color: transparent; font-family: Courier New; font-size: 11px;">=</span><span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;">new</span><span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;">byte</span>[context.Request.ContentLength];<br />
    context.Request.InputStream.Read(exceptionData, 0, exceptionData.Length);<br /><br />
    Exception transferredException;<br />
    MemoryStream stream <span style="color: Red; background-color: transparent; font-family: Courier New; font-size: 11px;">=</span><span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;">new</span> MemoryStream(exceptionData);<br />
    BinaryFormatter formatter <span style="color: Red; background-color: transparent; font-family: Courier New; font-size: 11px;">=</span><span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;">new</span> BinaryFormatter(<span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;">null</span>, <span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;">new</span> StreamingContext(StreamingContextStates.Persistence));<br />
    transferredException <span style="color: Red; background-color: transparent; font-family: Courier New; font-size: 11px;">=</span> (Exception)formatter.Deserialize(stream);<br />
    <span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;">throw</span><span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;">new</span> Exception(<span style="color: rgb(102, 102, 102); background-color: rgb(228, 228, 228); font-family: Courier New; font-size: 11px;">"[Background
exception transferred - see InnerException]"</span>, transferredException);<br />
  }<br />
}</span></p>
The handler is registered in web.config with the following entry:<br />
      &lt;httpHandlers&gt;<br />
        &lt;add verb="POST" path="TransferException.axd"
type="TransferredExceptionHandler" /&gt;<br />
      &lt;/httpHandlers&gt;<br /><br /><span style="font-weight: bold;">Let me know what you think</span><br />
I've attached the full source code in the form of a Web Site project. It includes
a Default.aspx page which demonstrates the different scenarios of an unhandled exception
(primary thread, background thread, "safe" background thread using my new
code).<br /><br />
This is <span style="font-style: italic;">not</span> production ready code, it is
still in the proof of concept stage. For one, it probably needs better exception handling
within the CallbackWrapper exception handler (what if the serialization blows up?).
More importantly, I'm not yet convinced this whole idea is a worthwhile approach.
It meets my goals, but it feels a little hackish. I wanted to see if it was possible,
and then throw it out there to get some feedback. Anyone see any major flaws in the
concept? Even better, does anyone know of a more elegant approach to achieve the same
goals?<br /><p><a href="http://flimflan.com/blog/content/binary/AspNetBackgroundExceptions.zip">Download
AspNetBackgroundExceptions.zip (2.55 KB)</a></p><img width="0" height="0" src="http://flimflan.com/blog/aggbug.ashx?id=b50b7d3a-d81d-462e-aece-72298bce00e2" /></body>
      <title>Safely running background threads in ASP.NET 2.0</title>
      <guid isPermaLink="false">http://flimflan.com/blog/PermaLink,guid,b50b7d3a-d81d-462e-aece-72298bce00e2.aspx</guid>
      <link>http://flimflan.com/blog/SafelyRunningBackgroundThreadsInASPNET20.aspx</link>
      <pubDate>Thu, 22 Jun 2006 02:50:02 GMT</pubDate>
      <description>The .NET Framework 2.0 no longer allows background threads to die silently when an unhandled exception is thrown. I'm not going to dive into the details of the change, as it is already well-documented on the web (&lt;a href="http://www.julmar.com/blog/mark/PermaLink,guid,f733e261-5d39-4ca1-be1a-c422f3cf1f1b.aspx"&gt;this
post describes the behavior for different application types&lt;/a&gt; &amp;amp; &lt;a href="http://odetocode.com/Blogs/scott/archive/2005/12/14/2618.aspx"&gt;Scott
Allen focuses on the ASP.NET impact&lt;/a&gt;).&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-weight: bold;"&gt;The impact is more significant for ASP.NET applications&lt;/span&gt;
&lt;br /&gt;
I think this is actually a bigger change for ASP.NET apps, because it has always had
a &amp;quot;safety net&amp;quot;. In console/WinForms applications, if there is an unhandled
exception on the &lt;span style="font-style: italic;"&gt;primary &lt;/span&gt;thread, the application
dies. Having your application die now because of an unhandled exception on a &lt;span style="font-style: italic;"&gt;background &lt;/span&gt;thread
is not that big of a difference. You have an unhandled exception in your application,
the application dies. Consistent.&lt;br /&gt;
&lt;br /&gt;
However, in ASP.NET, exceptions that you did not handle in your own code on the &lt;span style="font-style: italic;"&gt;primary &lt;/span&gt;thread
were always caught by a default handler (affectionately known as the &amp;quot;&lt;a href="http://en.wikipedia.org/wiki/Yellow_screen_of_death"&gt;yellow
screen of death&lt;/a&gt;&amp;quot;). Your application did not die. You could add a handler
for the HttpApplication.Error event (Application_Error in global.asax) to centralize
your exception handling and logging logic. In 1.x, exceptions that occurred on a background
thread would die silently. Your application did not die. Consistent. But now, in 2.0,
exceptions on your primary thread still do not kill your application, and can be logged
by your global handler. But exceptions on your background threads will kill your application,
and will not be logged.&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-weight: bold;"&gt;My approach to exception handling and how it is now
more difficult to implement&lt;/span&gt;
&lt;br /&gt;
My philosophy is to never catch exceptions unless there is something I can do to address
the issue. I prefer not to catch all possible exceptions throughout the internals
of my code, and instead rely on try...finally blocks to clean up in case of an exception,
and allow the exception to bubble up to a top-level handler where it can be logged
(of course I catch exceptions when there is something the code can do to resolve the
issue or continue in a known state).&lt;br /&gt;
&lt;br /&gt;
The new background thread exception behavior forces me to create &amp;quot;top level handler
and logging&amp;quot; code for the application (global.asax) AND within every method that
I run on a background thread. I end up with a lot of duplicate code, and explicit
exception handling and logging that I would prefer to be hidden behind the scenes
instead of cluttering up my application logic.&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-weight: bold;"&gt;A proposed solution&lt;/span&gt;
&lt;br /&gt;
My goals:&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;
Allow unexpected exceptions on all threads to be logged by a top level exception handler&lt;/li&gt;
&lt;li&gt;
Do not let the application die because of an exception, no matter which thread it
is running on (at least not before I get a chance to log it).&lt;/li&gt;
&lt;li&gt;
Do not clutter the application logic with repeated try..catch and logging code.&lt;/li&gt;
&lt;/ul&gt;
To satisfy the top level exception handler goal, I would like to make use of the existing
HttpApplication.Error / Application_Error mechanism. That means I need to somehow
transfer the exception that occurred on a background thread to a primary ASP.NET thread.
To satisfy the &amp;quot;do not die&amp;quot; and &amp;quot;do not clutter&amp;quot; goals, I need
to wrap all calls to background thread methods with a single piece of code.&lt;br /&gt;
&lt;br /&gt;
I've created the &lt;span style="font-family: 'courier new',courier; font-size: x-small;"&gt;SafeWaitCallback &lt;/span&gt;class.
It's &lt;span style="font-family: 'courier new',courier; font-size: x-small;"&gt;Call &lt;/span&gt;method
is used in place of a &lt;span style="font-family: 'courier new',courier; font-size: x-small;"&gt;WaitCallback &lt;/span&gt;delegate.
For example, if I want to execute the method &lt;span style="font-family: 'courier new',courier; font-size: x-small;"&gt;DoTask &lt;/span&gt;on
a background thread, I would call it like this:&lt;br /&gt;
&lt;p&gt;
&lt;span style="color: Black; background-color: transparent; font-family: Courier New; font-size: 11px;"&gt;System.Threading.ThreadPool.QueueUserWorkItem(&lt;span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;"&gt;new&lt;/span&gt; SafeWaitCallback().Call(DoTask));&lt;/span&gt;
&lt;/p&gt;
SafeWaitCallback does two things: it wraps calls to the target method in a try...catch
block, and it forwards the caught exception to a custom HttpHandler. It forwards the
exception by serializing it to a byte array, and then POSTing it to the handler, which
will receive the bytes and deserialize back to an Exception object.&lt;br /&gt;
&lt;br /&gt;
&lt;p&gt;
&lt;span style="color: Black; background-color: transparent; font-family: Courier New; font-size: 11px;"&gt;&lt;span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;"&gt;using&lt;/span&gt; System;&lt;br /&gt;
&lt;span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;"&gt;using&lt;/span&gt; System.Net;&lt;br /&gt;
&lt;span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;"&gt;using&lt;/span&gt; System.IO;&lt;br /&gt;
&lt;span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;"&gt;using&lt;/span&gt; System.Runtime.Serialization.Formatters.Binary;&lt;br /&gt;
&lt;span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;"&gt;using&lt;/span&gt; System.Runtime.Serialization;&lt;br /&gt;
&lt;br /&gt;
&lt;span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;"&gt;public&lt;/span&gt; &lt;span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;"&gt;class&lt;/span&gt; SafeWaitCallback
{&lt;br /&gt;
&amp;nbsp; &lt;span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;"&gt;public&lt;/span&gt; &lt;span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;"&gt;static&lt;/span&gt; Uri
ApplicationUri;&lt;br /&gt;
&amp;nbsp; System.Threading.WaitCallback callback;&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; &lt;span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;"&gt;public&lt;/span&gt; System.Threading.WaitCallback
Call(System.Threading.WaitCallback callback) {&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;"&gt;this&lt;/span&gt;.callback &lt;span style="color: Red; background-color: transparent; font-family: Courier New; font-size: 11px;"&gt;=&lt;/span&gt; callback;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;"&gt;return&lt;/span&gt; CallbackWrapper;&lt;br /&gt;
&amp;nbsp; }&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; &lt;span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;"&gt;private&lt;/span&gt; &lt;span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;"&gt;void&lt;/span&gt; CallbackWrapper(&lt;span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;"&gt;object&lt;/span&gt; state)
{&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;"&gt;try&lt;/span&gt;
&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; callback(state);&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;"&gt;catch&lt;/span&gt; (Exception
e)&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;"&gt;byte&lt;/span&gt;[]
exceptionData;&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; MemoryStream stream &lt;span style="color: Red; background-color: transparent; font-family: Courier New; font-size: 11px;"&gt;=&lt;/span&gt; &lt;span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;"&gt;new&lt;/span&gt; MemoryStream();&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; BinaryFormatter formatter &lt;span style="color: Red; background-color: transparent; font-family: Courier New; font-size: 11px;"&gt;=&lt;/span&gt; &lt;span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;"&gt;new&lt;/span&gt; BinaryFormatter(&lt;span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;"&gt;null&lt;/span&gt;, &lt;span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;"&gt;new&lt;/span&gt; StreamingContext(StreamingContextStates.Persistence));&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; formatter.Serialize(stream, e);&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; exceptionData &lt;span style="color: Red; background-color: transparent; font-family: Courier New; font-size: 11px;"&gt;=&lt;/span&gt; stream.ToArray();&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; WebClient client &lt;span style="color: Red; background-color: transparent; font-family: Courier New; font-size: 11px;"&gt;=&lt;/span&gt; &lt;span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;"&gt;new&lt;/span&gt; WebClient();&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Uri handler &lt;span style="color: Red; background-color: transparent; font-family: Courier New; font-size: 11px;"&gt;=&lt;/span&gt; &lt;span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;"&gt;new&lt;/span&gt; Uri(ApplicationUri, &lt;span style="color: rgb(102, 102, 102); background-color: rgb(228, 228, 228); font-family: Courier New; font-size: 11px;"&gt;&amp;quot;TransferException.axd&amp;quot;&lt;/span&gt;);&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;"&gt;try&lt;/span&gt;
&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; client.UploadData(handler, exceptionData);&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;"&gt;catch&lt;/span&gt; (WebException)
{ }&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;
&amp;nbsp; }&lt;br /&gt;
}&lt;br /&gt;
&lt;/span&gt;
&lt;/p&gt;
By forwarding the exception to the custom HttpHandler, I can re-raise the exception,
and since the handler will be running on a primary ASP.NET thread (not in the background),
the exception will be caught by my global handler, and logged just like any other
exception.&lt;br /&gt;
&lt;p&gt;
&lt;span style="color: Black; background-color: transparent; font-family: Courier New; font-size: 11px;"&gt;&lt;span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;"&gt;using&lt;/span&gt; System;&lt;br /&gt;
&lt;span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;"&gt;using&lt;/span&gt; System.Web;&lt;br /&gt;
&lt;span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;"&gt;using&lt;/span&gt; System.IO;&lt;br /&gt;
&lt;span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;"&gt;using&lt;/span&gt; System.Runtime.Serialization.Formatters.Binary;&lt;br /&gt;
&lt;span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;"&gt;using&lt;/span&gt; System.Runtime.Serialization;&lt;br /&gt;
&lt;br /&gt;
&lt;span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;"&gt;public&lt;/span&gt; &lt;span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;"&gt;class&lt;/span&gt; TransferredExceptionHandler
: IHttpHandler {&lt;br /&gt;
&amp;nbsp; &lt;span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;"&gt;public&lt;/span&gt; &lt;span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;"&gt;bool&lt;/span&gt; IsReusable
{ get { &lt;span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;"&gt;return&lt;/span&gt; &lt;span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;"&gt;true&lt;/span&gt;;
}}&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; &lt;span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;"&gt;public&lt;/span&gt; &lt;span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;"&gt;void&lt;/span&gt; ProcessRequest(HttpContext
context) {&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;"&gt;byte&lt;/span&gt;[]
exceptionData &lt;span style="color: Red; background-color: transparent; font-family: Courier New; font-size: 11px;"&gt;=&lt;/span&gt; &lt;span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;"&gt;new&lt;/span&gt; &lt;span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;"&gt;byte&lt;/span&gt;[context.Request.ContentLength];&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; context.Request.InputStream.Read(exceptionData, 0, exceptionData.Length);&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; Exception transferredException;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; MemoryStream stream &lt;span style="color: Red; background-color: transparent; font-family: Courier New; font-size: 11px;"&gt;=&lt;/span&gt; &lt;span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;"&gt;new&lt;/span&gt; MemoryStream(exceptionData);&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; BinaryFormatter formatter &lt;span style="color: Red; background-color: transparent; font-family: Courier New; font-size: 11px;"&gt;=&lt;/span&gt; &lt;span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;"&gt;new&lt;/span&gt; BinaryFormatter(&lt;span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;"&gt;null&lt;/span&gt;, &lt;span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;"&gt;new&lt;/span&gt; StreamingContext(StreamingContextStates.Persistence));&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; transferredException &lt;span style="color: Red; background-color: transparent; font-family: Courier New; font-size: 11px;"&gt;=&lt;/span&gt; (Exception)formatter.Deserialize(stream);&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;"&gt;throw&lt;/span&gt; &lt;span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;"&gt;new&lt;/span&gt; Exception(&lt;span style="color: rgb(102, 102, 102); background-color: rgb(228, 228, 228); font-family: Courier New; font-size: 11px;"&gt;&amp;quot;[Background
exception transferred - see InnerException]&amp;quot;&lt;/span&gt;, transferredException);&lt;br /&gt;
&amp;nbsp; }&lt;br /&gt;
}&lt;/span&gt;
&lt;/p&gt;
The handler is registered in web.config with the following entry:&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;httpHandlers&amp;gt;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;add verb=&amp;quot;POST&amp;quot; path=&amp;quot;TransferException.axd&amp;quot;
type=&amp;quot;TransferredExceptionHandler&amp;quot; /&amp;gt;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/httpHandlers&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-weight: bold;"&gt;Let me know what you think&lt;/span&gt;
&lt;br /&gt;
I've attached the full source code in the form of a Web Site project. It includes
a Default.aspx page which demonstrates the different scenarios of an unhandled exception
(primary thread, background thread, &amp;quot;safe&amp;quot; background thread using my new
code).&lt;br /&gt;
&lt;br /&gt;
This is &lt;span style="font-style: italic;"&gt;not&lt;/span&gt; production ready code, it is
still in the proof of concept stage. For one, it probably needs better exception handling
within the CallbackWrapper exception handler (what if the serialization blows up?).
More importantly, I'm not yet convinced this whole idea is a worthwhile approach.
It meets my goals, but it feels a little hackish. I wanted to see if it was possible,
and then throw it out there to get some feedback. Anyone see any major flaws in the
concept? Even better, does anyone know of a more elegant approach to achieve the same
goals?&lt;br /&gt;
&lt;p&gt;
&lt;a href="http://flimflan.com/blog/content/binary/AspNetBackgroundExceptions.zip"&gt;Download
AspNetBackgroundExceptions.zip (2.55 KB)&lt;/a&gt;
&lt;/p&gt;
&lt;img width="0" height="0" src="http://flimflan.com/blog/aggbug.ashx?id=b50b7d3a-d81d-462e-aece-72298bce00e2" /&gt;</description>
      <comments>http://flimflan.com/blog/CommentView,guid,b50b7d3a-d81d-462e-aece-72298bce00e2.aspx</comments>
      <category>.NET</category>
    </item>
    <item>
      <trackback:ping>http://flimflan.com/blog/Trackback.aspx?guid=03712e05-6bfe-4fc5-93f5-86b9856bba84</trackback:ping>
      <pingback:server>http://flimflan.com/blog/pingback.aspx</pingback:server>
      <pingback:target>http://flimflan.com/blog/PermaLink,guid,03712e05-6bfe-4fc5-93f5-86b9856bba84.aspx</pingback:target>
      <dc:creator>
      </dc:creator>
      <wfw:comment>http://flimflan.com/blog/CommentView,guid,03712e05-6bfe-4fc5-93f5-86b9856bba84.aspx</wfw:comment>
      <wfw:commentRss>http://flimflan.com/blog/SyndicationService.asmx/GetEntryCommentsRss?guid=03712e05-6bfe-4fc5-93f5-86b9856bba84</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
Now, instead of burying in your blog your sage advice on how to <em>really</em> use
the classes in the .NET Framework, despite what the documentation says, you can
add it right to the source for everyone to see.<br /><a href="http://msdnwiki.microsoft.com">http://msdnwiki.microsoft.com</a></p>
        <p>
I only mention it, because that's where I will be putting most of <a href="http://msdnwiki.microsoft.com/wikiedit/myprofile.aspx?name=Joshua%20Flanagan&amp;skinlocale=en-us">my
sage advice</a> going forward.
</p>
        <img width="0" height="0" src="http://flimflan.com/blog/aggbug.ashx?id=03712e05-6bfe-4fc5-93f5-86b9856bba84" />
      </body>
      <title>Add your two cents to the MSDN documentation</title>
      <guid isPermaLink="false">http://flimflan.com/blog/PermaLink,guid,03712e05-6bfe-4fc5-93f5-86b9856bba84.aspx</guid>
      <link>http://flimflan.com/blog/AddYourTwoCentsToTheMSDNDocumentation.aspx</link>
      <pubDate>Fri, 16 Jun 2006 04:24:19 GMT</pubDate>
      <description>&lt;p&gt;
Now, instead of burying in your blog your sage advice on how to &lt;em&gt;really&lt;/em&gt; use
the classes in the .NET Framework, despite what the documentation says,&amp;nbsp;you can
add it right to the source for everyone to see.&lt;br /&gt;
&lt;a href="http://msdnwiki.microsoft.com"&gt;http://msdnwiki.microsoft.com&lt;/a&gt;
&lt;/p&gt;
&lt;p&gt;
I only mention it, because that's where I will be putting most of &lt;a href="http://msdnwiki.microsoft.com/wikiedit/myprofile.aspx?name=Joshua%20Flanagan&amp;amp;skinlocale=en-us"&gt;my
sage advice&lt;/a&gt; going forward.
&lt;/p&gt;
&lt;img width="0" height="0" src="http://flimflan.com/blog/aggbug.ashx?id=03712e05-6bfe-4fc5-93f5-86b9856bba84" /&gt;</description>
      <comments>http://flimflan.com/blog/CommentView,guid,03712e05-6bfe-4fc5-93f5-86b9856bba84.aspx</comments>
      <category>.NET</category>
    </item>
    <item>
      <trackback:ping>http://flimflan.com/blog/Trackback.aspx?guid=92b02451-3dab-40fc-9616-093d54131502</trackback:ping>
      <pingback:server>http://flimflan.com/blog/pingback.aspx</pingback:server>
      <pingback:target>http://flimflan.com/blog/PermaLink,guid,92b02451-3dab-40fc-9616-093d54131502.aspx</pingback:target>
      <dc:creator>
      </dc:creator>
      <wfw:comment>http://flimflan.com/blog/CommentView,guid,92b02451-3dab-40fc-9616-093d54131502.aspx</wfw:comment>
      <wfw:commentRss>http://flimflan.com/blog/SyndicationService.asmx/GetEntryCommentsRss?guid=92b02451-3dab-40fc-9616-093d54131502</wfw:commentRss>
      <slash:comments>1</slash:comments>
      <body xmlns="http://www.w3.org/1999/xhtml">Jeff Key created a great little tool called <a href="http://www.sliver.com/dotnet/SnippetCompiler/">Snippet
Compiler</a>, which allowed you to experiment with some throwaway .NET code. This
is useful for doing a quick technical proof of concept (a "spike" in agile
practitioner terms). Before Snippet Compiler, I used to fill my Visual Studio Projects
folder with a bunch of junk projects that I intended to delete <span style="font-style: italic;">eventually</span>.<br />
However, with Visual Studio 2005, I think Snippet Compiler's days are numbered (no
offense Mr. Key). VS2005 supports a seemingly little known feature that I'll call
"temporary projects". It allows you to create and work on a new project
without saving it to disk. You can work on the project as long as you want. When you
close the project, you have the option to save it, but more importantly, you have
the option to just discard it (this should all sound familiar to fellow VB6 converts).
If you use the new <a href="http://webproject.scottgu.com/">Web Application Project</a> model,
you can even use this feature to create throwaway websites.<br /><br />
I use this feature all the time while trying to brush up on on the new functionality
in the 2.0 framework.<br /><br />
To enable temporary projects:<br /><br />
1) In Visual Studio 2005, go to the Tools | Options... menu<br />
2) Go to the Projects and Solutions node<br />
3) Uncheck "Save new projects when created"<img width="0" height="0" src="http://flimflan.com/blog/aggbug.ashx?id=92b02451-3dab-40fc-9616-093d54131502" /></body>
      <title>Temporary Projects in Visual Studio 2005</title>
      <guid isPermaLink="false">http://flimflan.com/blog/PermaLink,guid,92b02451-3dab-40fc-9616-093d54131502.aspx</guid>
      <link>http://flimflan.com/blog/TemporaryProjectsInVisualStudio2005.aspx</link>
      <pubDate>Fri, 24 Mar 2006 04:00:28 GMT</pubDate>
      <description>Jeff Key created a great little tool called &lt;a href="http://www.sliver.com/dotnet/SnippetCompiler/"&gt;Snippet
Compiler&lt;/a&gt;, which allowed you to experiment with some throwaway .NET code. This
is useful for doing a quick technical proof of concept (a &amp;quot;spike&amp;quot; in agile
practitioner terms). Before Snippet Compiler, I used to fill my Visual Studio Projects
folder with a bunch of junk projects that I intended to delete &lt;span style="font-style: italic;"&gt;eventually&lt;/span&gt;.&lt;br /&gt;
However, with Visual Studio 2005, I think Snippet Compiler's days are numbered (no
offense Mr. Key). VS2005 supports a seemingly little known feature that I'll call
&amp;quot;temporary projects&amp;quot;. It allows you to create and work on a new project
without saving it to disk. You can work on the project as long as you want. When you
close the project, you have the option to save it, but more importantly, you have
the option to just discard it (this should all sound familiar to fellow VB6 converts).
If you use the new &lt;a href="http://webproject.scottgu.com/"&gt;Web Application Project&lt;/a&gt; model,
you can even use this feature to create throwaway websites.&lt;br /&gt;
&lt;br /&gt;
I use this feature all the time while trying to brush up on on the new functionality
in the 2.0 framework.&lt;br /&gt;
&lt;br /&gt;
To enable temporary projects:&lt;br /&gt;
&lt;br /&gt;
1) In Visual Studio 2005, go to the Tools | Options... menu&lt;br /&gt;
2) Go to the Projects and Solutions node&lt;br /&gt;
3) Uncheck &amp;quot;Save new projects when created&amp;quot;&lt;img width="0" height="0" src="http://flimflan.com/blog/aggbug.ashx?id=92b02451-3dab-40fc-9616-093d54131502" /&gt;</description>
      <comments>http://flimflan.com/blog/CommentView,guid,92b02451-3dab-40fc-9616-093d54131502.aspx</comments>
      <category>.NET</category>
    </item>
    <item>
      <trackback:ping>http://flimflan.com/blog/Trackback.aspx?guid=7a21f40a-7b66-4fd7-8188-21271749e5c7</trackback:ping>
      <pingback:server>http://flimflan.com/blog/pingback.aspx</pingback:server>
      <pingback:target>http://flimflan.com/blog/PermaLink,guid,7a21f40a-7b66-4fd7-8188-21271749e5c7.aspx</pingback:target>
      <dc:creator>
      </dc:creator>
      <wfw:comment>http://flimflan.com/blog/CommentView,guid,7a21f40a-7b66-4fd7-8188-21271749e5c7.aspx</wfw:comment>
      <wfw:commentRss>http://flimflan.com/blog/SyndicationService.asmx/GetEntryCommentsRss?guid=7a21f40a-7b66-4fd7-8188-21271749e5c7</wfw:commentRss>
      <slash:comments>7</slash:comments>
      <body xmlns="http://www.w3.org/1999/xhtml">I've posted the source and binary for the
latest release of my <a href="http://flimflan.com/blog/ProfileView.aspx">ProfileView
ASP.NET server control</a>. I was finally able to address the much requested fix to
make the order of the properties displayed at runtime reflect the order they are declared
in the web.config. Here are the release notes:<br /><ul><li>
Properties now display in the order they are listed in web.config<br /></li><li>
Design-time view now uses same rendering method as runtime</li><li>
Fixed design-time bug that caused it to fail when a profile property type was not
specified</li><li>
Design-time view now has a Smart Tag to allow you to preview an anonymous user's profile<br /></li></ul><img width="0" height="0" src="http://flimflan.com/blog/aggbug.ashx?id=7a21f40a-7b66-4fd7-8188-21271749e5c7" /></body>
      <title>New release of ProfileView</title>
      <guid isPermaLink="false">http://flimflan.com/blog/PermaLink,guid,7a21f40a-7b66-4fd7-8188-21271749e5c7.aspx</guid>
      <link>http://flimflan.com/blog/NewReleaseOfProfileView.aspx</link>
      <pubDate>Mon, 09 Jan 2006 02:46:49 GMT</pubDate>
      <description>I've posted the source and binary for the latest release of my &lt;a href="http://flimflan.com/blog/ProfileView.aspx"&gt;ProfileView
ASP.NET server control&lt;/a&gt;. I was finally able to address the much requested fix to
make the order of the properties displayed at runtime reflect the order they are declared
in the web.config. Here are the release notes:&lt;br&gt;
&lt;ul&gt;
&lt;li&gt;
Properties now display in the order they are listed in web.config&lt;br&gt;
&lt;/li&gt;
&lt;li&gt;
Design-time view now uses same rendering method as runtime&lt;/li&gt;
&lt;li&gt;
Fixed design-time bug that caused it to fail when a profile property type was not
specified&lt;/li&gt;
&lt;li&gt;
Design-time view now has a Smart Tag to allow you to preview an anonymous user's profile&lt;br&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;img width="0" height="0" src="http://flimflan.com/blog/aggbug.ashx?id=7a21f40a-7b66-4fd7-8188-21271749e5c7" /&gt;</description>
      <comments>http://flimflan.com/blog/CommentView,guid,7a21f40a-7b66-4fd7-8188-21271749e5c7.aspx</comments>
      <category>.NET</category>
      <category>ProfileView</category>
    </item>
    <item>
      <trackback:ping>http://flimflan.com/blog/Trackback.aspx?guid=24eef427-dcfe-46ea-a849-46f40abe83cd</trackback:ping>
      <pingback:server>http://flimflan.com/blog/pingback.aspx</pingback:server>
      <pingback:target>http://flimflan.com/blog/PermaLink,guid,24eef427-dcfe-46ea-a849-46f40abe83cd.aspx</pingback:target>
      <dc:creator>
      </dc:creator>
      <wfw:comment>http://flimflan.com/blog/CommentView,guid,24eef427-dcfe-46ea-a849-46f40abe83cd.aspx</wfw:comment>
      <wfw:commentRss>http://flimflan.com/blog/SyndicationService.asmx/GetEntryCommentsRss?guid=24eef427-dcfe-46ea-a849-46f40abe83cd</wfw:commentRss>
      <slash:comments>2</slash:comments>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <a href="http://blogs.msdn.com/mikhailarkhipov/">Mikhail
Arkhipov</a> already posted exactly what you need to know to <a href="http://blogs.msdn.com/mikhailarkhipov/archive/2005/06/24/432308.aspx">debug
classic asp pages in Visual Studio 2005</a>. His post includes the instructions for
Win2K3, but the comments include instructions for WinXP.<br /><br /><font size="1">I'm only posting this in hopes that it helps the search engines lead
people to his post. When I searched for "debug classic asp visual studio 2005",
I had no luck. If I would have abbreviated visual studio as vs (as he did in his post
title), I would have found it immediately.</font><img width="0" height="0" src="http://flimflan.com/blog/aggbug.ashx?id=24eef427-dcfe-46ea-a849-46f40abe83cd" /></body>
      <title>Debug classic ASP pages in Visual Studio 2005</title>
      <guid isPermaLink="false">http://flimflan.com/blog/PermaLink,guid,24eef427-dcfe-46ea-a849-46f40abe83cd.aspx</guid>
      <link>http://flimflan.com/blog/DebugClassicASPPagesInVisualStudio2005.aspx</link>
      <pubDate>Sat, 07 Jan 2006 21:35:08 GMT</pubDate>
      <description>&lt;a href="http://blogs.msdn.com/mikhailarkhipov/"&gt;Mikhail Arkhipov&lt;/a&gt; already posted
exactly what you need to know to &lt;a href="http://blogs.msdn.com/mikhailarkhipov/archive/2005/06/24/432308.aspx"&gt;debug
classic asp pages in Visual Studio 2005&lt;/a&gt;. His post includes the instructions for
Win2K3, but the comments include instructions for WinXP.&lt;br /&gt;
&lt;br /&gt;
&lt;font size="1"&gt;I'm only posting this in hopes that it helps the search engines lead
people to his post. When I searched for &amp;quot;debug classic asp visual studio 2005&amp;quot;,
I had no luck. If I would have abbreviated visual studio as vs (as he did in his post
title), I would have found it immediately.&lt;/font&gt;&lt;img width="0" height="0" src="http://flimflan.com/blog/aggbug.ashx?id=24eef427-dcfe-46ea-a849-46f40abe83cd" /&gt;</description>
      <comments>http://flimflan.com/blog/CommentView,guid,24eef427-dcfe-46ea-a849-46f40abe83cd.aspx</comments>
      <category>.NET</category>
    </item>
    <item>
      <trackback:ping>http://flimflan.com/blog/Trackback.aspx?guid=eee213a5-56c2-4561-a242-ed813519717d</trackback:ping>
      <pingback:server>http://flimflan.com/blog/pingback.aspx</pingback:server>
      <pingback:target>http://flimflan.com/blog/PermaLink,guid,eee213a5-56c2-4561-a242-ed813519717d.aspx</pingback:target>
      <dc:creator>
      </dc:creator>
      <wfw:comment>http://flimflan.com/blog/CommentView,guid,eee213a5-56c2-4561-a242-ed813519717d.aspx</wfw:comment>
      <wfw:commentRss>http://flimflan.com/blog/SyndicationService.asmx/GetEntryCommentsRss?guid=eee213a5-56c2-4561-a242-ed813519717d</wfw:commentRss>
      <slash:comments>2</slash:comments>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
Of the billion toolbar buttons that Visual Studio 2005 includes, I couldn't find one
to open a command prompt to the project directory. This is a must-have for us command-line
SubVersion users. Luckily, a quick Google search turned up <a href="http://objectsharp.com/blogs/dave/archive/2003/12/10/227.aspx">this
post</a> (its actually the comment from <a href="http://www.objectsharp.com/Barry/">Barry
Gervin</a> that I credit). Updated for VS 2005:
</p>
        <p>
From the Tools -&gt; External Tools... menu, click Add, and fill in:
</p>
        <p>
          <strong>Title:</strong> Command Prompt &amp;Here<br /><strong>Command:</strong> C:\WINDOWS\system32\cmd.exe<br /><strong>Arguments:</strong> /k ""C:\Program Files\Microsoft Visual Studio 8\VC\vcvarsall.bat""
x86<br /><strong>Initial Directory:</strong> $(ProjectDir)
</p>
        <p>
Note the Title is important only because I wanted to use the letter 'H' as my shortcut
key since it is close to the 'T', and unused on the default Tools menu. This enables
the very easy one-handed keystroke ALT+T,H.
</p>
        <p>
I then went to Tools-&gt;Customize..., selected Tools from the Categories, then found
"External Command 3" (there were 2 other tools already registered in VS) in the Commands
section, and dragged it up to my toolbar. Right-click on the new button on the toolbar,
select Default Style, then Change Button Image, and choose the square (its a good
starting point). Using Edit Button Image... I drew a crude "C:".
</p>
        <img width="0" height="0" src="http://flimflan.com/blog/aggbug.ashx?id=eee213a5-56c2-4561-a242-ed813519717d" />
      </body>
      <title>Visual Studio Command Prompt Toolbar Button</title>
      <guid isPermaLink="false">http://flimflan.com/blog/PermaLink,guid,eee213a5-56c2-4561-a242-ed813519717d.aspx</guid>
      <link>http://flimflan.com/blog/VisualStudioCommandPromptToolbarButton.aspx</link>
      <pubDate>Thu, 05 Jan 2006 02:56:36 GMT</pubDate>
      <description>&lt;p&gt;
Of the billion toolbar buttons that Visual Studio 2005 includes, I couldn't find one
to open a command prompt to the project directory. This is a must-have for us command-line
SubVersion users. Luckily, a quick Google search turned up &lt;a href="http://objectsharp.com/blogs/dave/archive/2003/12/10/227.aspx"&gt;this
post&lt;/a&gt; (its actually the comment from &lt;a href="http://www.objectsharp.com/Barry/"&gt;Barry
Gervin&lt;/a&gt; that I credit). Updated for VS 2005:
&lt;/p&gt;
&lt;p&gt;
From the Tools -&amp;gt; External Tools... menu, click Add, and fill in:
&lt;/p&gt;
&lt;p&gt;
&lt;strong&gt;Title:&lt;/strong&gt; Command Prompt &amp;amp;Here&lt;br&gt;
&lt;strong&gt;Command:&lt;/strong&gt; C:\WINDOWS\system32\cmd.exe&lt;br&gt;
&lt;strong&gt;Arguments:&lt;/strong&gt; /k ""C:\Program Files\Microsoft Visual Studio 8\VC\vcvarsall.bat""
x86&lt;br&gt;
&lt;strong&gt;Initial Directory:&lt;/strong&gt; $(ProjectDir)
&lt;/p&gt;
&lt;p&gt;
Note the Title is important only because I wanted to use the letter 'H' as my shortcut
key since it is close to the 'T', and unused on the default Tools menu. This enables
the very easy one-handed keystroke ALT+T,H.
&lt;/p&gt;
&lt;p&gt;
I then went to Tools-&amp;gt;Customize..., selected Tools from the Categories, then found
"External Command 3" (there were 2 other tools already registered in VS) in the Commands
section, and dragged it up to my toolbar. Right-click on the new button on the toolbar,
select Default Style, then Change Button Image, and choose the square (its a good
starting point). Using Edit Button Image... I drew a crude "C:".
&lt;/p&gt;
&lt;img width="0" height="0" src="http://flimflan.com/blog/aggbug.ashx?id=eee213a5-56c2-4561-a242-ed813519717d" /&gt;</description>
      <comments>http://flimflan.com/blog/CommentView,guid,eee213a5-56c2-4561-a242-ed813519717d.aspx</comments>
      <category>.NET</category>
    </item>
    <item>
      <trackback:ping>http://flimflan.com/blog/Trackback.aspx?guid=0ff1619b-d1e7-4a4c-813d-16ecc677d53b</trackback:ping>
      <pingback:server>http://flimflan.com/blog/pingback.aspx</pingback:server>
      <pingback:target>http://flimflan.com/blog/PermaLink,guid,0ff1619b-d1e7-4a4c-813d-16ecc677d53b.aspx</pingback:target>
      <dc:creator>
      </dc:creator>
      <wfw:comment>http://flimflan.com/blog/CommentView,guid,0ff1619b-d1e7-4a4c-813d-16ecc677d53b.aspx</wfw:comment>
      <wfw:commentRss>http://flimflan.com/blog/SyndicationService.asmx/GetEntryCommentsRss?guid=0ff1619b-d1e7-4a4c-813d-16ecc677d53b</wfw:commentRss>
      <slash:comments>1</slash:comments>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
When creating a designer for an ASP.NET server control, it is often very useful to
read settings from the user's web.config file. In previous versions of the .NET Framework,
you had to <a href="http://blogs.msdn.com/mszcool/archive/2004/06/30/169793.aspx">jump
through hoops</a> to access the web.config file at design time. I was very thankful
for this solution <a href="http://flimflan.com/blog/SignificantUpdateToProfileView.aspx">when
I needed it</a>, but I'm happy to move on. The dependency on EnvDTE felt wrong, and
the fact that it used COM interop with the VS.NET IDE meant it probably would not
work with any other tool.
</p>
        <p>
Thankfully, in .NET 2.0, it is much simpler. If you want to get the full path to web.config
(useful for parsing the XML manually), it has been reduced to:
</p>
        <span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">
          <font face="Verdana" color="#003300" size="2">
            <p>
              <span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">
                <span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">using</span> System.Web.UI.Design;<br /><span style="FONT-SIZE: 11px; COLOR: green; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">//...</span><br />
IWebApplication webApp <span style="FONT-SIZE: 11px; COLOR: red; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">=</span> (IWebApplication)Component.Site.GetService(<br /><span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">typeof</span>(IWebApplication)
);<br />
IProjectItem item <span style="FONT-SIZE: 11px; COLOR: red; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">=</span> webApp.GetProjectItemFromUrl(<span style="FONT-SIZE: 11px; COLOR: #666666; FONT-FAMILY: Courier New; BACKGROUND-COLOR: #e4e4e4">"~/web.config"</span>);<br /><span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">string</span> webConfigPath <span style="FONT-SIZE: 11px; COLOR: red; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">=</span> item.PhysicalPath;</span>
            </p>
          </font>
        </span>
        <p>
          <span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">
            <font face="Verdana" color="#003300" size="1">Note:
you will want to check for nulls and handle appropriately. The call to GetService
could return null if the design tool hosting your control does not support this service
(something other than VS.NET). And of course the call to GetProjectItemFromUrl could
fail if there is no web.config in the project.</font>
          </span>
        </p>
        <p>
          <span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">
            <font face="Verdana" color="#003300" size="2">Even
better, instead of parsing web.config yourself, you can get strongly-typed access
to the configuration using the new classes in the System.Configuration namespace.
For example, in my <a href="http://flimflan.com/blog/ProfileView.aspx">ProfileView</a> control,
I use code similar (more null checking) to the following to discover information about
the configured profile properties:</font>
          </span>
        </p>
        <span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">
          <font face="Verdana" color="#003300" size="2">
            <p>
              <span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">
                <span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">using</span> System.Configuration;<br /><span style="FONT-SIZE: 11px; COLOR: green; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"><span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"><span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"><span style="FONT-SIZE: 11px; COLOR: green; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"><span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"><span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">using</span> System.Web.Configuration;<br /></span></span>using</span> System.Web.UI.Design;<br /></span>//...</span><br />
IWebApplication webApp <span style="FONT-SIZE: 11px; COLOR: red; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">=</span> (IWebApplication)Component.Site.GetService(<br /><span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">typeof</span>(IWebApplication)
);<br />
Configuration config <span style="FONT-SIZE: 11px; COLOR: red; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">=</span> webApp.OpenWebConfiguration(<span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">true</span>);<br />
ConfigurationSectionGroup systemWeb <span style="FONT-SIZE: 11px; COLOR: red; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">=</span> config.GetSectionGroup(<span style="FONT-SIZE: 11px; COLOR: #666666; FONT-FAMILY: Courier New; BACKGROUND-COLOR: #e4e4e4">"system.web"</span>);<br />
ProfileSection profileSection <span style="FONT-SIZE: 11px; COLOR: red; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">=</span> (ProfileSection)systemWeb.Sections[<span style="FONT-SIZE: 11px; COLOR: #666666; FONT-FAMILY: Courier New; BACKGROUND-COLOR: #e4e4e4">"profile"</span>];<br /><br /><span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">foreach</span> (ProfilePropertySettings
configProperty <span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">in</span> profileSection.PropertySettings)<br />
{ <span style="FONT-SIZE: 11px; COLOR: green; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">//
read the settings in each configProperty }</span></span>
            </p>
          </font>
        </span>
        <p>
          <span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">
            <font face="Verdana" color="#003300" size="2">Once
you get the Configuration object as demonstrated above, reading a value out of the
appSettings section is as easy as:</font>
          </span>
        </p>
        <span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">
          <p>
            <span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">config.AppSettings.Settings[<span style="FONT-SIZE: 11px; COLOR: #666666; FONT-FAMILY: Courier New; BACKGROUND-COLOR: #e4e4e4">"maxRetries"</span>].Value</span>
          </p>
        </span>
        <img width="0" height="0" src="http://flimflan.com/blog/aggbug.ashx?id=0ff1619b-d1e7-4a4c-813d-16ecc677d53b" />
      </body>
      <title>Accessing web.config at Design Time in .NET 2.0</title>
      <guid isPermaLink="false">http://flimflan.com/blog/PermaLink,guid,0ff1619b-d1e7-4a4c-813d-16ecc677d53b.aspx</guid>
      <link>http://flimflan.com/blog/AccessingWebconfigAtDesignTimeInNET20.aspx</link>
      <pubDate>Mon, 02 Jan 2006 18:23:51 GMT</pubDate>
      <description>&lt;p&gt;
When creating a designer for an ASP.NET server control, it is often very useful to
read settings from the user's web.config file. In previous versions of the .NET Framework,
you had to &lt;a href="http://blogs.msdn.com/mszcool/archive/2004/06/30/169793.aspx"&gt;jump
through hoops&lt;/a&gt; to access the web.config file at design time. I was very thankful
for this solution &lt;a href="http://flimflan.com/blog/SignificantUpdateToProfileView.aspx"&gt;when
I needed it&lt;/a&gt;, but I'm happy to move on. The dependency on EnvDTE felt wrong, and
the fact that it used COM interop with the VS.NET IDE meant it probably would not
work with any other tool.
&lt;/p&gt;
&lt;p&gt;
Thankfully, in .NET 2.0, it is much simpler. If you want to get the full path to web.config
(useful for parsing the XML manually), it has been reduced to:
&lt;/p&gt;
&lt;span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;&lt;font face=Verdana color=#003300 size=2&gt; 
&lt;p&gt;
&lt;span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;&lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;using&lt;/span&gt; System.Web.UI.Design;&lt;br&gt;
&lt;span style="FONT-SIZE: 11px; COLOR: green; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;//...&lt;/span&gt;
&lt;br&gt;
IWebApplication webApp &lt;span style="FONT-SIZE: 11px; COLOR: red; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;=&lt;/span&gt; (IWebApplication)Component.Site.GetService(&lt;br&gt;
&lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;typeof&lt;/span&gt;(IWebApplication)
);&lt;br&gt;
IProjectItem item &lt;span style="FONT-SIZE: 11px; COLOR: red; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;=&lt;/span&gt; webApp.GetProjectItemFromUrl(&lt;span style="FONT-SIZE: 11px; COLOR: #666666; FONT-FAMILY: Courier New; BACKGROUND-COLOR: #e4e4e4"&gt;"~/web.config"&lt;/span&gt;);&lt;br&gt;
&lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;string&lt;/span&gt; webConfigPath &lt;span style="FONT-SIZE: 11px; COLOR: red; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;=&lt;/span&gt; item.PhysicalPath;&lt;/span&gt;
&lt;/p&gt;
&lt;/font&gt;&lt;/span&gt; 
&lt;p&gt;
&lt;span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;&lt;font face=Verdana color=#003300 size=1&gt;Note:
you will want to check for nulls and handle appropriately. The call to GetService
could return null if the design tool hosting your control does not support this service
(something other than VS.NET). And of course the call to GetProjectItemFromUrl could
fail if there is no web.config in the project.&lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;&lt;font face=Verdana color=#003300 size=2&gt;Even
better, instead of parsing web.config yourself, you can get strongly-typed access
to the configuration using the new classes in the System.Configuration namespace.
For example, in my &lt;a href="http://flimflan.com/blog/ProfileView.aspx"&gt;ProfileView&lt;/a&gt; control,
I use code similar (more null checking) to the following to discover information about
the configured profile properties:&lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;&lt;font face=Verdana color=#003300 size=2&gt; 
&lt;p&gt;
&lt;span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;&lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;using&lt;/span&gt; System.Configuration;&lt;br&gt;
&lt;span style="FONT-SIZE: 11px; COLOR: green; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;&lt;span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;&lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;&lt;span style="FONT-SIZE: 11px; COLOR: green; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;&lt;span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;&lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;using&lt;/span&gt; System.Web.Configuration;&lt;br&gt;
&lt;/span&gt;&lt;/span&gt;using&lt;/span&gt; System.Web.UI.Design;&lt;br&gt;
&lt;/span&gt;//...&lt;/span&gt;
&lt;br&gt;
IWebApplication webApp &lt;span style="FONT-SIZE: 11px; COLOR: red; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;=&lt;/span&gt; (IWebApplication)Component.Site.GetService(&lt;br&gt;
&lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;typeof&lt;/span&gt;(IWebApplication)
);&lt;br&gt;
Configuration config &lt;span style="FONT-SIZE: 11px; COLOR: red; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;=&lt;/span&gt; webApp.OpenWebConfiguration(&lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;true&lt;/span&gt;);&lt;br&gt;
ConfigurationSectionGroup systemWeb &lt;span style="FONT-SIZE: 11px; COLOR: red; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;=&lt;/span&gt; config.GetSectionGroup(&lt;span style="FONT-SIZE: 11px; COLOR: #666666; FONT-FAMILY: Courier New; BACKGROUND-COLOR: #e4e4e4"&gt;"system.web"&lt;/span&gt;);&lt;br&gt;
ProfileSection profileSection &lt;span style="FONT-SIZE: 11px; COLOR: red; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;=&lt;/span&gt; (ProfileSection)systemWeb.Sections[&lt;span style="FONT-SIZE: 11px; COLOR: #666666; FONT-FAMILY: Courier New; BACKGROUND-COLOR: #e4e4e4"&gt;"profile"&lt;/span&gt;];&lt;br&gt;
&lt;br&gt;
&lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;foreach&lt;/span&gt; (ProfilePropertySettings
configProperty &lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;in&lt;/span&gt; profileSection.PropertySettings)&lt;br&gt;
{ &lt;span style="FONT-SIZE: 11px; COLOR: green; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;//
read the settings in each configProperty }&lt;/span&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;/font&gt;&lt;/span&gt; 
&lt;p&gt;
&lt;span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;&lt;font face=Verdana color=#003300 size=2&gt;Once
you get the Configuration object as demonstrated above, reading a value out of the
appSettings section is as easy as:&lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt; 
&lt;p&gt;
&lt;span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;config.AppSettings.Settings[&lt;span style="FONT-SIZE: 11px; COLOR: #666666; FONT-FAMILY: Courier New; BACKGROUND-COLOR: #e4e4e4"&gt;"maxRetries"&lt;/span&gt;].Value&lt;/span&gt;
&lt;/p&gt;
&lt;/span&gt;&lt;img width="0" height="0" src="http://flimflan.com/blog/aggbug.ashx?id=0ff1619b-d1e7-4a4c-813d-16ecc677d53b" /&gt;</description>
      <comments>http://flimflan.com/blog/CommentView,guid,0ff1619b-d1e7-4a4c-813d-16ecc677d53b.aspx</comments>
      <category>.NET</category>
      <category>ProfileView</category>
    </item>
    <item>
      <trackback:ping>http://flimflan.com/blog/Trackback.aspx?guid=80cdb32f-ea80-423a-9113-a07433af8140</trackback:ping>
      <pingback:server>http://flimflan.com/blog/pingback.aspx</pingback:server>
      <pingback:target>http://flimflan.com/blog/PermaLink,guid,80cdb32f-ea80-423a-9113-a07433af8140.aspx</pingback:target>
      <dc:creator>
      </dc:creator>
      <wfw:comment>http://flimflan.com/blog/CommentView,guid,80cdb32f-ea80-423a-9113-a07433af8140.aspx</wfw:comment>
      <wfw:commentRss>http://flimflan.com/blog/SyndicationService.asmx/GetEntryCommentsRss?guid=80cdb32f-ea80-423a-9113-a07433af8140</wfw:commentRss>
      <slash:comments>5</slash:comments>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
Of all the new providers that ASP.NET 2.0 introduces, I think the <a href="http://msdn2.microsoft.com/en-us/library/system.web.security.roleprovider.aspx">RoleProvider</a> will
be the most frequently implemented in a corporate IT environment. Intranet applications
can usually take advantage of Windows integrated authentication for user identification.
By default, this will create a <a href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpref/html/frlrfsystemsecurityprincipalwindowsprincipalclasstopic.asp">WindowsPrincipal</a> object
that contains all of the user's domain groups as roles to be used for authorization.
However, it has been my experience that most applications do not use domain groups
for their role-based authorization. It is more likely that they have a database
(or some other store) that associates a user's Windows login name with application
specific roles.
</p>
        <p>
In the past (.NET 1.x), you could get around this by hooking into the <a href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpref/html/frlrfsystemwebhttpapplicationclassauthenticaterequesttopic.asp">HttpApplication.AuthenticateRequest</a> event
(via <a href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpguide/html/cpconworkingwithhttpapplicationinstances.asp">Global.asax</a> or
an <a href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpref/html/frlrfsystemwebihttpmoduleclasstopic.asp">IHttpModule</a>).
You would lookup the user's roles in your data store, initialize a <a href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpref/html/frlrfsystemsecurityprincipalgenericprincipalclasstopic.asp">GenericPrincipal</a> with
the roles, and then use it to replace the WindowsPrincipal on the current thread*. 
</p>
        <p>
This process is greatly simplified by the introduction of the RoleProvider framework,
which is already hooked into the request processing lifecycle by way of the <a href="http://msdn2.microsoft.com/en-us/library/system.web.security.roleprincipal.aspx">RolePrincipal</a> class.
This means you no longer need to manually hook into an application event or create
a custom principal, just to set the user's roles. The provider model allows you to
focus your code on the singular task of retrieving the roles for a user.
</p>
        <p>
The biggest drawback to the new approach is that the contract for a RoleProvider is
pretty extensive. In addition to the large number of methods that must be implemented,
there are additional "expected implementation details" that the signatures do not
cover (a <a href="http://odetocode.com/Blogs/scott/archive/2005/11/17/2479.aspx">topic
recently discussed by K. Scott Allen</a>).
</p>
        <p>
The good news is that these implementation details have been thoroughly documented
in a <a href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnaspp/html/ASPNETProvMod_Intro.asp">white
paper on MSDN</a>. The bad new is that because of the wealth of information, you will
probably find yourself needing to re-read that paper every time you try to implement
a new provider.
</p>
        <p>
That is exactly the problem I am trying to solve by introducing my ASP.NET RoleProvider
Visual Studio template. <a href="/files/CustomRoleProvider.zip">Download</a> the zip
file, save it or rename it so it has a .vsi exentsion, run it, and accept the prompts
(and warnings - sorry, I did not sign the code**). You will now have a new option
when adding a new file to a project.
</p>
        <p>
          <img alt="Visual Studio Add New File dialog" src="http://flimflan.com/blog/content/binary/AddNewFileRoleProvider.JPG" border="0" />
        </p>
        <p>
Just name the file, and a class with that name will be added to your project. The
class inherits from RoleProvider, and has a stub implementation for all of the methods
so it can immediately compile. At the very least, you will need to modify the GetRolesForUser()
method, and take a look at each section marked with a TODO: comment. Most of the other
remaining methods will just throw a NotSupportedException. This is actually a legitimate
implementation for many scenarios, as you may not need the additional functionality
of the RoleManager. However, if you do want to implement a full solution, the
whitepaper guidance for each method is included as comments. If you find the guidance
comments distracting, I provided instructions on how to do a quick find/replace
to delete them all.
</p>
        <p>
I plan to create additional templates for the other common provider types, but I would
like to get some feedback first. I want to know if people find this helpful. How could
it be better? The biggest thing I struggled with is how much documentation to include.
I always get a little overwhelmed when I add a new file, thinking I'm starting fresh,
only to be presented with a bunch of code or comments. It creates the feeling that
the person has to read and understand it all before they modify anything. I tried
to put focus on the parts that matter (with the TODO comments, and calling out the
main method GetRolesForUser). What do you think? Should there be more guidance comments,
or less? Should I include the XML Documentation comments for each method, copied
from MSDN?
</p>
        <p>
          <a href="/files/CustomRoleProvider.zip">Download the installation file here</a> and
provide feedback in the comments below.
</p>
        <p>
 
</p>
        <p>
          <em>* For a few more details on the 1.x approach, check out <a href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnnetsec/html/secnetht04.asp">this
article on FormsAuthentication</a>. Step 4 is the relevant part, and works just as
well for Windows authentication (use the WindowsIdentity instead of FormsIdentity).</em>
        </p>
        <p>
          <em>** If you do not trust the automatic installation, you can perform a manual install. Keep
the file extension from as .zip and extract the contents (a .vscontent file that you
can delete, and 2 .zip files). Copy the 2 zip files to your user item templates folder
- the "Visual Studio user item templates location" setting in the Projects and Solutions
| General tab of the Visual Studio 2005 options dialog.</em>
        </p>
        <img width="0" height="0" src="http://flimflan.com/blog/aggbug.ashx?id=80cdb32f-ea80-423a-9113-a07433af8140" />
      </body>
      <title>ASP.NET Role Provider Visual Studio template</title>
      <guid isPermaLink="false">http://flimflan.com/blog/PermaLink,guid,80cdb32f-ea80-423a-9113-a07433af8140.aspx</guid>
      <link>http://flimflan.com/blog/ASPNETRoleProviderVisualStudioTemplate.aspx</link>
      <pubDate>Fri, 09 Dec 2005 00:00:56 GMT</pubDate>
      <description>&lt;p&gt;
Of all the new providers that ASP.NET 2.0 introduces, I think the &lt;a href="http://msdn2.microsoft.com/en-us/library/system.web.security.roleprovider.aspx"&gt;RoleProvider&lt;/a&gt; will
be the most frequently implemented in a corporate IT environment. Intranet applications
can usually take advantage of Windows integrated authentication for user identification.
By default, this will create a &lt;a href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpref/html/frlrfsystemsecurityprincipalwindowsprincipalclasstopic.asp"&gt;WindowsPrincipal&lt;/a&gt; object
that contains all of the user's domain groups as roles to be used for authorization.
However, it has been my&amp;nbsp;experience that most applications do not use domain groups
for their role-based&amp;nbsp;authorization. It is more likely that they have a database
(or some other store) that associates a user's Windows login name with application
specific roles.
&lt;/p&gt;
&lt;p&gt;
In the past (.NET 1.x), you could get around this by hooking into the &lt;a href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpref/html/frlrfsystemwebhttpapplicationclassauthenticaterequesttopic.asp"&gt;HttpApplication.AuthenticateRequest&lt;/a&gt; event
(via &lt;a href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpguide/html/cpconworkingwithhttpapplicationinstances.asp"&gt;Global.asax&lt;/a&gt; or
an &lt;a href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpref/html/frlrfsystemwebihttpmoduleclasstopic.asp"&gt;IHttpModule&lt;/a&gt;).
You would lookup the user's roles in your data store, initialize&amp;nbsp;a &lt;a href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpref/html/frlrfsystemsecurityprincipalgenericprincipalclasstopic.asp"&gt;GenericPrincipal&lt;/a&gt; with
the roles, and then use it to replace the WindowsPrincipal on the current thread*. 
&lt;/p&gt;
&lt;p&gt;
This process is greatly simplified by the introduction of the RoleProvider framework,
which is already hooked into the request processing lifecycle by way of the &lt;a href="http://msdn2.microsoft.com/en-us/library/system.web.security.roleprincipal.aspx"&gt;RolePrincipal&lt;/a&gt; class.
This means you no longer need to manually hook into an application event or create
a custom principal, just to set the user's roles. The provider model allows you to
focus your code on the singular task of retrieving the roles for a user.
&lt;/p&gt;
&lt;p&gt;
The biggest drawback to the new approach is that the contract for a RoleProvider is
pretty extensive.&amp;nbsp;In addition to the large number of methods that must be implemented,
there are additional "expected implementation details" that the signatures do not
cover (a &lt;a href="http://odetocode.com/Blogs/scott/archive/2005/11/17/2479.aspx"&gt;topic
recently discussed by K. Scott Allen&lt;/a&gt;).
&lt;/p&gt;
&lt;p&gt;
The good news is that these implementation details have been thoroughly documented
in a &lt;a href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnaspp/html/ASPNETProvMod_Intro.asp"&gt;white
paper on MSDN&lt;/a&gt;. The bad new is that because of the wealth of information, you will
probably find yourself needing to&amp;nbsp;re-read that paper every time you try to implement
a new provider.
&lt;/p&gt;
&lt;p&gt;
That is exactly the problem I am trying to solve by introducing my ASP.NET RoleProvider
Visual Studio template. &lt;a href="/files/CustomRoleProvider.zip"&gt;Download&lt;/a&gt; the zip
file, save it or rename it so it has a .vsi exentsion, run it, and accept the prompts
(and warnings -&amp;nbsp;sorry, I did not sign the code**). You will now have a new option
when adding a new file to a project.
&lt;/p&gt;
&lt;p&gt;
&lt;img alt="Visual Studio Add New File dialog" src="http://flimflan.com/blog/content/binary/AddNewFileRoleProvider.JPG" border=0&gt;
&lt;/p&gt;
&lt;p&gt;
Just name the file, and a class with that name will be added to your project. The
class inherits from RoleProvider, and has a stub implementation for all of the methods
so it can immediately compile. At the very least, you will need to modify the GetRolesForUser()
method, and take a look at each section marked with a TODO: comment. Most of the other
remaining methods will just throw a NotSupportedException. This is actually a legitimate
implementation for many&amp;nbsp;scenarios, as&amp;nbsp;you may not need the additional functionality
of the RoleManager. However,&amp;nbsp;if you do want to implement a full solution, the
whitepaper guidance for each method is included as comments. If you find the guidance
comments distracting,&amp;nbsp;I provided instructions on how to do a quick find/replace
to delete them all.
&lt;/p&gt;
&lt;p&gt;
I plan to create additional templates for the other common provider types, but I would
like to get some feedback first. I want to know if people find this helpful. How could
it be better? The biggest thing I struggled with is how much documentation to include.
I always get a little overwhelmed when I add a new file, thinking I'm starting fresh,
only to be presented with a bunch of code or comments. It creates the feeling that
the person has to read and understand it all before they modify anything.&amp;nbsp;I tried
to put focus on the parts that matter (with the TODO comments, and calling out the
main method GetRolesForUser). What do you think? Should there be more guidance comments,
or less?&amp;nbsp;Should I include the XML Documentation comments for each method, copied
from MSDN?
&lt;/p&gt;
&lt;p&gt;
&lt;a href="/files/CustomRoleProvider.zip"&gt;Download the installation file here&lt;/a&gt; and
provide feedback in the comments below.
&lt;/p&gt;
&lt;p&gt;
&amp;nbsp;
&lt;/p&gt;
&lt;p&gt;
&lt;em&gt;* For a few more details on the 1.x approach, check out &lt;a href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnnetsec/html/secnetht04.asp"&gt;this
article on FormsAuthentication&lt;/a&gt;. Step 4 is the relevant part, and works just as
well for Windows authentication (use the WindowsIdentity instead of FormsIdentity).&lt;/em&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;em&gt;** If you do not trust the automatic installation, you can perform a manual install.&amp;nbsp;Keep
the file extension from as .zip and extract the contents (a .vscontent file that you
can delete, and 2 .zip files). Copy the 2 zip files to your user item templates folder
- the "Visual Studio user item templates location" setting in the Projects and Solutions
| General tab of the Visual Studio 2005 options dialog.&lt;/em&gt;
&lt;/p&gt;
&lt;img width="0" height="0" src="http://flimflan.com/blog/aggbug.ashx?id=80cdb32f-ea80-423a-9113-a07433af8140" /&gt;</description>
      <comments>http://flimflan.com/blog/CommentView,guid,80cdb32f-ea80-423a-9113-a07433af8140.aspx</comments>
      <category>.NET</category>
    </item>
    <item>
      <trackback:ping>http://flimflan.com/blog/Trackback.aspx?guid=57a2115f-29a1-4ffa-8b2e-dbedf61263b9</trackback:ping>
      <pingback:server>http://flimflan.com/blog/pingback.aspx</pingback:server>
      <pingback:target>http://flimflan.com/blog/PermaLink,guid,57a2115f-29a1-4ffa-8b2e-dbedf61263b9.aspx</pingback:target>
      <dc:creator>
      </dc:creator>
      <wfw:comment>http://flimflan.com/blog/CommentView,guid,57a2115f-29a1-4ffa-8b2e-dbedf61263b9.aspx</wfw:comment>
      <wfw:commentRss>http://flimflan.com/blog/SyndicationService.asmx/GetEntryCommentsRss?guid=57a2115f-29a1-4ffa-8b2e-dbedf61263b9</wfw:commentRss>
      <slash:comments>2</slash:comments>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
        </p>
A little while ago, I <a href="http://flimflan.com/blog/MigratedToDasBlog.aspx">made
the move from the .TEXT blogging software to dasBlog</a>. Migrating the actual content
was pretty straightforward (as mentioned in the previous post). The problem was that
any existing links to my content that existed out in the wild would no longer resolve,
since .TEXT used a different URL format for identifying posts. Additionally, the URL
for my RSS feed changed, so any aggregators that tried to pull from my site would
get an error, and probably eventually drop me.<br />
It turns out that both of these problems were relatively easy to solve. I credit the
dasBlog development team for making a flexible platform.<br /><br />
To allow .TEXT permalink posts to resolve, I simply added the following entry to the
end of the newtelligence.DasBlog.UrlMapper section of web.config:<br /><font face="Courier New"><span style="COLOR: rgb(0,128,0)">&lt;!-- .TEXT archive compatibility
--&gt;</span><br style="COLOR: rgb(0,128,0)" /><span style="COLOR: rgb(0,128,0)">&lt;!-- Translates</span><br style="COLOR: rgb(0,128,0)" /><span style="COLOR: rgb(0,128,0)">  FROM: /blog/archive/2004/07/27/194.aspx</span><br style="COLOR: rgb(0,128,0)" /><span style="COLOR: rgb(0,128,0)">  TO: /blog/default.aspx?date=2004-07-27</span><br style="COLOR: rgb(0,128,0)" /><span style="COLOR: rgb(0,128,0)">--&gt;</span><br style="COLOR: rgb(0,128,0)" /><span style="COLOR: rgb(0,128,0)">&lt;<span style="COLOR: rgb(165,42,42)">ad</span></span><span style="COLOR: rgb(165,42,42)">d</span><span style="COLOR: rgb(255,0,0)">matchExpression </span>= </font><font face="Courier New" size="2"><span style="COLOR: rgb(0,0,255)">"(?&amp;lt;basedir&amp;gt;.*?)/archive/(?&amp;lt;year&amp;gt;\d{4})/(?&amp;lt;month&amp;gt;\d{2})/(?&amp;lt;day&amp;gt;\d{2})/(?&amp;lt;postid&amp;gt;\d+)\.aspx"</span><br /></font><font face="Courier New"> <span style="COLOR: rgb(255,0,0)">mapTo</span>=<span style="COLOR: rgb(0,0,255)">"{basedir}/default.aspx?date={year}-{month}-{day}"</span> /&gt;        
<br /></font><br />
Now, an old .TEXT url out in the wild like <a href="archive/2004/07/27/194.aspx" target="_blank">http://flimflan.com/blog/archive/2004/07/27/194.aspx</a> will
correctly resolve to the corresponding post in dasBlog.<br /><br /><br />
To allow the .TEXT feed URL to resolve (Rss.aspx), I changed this existing entry in
the UrlMapper section from:<br /><font face="Courier New">&lt;<span style="COLOR: rgb(165,42,42)">add</span><span style="COLOR: rgb(255,0,0)">matchExpression</span>=<span style="COLOR: rgb(0,0,255)">"(?&amp;lt;basedir&amp;gt;.*?)/rss\.ashx"</span>  <span style="COLOR: rgb(255,0,0)">mapTo</span>=<span style="COLOR: rgb(0,0,255)">"{basedir}/SyndicationService.asmx/GetRss?"</span> /&gt;</font><br /><br />
to:<br /><font face="Courier New">&lt;<span style="COLOR: rgb(165,42,42)">add</span><span style="COLOR: rgb(255,0,0)">matchExpression</span>=<span style="COLOR: rgb(0,0,255)">"(?&amp;lt;basedir&amp;gt;.*?)/rss\.as</span><span style="FONT-WEIGHT: bold; COLOR: rgb(0,0,255)">[hp]</span><span style="COLOR: rgb(0,0,255)">x"</span><span style="COLOR: rgb(255,0,0)"> mapTo</span>=<span style="COLOR: rgb(0,0,255)">"{basedir}/SyndicationService.asmx/GetRss?"</span> /&gt;</font><br /><br />
Now if only there was a way to migrate that skin I spent so much time on...<br /><img width="0" height="0" src="http://flimflan.com/blog/aggbug.ashx?id=57a2115f-29a1-4ffa-8b2e-dbedf61263b9" /></body>
      <title>Tips for migrating .TEXT to dasBlog</title>
      <guid isPermaLink="false">http://flimflan.com/blog/PermaLink,guid,57a2115f-29a1-4ffa-8b2e-dbedf61263b9.aspx</guid>
      <link>http://flimflan.com/blog/TipsForMigratingTEXTToDasBlog.aspx</link>
      <pubDate>Wed, 09 Nov 2005 03:48:08 GMT</pubDate>
      <description>&lt;p&gt;
&lt;/p&gt;
A little while ago, I &lt;a href="http://flimflan.com/blog/MigratedToDasBlog.aspx"&gt;made
the move from the .TEXT blogging software to dasBlog&lt;/a&gt;. Migrating the actual content
was pretty straightforward (as mentioned in the previous post). The problem was that
any existing links to my content that existed out in the wild would no longer resolve,
since .TEXT used a different URL format for identifying posts. Additionally, the URL
for my RSS feed changed, so any aggregators that tried to pull from my site would
get an error, and probably eventually drop me.&lt;br&gt;
It turns out that both of these problems were relatively easy to solve. I credit the
dasBlog development team for making a flexible platform.&lt;br&gt;
&lt;br&gt;
To allow .TEXT permalink posts to resolve, I simply added the following entry to the
end of the newtelligence.DasBlog.UrlMapper section of web.config:&lt;br&gt;
&lt;font face="Courier New"&gt;&lt;span style="COLOR: rgb(0,128,0)"&gt;&amp;lt;!-- .TEXT archive compatibility
--&amp;gt;&lt;/span&gt;
&lt;br style="COLOR: rgb(0,128,0)"&gt;
&lt;span style="COLOR: rgb(0,128,0)"&gt;&amp;lt;!-- Translates&lt;/span&gt;
&lt;br style="COLOR: rgb(0,128,0)"&gt;
&lt;span style="COLOR: rgb(0,128,0)"&gt;&amp;nbsp; FROM: /blog/archive/2004/07/27/194.aspx&lt;/span&gt;
&lt;br style="COLOR: rgb(0,128,0)"&gt;
&lt;span style="COLOR: rgb(0,128,0)"&gt;&amp;nbsp; TO: /blog/default.aspx?date=2004-07-27&lt;/span&gt;
&lt;br style="COLOR: rgb(0,128,0)"&gt;
&lt;span style="COLOR: rgb(0,128,0)"&gt;--&amp;gt;&lt;/span&gt;
&lt;br style="COLOR: rgb(0,128,0)"&gt;
&lt;span style="COLOR: rgb(0,128,0)"&gt;&amp;lt;&lt;span style="COLOR: rgb(165,42,42)"&gt;ad&lt;/span&gt;&lt;/span&gt;&lt;span style="COLOR: rgb(165,42,42)"&gt;d&lt;/span&gt; &lt;span style="COLOR: rgb(255,0,0)"&gt;matchExpression &lt;/span&gt;= &lt;/font&gt;&lt;font face="Courier New" size=2&gt;&lt;span style="COLOR: rgb(0,0,255)"&gt;"(?&amp;amp;lt;basedir&amp;amp;gt;.*?)/archive/(?&amp;amp;lt;year&amp;amp;gt;\d{4})/(?&amp;amp;lt;month&amp;amp;gt;\d{2})/(?&amp;amp;lt;day&amp;amp;gt;\d{2})/(?&amp;amp;lt;postid&amp;amp;gt;\d+)\.aspx"&lt;/span&gt;
&lt;br&gt;
&lt;/font&gt;&lt;font face="Courier New"&gt;&amp;nbsp;&lt;span style="COLOR: rgb(255,0,0)"&gt;mapTo&lt;/span&gt;=&lt;span style="COLOR: rgb(0,0,255)"&gt;"{basedir}/default.aspx?date={year}-{month}-{day}"&lt;/span&gt; /&amp;gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 
&lt;br&gt;
&lt;/font&gt;
&lt;br&gt;
Now, an old .TEXT url out in the wild like &lt;a href="archive/2004/07/27/194.aspx" target=_blank&gt;http://flimflan.com/blog/archive/2004/07/27/194.aspx&lt;/a&gt; will
correctly resolve to the corresponding post in dasBlog.&lt;br&gt;
&lt;br&gt;
&lt;br&gt;
To allow the .TEXT feed URL to resolve (Rss.aspx), I changed this existing entry in
the UrlMapper section from:&lt;br&gt;
&lt;font face="Courier New"&gt;&amp;lt;&lt;span style="COLOR: rgb(165,42,42)"&gt;add&lt;/span&gt; &lt;span style="COLOR: rgb(255,0,0)"&gt;matchExpression&lt;/span&gt;=&lt;span style="COLOR: rgb(0,0,255)"&gt;"(?&amp;amp;lt;basedir&amp;amp;gt;.*?)/rss\.ashx"&lt;/span&gt;&amp;nbsp; &lt;span style="COLOR: rgb(255,0,0)"&gt;mapTo&lt;/span&gt;=&lt;span style="COLOR: rgb(0,0,255)"&gt;"{basedir}/SyndicationService.asmx/GetRss?"&lt;/span&gt; /&amp;gt;&lt;/font&gt;
&lt;br&gt;
&lt;br&gt;
to:&lt;br&gt;
&lt;font face="Courier New"&gt;&amp;lt;&lt;span style="COLOR: rgb(165,42,42)"&gt;add&lt;/span&gt; &lt;span style="COLOR: rgb(255,0,0)"&gt;matchExpression&lt;/span&gt;=&lt;span style="COLOR: rgb(0,0,255)"&gt;"(?&amp;amp;lt;basedir&amp;amp;gt;.*?)/rss\.as&lt;/span&gt;&lt;span style="FONT-WEIGHT: bold; COLOR: rgb(0,0,255)"&gt;[hp]&lt;/span&gt;&lt;span style="COLOR: rgb(0,0,255)"&gt;x"&lt;/span&gt;&lt;span style="COLOR: rgb(255,0,0)"&gt; mapTo&lt;/span&gt;=&lt;span style="COLOR: rgb(0,0,255)"&gt;"{basedir}/SyndicationService.asmx/GetRss?"&lt;/span&gt; /&amp;gt;&lt;/font&gt; 
&lt;br&gt;
&lt;br&gt;
Now if only there was a way to migrate that skin I spent so much time on...&lt;br&gt;
&lt;img width="0" height="0" src="http://flimflan.com/blog/aggbug.ashx?id=57a2115f-29a1-4ffa-8b2e-dbedf61263b9" /&gt;</description>
      <comments>http://flimflan.com/blog/CommentView,guid,57a2115f-29a1-4ffa-8b2e-dbedf61263b9.aspx</comments>
      <category>.NET</category>
      <category>dasBlog</category>
    </item>
    <item>
      <trackback:ping>http://flimflan.com/blog/Trackback.aspx?guid=ad553aa7-c3f1-4394-b029-69b9b88af713</trackback:ping>
      <pingback:server>http://flimflan.com/blog/pingback.aspx</pingback:server>
      <pingback:target>http://flimflan.com/blog/PermaLink,guid,ad553aa7-c3f1-4394-b029-69b9b88af713.aspx</pingback:target>
      <dc:creator>
      </dc:creator>
      <wfw:comment>http://flimflan.com/blog/CommentView,guid,ad553aa7-c3f1-4394-b029-69b9b88af713.aspx</wfw:comment>
      <wfw:commentRss>http://flimflan.com/blog/SyndicationService.asmx/GetEntryCommentsRss?guid=ad553aa7-c3f1-4394-b029-69b9b88af713</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
The numbers in <a href="http://flimflan.com/blog/DoYouBelieveInConnectionPooling.aspx">my
last post</a> were a little misleading (as you might expect from un-scientific homebrew
benchmarks). I showed that ExplicitOpen (2.5 seconds) was slightly faster than ImplicitOpen
(2.9 seconds), but both were significantly faster than NoConnectionPooling (7.5 seconds).
The whole point of the test was to see how the performance of running 2 queries within
a method could vary, based on different approaches. However, in order to get a larger
sample size, I ran the methods within a loop for 1000 iterations. It was intended
to just give me more test runs, but the loop actually had a side effect. When connection
pooling was enabled (for ExplicitOpen and ImplicitOpen), the same connection was used
for all 1000 iterations. I had only wanted the same connection to be used for the
2 queries within the methods. So when I turned connection pooling off, the dramatic
difference wasn’t because running the 2 queries was much slower – it was because I
was now making 2000 connections to the database instead of 1.
</p>
        <p>
If I wanted to compare the performance of running the 2 queries with connection pooling
on and off, within a loop, I would need to make sure each iteration of the loop used
a new connection in all 3 scenarios (ExplicitOpen, ImplicitOpen, NoConnectionPooling). 
<br />
An easy way to force a new connection is to change the connection string. I changed
the signature of each of the methods to accept an integer argument:
</p>
        <p>
          <span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">
            <span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">static</span>
            <span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">void</span> ExplicitOpen(<span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">int</span> iteration)<br /></span>
        </p>
        <p>
I then added an Application Name property to the connection string; altering the application
name for each iteration:
</p>
        <p>
          <span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">
            <span style="FONT-SIZE: 11px; COLOR: #666666; FONT-FAMILY: Courier New; BACKGROUND-COLOR: #e4e4e4">"data
source=(local);initial catalog=issuevision;integrated security=true;application name=TestCP"</span>
            <span style="FONT-SIZE: 11px; COLOR: red; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">+</span> iteration.ToString()<br /></span>
        </p>
        <p>
The new results:
</p>
        <p>
          <span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">ExplicitOpen
9.0<br />
ImplicitOpen 9.5<br />
NoConnectionPooling 7.6</span>
        </p>
        <p>
These results show that ExplicitOpen is still faster than ImplicitOpen, but now NoConnectionPooling
is much faster than the other 2. How can this be? Well, since none of the scenarios
are reusing a connection across iterations, you gain an advantage by removing the
connection pooling overhead by explicitly disabling it in the connection string.
</p>
        <p>
The original conclusion was correct (ExplicitOpen is slightly faster than ImplicitOpen),
but it is difficult to measure the relative performance with connection pooling turned
off. The results of running a single iteration of each method vary too widely to draw
any conclusions -- you need the multiple iterations for things to average out. But
once you introduce multiple iterations, you blur the effect of connection pooling. 
</p>
        <p>
As a bonus, we can now conclude that if you know you are not going to re-use
a connection (rare, unless each user of your application is given their own database
login), it is better to turn off connection pooling explicitly.<br /></p>
        <img width="0" height="0" src="http://flimflan.com/blog/aggbug.ashx?id=ad553aa7-c3f1-4394-b029-69b9b88af713" />
      </body>
      <title>Fixing my connection pooling benchmarks</title>
      <guid isPermaLink="false">http://flimflan.com/blog/PermaLink,guid,ad553aa7-c3f1-4394-b029-69b9b88af713.aspx</guid>
      <link>http://flimflan.com/blog/FixingMyConnectionPoolingBenchmarks.aspx</link>
      <pubDate>Fri, 04 Nov 2005 17:12:58 GMT</pubDate>
      <description>&lt;p&gt;
The numbers in &lt;a href="http://flimflan.com/blog/DoYouBelieveInConnectionPooling.aspx"&gt;my
last post&lt;/a&gt; were a little misleading (as you might expect from un-scientific homebrew
benchmarks). I showed that ExplicitOpen (2.5 seconds) was slightly faster than ImplicitOpen
(2.9 seconds), but both were significantly faster than NoConnectionPooling (7.5 seconds).
The whole point of the test was to see how the performance of running 2 queries within
a method could vary, based on different approaches. However, in order to get a larger
sample size, I ran the methods within a loop for 1000 iterations. It was intended
to just give me more test runs, but the loop actually had a side effect. When connection
pooling was enabled (for ExplicitOpen and ImplicitOpen), the same connection was used
for all 1000 iterations. I had only wanted the same connection to be used for the
2 queries within the methods. So when I turned connection pooling off, the dramatic
difference wasn’t because running the 2 queries was much slower – it was because I
was now making 2000 connections to the database instead of 1.
&lt;/p&gt;
&lt;p&gt;
If I wanted to compare the performance of running the 2 queries with connection pooling
on and off, within a loop, I would need to make sure each iteration of the loop used
a new connection in all 3 scenarios (ExplicitOpen, ImplicitOpen, NoConnectionPooling). 
&lt;br&gt;
An easy way to force a new connection is to change the connection string. I changed
the signature of each of the methods to accept an integer argument:
&lt;/p&gt;
&lt;p&gt;
&lt;span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;&lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;static&lt;/span&gt; &lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;void&lt;/span&gt; ExplicitOpen(&lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;int&lt;/span&gt; iteration)&lt;br&gt;
&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;
I then added an Application Name property to the connection string; altering the application
name for each iteration:
&lt;/p&gt;
&lt;p&gt;
&lt;span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;&lt;span style="FONT-SIZE: 11px; COLOR: #666666; FONT-FAMILY: Courier New; BACKGROUND-COLOR: #e4e4e4"&gt;"data
source=(local);initial catalog=issuevision;integrated security=true;application name=TestCP"&lt;/span&gt; &lt;span style="FONT-SIZE: 11px; COLOR: red; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;+&lt;/span&gt; iteration.ToString()&lt;br&gt;
&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;
The new results:
&lt;/p&gt;
&lt;p&gt;
&lt;span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;ExplicitOpen
9.0&lt;br&gt;
ImplicitOpen 9.5&lt;br&gt;
NoConnectionPooling 7.6&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;
These results show that ExplicitOpen is still faster than ImplicitOpen, but now NoConnectionPooling
is much faster than the other 2. How can this be? Well, since none of the scenarios
are reusing a connection across iterations, you gain an advantage by removing the
connection pooling overhead by explicitly disabling it in the connection string.
&lt;/p&gt;
&lt;p&gt;
The original conclusion was correct (ExplicitOpen is slightly faster than ImplicitOpen),
but it is difficult to measure the relative performance with connection pooling turned
off. The results of running a single iteration of each method vary too widely to draw
any conclusions -- you need the multiple iterations for things to average out.&amp;nbsp;But
once you introduce multiple iterations, you blur the effect of connection pooling. 
&lt;/p&gt;
&lt;p&gt;
As a bonus, we can&amp;nbsp;now conclude that if you know you are not going to re-use
a connection (rare, unless each user of your application is given their own database
login), it is better to turn off connection pooling explicitly.&lt;br&gt;
&lt;/p&gt;
&lt;img width="0" height="0" src="http://flimflan.com/blog/aggbug.ashx?id=ad553aa7-c3f1-4394-b029-69b9b88af713" /&gt;</description>
      <comments>http://flimflan.com/blog/CommentView,guid,ad553aa7-c3f1-4394-b029-69b9b88af713.aspx</comments>
      <category>.NET</category>
    </item>
    <item>
      <trackback:ping>http://flimflan.com/blog/Trackback.aspx?guid=942c07d1-6b47-4006-8c6b-8c895ce48eee</trackback:ping>
      <pingback:server>http://flimflan.com/blog/pingback.aspx</pingback:server>
      <pingback:target>http://flimflan.com/blog/PermaLink,guid,942c07d1-6b47-4006-8c6b-8c895ce48eee.aspx</pingback:target>
      <dc:creator>
      </dc:creator>
      <wfw:comment>http://flimflan.com/blog/CommentView,guid,942c07d1-6b47-4006-8c6b-8c895ce48eee.aspx</wfw:comment>
      <wfw:commentRss>http://flimflan.com/blog/SyndicationService.asmx/GetEntryCommentsRss?guid=942c07d1-6b47-4006-8c6b-8c895ce48eee</wfw:commentRss>
      <slash:comments>3</slash:comments>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
David hayden's <a href="http://codebetter.com/blogs/david.hayden/archive/2005/11/03/134238.aspx">post
about explicitly opening SqlConnection objects</a> when doing multiple SqlDataAdapter.Fill
calls didn't sit well with me. The premise is that if you are going to make multiple
calls to Fill(), you should open the connection first yourself, to avoid Fill() opening
and closing the connection for each call. I'll quote his conclusion:
</p>
        <p>
          <!--StartFragment -->"...in the case of multiple back-to-back Fill requests to the
DataAdapter, it is more performant to explicitly open the connection in the beginning
so that each Fill request on the DataAdapter does not open and close the database
connection, resulting in the database connection being opened and closed several times."
</p>
        <p>
The reason it doesn't sit well with me, is that I believe in connection pooling. I
don't know all of the gory details of how it works under the hood, but I believe it
exists. I believe that when I call SqlConnection.Open(), I am not necessarily creating
a new network connection to the database - I may just be re-using an existing connection
that is sitting idle in the pool.
</p>
        <p>
But he was quoting <a href="http://codebetter.com/blogs/sahil.malik/">Sahil's</a> Pro
ADO.NET 2.0, and I have no doubt that Sahil knows more about ADO and SQL Server than
I do, so I started to doubt my belief.  Maybe connection pooling really DOESN'T
exist! Time to get some cold hard facts, (in the form of completely un-scientific
homebrew benchmarks).
</p>
        <p>
The test harness:
</p>
        <p>
          <span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">
            <span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">static</span>
            <span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">void</span> Main(<span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">string</span>[]
args)<br />
{<br />
System.Diagnostics.Stopwatch sw <span style="FONT-SIZE: 11px; COLOR: red; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">=</span><span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">new</span> System.Diagnostics.Stopwatch();<br />
sw.Start();<br /><span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">for</span> (<span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">int</span> i <span style="FONT-SIZE: 11px; COLOR: red; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">=</span> 0;
i &lt; 1000; i++)<br />
{<br />
ExplicitOpen();<br /><span style="FONT-SIZE: 11px; COLOR: green; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">//ImplicitOpen();</span><br />
}<br />
sw.Stop();<br />
Console.WriteLine(sw.Elapsed);<br />
}</span>
        </p>
        <p>
          <span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">
          </span>Very
simple. Run one of the methods a thousand times, and report the cumulative elapsed
time.  Comment it out, un-comment the other one, and re-run.
</p>
        <p>
The code for the two different methods are almost exactly the same. I only made very
minor changes to the code from David's post, to account for the fact that I didn't
have the pubs database handy (I used the <a href="http://www.windowsforms.net/Applications/application.aspx?PageID=40&amp;tabindex=9">IssueVision</a> database
from the DevDays 2004 sample app).
</p>
        <p>
Here is the code for ExplicitOpen():
</p>
        <p>
          <span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">
            <span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">static</span>
            <span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">void</span> ExplicitOpen()<br />
{<br /><span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">using</span> (SqlConnection
connection <span style="FONT-SIZE: 11px; COLOR: red; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">=</span><span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">new</span> SqlConnection(<span style="FONT-SIZE: 11px; COLOR: rgb(102,102,102); FONT-FAMILY: Courier New; BACKGROUND-COLOR: rgb(228,228,228)">"data
source=(local);initial catalog=issuevision;integrated security=true;"</span>))<br />
{<br />
SqlCommand sqlCat <span style="FONT-SIZE: 11px; COLOR: red; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">=</span> connection.CreateCommand();<br />
sqlCat.CommandText <span style="FONT-SIZE: 11px; COLOR: red; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">=</span><span style="FONT-SIZE: 11px; COLOR: rgb(102,102,102); FONT-FAMILY: Courier New; BACKGROUND-COLOR: rgb(228,228,228)">"Select
* from issues"</span>;<br />
SqlCommand sqlProd <span style="FONT-SIZE: 11px; COLOR: red; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">=</span> connection.CreateCommand();<br />
sqlProd.CommandText <span style="FONT-SIZE: 11px; COLOR: red; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">=</span><span style="FONT-SIZE: 11px; COLOR: rgb(102,102,102); FONT-FAMILY: Courier New; BACKGROUND-COLOR: rgb(228,228,228)">"Select
* from staffers"</span>;<br /><br />
SqlDataAdapter adapter <span style="FONT-SIZE: 11px; COLOR: red; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">=</span><span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">new</span> SqlDataAdapter();<br />
adapter.SelectCommand <span style="FONT-SIZE: 11px; COLOR: red; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">=</span> sqlCat;<br />
DataSet dataset <span style="FONT-SIZE: 11px; COLOR: red; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">=</span><span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">new</span> DataSet();<br /><br />
connection.Open();<br />
adapter.Fill(dataset, <span style="FONT-SIZE: 11px; COLOR: rgb(102,102,102); FONT-FAMILY: Courier New; BACKGROUND-COLOR: rgb(228,228,228)">"Issues"</span>);<br />
adapter.SelectCommand <span style="FONT-SIZE: 11px; COLOR: red; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">=</span> sqlProd;<br />
adapter.Fill(dataset, <span style="FONT-SIZE: 11px; COLOR: rgb(102,102,102); FONT-FAMILY: Courier New; BACKGROUND-COLOR: rgb(228,228,228)">"Staffers"</span>);<br />
connection.Close();<br />
}<br />
}</span>
        </p>
        <p>
ImplicitOpen() is exactly the same, only the connection.Open() and connection.Close()
lines are removed.
</p>
        <p>
Running ExplicitOpen() 1000 times took an average of 2.5 seconds. Running ImplicitOpen()
1000 times took an everage of 2.9 seconds. I ran them both multiple times and the
numbers were always consistent, so I think they are somewhat believable.<br />
How about that. Opening the connection explicitly IS a bit faster. So does that mean
connection pooling doesn't exist?
</p>
        <p>
I opened the Profiler tool included with SQL Server 2000 and created a connection
to my database with the default profiling template. I removed the looping in the main
method so that the method would only be called once.  This is what I saw when
I ran ExplicitOpen():
</p>
        <p>
          <span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">Audit
Login<br />
SQL:BatchCompleted   Select * from issues<br />
SQL:BatchCompleted   Select * from staffers<br />
Audit Logout</span>
        </p>
        <p>
          <span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">
            <font face="Verdana" color="#003300" size="2">This
is what I saw when I ran ImplicitOpen():</font>
          </span>
        </p>
        <p>
          <span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">Audit
Login<br />
SQL:BatchCompleted   Select * from issues<br />
RPC:Completed        exec sp_reset_connection<br />
SQL:BatchCompleted   Select * from staffers<br />
Audit Logout</span>
        </p>
        <p>
          <span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">
            <span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">
              <font face="Verdana" color="#003300" size="2">
                <font face="Verdana" color="#003300" size="2">Aha!
As you can see, there is still only 1 connection being made (a single Audit Login
and Audit Logout). So it looks like we're both right. There is always 1 connection,
but explictly opening is still slightly faster. The difference is the call to
sp_reset_connection (which is undocumented in Books Online) which cleans up the connection
so it can be re-used.</font>
              </font>
            </span>
          </span>
        </p>
        <p>
          <span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">
            <span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">
              <font face="Verdana" color="#003300" size="2">
                <font face="Verdana" color="#003300" size="2">So,
if I could get rid of that call to sp_reset_connection, could I get the same performance
as ExplicitOpen()? I copied ImplicitOpen() to a new method and named it ImplicitOpenNoReset().
The only change I made was appending "connection reset=false;" to the end of the connection
string. Running 1000 iterations took 2.6 seconds. Much closer to ExplicitOpen(), but
there is still a bit of overhead. (Warning: I have no idea how safe or advisable it
is to disable the connection reset - do not interpret this as a recommendation for
improving your connection pooling performance for general usage - it was just for
the purposes of this test.)<br /></font>
              </font>
            </span>
          </span>
        </p>
        <p>
          <span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">
            <span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">
              <font face="Verdana" color="#003300" size="2">
                <font face="Verdana" color="#003300" size="2">Finally,
to prove to myself that connection pooling really does exist, and really does help,
I created a new copy of ImplicitOpen() named NoConnectionPooling(). The only difference
is the connection string includes "pooling=false;". Running 1000 iterations took...
7.5 seconds! Ouch.</font>
              </font>
            </span>
          </span>
        </p>
        <p>
          <span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">
            <span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">
              <font face="Verdana" color="#003300" size="2">
                <font face="Verdana" color="#003300" size="2">My
take away is that connection pooling really exists, it really does help you, and in
general, you do not have to worry about maximing the use of an open SqlConnection
object by keeping it around for multiple queries. But if you have to squeeze out the
absolute best performance possible, you will get a slight gain by calling Open() once
when you have consecutive queries. Thanks to David for a thought-provoking post. </font>
              </font>
            </span>
          </span>
        </p>
        <p>
          <span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">
            <span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">
              <font face="Verdana" color="#003300" size="2">
                <font face="Verdana" color="#003300" size="2">
                  <strong>Update</strong>:
I discovered a flaw in my benchmarking approach which skewed some of these results. I
wrote up the details in a <a href="http://flimflan.com/blog/FixingMyConnectionPoolingBenchmarks.aspx">new
post</a>.<br /></font>
              </font>
            </span>
          </span>
        </p>
        <img width="0" height="0" src="http://flimflan.com/blog/aggbug.ashx?id=942c07d1-6b47-4006-8c6b-8c895ce48eee" />
      </body>
      <title>Do you believe in connection pooling?</title>
      <guid isPermaLink="false">http://flimflan.com/blog/PermaLink,guid,942c07d1-6b47-4006-8c6b-8c895ce48eee.aspx</guid>
      <link>http://flimflan.com/blog/DoYouBelieveInConnectionPooling.aspx</link>
      <pubDate>Fri, 04 Nov 2005 05:17:56 GMT</pubDate>
      <description>&lt;p&gt;
David hayden's &lt;a href="http://codebetter.com/blogs/david.hayden/archive/2005/11/03/134238.aspx"&gt;post
about explicitly opening SqlConnection objects&lt;/a&gt; when doing multiple SqlDataAdapter.Fill
calls didn't sit well with me. The premise is that if you are going to make multiple
calls to Fill(), you should open the connection first yourself, to avoid Fill() opening
and closing the connection for each call. I'll quote his conclusion:
&lt;/p&gt;
&lt;p&gt;
&lt;!--StartFragment --&gt;"...in the case of multiple back-to-back Fill requests to the
DataAdapter, it is more performant to explicitly open the connection in the beginning
so that each Fill request on the DataAdapter does not open and close the database
connection, resulting in the database connection being opened and closed several times."
&lt;/p&gt;
&lt;p&gt;
The reason it doesn't sit well with me, is that I believe in connection pooling.&amp;nbsp;I
don't know all of the gory details of how it works under the hood, but I believe it
exists. I believe that when I call SqlConnection.Open(), I am not necessarily creating
a new network connection to the database - I may just be re-using an existing connection
that is sitting idle in the pool.
&lt;/p&gt;
&lt;p&gt;
But he was quoting &lt;a href="http://codebetter.com/blogs/sahil.malik/"&gt;Sahil's&lt;/a&gt; Pro
ADO.NET 2.0, and I have no doubt that Sahil knows more about ADO and SQL Server than
I do, so I started to doubt my belief.&amp;nbsp; Maybe connection pooling really DOESN'T
exist! Time to get some cold hard facts, (in the form of completely un-scientific
homebrew benchmarks).
&lt;/p&gt;
&lt;p&gt;
The test harness:
&lt;/p&gt;
&lt;p&gt;
&lt;span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;&lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;static&lt;/span&gt; &lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;void&lt;/span&gt; Main(&lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;string&lt;/span&gt;[]
args)&lt;br&gt;
{&lt;br&gt;
System.Diagnostics.Stopwatch sw &lt;span style="FONT-SIZE: 11px; COLOR: red; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;=&lt;/span&gt; &lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;new&lt;/span&gt; System.Diagnostics.Stopwatch();&lt;br&gt;
sw.Start();&lt;br&gt;
&lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;for&lt;/span&gt; (&lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;int&lt;/span&gt; i &lt;span style="FONT-SIZE: 11px; COLOR: red; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;=&lt;/span&gt; 0;
i &amp;lt; 1000; i++)&lt;br&gt;
{&lt;br&gt;
ExplicitOpen();&lt;br&gt;
&lt;span style="FONT-SIZE: 11px; COLOR: green; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;//ImplicitOpen();&lt;/span&gt;
&lt;br&gt;
}&lt;br&gt;
sw.Stop();&lt;br&gt;
Console.WriteLine(sw.Elapsed);&lt;br&gt;
}&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;&lt;/span&gt;Very
simple. Run one of the methods a thousand times, and report the cumulative elapsed
time.&amp;nbsp; Comment it out, un-comment the other one, and re-run.
&lt;/p&gt;
&lt;p&gt;
The code for the two different methods are almost exactly the same. I only made very
minor changes to the code from David's post, to account for the fact that I didn't
have the pubs database handy (I used the &lt;a href="http://www.windowsforms.net/Applications/application.aspx?PageID=40&amp;amp;tabindex=9"&gt;IssueVision&lt;/a&gt; database
from the DevDays 2004 sample app).
&lt;/p&gt;
&lt;p&gt;
Here is the code for ExplicitOpen():
&lt;/p&gt;
&lt;p&gt;
&lt;span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;&lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;static&lt;/span&gt; &lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;void&lt;/span&gt; ExplicitOpen()&lt;br&gt;
{&lt;br&gt;
&lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;using&lt;/span&gt; (SqlConnection
connection &lt;span style="FONT-SIZE: 11px; COLOR: red; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;=&lt;/span&gt; &lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;new&lt;/span&gt; SqlConnection(&lt;span style="FONT-SIZE: 11px; COLOR: rgb(102,102,102); FONT-FAMILY: Courier New; BACKGROUND-COLOR: rgb(228,228,228)"&gt;"data
source=(local);initial catalog=issuevision;integrated security=true;"&lt;/span&gt;))&lt;br&gt;
{&lt;br&gt;
SqlCommand sqlCat &lt;span style="FONT-SIZE: 11px; COLOR: red; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;=&lt;/span&gt; connection.CreateCommand();&lt;br&gt;
sqlCat.CommandText &lt;span style="FONT-SIZE: 11px; COLOR: red; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;=&lt;/span&gt; &lt;span style="FONT-SIZE: 11px; COLOR: rgb(102,102,102); FONT-FAMILY: Courier New; BACKGROUND-COLOR: rgb(228,228,228)"&gt;"Select
* from issues"&lt;/span&gt;;&lt;br&gt;
SqlCommand sqlProd &lt;span style="FONT-SIZE: 11px; COLOR: red; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;=&lt;/span&gt; connection.CreateCommand();&lt;br&gt;
sqlProd.CommandText &lt;span style="FONT-SIZE: 11px; COLOR: red; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;=&lt;/span&gt; &lt;span style="FONT-SIZE: 11px; COLOR: rgb(102,102,102); FONT-FAMILY: Courier New; BACKGROUND-COLOR: rgb(228,228,228)"&gt;"Select
* from staffers"&lt;/span&gt;;&lt;br&gt;
&lt;br&gt;
SqlDataAdapter adapter &lt;span style="FONT-SIZE: 11px; COLOR: red; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;=&lt;/span&gt; &lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;new&lt;/span&gt; SqlDataAdapter();&lt;br&gt;
adapter.SelectCommand &lt;span style="FONT-SIZE: 11px; COLOR: red; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;=&lt;/span&gt; sqlCat;&lt;br&gt;
DataSet dataset &lt;span style="FONT-SIZE: 11px; COLOR: red; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;=&lt;/span&gt; &lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;new&lt;/span&gt; DataSet();&lt;br&gt;
&lt;br&gt;
connection.Open();&lt;br&gt;
adapter.Fill(dataset, &lt;span style="FONT-SIZE: 11px; COLOR: rgb(102,102,102); FONT-FAMILY: Courier New; BACKGROUND-COLOR: rgb(228,228,228)"&gt;"Issues"&lt;/span&gt;);&lt;br&gt;
adapter.SelectCommand &lt;span style="FONT-SIZE: 11px; COLOR: red; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;=&lt;/span&gt; sqlProd;&lt;br&gt;
adapter.Fill(dataset, &lt;span style="FONT-SIZE: 11px; COLOR: rgb(102,102,102); FONT-FAMILY: Courier New; BACKGROUND-COLOR: rgb(228,228,228)"&gt;"Staffers"&lt;/span&gt;);&lt;br&gt;
connection.Close();&lt;br&gt;
}&lt;br&gt;
}&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;
ImplicitOpen() is exactly the same, only the connection.Open() and connection.Close()
lines are removed.
&lt;/p&gt;
&lt;p&gt;
Running ExplicitOpen() 1000 times took an average of 2.5 seconds. Running ImplicitOpen()
1000 times took an everage of 2.9 seconds. I ran them both multiple times and the
numbers were always consistent, so I think they are somewhat believable.&lt;br&gt;
How about that. Opening the connection explicitly IS a bit faster. So does that mean
connection pooling doesn't exist?
&lt;/p&gt;
&lt;p&gt;
I opened the Profiler tool included with SQL Server 2000 and created a connection
to my database with the default profiling template. I removed the looping in the main
method so that the method would only be called once.&amp;nbsp; This is what I saw when
I ran ExplicitOpen():
&lt;/p&gt;
&lt;p&gt;
&lt;span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;Audit
Login&lt;br&gt;
SQL:BatchCompleted&amp;nbsp;&amp;nbsp;&amp;nbsp;Select * from issues&lt;br&gt;
SQL:BatchCompleted&amp;nbsp;&amp;nbsp;&amp;nbsp;Select * from staffers&lt;br&gt;
Audit Logout&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;&lt;font face=Verdana color=#003300 size=2&gt;This
is what I saw when I ran ImplicitOpen():&lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;Audit
Login&lt;br&gt;
SQL:BatchCompleted&amp;nbsp;&amp;nbsp;&amp;nbsp;Select * from issues&lt;br&gt;
RPC:Completed&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;exec sp_reset_connection&lt;br&gt;
SQL:BatchCompleted&amp;nbsp;&amp;nbsp;&amp;nbsp;Select * from staffers&lt;br&gt;
Audit Logout&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;&lt;span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;&lt;font face=Verdana color=#003300 size=2&gt;&lt;font face=Verdana color=#003300 size=2&gt;Aha!
As you can see, there is still only 1 connection being made (a single Audit Login
and Audit Logout). So it looks like we're both right. There is always 1 connection,
but explictly opening is still slightly faster.&amp;nbsp;The difference is the call to
sp_reset_connection (which is undocumented in Books Online) which cleans up the connection
so it can be re-used.&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;&lt;span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;&lt;font face=Verdana color=#003300 size=2&gt;&lt;font face=Verdana color=#003300 size=2&gt;So,
if I could get rid of that call to sp_reset_connection, could I get the same performance
as ExplicitOpen()? I copied ImplicitOpen() to a new method and named it ImplicitOpenNoReset().
The only change I made was appending "connection reset=false;" to the end of the connection
string. Running 1000 iterations took 2.6 seconds. Much closer to ExplicitOpen(), but
there is still a bit of overhead. (Warning: I have no idea how safe or advisable it
is to disable the connection reset - do not interpret this as a recommendation for
improving your connection pooling performance for general usage - it was just for
the purposes of this test.)&lt;br&gt;
&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;&lt;span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;&lt;font face=Verdana color=#003300 size=2&gt;&lt;font face=Verdana color=#003300 size=2&gt;Finally,
to prove to myself that connection pooling really does exist, and really does help,
I created a new copy of ImplicitOpen() named NoConnectionPooling(). The only difference
is the connection string includes "pooling=false;". Running 1000 iterations took...
7.5 seconds! Ouch.&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;&lt;span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;&lt;font face=Verdana color=#003300 size=2&gt;&lt;font face=Verdana color=#003300 size=2&gt;My
take away is that connection pooling really exists, it really does help you, and in
general, you do not have to worry about maximing the use of an open SqlConnection
object by keeping it around for multiple queries. But if you have to squeeze out the
absolute best performance possible, you will get a slight gain by calling Open() once
when you have consecutive queries. Thanks to David for a thought-provoking post. &lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;&lt;span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;&lt;font face=Verdana color=#003300 size=2&gt;&lt;font face=Verdana color=#003300 size=2&gt;&lt;strong&gt;Update&lt;/strong&gt;:
I discovered a flaw in my benchmarking approach which skewed some of these results.&amp;nbsp;I
wrote up the details in a &lt;a href="http://flimflan.com/blog/FixingMyConnectionPoolingBenchmarks.aspx"&gt;new
post&lt;/a&gt;.&lt;br&gt;
&lt;/p&gt;
&gt;&gt;&gt;&gt;&lt;img width="0" height="0" src="http://flimflan.com/blog/aggbug.ashx?id=942c07d1-6b47-4006-8c6b-8c895ce48eee" /&gt;</description>
      <comments>http://flimflan.com/blog/CommentView,guid,942c07d1-6b47-4006-8c6b-8c895ce48eee.aspx</comments>
      <category>.NET</category>
    </item>
  </channel>
</rss>