<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/atom10full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><feed xmlns="http://www.w3.org/2005/Atom" xmlns:openSearch="http://a9.com/-/spec/opensearch/1.1/" xmlns:georss="http://www.georss.org/georss" xmlns:gd="http://schemas.google.com/g/2005" gd:etag="W/&quot;D0QNRn49fCp7ImA9WxBUFUo.&quot;"><id>tag:blogger.com,1999:blog-1664217632350055880</id><updated>2010-03-02T17:16:37.064-07:00</updated><title>Murray on .NET</title><subtitle type="html">If only someone else had posted about this stuff first...</subtitle><link rel="http://schemas.google.com/g/2005#feed" type="application/atom+xml" href="http://murrayon.net/feeds/posts/default" /><link rel="alternate" type="text/html" href="http://murrayon.net/" /><link rel="hub" href="http://pubsubhubbub.appspot.com/" /><link rel="next" type="application/atom+xml" href="http://www.blogger.com/feeds/1664217632350055880/posts/default?start-index=26&amp;max-results=25&amp;redirect=false&amp;v=2" /><author><name>Mike Murray</name><uri>http://www.blogger.com/profile/01990150469958605173</uri><email>noreply@blogger.com</email></author><generator version="7.00" uri="http://www.blogger.com">Blogger</generator><openSearch:totalResults>62</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/atom+xml" href="http://feeds.feedburner.com/MurrayOnNET" /><feedburner:info xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" uri="murrayonnet" /><entry gd:etag="W/&quot;CUAHSH8yfip7ImA9WxBVF0w.&quot;"><id>tag:blogger.com,1999:blog-1664217632350055880.post-2654738557567584288</id><published>2010-02-20T17:55:00.001-07:00</published><updated>2010-02-20T17:55:39.196-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-02-20T17:55:39.196-07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="New Technology" /><category scheme="http://www.blogger.com/atom/ns#" term="BDD" /><category scheme="http://www.blogger.com/atom/ns#" term=".NET" /><category scheme="http://www.blogger.com/atom/ns#" term="Testing" /><category scheme="http://www.blogger.com/atom/ns#" term="Anagram Code Kata Series" /><category scheme="http://www.blogger.com/atom/ns#" term="MSpec" /><category scheme="http://www.blogger.com/atom/ns#" term="Mocking" /><category scheme="http://www.blogger.com/atom/ns#" term="C#" /><category scheme="http://www.blogger.com/atom/ns#" term="Visual Studio" /><category scheme="http://www.blogger.com/atom/ns#" term="Microsoft" /><category scheme="http://www.blogger.com/atom/ns#" term="Code Organization" /><category scheme="http://www.blogger.com/atom/ns#" term="SOLID" /><title>Anagram Code Kata Part 5 – Domain Objects Over Language Primitives</title><content type="html">&lt;p&gt;This post is part of a &lt;a href="http://murrayon.net/2009/11/anagram-code-kata-bdd-mspec.html"&gt;series on coding Kata, BDD, MSpec, and SOLID principles&lt;/a&gt;.&amp;#160; Feel free to visit the above link which points to the introductory post, also containing an index of all posts in the series.&lt;/p&gt;  &lt;p&gt;In this post, we will discuss some reasons why you might want to avoid using language primitives directly in place of domain objects.&amp;#160; Specifically, I have been using &lt;font face="Courier New"&gt;String&lt;/font&gt; variables and objects to represent words up to this point.&amp;#160; &lt;a href="http://adotnetdude.blogspot.com/"&gt;Esteban&lt;/a&gt; suggested I create a &lt;font face="Courier New"&gt;Word&lt;/font&gt; class for a few good reasons which I’ll layout for you.&amp;#160; Out of sheer luck and good timing, &lt;a href="http://codebetter.com/blogs/dru.sellers/default.aspx"&gt;Dru Sellers&lt;/a&gt; of &lt;a href="http://codebetter.com/"&gt;CodeBetter.com&lt;/a&gt; also wrote on this subject shortly afterward and confirmed Esteban’s reasoning.&lt;/p&gt; &lt;span class="fullpost"&gt;   &lt;h3&gt;Use &lt;font face="Courier New"&gt;String&lt;/font&gt; Class or Create &lt;font face="Courier New"&gt;Word&lt;/font&gt; Domain Object?&lt;/h3&gt;    &lt;p&gt;I mentioned in the previous post that Esteban had suggested creating a &lt;font face="Courier New"&gt;Word&lt;/font&gt; class instead of just passing around strings everywhere through my application.&amp;#160; One good reason is that we don’t own the &lt;font face="Courier New"&gt;String&lt;/font&gt; class and so further modification to our string-based implementation is difficult because the logic is scattered throughout the application, instead of centralized under the responsibility and definition of one domain class.&amp;#160; It is much more difficult to refactor the word-specific logic with its behaviors and attributes spread throughout the code.&amp;#160; Even if your &lt;font face="Courier New"&gt;Word&lt;/font&gt; class doesn’t grow any more beyond a seemingly unnecessary wrapper of the &lt;font face="Courier New"&gt;String&lt;/font&gt; class, the code is more cohesive and ready for change should the need arise.&lt;/p&gt;    &lt;p&gt;But more importantly, you designed the code thinking in a true object-oriented mindset.&amp;#160; You have to keep in mind that the &lt;font face="Courier New"&gt;String&lt;/font&gt; class is someone else’s implementation, and is hardly ever sufficient in and of itself as a domain object within your solution.&amp;#160; Think about it, the behaviors that a string object performs are so generic and multipurpose that you likely don’t need two-thirds of the class as defined (and there’s likely a few behaviors you really need that aren’t there).&amp;#160; Of course nearly every application on earth makes use of the &lt;font face="Courier New"&gt;String&lt;/font&gt; class; but because of this fact, it has no meaning in and of itself within any given application.&amp;#160; You would have to look at how the stings are actually used within the code in order to understand its unique application within the app’s context.&amp;#160; Of course that task of research is much easier for everyone (including the original author of the code) if it’s all encapsulated within a dedicated domain object class.&amp;#160; True object-orientation means describing in code form the properties, behaviors, and interactions/relationships of real world objects within your problem domain.&lt;/p&gt;    &lt;p&gt;Esteban gave me a great example to illustrate these points.&amp;#160; He said that you can always represent money as a decimal (and even when you use a domain object, it’s got to have a decimal language primitive underneath the covers).&amp;#160; However, what happens when you need to attach metadata to the amount (like currency denomination), or if you need to change decimal precision?&amp;#160; You would have to go through all of the code and make sure your use of decimal language primitives is modified uniformly in order to retain consistency.&amp;#160; Also, mathematic operations involving money are hardly ever the same as their counterparts involving standard decimals, because currency deals with discrete values to a certain decimal precision.&amp;#160; Typically when the behaviors and properties within our system begin to get complex, we are cognizant enough to create domain objects in order to bring it all under one class.&amp;#160; We definitely don’t want to over-architect features and interactions before we need them, but I think there is power in this principle of abstracting away language primitives and instead encapsulating their use within domain objects located in just one place in your codebase.&amp;#160; I believe it is one thing we can keep in mind to help guide us to better object-oriented thinking, and avoid language-oriented coding.&lt;/p&gt;    &lt;p&gt;As mentioned above, Esteban’s thoughts were confirmed nearly verbatim by &lt;a href="http://codebetter.com/blogs/dru.sellers/default.aspx"&gt;Dru Sellers&lt;/a&gt; of &lt;a href="http://codebetter.com/"&gt;CodeBetter.com&lt;/a&gt; in his blog post that he wrote just a few days after I had the conversation with Esteban.&amp;#160; A great coincidence no doubt, and worth a read; here’s the link:&lt;/p&gt;    &lt;p&gt;&lt;a href="http://codebetter.com/blogs/dru.sellers/archive/2010/01/27/business-primitives-1-2.aspx"&gt;Business Primitives (1/2)&lt;/a&gt;&amp;#160;&lt;/p&gt;    &lt;h3&gt;&lt;font face="Courier New"&gt;Word&lt;/font&gt; Class Implementation&lt;/h3&gt;    &lt;p&gt;So basically I created the following class implementation and then replaced string with a reference to this new class, &lt;font face="Courier new"&gt;Word&lt;/font&gt;:&lt;/p&gt;    &lt;pre class="brush: csharp"&gt;public class Word
{
    private string wordStr = string.Empty;

    public Word(string wordStr)
    {
        this.wordStr = wordStr;
    }

    public override string ToString()
    {
        return wordStr;
    }

    public override bool Equals(object obj)
    {
        return wordStr == ((Word)obj).ToString();
    }

    public override int GetHashCode()
    {
        return base.GetHashCode();
    }

    public int GetCanonicalHashCode()
    {
        char[] letters = wordStr.ToCharArray();
        Array.Sort&amp;lt;char&amp;gt;(letters);
        return new string(letters).GetHashCode();
    }
}&lt;/pre&gt;

  &lt;p&gt;I have defined an overridden implementation for &lt;font face="Courier New"&gt;Equals(object)&lt;/font&gt; (so that the test assertions and other &lt;font face="Courier New"&gt;IEnumerable.Contains()&lt;/font&gt; queries work) and &lt;font face="Courier New"&gt;GetHashCode()&lt;/font&gt; (solely to satisfy a compiler warning).&amp;#160; I also moved the &lt;font face="Courier New"&gt;GetCanoncialHashCode()&lt;/font&gt; method from &lt;font face="Courier New"&gt;AnagramGrouper&lt;/font&gt;, in order to better encapsulate it as a behavior a Word knows how to do innately.&lt;/p&gt;

  &lt;p&gt;One other change I had to make was to convert strings into &lt;font face="Courier New"&gt;Word&lt;/font&gt; objects in our &lt;font face="Courier New"&gt;NewlineFileParser&lt;/font&gt;, which I accomplished by using an &lt;font face="Courier New"&gt;IEnumberable.Select()&lt;/font&gt; call as shown below:&lt;/p&gt;

  &lt;pre class="brush: csharp"&gt;return File.ReadAllLines(filePath).Select&amp;lt;string, Word&amp;gt;(x =&amp;gt; new Word(x));&lt;/pre&gt;

  &lt;p&gt;&lt;/p&gt;

  &lt;h3&gt;Let’s Revisit &lt;font face="Courier New"&gt;AssertWasCalled&lt;/font&gt; One More Time&lt;/h3&gt;

  &lt;p&gt;Trust me, I am groaning with you, even as I wrote that heading text.&amp;#160; The last thing we need is for me to rehash the topic again and flip flop my stance yet another time.&amp;#160; Yes, that’s right I’ve changed my mind again.&amp;#160; First I couldn’t understand what utility asserting methods were called would have under normal test scenarios.&amp;#160; Then I changed my mind that perhaps using it would help my test specifications have clearer intent of what I am asserting.&amp;#160; After an email conversation with &lt;a href="http://www.davesquared.net/"&gt;David Tchepak&lt;/a&gt;, I think I’m now back to my original stance.&amp;#160; Here is what Dave said that had me reconsidering, and I think it’s pretty sound reasoning (emphasis added by me):&lt;/p&gt;

  &lt;blockquote&gt;
    &lt;p&gt;…&lt;/p&gt;

    &lt;p&gt;“But seeing as you asked for it, here goes. :)&lt;/p&gt;

    &lt;p&gt;“I try and avoid &lt;font face="Courier New"&gt;AssertWasCalled&lt;/font&gt; like the plague. Generally I don't care that some method was called, I care that my class does the work it needs to. If that involves calling a dependency then great, but that is not my class' reason for existence.&lt;/p&gt;

    &lt;p&gt;“I prefer your original approach of stubbing out everything in the setup and having that tested indirectly. One reason I prefer this is I find it makes it easier to refactor: the assertions in my test don't change, the class still does the same thing. However I can add or change dependencies by changing some wiring in the setup, and then make sure I haven't stuffed anything up as my assertions still pass. &lt;strong&gt;I prefer that my tests specify what I want, not how it does it.&lt;/strong&gt; To me, &lt;font face="Courier New"&gt;AssertWasCalled&lt;/font&gt; reeks of over-specification. The one exception is where I hit the external boundaries of my code, so where I want to send an email or something without side effects that I can test. Then the core of the behaviour is the call itself, so I'm happy to assert on that then.”&lt;/p&gt;
  &lt;/blockquote&gt;

  &lt;p&gt;And with that I’ll promise to never bring this up again…unless of course I get swayed by someone else. :)&amp;#160; In all seriousness, I think this is an interesting discussion and so if you have insight, please share via comment below.&lt;/p&gt;

  &lt;h3&gt;Summary&lt;/h3&gt;

  &lt;p&gt;Please leave your thoughts in the comments below in regard to creating domain objects over using language primitives (or heaven forbid, the &lt;font face="Courier New"&gt;AssertWasCalled&lt;/font&gt; debate).&amp;#160; As far as this coding kata exercise, I need to take a high-level look at where this should go next.&amp;#160; Perhaps the next post will tie up loose ends and see how our code performs on large text files as input.&amp;#160; It may be that we will need to refactor our architecture to achieve better runtimes.&amp;#160; If not, maybe we can still discuss where would could have headed if it had been necessary.&lt;/p&gt;
&lt;/span&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1664217632350055880-2654738557567584288?l=murrayon.net' alt='' /&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://murrayon.net/feeds/2654738557567584288/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://murrayon.net/2010/02/anagram-code-kata-part-5-domain-objects.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/1664217632350055880/posts/default/2654738557567584288?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/1664217632350055880/posts/default/2654738557567584288?v=2" /><link rel="alternate" type="text/html" href="http://murrayon.net/2010/02/anagram-code-kata-part-5-domain-objects.html" title="Anagram Code Kata Part 5 – Domain Objects Over Language Primitives" /><author><name>Mike Murray</name><uri>http://www.blogger.com/profile/01990150469958605173</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="15380857253844311568" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total></entry><entry gd:etag="W/&quot;CkcARngzcSp7ImA9WxBXFUo.&quot;"><id>tag:blogger.com,1999:blog-1664217632350055880.post-8196351134851458941</id><published>2010-01-26T22:27:00.001-07:00</published><updated>2010-01-26T22:27:27.689-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-01-26T22:27:27.689-07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="BDD" /><category scheme="http://www.blogger.com/atom/ns#" term=".NET" /><category scheme="http://www.blogger.com/atom/ns#" term="C#" /><category scheme="http://www.blogger.com/atom/ns#" term="MSpec" /><category scheme="http://www.blogger.com/atom/ns#" term="Code Organization" /><category scheme="http://www.blogger.com/atom/ns#" term="Microsoft" /><category scheme="http://www.blogger.com/atom/ns#" term="New Technology" /><category scheme="http://www.blogger.com/atom/ns#" term="Testing" /><category scheme="http://www.blogger.com/atom/ns#" term="Anagram Code Kata Series" /><category scheme="http://www.blogger.com/atom/ns#" term="Mocking" /><category scheme="http://www.blogger.com/atom/ns#" term="Visual Studio" /><category scheme="http://www.blogger.com/atom/ns#" term="Algorithms" /><category scheme="http://www.blogger.com/atom/ns#" term="SOLID" /><title>Anagram Code Kata Part 4 – Will it Write My Code for Me?</title><content type="html">&lt;p&gt;This post is part of a &lt;a href="http://murrayon.net/2009/11/anagram-code-kata-bdd-mspec.html"&gt;series on coding Kata, BDD, MSpec, and SOLID principles&lt;/a&gt;.&amp;#160; Feel free to visit the above link which points to the introductory post, also containing an index of all posts in the series.&lt;/p&gt;  &lt;p&gt;In this post, we work on implementing the other main dependency, &lt;font face="Courier New"&gt;IAnagramsFinder&lt;/font&gt;.&amp;#160; In doing so, you will discover that I have been a little naïve with this BDD methodology. Apparently I expected a different experience than what I ran into doing the exercise.&amp;#160; In gathering feedback, I had a very interesting discussion about Object-Oriented Programming with &lt;a href="http://adotnetdude.blogspot.com/"&gt;Esteban&lt;/a&gt; that I will summarize and ask for further discussion from all of you.&amp;#160; I’ll also show you one way to debug your code when running the MSpec tests via the console test runner.&lt;/p&gt; &lt;span class="fullpost"&gt;   &lt;h3&gt;New Thoughts on Mocks vs. Stubs&lt;/h3&gt;    &lt;p&gt;During &lt;a href="http://murrayon.net/2009/11/anagram-code-kata-part-2-mocking-and.html"&gt;Part 2 of this series&lt;/a&gt;, &lt;a href="http://papamufflon.blogspot.com/"&gt;Tobias&lt;/a&gt; left &lt;a href="http://murrayon.net/2009/11/anagram-code-kata-part-2-mocking-and.html#comments"&gt;a comment about using mocks and &lt;font face="Courier New"&gt;AssertWasCalled&lt;/font&gt;&lt;/a&gt;, rather than stubs and defining fake responses.&amp;#160; I didn’t understand how it would help, as it appeared they would accomplish roughly the same thing.&amp;#160; With stubs and fake responses, if you don’t get back the return you are looking for, then you can infer that the dependencies weren’t called since you had previously hard-coded their return values when called.&amp;#160; With mocks and asserting methods were called, you directly assert that the manager class did in fact call it’s dependencies.&lt;/p&gt;    &lt;p&gt;When I looked more closely into using the &lt;font face="Courier New"&gt;AssertWasCalled&lt;/font&gt; method in Rhino.Mocks, I noticed that my strategy of using stubs and faked return values wasn’t very explicit in signifying that the ultimate responsibility of the manager class was to delegate to its dependencies.&amp;#160; I mean the test context does rigorously stub out the dependencies, but the actual assertions weren’t clear what we were testing.&amp;#160; Therefore, I decided to pop in a pair of &lt;font face="Courier New"&gt;AssertWasCalled&lt;/font&gt; statements (as found below), leaving &lt;a href="http://murrayon.net/2009/11/anagram-code-kata-part-2-mocking-and.html#firstSpec"&gt;the rest of the test the same as it was back in Part 2&lt;/a&gt;.&lt;/p&gt;    &lt;pre class="brush: csharp"&gt;It should_result_in_list_of_anagram_sets_and_both_dependencies_should_have_been_called = () =&amp;gt;
{
    fileParser.AssertWasCalled(x =&amp;gt; x.ExtractWordListFromFile(filePath));
    anagramGrouper.AssertWasCalled(x =&amp;gt; x.FindAnagramSets(wordListFromFile));

    result.ShouldEqual(expected);
};&lt;/pre&gt;

  &lt;p&gt;However, when I thought to simplify the test code by removing most of stubbing setup, it appeared I had to leave most of the stub logic in tact in order to test if &lt;font face="Courier New"&gt;anagramGrouper.FindAnagramSets()&lt;/font&gt; was called with parameter &lt;font face="Courier New"&gt;wordListFromFile&lt;/font&gt;, which was one of the stubbed fake responses.&amp;#160; The one dependency (the file parser) needed to pass it’s return value to the next dependency (the anagrams finder).&amp;#160; I could not think of a way to accomplish testing that the manager class facilitated that without the stubbing logic (fake responses) that I created.&lt;/p&gt;

  &lt;p&gt;It would be great if someone could enlighten me since I’m such a newbie to mocking and stubbing.&amp;#160; Otherwise, I feel the intent of the test is now more clear with the &lt;font face="Courier New"&gt;AssertWasCalled&lt;/font&gt; checks that I added, even if that I means I’m needlessly mixing stubbing and mocking.&amp;#160; But one last question:&amp;#160; should I try to stick more closely to the rule of thumb guiding me to stick to one all-encompassing assertion per test if possible?&amp;#160; Let me know your thoughts.&lt;/p&gt;

  &lt;h3&gt;Implementing the &lt;font face="Courier New"&gt;AnagramGrouper&lt;/font&gt; Dependency&lt;/h3&gt;

  &lt;p&gt;So let’s continue onward with some more actual design and code.&amp;#160; We are tackling the &lt;font face="Courier New"&gt;AnagramGrouper&lt;/font&gt; dependency, whose sole responsibility is to take in the parsed collection of words and find anagram sets.&amp;#160; Here is the test spec (one thing to note is that in some of my earlier tests for the &lt;font face="Courier New"&gt;AnagramsFinder&lt;/font&gt; manager class and &lt;font face="Courier New"&gt;IFileParser&lt;/font&gt;, I had used string arrays liberally; I decided to go with &lt;font face="Courier New"&gt;IList&amp;lt;string&amp;gt;&lt;/font&gt; collections instead):&lt;/p&gt;

  &lt;pre class="brush: csharp"&gt;public class AnagramGrouperSpecs
{
    [Subject(typeof(AnagramGrouperSpecs))]
    public class when_given_word_list_collection
    {
        static AnagramGrouper sut;
        static IEnumerable&amp;lt;IList&amp;lt;string&amp;gt;&amp;gt; result;
        static IEnumerable&amp;lt;string&amp;gt; wordList = new[] { &amp;quot;wordA&amp;quot;, &amp;quot;wordB&amp;quot;, &amp;quot;Aword&amp;quot;, &amp;quot;wordC&amp;quot; };

        Establish context = () =&amp;gt;
        {
            sut = new AnagramGrouper();
        };

        Because of = () =&amp;gt;
        {
            result = sut.FindAnagramSets(wordList);
        };

        It should_result_in_anagram_sets_collection_of_length_1 = () =&amp;gt;
        {
            result.Count().ShouldEqual(1);
        };

        It should_contain_2_specific_words_in_the_anagram_set = () =&amp;gt;
        {
            result.First().ShouldContain(&amp;quot;wordA&amp;quot;, &amp;quot;Aword&amp;quot;);
        };
    }
}&lt;/pre&gt;

  &lt;p&gt;Here too I have basically two assertions (but split it up differently than last time); should I also try harder to avoid this as well?&lt;/p&gt;

  &lt;p&gt;When contemplating how to further breakdown this responsibility of finding anagram sets into subtasks, I figure we would need one piece of code that would compare two words and answer whether they are anagrams of each other, and another piece of code that would keep track of the various anagram sets (perhaps a collection or dictionary of string arrays).&amp;#160; With what BDD has revealed to me thus far, I figure this means we are going to see two more dependencies (and interfaces, and spec tests) added to the codebase.&lt;/p&gt;

  &lt;p&gt;So I start with the word comparison task, thinking I could perhaps leverage the &lt;font face="Courier New"&gt;String.GetHashCode()&lt;/font&gt; method for assigning meaningful value to the list of characters in the string.&amp;#160; However, string hash codes give importance to letter casing and order of characters, so a modified strategy would have to be utilized, even though &lt;font face="Courier New"&gt;GetHashCode()&lt;/font&gt; seems quite close to filling our need.&lt;/p&gt;

  &lt;p&gt;Now I probably should have come up with this ingenious algorithm all by myself, but…it is what it is and this is the best, most concise solution that I can put together to solve the problem.&amp;#160; With that said, I ended up doing some internet searching in order to proof-of-concept my &lt;font face="Courier New"&gt;GetHashCode()&lt;/font&gt; idea.&amp;#160; I came across pure genius in the form of &lt;a href="http://www.formatexception.com/"&gt;Brian Mullen’s&lt;/a&gt; blog post entitled &lt;a href="http://www.formatexception.com/2009/03/linq-group-by-and-groupby/"&gt;LINQ group by and GroupBy&lt;/a&gt;, specifically the second-to-last code snippet.&amp;#160; Just &lt;font face="Courier New"&gt;String.ToCharArray()&lt;/font&gt; the word and then &lt;font face="Courier New"&gt;Array.Sort()&lt;/font&gt; the resultant array; now turn it back into a string and do &lt;font face="Courier New"&gt;GetHashCode()&lt;/font&gt; now.&amp;#160; (As a side note, we can worry about case-insensitivity later if desired by simply doing a &lt;font face="Courier New"&gt;String.ToLower()&lt;/font&gt; on the word before getting the hash code.)&amp;#160; Now anagrams will have the same hash code (Brian uses the term “canonical”, which I think is very fitting); it’s literally perfect in every way!&lt;/p&gt;

  &lt;p&gt;So now for the other dependency, I figure we could use a &lt;font face="Courier New"&gt;Dictionary&amp;lt;int, IList&amp;lt;string&amp;gt;&amp;gt;&lt;/font&gt;, where the key is the canonical hash code and the value is a string list collection representing an anagram set of words.&amp;#160; These two dependency implementations are so simple and straight forward that I have a hard time seeing a reason to continue breaking out full-fledged object dependencies with interfaces and Dependency Injection.&amp;#160; However, I will make a case for moving the canonical hash code logic outside this &lt;font face="Courier New"&gt;AnagramsGrouper&lt;/font&gt; class, but that will come later.&lt;/p&gt;

  &lt;p&gt;So let’s write some code to pass our test/spec:&lt;/p&gt;

  &lt;pre class="brush: csharp"&gt;public class AnagramGrouper : IAnagramGrouper
{
    public IEnumerable&amp;lt;IList&amp;lt;string&amp;gt;&amp;gt; FindAnagramSets(IEnumerable&amp;lt;string&amp;gt; wordList)
    {
        Dictionary&amp;lt;int, IList&amp;lt;string&amp;gt;&amp;gt; results = new Dictionary&amp;lt;int, IList&amp;lt;string&amp;gt;&amp;gt;();

        foreach (string word in wordList)
        {
            int canonicalHashCode = GetCanonicalHashCode(word);

            if (results.ContainsKey(canonicalHashCode))
            {
                results[canonicalHashCode].Add(word);
            }
            else
            {
                results.Add(canonicalHashCode, new List&amp;lt;string&amp;gt;(new[] { word }));
            }
        }

        return results.Values;
    }

    public static int GetCanonicalHashCode(string word)
    {
        char[] letters = word.ToCharArray();
        Array.Sort&amp;lt;char&amp;gt;(letters);

        return new string(letters).GetHashCode();
    }
}&lt;/pre&gt;

  &lt;p&gt;Maybe you noticed already, but there is a bug in my logic.&amp;#160; At that time, I didn’t see it and needed to debug the code while running.&amp;#160; Setting a debug break point in your code doesn’t work like you’re probably used to, and this is because we’re running the MSpec tests via its console test runner.&amp;#160; I had to do some searching to figure this one out, and that’s what we’ll cover next.&lt;/p&gt;

  &lt;h3&gt;How to Debug MSpec Specifications and the Code They Test&lt;/h3&gt;

  &lt;p&gt;After a short ride on the Google super highway, I found a &lt;a href="http://codebetter.com/blogs/aaron.jensen/archive/2008/09/02/mspec-v0-2.aspx#comments"&gt;blog post containing a November 2009 comment&lt;/a&gt; from &lt;a href="http://codebetter.com/blogs/aaron.jensen/default.aspx"&gt;Aaron Jensen&lt;/a&gt;, author of MSpec, that gave a few possible solutions.&amp;#160; I opted to go with the &lt;font face="Courier new"&gt;Debugger.Break()&lt;/font&gt; solution, which I put at the very top of my &lt;font face="Courier new"&gt;FindAnagramSets&lt;/font&gt; method.&amp;#160; It is a tad awkward because it will show a Windows error dialog box that says the program encountered a problem and Windows is searching the web for a solution.&amp;#160; If you wait through that, it will give you an option to debug the program via a Visual Studio dialog where you select the currently running instance of Visual Studio as your debugger instance.&amp;#160; You just remove the statement when you’re done (and you’ll really want to remember to remove it from your production code).&amp;#160; Does the trick, though it is a bit obtrusive to your code base.&lt;/p&gt;

  &lt;p&gt;If you haven’t already figured it out, the bug is that my &lt;font face="Courier New"&gt;FindAnagramSets&lt;/font&gt; method is returning all anagram sets found in the dictionary.&amp;#160; An anagram set of just one word is not really an anagram set, which is why our test specification which is based on that assumption failed.&amp;#160; The fix is to filter out anagram word sets with less than two words before returning, like this:&lt;/p&gt;

  &lt;pre class="brush: csharp"&gt;// Return anagram sets with more than one word in it
return results.Values.Where(x =&amp;gt; x.Count &amp;gt; 1);&lt;/pre&gt;

  &lt;p&gt;That will make the code pass the tests now.&amp;#160; Remember to remove the debugger statement we added.&lt;/p&gt;

  &lt;h3&gt;BDD, OOP…WTH?!&lt;/h3&gt;

  &lt;p&gt;Just kidding.&amp;#160; But I do want to discuss a reaction I had to BDD after implementing this anagram finding solution.&amp;#160; After I completed the code and finished the tests, I was feeling pretty great.&amp;#160; But then I started thinking about how I didn’t really go down the path that I felt BDD was originally trying to lead me down with &lt;font face="Courier New"&gt;AnagramGrouper&lt;/font&gt;, which was to create two more dependencies, just as I had done for the first managing class &lt;font face="Courier New"&gt;AnagramsFinder&lt;/font&gt;.&amp;#160; I mean I felt pretty frustrated because I was digging BDD to this point.&amp;#160; I’m not quite sure what my original expectations were, but I might have thought BDD was magically going to right my algorithms for me as well.&lt;/p&gt;

  &lt;p&gt;I decided to discuss the whole thing with &lt;a href="http://adotnetdude.blogspot.com/"&gt;Esteban&lt;/a&gt; to get some perspective on the issue.&amp;#160; He told me he didn’t know a thing about BDD and how it’s supposed to work, but he figured BDD would lead me to decoupled, cohesive code design, but he couldn’t see how it would aide with algorithmic solutions to the problems at hand.&amp;#160; I’m not sure why I was so naïve, but it makes complete sense.&amp;#160; I mean these methodologies are designed to keep you disciplined to some proven, guiding principles, but you still need to use your brain and creativity to actually solve the problem.&amp;#160; I guess it would help to get some feedback and suggestions from you all in regard to knowing when it is time to switch from BDD architecture design mode to algorithm design mode within the broken down dependencies that handle the very specific sub-responsibilities.&amp;#160; Please let me know if you have found some guiding concept or question you’ve come up with that you put to the test in order to lead you into the right coding mindset for that particular context (design or algorithm; or do I even have the right categories?).&lt;/p&gt;

  &lt;p&gt;Perhaps it’s just that this design process feels so new to me.&amp;#160; Maybe I have solely been in the coding, algorithm mindset this whole time throughout my career.&amp;#160; Perhaps it will become more natural with practice and experience.&amp;#160; I guess it just feels like I’m learning to drive a manual, stick-shift car or something, and I am a little rough with the clutch when transitioning between gears.&lt;/p&gt;

  &lt;p&gt;To take this discussion further, &lt;a href="http://adotnetdude.blogspot.com/"&gt;Esteban&lt;/a&gt; made a comment in our conversation about his personal thoughts on these methodologies (like BDD) and Object-Oriented Programming.&amp;#160; He has come to believe that we invent these methodologies like flavors of the week “because as programmers we don’t really get OOP.”&amp;#160; Perhaps OOP just comes more naturally to his thought process that most people (or he admits it’s possible he could just be completely ignorant), but he feels that there’s really just a few simple rules and guidelines to keep in mind at all times in order to keep your objects behaving like real life objects and not acting like data constructs.&amp;#160; I encouraged him to give his theory some additional thought and make it a little more formal by writing it down.&amp;#160; He did this and the following is a link to the resultant blog post:&lt;/p&gt;

  &lt;p&gt;&lt;a href="http://adotnetdude.blogspot.com/2010/01/3-simple-rules-to-good-object-oriented.html"&gt;3 Simple Rules to Good Object Oriented Code&lt;/a&gt;&lt;/p&gt;

  &lt;p&gt;Please read through that post and comment on it.&amp;#160; His idea needs to be criticized and/or validated.&amp;#160; He admits he may have no clue what he’s talking about, but I said that’s why it needs to be put to the test by posting it in the open.&amp;#160; We both think it’s an interesting theory, but we’re unsure if it even holds any water.&amp;#160; Perhaps Esteban’s theory is too simplistic to be practical for many programmers.&amp;#160; Provide feedback and lots of it.&lt;/p&gt;

  &lt;h3&gt;Summary&lt;/h3&gt;

  &lt;p&gt;So I think I need to wrap this post up about now.&amp;#160; I think I have raised enough discussion points to write a book, but please do take the time to comment on what I’m doing wrong, what I’m doing right, or how to make the BDD mentality more flowing and natural.&amp;#160; I promised to talk about having a Word class as opposed to using primitive strings everywhere, and that will definitely be in the next post.&amp;#160; Also, I think our &lt;font face="Courier New"&gt;AnagramGrouper&lt;/font&gt; class may need some more testing and flushing out of how it should handle spaces, punctuation, casing, and so on.&lt;/p&gt;

  &lt;p&gt;Thanks for sticking with me thus far.&lt;/p&gt;
&lt;/span&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1664217632350055880-8196351134851458941?l=murrayon.net' alt='' /&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://murrayon.net/feeds/8196351134851458941/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://murrayon.net/2010/01/anagram-code-kata-part-4-will-it-write.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/1664217632350055880/posts/default/8196351134851458941?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/1664217632350055880/posts/default/8196351134851458941?v=2" /><link rel="alternate" type="text/html" href="http://murrayon.net/2010/01/anagram-code-kata-part-4-will-it-write.html" title="Anagram Code Kata Part 4 – Will it Write My Code for Me?" /><author><name>Mike Murray</name><uri>http://www.blogger.com/profile/01990150469958605173</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="15380857253844311568" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total></entry><entry gd:etag="W/&quot;D0cAR3s9fyp7ImA9WxBSEUU.&quot;"><id>tag:blogger.com,1999:blog-1664217632350055880.post-8576876761767361973</id><published>2009-12-18T18:10:00.001-07:00</published><updated>2009-12-18T18:10:46.567-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-12-18T18:10:46.567-07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="New Technology" /><category scheme="http://www.blogger.com/atom/ns#" term="BDD" /><category scheme="http://www.blogger.com/atom/ns#" term=".NET" /><category scheme="http://www.blogger.com/atom/ns#" term="Testing" /><category scheme="http://www.blogger.com/atom/ns#" term="Anagram Code Kata Series" /><category scheme="http://www.blogger.com/atom/ns#" term="MSpec" /><category scheme="http://www.blogger.com/atom/ns#" term="Mocking" /><category scheme="http://www.blogger.com/atom/ns#" term="C#" /><category scheme="http://www.blogger.com/atom/ns#" term="Visual Studio" /><category scheme="http://www.blogger.com/atom/ns#" term="Microsoft" /><category scheme="http://www.blogger.com/atom/ns#" term="SOLID" /><title>Anagram Code Kata Part 3 – Use Common Sense</title><content type="html">&lt;p&gt;This post is part of a &lt;a href="http://murrayon.net/2009/11/anagram-code-kata-bdd-mspec.html"&gt;series on coding Kata, BDD, MSpec, and SOLID principles&lt;/a&gt;.&amp;#160; Feel free to visit the above link which points to the introductory post, also containing an index of all posts in the series.&lt;/p&gt;  &lt;p&gt;In this post, we will discuss how far to take the idea of creating mockable contracts via interfaces for testing purposes and to keep responsibilities modular.&amp;#160; As I solicited feedback from commenters, I was getting hung up on applying this concept to every object and dependency.&amp;#160; We’ll talk about how I’m now thinking that overly strict adherence to the practice can drive you nuts and decrease productivity.&amp;#160; It is meant to help guide your design process along rather than hinder it.&amp;#160; We’ll finish this post off with one of our two dependencies implemented in an extremely simple manner.&lt;/p&gt; &lt;span class="fullpost"&gt;   &lt;h3&gt;&lt;font face="Courier New"&gt;IFileParser&lt;/font&gt; Dependency&lt;/h3&gt;    &lt;p&gt;When we left off last time, we had defined two separate responsibilities that &lt;font face="Courier New"&gt;AnagramsFinder&lt;/font&gt; was going to push down into its dependencies.&amp;#160; As I started to write a specification test for the newly created &lt;font face="Courier New"&gt;NewlineFileParser&lt;/font&gt;, I realized it would be difficult to stub based on providing a file path to a text file as the only parameter.&amp;#160; I began having thoughts that maybe I could break up another pair of dependencies for file parsing, namely obtaining a file stream (or file contents string) from a path and then parsing the file contents into a list of multiple lines.&amp;#160; But then again, my first of the two dependencies is still dependent on the physical file system and I cannot get away from this unless I somehow mock up an in-memory file system.&amp;#160; This began to feel silly to me as I was hoping I would just use the built-in .NET APIs for file systems and string parsing.&lt;/p&gt;    &lt;p&gt;After emailing &lt;a href="http://www.davesquared.net/" target="_blank"&gt;Dave&lt;/a&gt; and &lt;a href="http://adotnetdude.blogspot.com/" target="_blank"&gt;Esteban&lt;/a&gt; asking for guidance, the revelation I received via these two fine gentlemen is that file parsing is not an essential purpose of this application nor exercise (at least not yet; we won’t be focusing on performance unless it appears to be grossly deficient as we go along).&amp;#160; What we could do is write integration tests instead, where we have a set of simple test files sitting in a folder that we run our &lt;font face="Courier New"&gt;NewlineFileParser&lt;/font&gt; against to ensure it working as we expect.&amp;#160; But I don’t think I’m even going to do this at this point.&amp;#160; I really do want to get to the core of the application.&amp;#160; Plus, I feel certain that I can trust the implementation of &lt;font face="Courier New"&gt;File.ReadAllLines()&lt;/font&gt; from the .NET Framework.&lt;/p&gt;    &lt;p&gt;Unless it needs to be changed further down the road, the following code implementation will likely be sufficient for the remainder of this coding exercise:&lt;/p&gt;    &lt;pre class="brush: csharp"&gt;public class NewlineFileParser : IFileParser
{
    public IEnumerable&amp;lt;string&amp;gt; ExtractWordListFromFile(string filePath)
    {
        return File.ReadAllLines(filePath);
    }
}&lt;/pre&gt;

  &lt;p&gt;I feel great about this because I haven’t gone insane trying to mock and test everything in sight, nor have I broken up every single responsibility in such small chunks that it becomes tedious.&amp;#160; Instead, I have broken up the two core responsibilities of &lt;font face="Courier New"&gt;AnagramsFinder&lt;/font&gt; which means I can change and test the two dependencies independent of each other and from their manager class.&amp;#160; Even though I haven’t written a ton of code yet, I feel the tests specs have driven my design into a cohesive, decoupled design that should prove flexible if requirements change or if I encounter friction later on and need to rethink my design.&amp;#160; A flexible architecture for the application is being flushed out based on a “top-to-bottom” design view of the requirements.&lt;/p&gt;

  &lt;h3&gt;Create Stubs or Assert Methods were Called&lt;/h3&gt;

  &lt;p&gt;&lt;a href="http://papamufflon.blogspot.com/"&gt;Tobias Walter&lt;/a&gt; left &lt;a href="http://murrayon.net/2009/11/anagram-code-kata-part-2-mocking-and.html#comments"&gt;a comment on my last post&lt;/a&gt; with some suggestions that I would like to get clarification on and discuss further with my growing audience of three now.&amp;#160; He compared some of my implementation to &lt;a href="http://www.davesquared.net/2009/11/favour-test-driving-logic-over-data.html"&gt;Dave’s implementation on his Favour test driving logic over data post&lt;/a&gt;, but the comparison was lost on me.&amp;#160; It seemed Tobias was saying that I had gone too far breaking up the responsibilities into such small dependencies.&amp;#160; I am unsure what his argument was, but as far as I could tell both Dave and I broke up a managing class into two separate responsibilities so that the more crucial of the two could be tested independently.&amp;#160; Also in doing so, we both created stubs that were given specific dummy responses to method calls using Rhino.Mocks.&amp;#160; One more comment I would like to say is that I broke the file parsing responsibility away into its own dependency more because of the need to isolate the anagrams grouping than because file parsing is of itself a difficult task.&amp;#160; If Tobias or anyone else could try to clarify his argument, that would really help me understand the merits of his suggestions.&lt;/p&gt;

  &lt;p&gt;Another suggestion that Tobias brought up that I would like to petition feedback on is to use the mocking feature of testing whether a method was called instead of creating a stub programmed with a dummy response.&amp;#160; I have to admit, I’m not sure when to use one method over another.&amp;#160; I guess I’ve felt in the past that testing whether a method was called seems silly, since it seems odd to have your test know the implementation and inner method calls of the subject under test.&amp;#160; But I am now realizing that my stubs appear to be doing the same thing, but with dummy input and output programmed in.&amp;#160; If you have an opinion or experience on this subject, please leave some feedback in the comments of this post.&lt;/p&gt;

  &lt;h3&gt;What’s Next?&lt;/h3&gt;

  &lt;p&gt;In my next post I hope to summarize this mocking debate brought up above regarding two differing methods of verifying my manager class is correctly managing its dependencies.&amp;#160; I also hope to begin driving out the design and implementation of the &lt;font face="Courier New"&gt;AnagramGrouper&lt;/font&gt; dependency via behavior specification tests.&amp;#160; Thanks and any feedback is greatly appreciated.&lt;/p&gt;
&lt;/span&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1664217632350055880-8576876761767361973?l=murrayon.net' alt='' /&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://murrayon.net/feeds/8576876761767361973/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://murrayon.net/2009/12/anagram-code-kata-part-3-use-common.html#comment-form" title="1 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/1664217632350055880/posts/default/8576876761767361973?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/1664217632350055880/posts/default/8576876761767361973?v=2" /><link rel="alternate" type="text/html" href="http://murrayon.net/2009/12/anagram-code-kata-part-3-use-common.html" title="Anagram Code Kata Part 3 – Use Common Sense" /><author><name>Mike Murray</name><uri>http://www.blogger.com/profile/01990150469958605173</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="15380857253844311568" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">1</thr:total></entry><entry gd:etag="W/&quot;D0YNQnkycCp7ImA9WxBXEUQ.&quot;"><id>tag:blogger.com,1999:blog-1664217632350055880.post-1713026628293781613</id><published>2009-11-17T00:59:00.000-07:00</published><updated>2010-01-22T14:19:53.798-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-01-22T14:19:53.798-07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="BDD" /><category scheme="http://www.blogger.com/atom/ns#" term=".NET" /><category scheme="http://www.blogger.com/atom/ns#" term="Dependency Injection" /><category scheme="http://www.blogger.com/atom/ns#" term="C#" /><category scheme="http://www.blogger.com/atom/ns#" term="MSpec" /><category scheme="http://www.blogger.com/atom/ns#" term="Code Organization" /><category scheme="http://www.blogger.com/atom/ns#" term="Microsoft" /><category scheme="http://www.blogger.com/atom/ns#" term="New Technology" /><category scheme="http://www.blogger.com/atom/ns#" term="Testing" /><category scheme="http://www.blogger.com/atom/ns#" term="Anagram Code Kata Series" /><category scheme="http://www.blogger.com/atom/ns#" term="Mocking" /><category scheme="http://www.blogger.com/atom/ns#" term="Visual Studio" /><category scheme="http://www.blogger.com/atom/ns#" term="SOLID" /><title>Anagram Code Kata Part 2 – Mocking and SRP</title><content type="html">&lt;p&gt;This post is part of a &lt;a href="http://murrayon.net/2009/11/anagram-code-kata-bdd-mspec.html"&gt;series on coding Kata, BDD, MSpec, and SOLID principles&lt;/a&gt;.&amp;#160; Feel free to visit the above link which points to the introductory post, also containing an index of all posts in the series.&lt;/p&gt;  &lt;p&gt;In this post, we will rewrite our &lt;a href="http://murrayon.net/2009/11/anagram-code-kata-part-1-getting.html" target="_blank"&gt;first specification/test from the previous post&lt;/a&gt;, where we didn’t feel very confident about the direction we were heading.&amp;#160; We got some great feedback and will now better &lt;a href="http://www.davesquared.net/2009/11/favour-test-driving-logic-over-data.html" target="_blank"&gt;focus on test driving logic and not just data&lt;/a&gt;; we will also be more careful in extracting the requirements from problem statement and in giving our classes a &lt;a href="http://www.davesquared.net/2009/01/introduction-to-solid-principles-of-oo.html" target="_blank"&gt;Single Responsibility (the first of the SOLID principles of Object-Oriented Design)&lt;/a&gt;.&amp;#160; As we are test driving our design from a “top-down” perspective, we will encounter the need for dependencies not yet implemented while creating the higher level classes.&amp;#160; Instead of halting our rhythm and progress, we will utilize a mocking framework to stub out non-existent implementations according to interfaces.&amp;#160; This also encourages us to use &lt;a href="http://www.davesquared.net/2009/01/introduction-to-solid-principles-of-oo.html" target="_blank"&gt;Dependency Inversion (last of the SOLID principles; same link as above)&lt;/a&gt; and we can prove the validity of our modules by testing them in complete isolation from their dependencies.&lt;/p&gt; &lt;span class="fullpost"&gt;   &lt;h3&gt;Don’t Focus on Data (Yet) and SRP (Single Responsibility Principle)&lt;/h3&gt;    &lt;p&gt;I had a feeling I was focusing too much on testing data, and I also knew it seemed to odd to be writing my very first test to be dependent on solving a specific instance of the problem (especially a test case with thousands of words in it), instead of working on solving the problem generally.&amp;#160; After some terrific feedback from &lt;a href="http://www.davesquared.net/" target="_blank"&gt;David Tchepak&lt;/a&gt; in the &lt;a href="http://murrayon.net/2009/11/anagram-code-kata-part-1-getting.html#comments" target="_blank"&gt;comments of my last post&lt;/a&gt;, I now understand that wasn’t my only mistake.&amp;#160; I was also trying to give my &lt;font face="Courier New"&gt;AnagramsFinder&lt;/font&gt; class too many responsibilities (especially with just one &lt;font face="Courier New"&gt;ParseTextFile&lt;/font&gt; method), namely extracting the words out of the text file and then grouping the anagrams together.&amp;#160; Not only that, I also was returning a count of anagram sets when the &lt;a href="http://codekata.pragprog.com/2007/01/kata_six_anagra.html" target="_blank"&gt;problem statement specifically asked for output of the anagram sets themselves&lt;/a&gt;.&amp;#160; Even though this is a simple problem scenario, it can be foolish to make assumptions or simplifications like I did that are not part of the requirements.&lt;/p&gt;    &lt;p&gt;Let us first focus on the responsibilities required of our &lt;font face="Courier New"&gt;AnagramsFinder&lt;/font&gt; class.&amp;#160; It needs to parse a list of words out of a text file given the file path and it also needs to group words together into sets that are anagrams of each other.&amp;#160; However, we just named two responsibilities; implementing both in the same class would make it less cohesive and therefore less maintainable.&amp;#160; This is because our class would have more than one responsibility that could change in the future, and because these responsibilities are in the same class, they could be considered coupled and one could be affected by modifications to the other.&amp;#160; All of this train of thought falls under the Single Responsibility Principle from the SOLID principles (see links at the beginning of the post).&lt;/p&gt;    &lt;p&gt;To solve this predicament, we will make &lt;font face="Courier New"&gt;AnagramsFinder&lt;/font&gt; a managing class of dependencies that individually solve these separate concerns.&amp;#160; Each of these dependencies will adhere to the Single Responsibility principle, as does this higher abstraction manager class.&amp;#160; Its responsibility can be summarized as managing the inputs, outputs, and execution order of its dependencies.&amp;#160; We shall name the dependencies directly after each of their responsibilities, namely &lt;font face="Courier New"&gt;FileParser&lt;/font&gt; and &lt;font face="Courier New"&gt;AnagramGrouper&lt;/font&gt;.&amp;#160; However, I don’t want to go implement these dependencies and throw off the flow of fleshing out the design and logic of my manager class.&amp;#160; We are trying to design from a more “top-down” approach, instead of focusing on the lower level data concerns of the solution too early in the design process.&amp;#160; To accomplish completing the design of our manager class without actually implementing the dependencies, we will code to interfaces (namely &lt;font face="Courier New"&gt;IFileParser&lt;/font&gt; and &lt;font face="Courier New"&gt;IAnagramGrouper&lt;/font&gt;).&lt;/p&gt;    &lt;h3&gt;DIP (Dependency Inversion Principle)&lt;/h3&gt;    &lt;p&gt;The advantages of using interfaces are that we abstract out the actual implementation of the dependencies, allowing us to be more modular and less coupled between dependencies.&amp;#160; One class is not strongly tied to a specific implementation of its dependency, but rather the general contracts made available by the interface’s defined method signatures.&amp;#160; What this really means is that we can swap out actual implementations of the dependency without the consuming class being modified in the least bit.&amp;#160; This makes for truly maintainable code, especially when requirements change down the road after version one of the application is up and running.&amp;#160; This is what the Dependency Inversion Principle (again, from SOLID) is all about.&lt;/p&gt;    &lt;p&gt;We can take this a step further by passing the necessary dependencies into our consuming class at construction.&amp;#160; This allows for us to “inject” into the object any implementation of the interface we see fit; this technique is aptly named Dependency Injection (DI).&amp;#160; Our manager class doesn’t have to fret about any concrete details regarding its dependencies’ actual implementations, nor about any of the construction ceremony associated with “newing” up and initializing said dependencies.&amp;#160; We won’t be using any DI containers (as our dependency needs are very light in this exercise), but the use of the Dependency Inversion Principle does set us up nicely to use a mocking framework so that we can finish fleshing out our tests without implementing any of the dependencies yet.&lt;/p&gt;    &lt;h3&gt;Mocking Dependencies&lt;/h3&gt;    &lt;p&gt;We would like to finish the design of our top level &lt;font face="Courier New"&gt;AnagramsFinder&lt;/font&gt; manager class, but not fully commit to how its dependencies will be implemented yet.&amp;#160; We have a general idea of how we want our consuming class to interact with its dependencies via interfaces.&amp;#160; Let’s go ahead and look at our interfaces we named earlier:&lt;/p&gt;    &lt;pre class="brush: csharp"&gt;public interface IFileParser
{
    IEnumerable&amp;lt;string&amp;gt; ExtractWordListFromFile(string filePath);
}

public interface IAnagramGrouper
{
    IEnumerable&amp;lt;string[]&amp;gt; FindAnagramSets(IEnumerable&lt;string&gt; wordList);
}&lt;/pre&gt;

  &lt;p&gt;Now, we could create concrete implementations of the interfaces to be used in our tests that return simple dummy results.&amp;#160; An example could look like this:&lt;/p&gt;

  &lt;pre class="brush: csharp"&gt;public class TestFileParser : IFileParser
{
    public IEnumerable&amp;lt;string&amp;gt; ExtractWordListFromFile(string filePath)
    {
        return new[] { &amp;quot;wordA&amp;quot;, &amp;quot;wordB&amp;quot;, &amp;quot;Aword&amp;quot;, &amp;quot;wordC&amp;quot; };;
    }
}&lt;/pre&gt;

  &lt;p&gt;This is helpful because it keeps the one class we are interested in from being dependent on any real logic in its dependencies.&amp;#160; We want to be able to test our modules in isolation from any dependencies, so that no secondary or outside influences skew the test results.&amp;#160; We are basically providing dummy dependencies to our tests that have no logic that could cause side effects.&lt;/p&gt;

  &lt;p&gt;However, the software development community has provided tools called mocking frameworks that can create these dependency stubs for you.&amp;#160; This can save you from creating concrete interface implementations that have no use except for in testing.&amp;#160; The mocking framework I will try out is &lt;a href="http://www.ayende.com/projects/rhino-mocks.aspx" target="_blank"&gt;Rhino.Mocks from Ayende&lt;/a&gt;.&amp;#160; To get set up, you merely need to &lt;a href="http://www.ayende.com/projects/rhino-mocks/downloads.aspx" target="_blank"&gt;download the latest build zip archive&lt;/a&gt;, extract out the &lt;font face="Courier New"&gt;Rhino.Mocks.dll&lt;/font&gt; library to our &lt;font face="Courier New"&gt;Libraries&lt;/font&gt; folder created in the last blog post, and add a reference to the DLL in our Visual Studio solution.&amp;#160; I will next show you how to use Rhino.Mocks as we rewrite our first specification test.&lt;/p&gt;
  &lt;a name="firstSpec"&gt;&lt;/a&gt;

  &lt;h3&gt;Rewrite of Our First Specification/Test&lt;/h3&gt;

  &lt;p&gt;Armed with SRP, DIP, mocking, a more strict adherence to the actual problem statement, and a renewed focus on “favoring test driving logic over just testing data,” we now rewrite our first specification as follows:&lt;/p&gt;

  &lt;pre class="brush: csharp"&gt;[Subject(typeof(AnagramsFinder), &amp;quot;Finding Anagrams&amp;quot;)]
public class when_given_text_file_with_word_on_each_line
{
    static AnagramsFinder sut;
    static IEnumerable&amp;lt;string[]&amp;gt; result;
    static string filePath = &amp;quot;dummy_file_path.txt&amp;quot;;
    static IEnumerable&amp;lt;string&amp;gt; wordListFromFile = new[] { &amp;quot;wordA&amp;quot;, &amp;quot;wordB&amp;quot;, &amp;quot;Aword&amp;quot;, &amp;quot;wordC&amp;quot; };
    static IEnumerable&amp;lt;string[]&amp;gt; expected = new[] { new[] { &amp;quot;anagram&amp;quot;, &amp;quot;gramana&amp;quot; } };

    Establish context = () =&amp;gt;
    {
        var fileParser = MockRepository.GenerateStub&amp;lt;IFileParser&amp;gt;();
        fileParser.Stub(x =&amp;gt; x.ExtractWordListFromFile(filePath)).Return(wordListFromFile);

        var anagramGrouper = MockRepository.GenerateStub&amp;lt;IAnagramGrouper&amp;gt;();
        anagramGrouper.Stub(x =&amp;gt; x.FindAnagramSets(wordListFromFile)).Return(expected);

        sut = new AnagramsFinder(fileParser, anagramGrouper);
    };

    Because of = () =&amp;gt;
    {
        result = sut.ExtractAnagramSets(filePath);
    };

    It should_result_in_list_of_anagram_sets = () =&amp;gt;
    {
        result.ShouldEqual(expected);
    };
}&lt;/pre&gt;

  &lt;p&gt;I should mention a few notes about the code.&amp;#160; First, we need to add a using Rhino.Mocks statement at the top of our specification class file.&amp;#160; Second, our &lt;font face="Courier New"&gt;AnagramsFinder&lt;/font&gt; instance variable named &lt;font face="Courier New"&gt;sut&lt;/font&gt; stands for the “Subject Under Test,” a mannerism I picked up from David Tchepak, whom I’ve mentioned several times throughout this post series.&lt;/p&gt;

  &lt;p&gt;Our use of Rhino.Mocks is found when we call the &lt;font face="Courier New"&gt;MockRepository.GenerateStub&lt;/font&gt; method against an interface.&amp;#160; We then proceed to tell the stubbed object how to behave by specifying dummy return values when given methods of the object are called with given parameters.&amp;#160; The last line of our “context” setup is to then inject these two newly generated, stubbed dependencies into our manager class for testing.&amp;#160; It’s also interesting to note that none of my parameters and expected outputs really make much sense.&amp;#160; This is done on purpose to show that the data really doesn’t matter to this class, as we are not testing the logic of any data processing by the dependencies (remember, test in isolation).&amp;#160; It is true that this test really isn’t testing any real logic at this point, and it may even never evolve into testing any real logic either.&amp;#160; However, I think the important point is that it aided us in fleshing out the design, which we previously didn’t know how we were going to implement.&amp;#160; Not all tests will created equal in regard to validating our logic, but they all will play a part in driving the design of our code.&amp;#160; Hopefully these statements are true, and I would love to hear feedback on this topic in the comments.&lt;/p&gt;

  &lt;p&gt;I also want to touch on the Specification pattern of Behavior Driven Design and testing.&amp;#160; Specification tests are commonly set up into a workflow of context establishing, behavior performing, and results asserting.&amp;#160; The MSpec framework is designed to encourage this test organization.&lt;/p&gt;

  &lt;h3&gt;Red, Green, Refactor and MSpec Test Runner Output&lt;/h3&gt;

  &lt;p&gt;To make our first test run, we need to create the basic outline of our &lt;font face="Courier New"&gt;AnagramsFinder&lt;/font&gt; class as outlined in our test.&amp;#160; This includes a constructor that takes our two dependencies and an &lt;font face="Courier New"&gt;ExtractAnagramSets&lt;/font&gt; method:&lt;/p&gt;

  &lt;pre class="brush: csharp"&gt;public class AnagramsFinder
{
    private IFileParser fileParser;
    private IAnagramGrouper anagramGrouper;

    public AnagramsFinder(IFileParser fileParser, IAnagramGrouper anagramGrouper)
    {
        this.fileParser = fileParser;
        this.anagramGrouper = anagramGrouper;
    }

    public IEnumerable&amp;lt;string[]&amp;gt; ExtractAnagramSets(string filePath)
    {
        throw new NotImplementedException();
    }
}&lt;/pre&gt;

  &lt;p&gt;I am using the ConsoleRunner according to the method described in Rob Conery’s introductory MSpec and BDD post, including output to an HTML report.&amp;#160; After running our specifications, we get the following output:&lt;/p&gt;

  &lt;pre style="border-bottom: #cecece 1px solid; border-left: #cecece 1px solid; padding-bottom: 5px; background-color: #fbfbfb; min-height: 40px; padding-left: 5px; width: 567px; padding-right: 5px; height: 239px; border-top: #cecece 1px solid; border-right: #cecece 1px solid; padding-top: 5px"&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;Specs in AnagramCodeKata:

AnagramsFinder Finding Anagrams, when given text file with word on each line
¯ should result in list of anagram sets (FAIL)
System.NotImplementedException: The method or operation is not implemented.
   ... Stack Trace here ...

Contexts: 1, Specifications: 1
  0 passed, 1 failed&lt;/pre&gt;&lt;/pre&gt;

  &lt;p&gt;…and the HTML report:&lt;/p&gt;

  &lt;p&gt;&lt;/p&gt;
  &lt;a href="http://lh6.ggpht.com/_rps657FzHZ0/SwJYInxVVSI/AAAAAAAAADU/jcI2a8kADCA/s1600-h/htmlReportError%5B3%5D.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="htmlReportError" border="0" alt="htmlReportError" src="http://lh3.ggpht.com/_rps657FzHZ0/SwJYJUz3eMI/AAAAAAAAADY/bBzyAsPXUsw/htmlReportError_thumb%5B1%5D.png?imgmax=800" width="564" height="445" /&gt;&lt;/a&gt; &lt;/a&gt;

  &lt;p&gt;A highly encouraged tenet of Test Driven Development is the practice of “Red, Green, Refactor.”&amp;#160; It is meant to denote the evolution of the results and state of your tests.&amp;#160; You are encouraged to write the test and then do the minimum work necessary to get the code base to compile and run.&amp;#160; You are first running your test in a control state where you know it should fail.&amp;#160; Most test runners will show the color Red in regard to failed tests, and thus the name of the first step.&amp;#160; Your next stage is to implement the code to make the test pass and turn the output color to Green, commonly indicating passing tests.&amp;#160; The Refactor stage is a time to pause and see if any code can be reorganized or simplified.&amp;#160; Then “rinse and repeat as necessary”, an applicable instruction from shampoo bottles.&lt;/p&gt;

  &lt;p&gt;To make our test pass, we implement real logic to coordinate the calls into our dependencies, like so:&lt;/p&gt;

  &lt;pre class="brush: csharp"&gt;public IEnumerable&amp;lt;string[]&amp;gt; ExtractAnagramSets(string filePath)
{
    var wordList = fileParser.ExtractWordListFromFile(filePath);
    return anagramGrouper.FindAnagramSets(wordList);
}&lt;/pre&gt;

  &lt;p&gt;…and the successful outputs of our test runner:&lt;/p&gt;

  &lt;pre style="border-bottom: #cecece 1px solid; border-left: #cecece 1px solid; padding-bottom: 5px; background-color: #fbfbfb; min-height: 40px; padding-left: 5px; width: 579px; padding-right: 5px; height: 156px; border-top: #cecece 1px solid; border-right: #cecece 1px solid; padding-top: 5px"&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;Specs in AnagramCodeKata:

AnagramsFinder Finding Anagrams, when given text file with word on each line
¯ should result in list of anagram sets

Contexts: 1, Specifications: 1&lt;/pre&gt;&lt;/pre&gt;

  &lt;p&gt;&amp;#160;&lt;/p&gt;

  &lt;p&gt;&lt;a href="http://lh5.ggpht.com/_rps657FzHZ0/SwJYJpq8OfI/AAAAAAAAADc/noptZ4ChfGo/s1600-h/htmlReportSuccess%5B3%5D.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="htmlReportSuccess" border="0" alt="htmlReportSuccess" src="http://lh5.ggpht.com/_rps657FzHZ0/SwJYKGw-YWI/AAAAAAAAADg/0aPU7UnGVno/htmlReportSuccess_thumb%5B1%5D.png?imgmax=800" width="583" height="436" /&gt;&lt;/a&gt; &lt;/p&gt;

  &lt;h3&gt;Final Thoughts and Questions&lt;/h3&gt;

  &lt;p&gt;So what do you think of the new test?&amp;#160; Are we better able to see the Single Responsibility of the &lt;font face="Courier New"&gt;AnagramsFinder&lt;/font&gt; manager class?&amp;#160; Are we more inline with solving the actual problem statement?&amp;#160; Your feedback would be much appreciated.&lt;/p&gt;

  &lt;p&gt;In the next post, we will begin work on test driving the design and implementation of the dependencies…unless of course I get feedback that I should be focusing on a different area first or that this last rewrite still needs more help.&lt;/p&gt;
&lt;/span&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1664217632350055880-1713026628293781613?l=murrayon.net' alt='' /&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://murrayon.net/feeds/1713026628293781613/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://murrayon.net/2009/11/anagram-code-kata-part-2-mocking-and.html#comment-form" title="2 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/1664217632350055880/posts/default/1713026628293781613?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/1664217632350055880/posts/default/1713026628293781613?v=2" /><link rel="alternate" type="text/html" href="http://murrayon.net/2009/11/anagram-code-kata-part-2-mocking-and.html" title="Anagram Code Kata Part 2 – Mocking and SRP" /><author><name>Mike Murray</name><uri>http://www.blogger.com/profile/01990150469958605173</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="15380857253844311568" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">2</thr:total></entry><entry gd:etag="W/&quot;CUMMQX45fyp7ImA9WxNbEEs.&quot;"><id>tag:blogger.com,1999:blog-1664217632350055880.post-8086161173571722818</id><published>2009-11-12T15:03:00.001-07:00</published><updated>2009-11-12T15:04:40.027-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-11-12T15:04:40.027-07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="BDD" /><category scheme="http://www.blogger.com/atom/ns#" term=".NET" /><category scheme="http://www.blogger.com/atom/ns#" term="Testing" /><category scheme="http://www.blogger.com/atom/ns#" term="Anagram Code Kata Series" /><category scheme="http://www.blogger.com/atom/ns#" term="MSpec" /><category scheme="http://www.blogger.com/atom/ns#" term="C#" /><category scheme="http://www.blogger.com/atom/ns#" term="Visual Studio" /><category scheme="http://www.blogger.com/atom/ns#" term="Microsoft" /><category scheme="http://www.blogger.com/atom/ns#" term="Code Organization" /><category scheme="http://www.blogger.com/atom/ns#" term="Algorithms" /><title>Anagram Code Kata Part 1 – Getting Started</title><content type="html">&lt;p&gt;This post is part of a &lt;a href="http://murrayon.net/2009/11/anagram-code-kata-bdd-mspec.html" target="_blank"&gt;series on coding Kata, BDD, MSpec, and SOLID principles&lt;/a&gt;.&amp;#160; Feel free to visit the above link which points to the introductory post, also containing an index of all posts in the series.&lt;/p&gt;  &lt;p&gt;This post will provide resources that serve as an introduction to the &lt;a href="http://github.com/machine/machine.specifications" target="_blank"&gt;MSpec BDD testing framework&lt;/a&gt;.&amp;#160; We will also set up our Visual Studio solution, explain the Anagram Code Kata problem statement, and write our first specification and test.&lt;/p&gt; &lt;span class="fullpost"&gt;   &lt;h3&gt;Machine.Specifications (MSpec)&lt;/h3&gt;    &lt;p&gt;The author of this BDD testing framework is &lt;a href="http://codebetter.com/blogs/aaron.jensen/default.aspx" target="_blank"&gt;Aaron Jensen&lt;/a&gt; of &lt;a href="http://codebetter.com/" target="_blank"&gt;CodeBetter.com&lt;/a&gt;.&amp;#160; Probably the best introduction to the framework (and lightly touching on general principles of BDD) is &lt;a href="http://blog.wekeroad.com/" target="_blank"&gt;Rob Conery’s&lt;/a&gt; post entitled &lt;a href="http://blog.wekeroad.com/blog/make-bdd-your-bff-2" target="_blank"&gt;Make BDD Your BFF&lt;/a&gt;.&amp;#160; MSpec is hosted on &lt;a href="http://github.com/" target="_blank"&gt;GitHub&lt;/a&gt; using the &lt;a href="http://en.wikipedia.org/wiki/Git_(software)" target="_blank"&gt;Git source control software&lt;/a&gt; (and &lt;a href="http://github.com/machine/machine.specifications" target="_blank"&gt;here is the link for the repository again&lt;/a&gt;).&amp;#160; Download the code and build it to get the necessary libraries that you need into a &lt;font face="Courier New"&gt;Bin&lt;/font&gt; folder.&amp;#160; My MSpec libraries are a few months old, as I haven’t upgraded my source since my initial download back then.&amp;#160; I have not set up TestDriven.NET and am not sure it will be necessary for this simple coding exercise.&amp;#160; I am using NUnit for the actual testing framework underneath MSpec; the following article may be of interest to you if you would like to use a newer version of NUnit than what MSpec targets:&lt;/p&gt;    &lt;p&gt;&lt;a href="http://codebetter.com/blogs/howard.dierking/archive/2009/11/08/using-latest-nunit-version-with-mspec.aspx" target="_blank"&gt;Using Latest NUnit Version with MSpec&lt;/a&gt;&lt;/p&gt;    &lt;p&gt;MSpec helps you organize your code into Specifications, a core BDD concept.&amp;#160; It is inspired by early BDD testing frameworks like Ruby’s &lt;a href="http://rspec.info/" target="_blank"&gt;RSpec&lt;/a&gt;.&amp;#160; The syntax and arrangement can be a little odd for a static language like C#, but I think I like the direction it is heading.&amp;#160; Again, the best way to get familiar with the syntax, set up the MSpec Test Runner, and configure HTML reporting output is to read &lt;a href="http://blog.wekeroad.com/blog/make-bdd-your-bff-2" target="_blank"&gt;Rob’s introductory post on BDD and MSpec&lt;/a&gt;.&lt;/p&gt;    &lt;h3&gt;Setting Up the Visual Studio Solution&lt;/h3&gt;    &lt;p&gt;Let’s begin by creating a C# console application named &lt;font face="Courier New"&gt;AnagramCodeKata&lt;/font&gt; targeting .NET Framework 3.5.&amp;#160; The solution name (and solution folder) will be the same.&amp;#160; For our dependencies on MSpec (and NUnit), I have created a physical file system folder named &lt;font face="Courier New"&gt;Libraries&lt;/font&gt; and made it a sibling folder to the project’s physical folder (same level as the solution file).&amp;#160; That folder contains the following DLL libraries from the &lt;font face="Courier New"&gt;Bin&lt;/font&gt; folder of the compiled MSpec source code:&lt;/p&gt;    &lt;ul&gt;     &lt;li&gt;&lt;font face="Courier New"&gt;CommandLine.dll&lt;/font&gt; &lt;/li&gt;      &lt;li&gt;&lt;font face="Courier New"&gt;Machine.Specifications.ConsoleRunner.exe&lt;/font&gt; &lt;/li&gt;      &lt;li&gt;&lt;font face="Courier New"&gt;Machine.Specifications.dll&lt;/font&gt; &lt;/li&gt;      &lt;li&gt;&lt;font face="Courier New"&gt;Machine.Specifications.NUnit.dll&lt;/font&gt; &lt;/li&gt;      &lt;li&gt;&lt;font face="Courier New"&gt;Machine.Specifications.Reporting.dll&lt;/font&gt; &lt;/li&gt;      &lt;li&gt;&lt;font face="Courier New"&gt;nunit.framework.dll&lt;/font&gt; &lt;/li&gt;   &lt;/ul&gt;    &lt;p&gt;Then within our Solution Explorer, we only need to make references to 3 of these libraries (namely &lt;font face="Courier New"&gt;Machine.Specifications.dll&lt;/font&gt;, &lt;font face="Courier New"&gt;Machine.Specifications.NUnit.dll&lt;/font&gt;, and &lt;font face="Courier New"&gt;nunit.framework.dll&lt;/font&gt;).&amp;#160; I have also created two folders within our project in Solution Explorer, naming them &lt;font face="Courier New"&gt;Reports&lt;/font&gt; and &lt;font face="Courier New"&gt;Specifications&lt;/font&gt;.&amp;#160; The &lt;font face="Courier New"&gt;Reports&lt;/font&gt; folder will contain the HTML-generated report of running our tests every time.&amp;#160; The &lt;font face="Courier New"&gt;Specifications&lt;/font&gt; folder will hold our specifications and tests.&amp;#160; This is what our current Solution Explorer looks like now:&lt;/p&gt;    &lt;p&gt;&lt;a href="http://lh3.ggpht.com/_rps657FzHZ0/SvyGOtiALTI/AAAAAAAAADM/Xeygzia8cho/s1600-h/anagramScreenshot%5B6%5D.png"&gt;&lt;img style="border-right-width: 0px; display: block; float: none; border-top-width: 0px; border-bottom-width: 0px; margin-left: auto; border-left-width: 0px; margin-right: auto" title="anagramScreenshot" border="0" alt="anagramScreenshot" src="http://lh4.ggpht.com/_rps657FzHZ0/SvyGO870IZI/AAAAAAAAADQ/lDW6F6bIuhI/anagramScreenshot_thumb%5B4%5D.png?imgmax=800" width="289" height="340" /&gt;&lt;/a&gt; &lt;/p&gt;    &lt;p&gt;Also notice the &lt;font face="Courier New"&gt;MSpecRunner &lt;/font&gt;button at the top, which I’ve created to execute a custom External Tool that points to &lt;font face="Courier New"&gt;Machine.Specifications.ConsoleRunner.exe&lt;/font&gt; and passes in the appropriate parameters.&amp;#160; This helpful setup was put forth by Rob Conery in the link to his introductory blog post that I provided above.&lt;/p&gt;    &lt;h3&gt;Anagram Problem Statement&lt;/h3&gt;    &lt;p&gt;So let’s go ahead and look at the &lt;a href="http://codekata.pragprog.com/2007/01/kata_six_anagra.html"&gt;Anagram problem&lt;/a&gt; we are trying to solve.&amp;#160; Here’s a quick summary of what we are trying to accomplish:&lt;/p&gt;    &lt;blockquote&gt;     &lt;p&gt;“The challenge is fairly simple: given a file containing one word per line, print out all the combinations of words that are anagrams; each line in the output contains all the words from the input that are anagrams of each other.”&lt;/p&gt;   &lt;/blockquote&gt;    &lt;p&gt;Unfortunately, Dave Thomas’ &lt;font face="Courier New"&gt;wordlist.txt&lt;/font&gt; link is broken on his blog post, and when responding to commenters asking for a fixed link to the text file, he pointed us all to some website that aggregates links to several word lists from around the Web.&amp;#160; Many of us readers wanted to know the exact word list file he used so that we could compare our results to his.&amp;#160; In his post, he states that there should be 2,530 sets of anagrams and 5,680 total words participating in those anagram sets.&amp;#160; The tough part about this is that we’ve got to have the same word list text file.&amp;#160; I searched the web and found a few, but I only found one that might be the same list.&amp;#160; It is from some guy’s personal GitHub repository:&lt;/p&gt;    &lt;p&gt;&lt;a title="http://github.com/krist0ff/code_kata/tree/ba975c3a64f11a81db2f3716b40de046f1ca7ef4/kata6" href="http://github.com/krist0ff/code_kata/tree/ba975c3a64f11a81db2f3716b40de046f1ca7ef4/kata6"&gt;http://github.com/krist0ff/code_kata/tree/ba975c3a64f11a81db2f3716b40de046f1ca7ef4/kata6&lt;/a&gt;&lt;/p&gt;    &lt;p&gt;If you’re visiting this blog post, months or years after it was originally written, I obviously can’t guarantee this file will still be out there.&amp;#160; You can try emailing me or commenting here and I can hopefully send it to you via email if I still have it.&amp;#160; But more importantly, as we progress with this series, we’ll find out if it’s even the right word list or not.&lt;/p&gt;    &lt;p&gt;Lastly, I’d like to look at the objectives for the coding kata that Dave Thomas outlines:&lt;/p&gt;    &lt;blockquote&gt;     &lt;p&gt;“Apart from having some fun with words, this kata should make you think somewhat about algorithms. The simplest algorithms to find all the anagram combinations may take inordinate amounts of time to do the job. Working though alternatives should help bring the time down by orders of magnitude. To give you a possible point of comparison, I hacked a solution together in 25 lines of Ruby. It runs on the word list from my web site in 1.5s on a 1GHz PPC. It’s also an interesting exercise in testing: can you write unit tests to verify that your code is working correctly before setting it to work on the full dictionary.”&lt;/p&gt;   &lt;/blockquote&gt;    &lt;p&gt;I don’t think we’ll focus on runtime as much, but we’ll certainly revisit our algorithm as necessary if we have unacceptable wait times for the code to finish.&amp;#160; To complete this section, let’s go ahead and add the &lt;font face="Courier New"&gt;wordlist.txt&lt;/font&gt; to our solution at the root of of our Project node.&lt;/p&gt;    &lt;h3&gt;How About Some Actual Code?!&lt;/h3&gt;    &lt;p&gt;So let’s now start off by creating our first specification.&amp;#160; I have created a new C# file named &lt;font face="Courier New"&gt;AnagramsFinderSpecs.cs&lt;/font&gt; under our &lt;font face="Courier New"&gt;Specifications&lt;/font&gt; folder in our solution.&amp;#160; I attempted to write our first test, but already feel like I’m not inline with “&lt;a href="http://www.davesquared.net/2009/11/favour-test-driving-logic-over-data.html"&gt;favoring test driving logic over just testing data&lt;/a&gt;.”&lt;/p&gt;    &lt;pre class="brush: csharp"&gt;using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using Machine.Specifications;

namespace AnagramCodeKata.Specifications
{
    [Subject(typeof(AnagramsFinder), &amp;quot;Finding Anagrams&amp;quot;)]
    public class when_given_text_file_with_word_on_each_line
    {
        static int result;
        static AnagramsFinder sut;

        Establish context = () =&amp;gt;
        {
            sut = new AnagramsFinder();
        };

        Because of = () =&amp;gt;
        {
            result = sut.ParseTextFile(&amp;quot;wordslist.txt&amp;quot;);
        };

        It should_result_in_count_of_2530_anagram_sets = () =&amp;gt;
        {
            result.ShouldEqual(2530);
        };
    }
}&lt;/pre&gt;

  &lt;p&gt;If you can’t make out the funky structure and syntax, again refer back to Rob Conery’s introductory post to all of this stuff that I link to at the top.&amp;#160; He does a great job of explaining what’s going on here.&lt;/p&gt;

  &lt;p&gt;Also, please remember that I have no clue what I’m doing and I’m just trying to copy people who know what they are doing.&amp;#160; I am hoping that I’ll be corrected by those who have a better idea of how to approach all of this.&amp;#160; This is a good stopping point because of my desire for feedback and the feeling of uncertainty I’m already getting.&lt;/p&gt;

  &lt;p&gt;Seriously, please guide me in the right direction or validate where I’m headed, because even I’m not sure where that is yet.&amp;#160; I will say this, I’m pretty sure I shouldn’t be reading in &lt;font face="Courier New"&gt;wordslist.txt&lt;/font&gt; yet, and that this might be where I need to start using a mocking framework.&lt;/p&gt;

  &lt;p&gt;Stay tuned, there’s more to come.&amp;#160; I just can’t tell what it will be about yet.&amp;#160; It’ll still be fun though, I promise.&lt;/p&gt;
&lt;/span&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1664217632350055880-8086161173571722818?l=murrayon.net' alt='' /&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://murrayon.net/feeds/8086161173571722818/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://murrayon.net/2009/11/anagram-code-kata-part-1-getting.html#comment-form" title="2 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/1664217632350055880/posts/default/8086161173571722818?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/1664217632350055880/posts/default/8086161173571722818?v=2" /><link rel="alternate" type="text/html" href="http://murrayon.net/2009/11/anagram-code-kata-part-1-getting.html" title="Anagram Code Kata Part 1 – Getting Started" /><author><name>Mike Murray</name><uri>http://www.blogger.com/profile/01990150469958605173</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="15380857253844311568" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">2</thr:total></entry><entry gd:etag="W/&quot;DE4MSXs6cSp7ImA9WxNUGUo.&quot;"><id>tag:blogger.com,1999:blog-1664217632350055880.post-2610711337538360854</id><published>2009-11-11T15:03:00.001-07:00</published><updated>2009-11-11T15:03:08.519-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-11-11T15:03:08.519-07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="MSI" /><category scheme="http://www.blogger.com/atom/ns#" term=".NET" /><category scheme="http://www.blogger.com/atom/ns#" term="Build" /><category scheme="http://www.blogger.com/atom/ns#" term="Windows" /><category scheme="http://www.blogger.com/atom/ns#" term="C#" /><category scheme="http://www.blogger.com/atom/ns#" term="Prerequisites" /><category scheme="http://www.blogger.com/atom/ns#" term="Microsoft" /><category scheme="http://www.blogger.com/atom/ns#" term="Deployment and Installers" /><category scheme="http://www.blogger.com/atom/ns#" term="Bootstrapper" /><category scheme="http://www.blogger.com/atom/ns#" term="MSBuild" /><category scheme="http://www.blogger.com/atom/ns#" term="Visual Studio" /><category scheme="http://www.blogger.com/atom/ns#" term="C/C++" /><category scheme="http://www.blogger.com/atom/ns#" term="Registry" /><category scheme="http://www.blogger.com/atom/ns#" term="Launch Condition" /><title>Custom Setup Bootstrappers</title><content type="html">&lt;p&gt;At work, we have a line of desktop products for one of clients installed on the user’s Windows machine via MSI installers.&amp;#160; We use Visual Studio Setup Projects to create the MSI installers.&amp;#160; Visual Studio also provides the ability to create setup bootstrappers to make sure the user has all the prerequisites needed for the MSI install technology and any dependencies required by your desktop product.&amp;#160; These bootstrappers are unmanaged code, because you can’t always depend on the .NET framework already being there (at least not until everyone is off of XP and lower).&amp;#160; I have developed a solution that has worked for the last year or more, but has felt clumsy and slapped together.&amp;#160; Recently I found the &lt;a href="http://dotnetinstaller.codeplex.com/"&gt;open source project called dotNetInstaller&lt;/a&gt; which has better provided me with the control and flexibility I need for custom logic during bootstrap and install time.&amp;#160; I’ll first introduce you to my “hack” solution.&lt;/p&gt; &lt;span class="fullpost"&gt;   &lt;p&gt;It has been difficult for me to find ways to tie into the bootstrapper logic workflow to add in custom logic during installs, and Visual Studio is very rigid in its flexibility and basic in its configuration options in this regard.&amp;#160; Until recently, I had settled on writing managed, C# code for this custom logic meant to run before or after the MSI installer, and then creating another unmanaged &lt;font face="Courier New"&gt;setup.exe&lt;/font&gt; bootstrapper to ensure the .NET framework was installed just so that executable could run.&amp;#160; So the user would run this new unmanaged &lt;font face="Courier New"&gt;setup.exe&lt;/font&gt; bootstrapper (making sure .NET framework was installed), which would then call my managed custom logic executable, which would then call the MSI installer’s unmanaged, Visual Studio-generated &lt;font face="Courier New"&gt;setup.exe&lt;/font&gt; bootstrapper (ensuring more prerequisites were installed), which would then finally install the MSI, and which would then lastly return to my managed custom logic executable for any post-install, clean up logic.&amp;#160; I describe this solution in full (and how to generate the same bootstrappers that Visual Studio creates using MSBuild outside the IDE) in a StackOverflow.com answer that I submitted:&lt;/p&gt;    &lt;p&gt;&lt;a title="http://stackoverflow.com/questions/1106768/how-can-i-reverse-engineer-an-installer-that-was-written-with-ghost-installer/1121846#1121846" href="http://stackoverflow.com/questions/1106768/how-can-i-reverse-engineer-an-installer-that-was-written-with-ghost-installer/1121846#1121846"&gt;http://stackoverflow.com/questions/1106768/how-can-i-reverse-engineer-an-installer-that-was-written-with-ghost-installer/1121846#1121846&lt;/a&gt;&lt;/p&gt;    &lt;p&gt;Well, recently I found the &lt;a href="http://dotnetinstaller.codeplex.com/"&gt;dotNetInstaller project on CodePlex.com&lt;/a&gt; and have found it to be the control and flexibility I need for custom logic when bootstrapping installers.&amp;#160; Not only does it give you great control over prerequisite install order, it also gives you the ability to run code after MSI install and to also filter on CPU architecture types, OS versions, and other registry or file system conditions.&amp;#160; I have currently setup branching scenarios for the prerequisites based on if the user has a 32-bit (x86) or 64-bit (x64) OS.&amp;#160; This utility will even let you brand the bootstrapper with a banner and icon, which is a change of pace from the plain and unlabeled bootstrapper that Visual Studio and MSBuild produce.&lt;/p&gt;    &lt;p&gt;If you have custom bootstrapping needs, I have to highly recommend you give dotNetInstaller a look.&amp;#160; Hopefully it will prove as flexible and powerful for your needs as it has for mine.&lt;/p&gt; &lt;/span&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1664217632350055880-2610711337538360854?l=murrayon.net' alt='' /&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://murrayon.net/feeds/2610711337538360854/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://murrayon.net/2009/11/custom-setup-bootstrappers.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/1664217632350055880/posts/default/2610711337538360854?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/1664217632350055880/posts/default/2610711337538360854?v=2" /><link rel="alternate" type="text/html" href="http://murrayon.net/2009/11/custom-setup-bootstrappers.html" title="Custom Setup Bootstrappers" /><author><name>Mike Murray</name><uri>http://www.blogger.com/profile/01990150469958605173</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="15380857253844311568" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total></entry><entry gd:etag="W/&quot;C0EASHk6eip7ImA9WxBVGE0.&quot;"><id>tag:blogger.com,1999:blog-1664217632350055880.post-5468325837601038177</id><published>2009-11-10T21:32:00.003-07:00</published><updated>2010-02-21T18:20:49.712-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-02-21T18:20:49.712-07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="New Technology" /><category scheme="http://www.blogger.com/atom/ns#" term="BDD" /><category scheme="http://www.blogger.com/atom/ns#" term=".NET" /><category scheme="http://www.blogger.com/atom/ns#" term="Testing" /><category scheme="http://www.blogger.com/atom/ns#" term="Anagram Code Kata Series" /><category scheme="http://www.blogger.com/atom/ns#" term="MSpec" /><category scheme="http://www.blogger.com/atom/ns#" term="Code Organization" /><category scheme="http://www.blogger.com/atom/ns#" term="SOLID" /><title>Anagram Code Kata – BDD &amp; MSpec</title><content type="html">&lt;p&gt;Many forms of martial arts utilize the &lt;a href="http://en.wikipedia.org/wiki/Kata" target="_blank"&gt;kata&lt;/a&gt; as a means for detailed, focused practice and training.&amp;#160; The power of this practice comes from repetition and focus on simple fundamentals, “while attempting to maintain perfect form.”&amp;#160; The principle goal is to “try out different combinations of techniques in a safe, practice environment to ultimately find out how to defeat your opponent”.&amp;#160; In the last few years, this concept has taken hold within the software development world in the form of &lt;a href="http://en.wikipedia.org/wiki/Code_Kata" target="_blank"&gt;Code Kata&lt;/a&gt;, a phrase coined by &lt;a href="http://pragprog.com/" target="_blank"&gt;Pragmatic Programmer&lt;/a&gt; &lt;a href="http://pragdave.pragprog.com/" target="_blank"&gt;Dave Thomas&lt;/a&gt; (and &lt;a href="http://codekata.pragprog.com/" target="_blank"&gt;here is his blog dedicated to the Code Kata&lt;/a&gt;).&lt;/p&gt;  &lt;p&gt;My inspiration for all of this is &lt;a href="http://www.davesquared.net/2009/10/calculators-and-tale-of-two-tdds-pt-1.html" target="_blank"&gt;David Tchepak’s Calculator Kata series of posts&lt;/a&gt;.&amp;#160; Hopefully he will stop by and provide some helpful guidance and advice.&amp;#160; I have selected the &lt;a href="http://codekata.pragprog.com/2007/01/kata_six_anagra.html" target="_blank"&gt;Anagram Kata (code kata number 6)&lt;/a&gt; for me to practice.&amp;#160; My goals for this series of posts are:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;To practice coding and share my learning experience with you, while also soliciting feedback and suggestions. &lt;/li&gt;    &lt;li&gt;To more fully understand the concepts driving &lt;a href="http://en.wikipedia.org/wiki/Behavior_Driven_Development" target="_blank"&gt;Behavior Driven Development (BDD)&lt;/a&gt; via a testing framework designed for such a practice, namely &lt;a href="http://blog.wekeroad.com/blog/make-bdd-your-bff-2/" target="_blank"&gt;MSpec&lt;/a&gt;. &lt;/li&gt;    &lt;li&gt;To keep to the &lt;a href="http://www.davesquared.net/2009/01/introduction-to-solid-principles-of-oo.html" target="_blank"&gt;SOLID principles of Object-Oriented Design&lt;/a&gt;, especially &lt;a href="http://www.davesquared.net/2009/11/favour-test-driving-logic-over-data.html" target="_blank"&gt;in favor of test driving logic over just testing data&lt;/a&gt;. &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;Below I will keep an updated list of blog posts in this series.&amp;#160; Hope you enjoy it!&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;&lt;a href="http://murrayon.net/2009/11/anagram-code-kata-part-1-getting.html"&gt;Part 1 – Getting Started&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href="http://murrayon.net/2009/11/anagram-code-kata-part-2-mocking-and.html" target="_blank"&gt;Part 2 – Mocking and SRP (Single Responsibility Principle)&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href="http://murrayon.net/2009/12/anagram-code-kata-part-3-use-common.html" target="_blank"&gt;Part 3 – Use Common Sense&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href="http://murrayon.net/2010/01/anagram-code-kata-part-4-will-it-write.html"&gt;Part 4 – Will it Write My Code for Me?&lt;/a&gt;&lt;/li&gt;    &lt;li&gt;&lt;a href="http://murrayon.net/2010/02/anagram-code-kata-part-5-domain-objects.html"&gt;Part 5 – Domain Objects Over Language Primitives&lt;/a&gt;&amp;#160;&lt;/li&gt; &lt;/ul&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1664217632350055880-5468325837601038177?l=murrayon.net' alt='' /&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://murrayon.net/feeds/5468325837601038177/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://murrayon.net/2009/11/anagram-code-kata-bdd-mspec.html#comment-form" title="1 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/1664217632350055880/posts/default/5468325837601038177?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/1664217632350055880/posts/default/5468325837601038177?v=2" /><link rel="alternate" type="text/html" href="http://murrayon.net/2009/11/anagram-code-kata-bdd-mspec.html" title="Anagram Code Kata – BDD &amp;amp; MSpec" /><author><name>Mike Murray</name><uri>http://www.blogger.com/profile/01990150469958605173</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="15380857253844311568" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">1</thr:total></entry><entry gd:etag="W/&quot;D04DR3c7fCp7ImA9WxNVFkQ.&quot;"><id>tag:blogger.com,1999:blog-1664217632350055880.post-1145610350465942405</id><published>2009-10-23T19:54:00.006-06:00</published><updated>2009-10-27T20:12:56.904-06:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-10-27T20:12:56.904-06:00</app:edited><title>Trying Out SyntaxHighlighter</title><content type="html">&lt;p&gt;This is just a test post to see if I'm smart enough to add the javascript &lt;a href="http://alexgorbatchev.com/wiki/SyntaxHighlighter:Demo"&gt;SyntaxHighlighter&lt;/a&gt; to my blog. ;)&lt;/p&gt;

&lt;pre class="brush: csharp"&gt;
public int ScoreDice(int[] selectedDice)
{
    int score = 0;

    foreach (IScoringCombo scoreCombo in ScoringCombos)
    {
        IEnumerable&amp;lt;int&amp;gt; satisfyingIndices = scoreCombo.SatisfiedBy(selectedDice);

        if (satisfyingIndices.Count() &amp;gt; 0)
        {
            score += scoreCombo.ScoreDice(selectedDice);

            // Remove the dice at satisfyingIndices from selectedDice collection so not double-scored
            selectedDice = selectedDice
                .Select((value, index) =&amp;gt; index)
                .Except(satisfyingIndices)
                .ToArray();
        }
    }

    return score;
}
&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1664217632350055880-1145610350465942405?l=murrayon.net' alt='' /&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://murrayon.net/feeds/1145610350465942405/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://murrayon.net/2009/10/trying-out-syntaxhighlighter.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/1664217632350055880/posts/default/1145610350465942405?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/1664217632350055880/posts/default/1145610350465942405?v=2" /><link rel="alternate" type="text/html" href="http://murrayon.net/2009/10/trying-out-syntaxhighlighter.html" title="Trying Out SyntaxHighlighter" /><author><name>Mike Murray</name><uri>http://www.blogger.com/profile/01990150469958605173</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="15380857253844311568" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total></entry><entry gd:etag="W/&quot;DU4FRH09eCp7ImA9WxNXEks.&quot;"><id>tag:blogger.com,1999:blog-1664217632350055880.post-3190857442496647610</id><published>2009-09-29T17:45:00.001-06:00</published><updated>2009-09-29T17:45:15.360-06:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-09-29T17:45:15.360-06:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Web" /><category scheme="http://www.blogger.com/atom/ns#" term="New Technology" /><category scheme="http://www.blogger.com/atom/ns#" term="MSI" /><category scheme="http://www.blogger.com/atom/ns#" term=".NET" /><category scheme="http://www.blogger.com/atom/ns#" term="Deployment and Installers" /><category scheme="http://www.blogger.com/atom/ns#" term="IIS" /><category scheme="http://www.blogger.com/atom/ns#" term="Windows" /><category scheme="http://www.blogger.com/atom/ns#" term="Visual Studio" /><category scheme="http://www.blogger.com/atom/ns#" term="PowerShell" /><category scheme="http://www.blogger.com/atom/ns#" term="Microsoft" /><title>Web Deployment Tool</title><content type="html">&lt;p&gt;It appears that the IIS team at Microsoft has officially completed a 1.0 version of the deployment utility I mentioned at the end of &lt;a title="Visual Studio Web Deployment Projects" href="http://murrayon.net/2008/02/visual-studio-web-deployment-projects.html"&gt;my previous post about Visual Studio Web Deployment Projects&lt;/a&gt; almost two years ago.&amp;#160; It includes a command-line tool named MSDeploy that helps with deploying and syncing web projects across all of the web servers in your server farm.&amp;#160; The installation also includes all kinds of packaging and deployment features that seem really handy.&amp;#160; You can even do migrations from IIS 6 to IIS 7 or package your apps to be distributed via the &lt;a href="http://www.microsoft.com/web/downloads/platform.aspx"&gt;Microsoft Web Platform Installer&lt;/a&gt;.&lt;/p&gt;  &lt;p&gt;I thought that maybe the tool creates MSI installers, but it appears the package may actually just be a ZIP file that you can import and export through the IIS Manager or various other command-line tools or PowerShell Cmdlets.&lt;/p&gt;  &lt;p&gt;Here is the page where you can read more about the toolset and download the installer:&amp;#160; &lt;a title="http://www.iis.net/extensions/WebDeploymentTool" href="http://www.iis.net/extensions/WebDeploymentTool"&gt;http://www.iis.net/extensions/WebDeploymentTool&lt;/a&gt;&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1664217632350055880-3190857442496647610?l=murrayon.net' alt='' /&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://murrayon.net/feeds/3190857442496647610/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://murrayon.net/2009/09/web-deployment-tool.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/1664217632350055880/posts/default/3190857442496647610?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/1664217632350055880/posts/default/3190857442496647610?v=2" /><link rel="alternate" type="text/html" href="http://murrayon.net/2009/09/web-deployment-tool.html" title="Web Deployment Tool" /><author><name>Mike Murray</name><uri>http://www.blogger.com/profile/01990150469958605173</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="15380857253844311568" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total></entry><entry gd:etag="W/&quot;DkQGSH85fip7ImA9WxNVGEg.&quot;"><id>tag:blogger.com,1999:blog-1664217632350055880.post-7109317170222139904</id><published>2009-09-23T16:09:00.000-06:00</published><updated>2009-10-29T16:12:09.126-06:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-10-29T16:12:09.126-06:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Error" /><category scheme="http://www.blogger.com/atom/ns#" term="Java" /><category scheme="http://www.blogger.com/atom/ns#" term=".NET" /><category scheme="http://www.blogger.com/atom/ns#" term="C#" /><category scheme="http://www.blogger.com/atom/ns#" term="C/C++" /><category scheme="http://www.blogger.com/atom/ns#" term="Microsoft" /><title>Variable Declaration Restrictions</title><content type="html">&lt;p&gt;I came across a surprising restriction on variable declarations that I thought I would share.&lt;/p&gt;  &lt;p&gt;My own investigation into C# was prompted by &lt;a title="Declaring variables inside a switch statement - Stack Overflow" href="http://stackoverflow.com/questions/1231198/declaring-variables-inside-a-switch-statement/1231209#1231209"&gt;an answer given to a Stack Overflow question regarding an odd Objective-C compiler error&lt;/a&gt;.&amp;#160; The answer seemed to allude to a language specification somewhere that doesn’t allow variable declarations in one-liner embedded statements of control structures (loops, &lt;font face="Courier New"&gt;switch&lt;/font&gt; statements, &lt;font face="Courier New"&gt;if-else&lt;/font&gt; statements, etc.).&amp;#160; Not only that, Objective-C wasn’t unique in this restriction; it appears Java and even C itself have had this restriction for quite a while as well.&lt;/p&gt;  &lt;p&gt;Naturally this got my curiosity going and I decided to see if C# had also carried over such a restriction.&amp;#160; The answer is yes; it appears that Java, C#, and Objective-C have all kept this language restriction from their common ancestor C.&amp;#160; Let’s get right to what it looks like:&lt;/p&gt; &lt;span class='fullpost'&gt; &lt;p&gt;&lt;a href="http://lh5.ggpht.com/_rps657FzHZ0/SrqdKFwyBLI/AAAAAAAAADA/8fajE6RTF0o/s1600-h/code_screenshot%5B6%5D.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="code_screenshot" border="0" alt="code_screenshot" src="http://lh3.ggpht.com/_rps657FzHZ0/SrqdKaU74uI/AAAAAAAAADE/HGin3AOsrsM/code_screenshot_thumb%5B4%5D.png?imgmax=800" width="416" height="712" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;The red-underlined errors read “&lt;font face="Courier New"&gt;embedded statement cannot be a declaration or labeled statement&lt;/font&gt;” and the green-underlined warnings read “&lt;font face="Courier New"&gt;the variable ‘i’ is assigned but its value is never used&lt;/font&gt;.”&amp;#160; You’ve probably seen the warning quite a few times before, but the compiler error really caught me by surprise.&amp;#160; I mean it makes sense that declaring a variable in the one-line body of a control structure is pointless, as it would immediately go out of scope (and usefulness) after declared.&amp;#160; But I thought it odd for the compiler to actually deny such a program statement, as if it put the compiler in an invalid state or maybe it was somehow dangerous.&lt;/p&gt;  &lt;p&gt;One thing I do want to point out that appears to be different from the other languages (or at the very least Objective-C) is that the variable declaration is allowed in the &lt;font face="Courier New"&gt;switch&lt;/font&gt; statement, as illustrated in the image above.&lt;/p&gt;  &lt;p&gt;To figure out why this isn’t allowed, I decided to actually look into the &lt;a href="http://msdn.microsoft.com/en-us/vcsharp/aa336809.aspx"&gt;C# 3.0 Language Specification&lt;/a&gt; to see if there were any comments or explanations regarding this issue.&amp;#160; I ended up finding the C# language grammar in Appendix B.&amp;#160; I was able to parse through the grammar and find this restriction in the grammar itself.&amp;#160; Take a look:&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;B.2.5 &lt;/strong&gt;&lt;a name="_Toc174237894"&gt;&lt;strong&gt;Statements&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;  &lt;div&gt;&lt;em&gt;statement: &lt;/em&gt;&lt;/div&gt;  &lt;div style="margin-left: 40px"&gt;&lt;em&gt;labeled-statement      &lt;br /&gt;declaration-statement       &lt;br /&gt;embedded-statement&lt;/em&gt;&lt;/div&gt;  &lt;p&gt;&lt;/p&gt;  &lt;div&gt;&lt;em&gt;embedded-statement: &lt;/em&gt;&lt;/div&gt;  &lt;div style="margin-left: 40px"&gt;&lt;em&gt;block      &lt;br /&gt;empty-statement       &lt;br /&gt;expression-statement       &lt;br /&gt;selection-statement       &lt;br /&gt;iteration-statement       &lt;br /&gt;jump-statement       &lt;br /&gt;try-statement       &lt;br /&gt;checked-statement       &lt;br /&gt;unchecked-statement       &lt;br /&gt;lock-statement       &lt;br /&gt;using-statement       &lt;br /&gt;yield-statement&lt;/em&gt;&lt;/div&gt;  &lt;p&gt;&lt;/p&gt;  &lt;div&gt;&lt;em&gt;block: &lt;/em&gt;&lt;/div&gt;  &lt;div style="margin-left: 40px"&gt;{&lt;em&gt; statement-list&lt;sub&gt;optional&lt;/sub&gt;&lt;/em&gt; }&lt;/div&gt;  &lt;p&gt;&lt;/p&gt;  &lt;div&gt;&lt;em&gt;statement-list: &lt;/em&gt;&lt;/div&gt;  &lt;div style="margin-left: 40px"&gt;&lt;em&gt;statement      &lt;br /&gt;statement-list statement&lt;/em&gt;&lt;/div&gt;  &lt;p&gt;...&lt;/p&gt;  &lt;div&gt;&lt;em&gt;selection-statement: &lt;/em&gt;&lt;/div&gt;  &lt;div style="margin-left: 40px"&gt;&lt;em&gt;if-statement      &lt;br /&gt;switch-statement&lt;/em&gt;&lt;/div&gt;  &lt;p&gt;&lt;/p&gt;  &lt;div&gt;&lt;em&gt;if-statement: &lt;/em&gt;&lt;/div&gt;  &lt;div style="margin-left: 40px"&gt;if ( &lt;em&gt;boolean-expression&lt;/em&gt; ) &lt;em&gt;embedded-statement&lt;/em&gt;     &lt;br /&gt;if ( &lt;em&gt;boolean-expression&lt;/em&gt; ) &lt;em&gt;embedded-statement&lt;/em&gt; else &lt;em&gt;embedded-statement&lt;/em&gt;&lt;/div&gt;  &lt;p&gt;&lt;/p&gt;  &lt;div&gt;&lt;em&gt;switch-statement: &lt;/em&gt;&lt;/div&gt;  &lt;div style="margin-left: 40px"&gt;switch ( &lt;em&gt;expression&lt;/em&gt; ) &lt;em&gt;switch-block&lt;/em&gt;&lt;/div&gt;  &lt;p&gt;&lt;/p&gt;  &lt;div&gt;&lt;em&gt;switch-block: &lt;/em&gt;&lt;/div&gt;  &lt;div style="margin-left: 40px"&gt;{ &lt;em&gt;switch-sections&lt;sub&gt;optional&lt;/sub&gt;&lt;/em&gt; }&lt;/div&gt;  &lt;p&gt;&lt;/p&gt;  &lt;div&gt;&lt;em&gt;switch-sections: &lt;/em&gt;&lt;/div&gt;  &lt;div style="margin-left: 40px"&gt;&lt;em&gt;switch-section      &lt;br /&gt;switch-sections switch-section&lt;/em&gt;&lt;/div&gt;  &lt;p&gt;&lt;/p&gt;  &lt;div&gt;&lt;em&gt;switch-section: &lt;/em&gt;&lt;/div&gt;  &lt;div style="margin-left: 40px"&gt;&lt;em&gt;switch-labels statement-list&lt;/em&gt;&lt;/div&gt;  &lt;p&gt;&lt;/p&gt;  &lt;div&gt;&lt;em&gt;switch-labels: &lt;/em&gt;&lt;/div&gt;  &lt;div style="margin-left: 40px"&gt;&lt;em&gt;switch-label      &lt;br /&gt;switch-labels switch-label&lt;/em&gt;&lt;/div&gt;  &lt;p&gt;&lt;/p&gt;  &lt;div&gt;&lt;em&gt;switch-label: &lt;/em&gt;&lt;/div&gt;  &lt;div style="margin-left: 40px"&gt;case &lt;em&gt;constant-expression&lt;/em&gt; :     &lt;br /&gt;default :&lt;/div&gt;  &lt;p&gt;...&lt;/p&gt;  &lt;p&gt;You’ll notice that there is the concept of a &lt;font face="Courier New"&gt;statement&lt;/font&gt; and an &lt;font face="Courier New"&gt;embedded-statement&lt;/font&gt;; also note that &lt;font face="Courier New"&gt;statement&lt;/font&gt; is a superset of &lt;font face="Courier New"&gt;embedded-statement&lt;/font&gt;, adding two other types of statements: &lt;font face="Courier New"&gt;labeled-statement&lt;/font&gt; and &lt;font face="Courier New"&gt;declaration-statement&lt;/font&gt;.&amp;#160; If a particular grammar rule requires an &lt;font face="Courier New"&gt;embedded-statement&lt;/font&gt;, then those two latter types of statements are not allowed in that context.&amp;#160; If we wanted to allow those two statement types, our grammar rule should specify the generic &lt;font face="Courier New"&gt;statement&lt;/font&gt; category instead.&lt;/p&gt;  &lt;p&gt;Also noteworthy is that an &lt;font face="Courier New"&gt;embedded-statement&lt;/font&gt; can resolve to a &lt;font face="Courier New"&gt;block&lt;/font&gt;, which includes braces around a &lt;font face="Courier New"&gt;statement-list&lt;/font&gt;.&amp;#160; A &lt;font face="Courier New"&gt;statement-list&lt;/font&gt; is one or more &lt;font face="Courier New"&gt;statement&lt;/font&gt; entities, which would now allow us to use the two statement types excluded from &lt;font face="Courier New"&gt;embedded-statement&lt;/font&gt;.&lt;/p&gt;  &lt;p&gt;Something interesting that is not included in the grammar snippet above, the following statement constructs (and language keywords) require the &lt;font face="Courier New"&gt;block&lt;/font&gt; statement construct, bypassing the option of a grammar resolution to &lt;font face="Courier New"&gt;embedded-statement&lt;/font&gt; directly and allowing you to leave off surrounding braces: &lt;font face="Courier New"&gt;try&lt;/font&gt;, &lt;font face="Courier New"&gt;catch&lt;/font&gt;, &lt;font face="Courier New"&gt;finally&lt;/font&gt;, &lt;font face="Courier New"&gt;checked&lt;/font&gt;, and &lt;font face="Courier New"&gt;unchecked&lt;/font&gt;.&lt;/p&gt;  &lt;p&gt;Almost all of the other statement constructs allow you the option of a one-liner &lt;font face="Courier New"&gt;embedded-statement&lt;/font&gt; (or which can be resolved into a &lt;font face="Courier New"&gt;block&lt;/font&gt;), including &lt;font face="Courier New"&gt;if&lt;/font&gt;, &lt;font face="Courier New"&gt;if-else&lt;/font&gt;, &lt;font face="Courier New"&gt;while&lt;/font&gt;, &lt;font face="Courier New"&gt;do-while&lt;/font&gt;, &lt;font face="Courier New"&gt;for&lt;/font&gt;, and &lt;font face="Courier New"&gt;foreach&lt;/font&gt;.&amp;#160; The one surprising exception is the &lt;font face="Courier New"&gt;switch&lt;/font&gt; construct, which allows for a &lt;font face="Courier New"&gt;statement-list&lt;/font&gt; after each &lt;font face="Courier New"&gt;switch-label&lt;/font&gt;.&amp;#160; As a side note, this allows you to put useless braces (via &lt;font face="Courier New"&gt;block&lt;/font&gt;) around your &lt;font face="Courier New"&gt;statement-list&lt;/font&gt; (or anywhere inside it) after any of your &lt;font face="Courier New"&gt;switch-label&lt;/font&gt; statements if you wanted.&amp;#160; But back to the point, these facts explain the existence of (and in one case, lack of) compiler errors regarding embedded statements in the code screenshot near the top.&lt;/p&gt;  &lt;p&gt;Now you will know exactly what the compiler means when it gives you the error that an “&lt;font face="Courier New"&gt;embedded statement cannot be a declaration or labeled statement.&lt;/font&gt;”&lt;/p&gt; &lt;/span&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1664217632350055880-7109317170222139904?l=murrayon.net' alt='' /&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://murrayon.net/feeds/7109317170222139904/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://murrayon.net/2009/09/variable-declaration-restrictions.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/1664217632350055880/posts/default/7109317170222139904?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/1664217632350055880/posts/default/7109317170222139904?v=2" /><link rel="alternate" type="text/html" href="http://murrayon.net/2009/09/variable-declaration-restrictions.html" title="Variable Declaration Restrictions" /><author><name>Mike Murray</name><uri>http://www.blogger.com/profile/01990150469958605173</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="15380857253844311568" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total></entry><entry gd:etag="W/&quot;DkUDRXY7fip7ImA9WxNVGEg.&quot;"><id>tag:blogger.com,1999:blog-1664217632350055880.post-1297116529623161852</id><published>2009-05-21T16:29:00.001-06:00</published><updated>2009-10-29T16:11:14.806-06:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-10-29T16:11:14.806-06:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Threading" /><category scheme="http://www.blogger.com/atom/ns#" term="Delegates" /><category scheme="http://www.blogger.com/atom/ns#" term=".NET" /><category scheme="http://www.blogger.com/atom/ns#" term="Windows Forms" /><category scheme="http://www.blogger.com/atom/ns#" term="UI" /><category scheme="http://www.blogger.com/atom/ns#" term="Microsoft" /><title>BeginInvoke Methods and OneWay Attribute</title><content type="html">&lt;p&gt;In a previous post I talked about &lt;a href="http://murrayon.net/2008/01/windows-forms-ui-threading.html"&gt;Windows Forms UI Threading&lt;/a&gt; using delegates.&amp;#160; Recently I needed to replicate what I had learned, and I happened to do so without reviewing my notes in the former blog post.&amp;#160; Apparently I didn’t remember everything I had learned and became confused over thread invocation techniques, introducing a bug into my thread messaging.&amp;#160; The UI thread was blocking while the background worker thread was processing.&lt;/p&gt;  &lt;p&gt;The cause was related to figuring out which &lt;font face="Courier New"&gt;BeginInvoke&lt;/font&gt; method to call when kicking off the worker thread, the &lt;font face="Courier New"&gt;BeginInvoke&lt;/font&gt; of the &lt;font face="Courier New"&gt;Form&lt;/font&gt; object or the &lt;font face="Courier New"&gt;BeginInvoke&lt;/font&gt; of the delegate.&amp;#160; The answer is the &lt;font face="Courier New"&gt;BeginInvoke&lt;/font&gt; method of the delegate.&amp;#160; All of the examples linked to in the previous post had it right, but I got it mixed up with making &lt;font face="Courier New"&gt;Invoke&lt;/font&gt; or &lt;font face="Courier New"&gt;BeginInvoke&lt;/font&gt; calls from the background thread using the &lt;font face="Courier New"&gt;Form&lt;/font&gt; object’s version of these methods.&amp;#160; If you don’t care whether your messaging from the background thread is synchronous or asynchronous, then you can use either methods and you can use the ones from the &lt;font face="Courier New"&gt;Form&lt;/font&gt; object.&lt;/p&gt;  &lt;p&gt;The problem is using these &lt;font face="Courier New"&gt;Form&lt;/font&gt; object methods in order to kick off your background worker thread.&amp;#160; The description of the &lt;font face="Courier New"&gt;BeginInvoke&lt;/font&gt; method on the &lt;font face="Courier New"&gt;Form&lt;/font&gt; object states that it &lt;font face="Courier New"&gt;“executes the specified delegate asynchronously on the thread that the control’s underlying handle was created on.”&lt;/font&gt;&amp;#160; I translate this to mean that calling your &lt;font face="Courier New"&gt;Form&lt;/font&gt; object’s &lt;font face="Courier New"&gt;BeginInvoke&lt;/font&gt; will process on your UI thread.&amp;#160; Apparently the delegate &lt;font face="Courier New"&gt;BeginInvoke&lt;/font&gt; method has no such wording in its description.&lt;/p&gt; &lt;span class='fullpost'&gt; &lt;p&gt;Rereading &lt;a title="Safe, Simple Multithreading in Windows Forms, Part 1" href="http://msdn.microsoft.com/en-us/library/ms951089.aspx"&gt;this MSDN article&lt;/a&gt; from the former post and reading the &lt;font face="Courier New"&gt;Form&lt;/font&gt; object’s &lt;font face="Courier New"&gt;BeginInvoke&lt;/font&gt; method description which I quoted above set me straight and got rid of my blocking UI problem (again).&lt;/p&gt;  &lt;p&gt;During this research session, I came across another informative resource when trying to figure out what was meant by potential resource leaks when using &lt;font face="Courier New"&gt;BeginInvoke&lt;/font&gt; with out later calling &lt;font face="Courier New"&gt;EndInvoke&lt;/font&gt;.&amp;#160; From reading the article, I gather you can substitute the &lt;font face="Courier New"&gt;EndInvoke&lt;/font&gt; call with the &lt;a title="OneWayAttribute Class" href="http://msdn.microsoft.com/en-us/library/system.runtime.remoting.messaging.onewayattribute.aspx"&gt;&lt;font face="Courier New"&gt;OneWay&lt;/font&gt; attribute&lt;/a&gt;&lt;font face="Courier New"&gt;&lt;font color="#333333"&gt;&lt;font face="Verdana"&gt;&lt;/font&gt;&lt;/font&gt;&lt;/font&gt; on the method being invoked, as long as it has a &lt;font face="Courier New"&gt;void&lt;/font&gt; return signature and no &lt;font face="Courier New"&gt;ref&lt;/font&gt; nor &lt;font face="Courier New"&gt;out&lt;/font&gt; parameters.&amp;#160; Please let me know if my interpretation is wrong.&amp;#160; I added the attribute to my code in the applicable spots and have seen no side effects of doing so.&amp;#160; Here is the article on read mentioning this attribute:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://weblogs.asp.net/rosherove/pages/DefensiveEventPublishing.aspx"&gt;Defensive Event Publishing in .NET – Part I&lt;/a&gt;&lt;/p&gt; &lt;/span&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1664217632350055880-1297116529623161852?l=murrayon.net' alt='' /&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://murrayon.net/feeds/1297116529623161852/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://murrayon.net/2009/05/begininvoke-methods-and-oneway.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/1664217632350055880/posts/default/1297116529623161852?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/1664217632350055880/posts/default/1297116529623161852?v=2" /><link rel="alternate" type="text/html" href="http://murrayon.net/2009/05/begininvoke-methods-and-oneway.html" title="BeginInvoke Methods and OneWay Attribute" /><author><name>Mike Murray</name><uri>http://www.blogger.com/profile/01990150469958605173</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="15380857253844311568" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total></entry><entry gd:etag="W/&quot;CUAMSHg_eyp7ImA9WxNVGEg.&quot;"><id>tag:blogger.com,1999:blog-1664217632350055880.post-5809824401959368426</id><published>2009-03-24T14:08:00.001-06:00</published><updated>2009-10-29T16:03:09.643-06:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-10-29T16:03:09.643-06:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="New Technology" /><category scheme="http://www.blogger.com/atom/ns#" term=".NET" /><category scheme="http://www.blogger.com/atom/ns#" term="Windows" /><category scheme="http://www.blogger.com/atom/ns#" term="PowerShell" /><category scheme="http://www.blogger.com/atom/ns#" term="Microsoft" /><title>PowerShell 1.0 for Windows XP</title><content type="html">&lt;p&gt;I just noticed in today's Tuesday round of Microsoft Updates that there is an optional software download for PowerShell 1.0 on Windows XP.&amp;#160; PowerShell has been one of those things that I really want to learn, but just haven't devoted the time.&amp;#160; I desperately would like to replace my use of the Command Prompt with Windows PowerShell.&lt;/p&gt;  &lt;p&gt;PowerShell really is more than just your regular &lt;a href="http://en.wikipedia.org/wiki/Command_line_interpreter"&gt;Command Line Interpreter&lt;/a&gt; that you have been used to, especially compared to the &lt;a href="http://en.wikipedia.org/wiki/Command_Prompt_(Windows)"&gt;Windows Command Prompt&lt;/a&gt;.&amp;#160; You get the power of the command line shells that you may have tried out in Linux environments, but it really does go beyond those as well.&amp;#160; PowerShell is (from Wikipedia) &lt;font face="Courier New"&gt;&amp;quot;Microsoft's new extensible command line shell and task-based scripting technology.&amp;quot;&lt;/font&gt;&amp;#160; Here is a quote from an MSDN document that better explains the advantages PowerShell brings:&lt;/p&gt; &lt;span class='fullpost'&gt; &lt;blockquote&gt;   &lt;p&gt;&amp;quot;Unlike most shells, which accept and return text, Windows PowerShell is built on top of the .NET common language runtime (CLR) and the .NET Framework, and accepts and returns .NET objects. This fundamental change in the environment brings entirely new tools and methods to the management and configuration of Windows.&lt;/p&gt;   &lt;p&gt;&amp;quot;Windows PowerShell introduces the concept of a cmdlet (pronounced &amp;quot;command-let&amp;quot;), a simple, single-function command-line tool built into the shell. You can use each cmdlet separately, but their power is realized when you use these simple tools in combination to perform complex tasks. Windows PowerShell includes more than one hundred basic core cmdlets, and you can write your own cmdlets and share them with other users.&lt;/p&gt;   &lt;p&gt;&amp;quot;Like many shells, Windows PowerShell gives you access to the file system on the computer. In addition, Windows PowerShell providers enable you to access other data stores, such as the registry and the digital signature certificate stores, as easily as you access the file system.&amp;quot;&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;If you want to know more about PowerShell, I would suggest the following readings:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;&lt;a href="http://en.wikipedia.org/wiki/Windows_PowerShell"&gt;Wikipedia - Windows PowerShell&lt;/a&gt;&lt;/li&gt;    &lt;li&gt;&lt;a href="http://msdn.microsoft.com/en-us/library/aa973757(VS.85).aspx"&gt;MSDN - Windows PowerShell Getting Started Guide&lt;/a&gt;&lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;Also, &lt;a href="http://codebetter.com/members/james.kovacs.aspx"&gt;James Kovacs&lt;/a&gt; from &lt;a href="http://codebetter.com/"&gt;CodeBetter.com&lt;/a&gt; has been doing &lt;a href="http://codebetter.com/blogs/james.kovacs/archive/tags/PowerShell/default.aspx"&gt;a series of posts on the basics of PowerShell&lt;/a&gt; that is a great light introduction to how a developer would find the tool most useful.&amp;#160; Here are two of the starting posts from that series:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;&lt;a href="http://codebetter.com/blogs/james.kovacs/archive/2009/02/01/getting-started-with-powershell-developer-edition.aspx"&gt;Getting Started with PowerShell - Developer Edition&lt;/a&gt;&lt;/li&gt;    &lt;li&gt;&lt;a href="http://codebetter.com/blogs/james.kovacs/archive/2009/02/07/powershell-processes-and-piping.aspx"&gt;PowerShell, Processes, and Piping&lt;/a&gt;&lt;/li&gt; &lt;/ul&gt; &lt;/span&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1664217632350055880-5809824401959368426?l=murrayon.net' alt='' /&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://murrayon.net/feeds/5809824401959368426/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://murrayon.net/2009/03/powershell-10-for-windows-xp.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/1664217632350055880/posts/default/5809824401959368426?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/1664217632350055880/posts/default/5809824401959368426?v=2" /><link rel="alternate" type="text/html" href="http://murrayon.net/2009/03/powershell-10-for-windows-xp.html" title="PowerShell 1.0 for Windows XP" /><author><name>Mike Murray</name><uri>http://www.blogger.com/profile/01990150469958605173</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="15380857253844311568" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total></entry><entry gd:etag="W/&quot;CUAEQn49cCp7ImA9WxNVGEg.&quot;"><id>tag:blogger.com,1999:blog-1664217632350055880.post-2958618679460091764</id><published>2009-03-02T17:51:00.000-07:00</published><updated>2009-10-29T16:01:43.068-06:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-10-29T16:01:43.068-06:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term=".NET" /><category scheme="http://www.blogger.com/atom/ns#" term="C#" /><category scheme="http://www.blogger.com/atom/ns#" term="Microsoft" /><category scheme="http://www.blogger.com/atom/ns#" term="LINQ" /><title>The "Yield" Keyword in C# (AKA Execution Control Hot Potato)</title><content type="html">&lt;p&gt;I actually read about this topic a while back when I saw a C# code sample containing an unfamiliar keyword -- &lt;font face="Courier New"&gt;yield&lt;/font&gt;.&amp;#160; Well just today I saw another code sample using this keyword again, and had since forgotten everything I had learned.&amp;#160; As I Googled the topic again, I happened across the same article I read back then, a terrific blog post by &lt;a href="http://flimflan.com/blog/"&gt;Joshua Flanagan&lt;/a&gt;.&amp;#160; Here is a link to Joshua's simple introduction to the &lt;font face="Courier New"&gt;yield&lt;/font&gt; C# keyword:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://flimflan.com/blog/ThePowerOfYieldReturn.aspx"&gt;The power of yield (return)&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;I would also suggest the following MSDN article as well:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://msdn.microsoft.com/en-us/library/9k7k7cf0.aspx"&gt;yield (C# Reference)&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;I'll give you the gist of this .NET 2.0 feature.&amp;#160; If you have a method that returns an iterative collection and the consumers of your function will only need &lt;a title="foreach, in (C# Reference)" href="http://msdn.microsoft.com/en-us/library/ttw7t8t6.aspx"&gt;&lt;font face="Courier New"&gt;foreach&lt;/font&gt;&lt;/a&gt;, read-only access to that collection, then it is good practice to have your method return the universal &lt;font face="Courier New"&gt;IEnumerable&lt;/font&gt; collection (as opposed to you arbitrarily selecting an implementation-specific collection to be forced upon the consumers of your code).&amp;#160; In C#, when you are returning an &lt;font face="Courier New"&gt;IEnumerable&lt;/font&gt; collection from a method, you are allowed to use the &lt;font face="Courier New"&gt;yield&lt;/font&gt; keyword in order to transform your method into what Microsoft calls an &amp;quot;iterator block&amp;quot;.&amp;#160; Here is a quote from the MSDN article I mentioned above to explain this phrase and the &lt;font face="Courier New"&gt;yield&lt;/font&gt; keyword:&lt;/p&gt; &lt;span class='fullpost'&gt; &lt;blockquote&gt;   &lt;p&gt;&amp;quot;The &lt;strong&gt;yield&lt;/strong&gt; keyword signals to the compiler that the method in which it appears is an iterator block.&amp;#160; The compiler generates a class to implement the behavior that is expressed in the iterator block.&amp;#160; In the iterator block, the &lt;strong&gt;yield&lt;/strong&gt; keyword is used together with the &lt;strong&gt;return&lt;/strong&gt; keyword to provide a value to the enumerator object.&amp;#160; This is the value that is returned, for example, in each loop of a &lt;strong&gt;foreach&lt;/strong&gt; statement.&amp;#160; The &lt;strong&gt;yield&lt;/strong&gt; keyword is also used with &lt;strong&gt;break&lt;/strong&gt; to signal the end of iteration.&amp;quot;&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;You are essentially building an enumerator (or iterator), and with each iteration of your &lt;font face="Courier New"&gt;foreach&lt;/font&gt; loop in the calling, consuming code, you are executing your method containing the iterator block until it reaches a &lt;font face="Courier New"&gt;yield return&lt;/font&gt; statement.&amp;#160; At this point, only one item at a time in the collection is returned back to the consuming &lt;font face="Courier New"&gt;foreach&lt;/font&gt; loop for immediate logic execution by the body of the loop.&amp;#160; On the next iteration of the consuming &lt;font face="Courier New"&gt;foreach&lt;/font&gt; loop, the method containing the iterator block will be called again and another single item in the collection will be returned for similar logic execution.&lt;/p&gt;  &lt;p&gt;This game of execution control &lt;a href="http://en.wikipedia.org/wiki/Hot_Potato_(game)"&gt;Hot Potato&lt;/a&gt; has its benefits, in that you can stop the flip-flop of execution control when the music has stopped.&amp;#160; In this analogy, I am comparing the &amp;quot;music stopping&amp;quot; to your code satisfying some logic that makes the rest of your &lt;font face="Courier New"&gt;foreach&lt;/font&gt; loop iterations unnecessary (perhaps you have found the one item in the collection you were looking for by meeting the sufficient requirements of an &lt;font face="Courier New"&gt;if&lt;/font&gt; statement).&amp;#160; The benefit is that when you &lt;font face="Courier New"&gt;&lt;a title="break (C# Reference)" href="http://msdn.microsoft.com/en-us/library/adbctzc4.aspx"&gt;break&lt;/a&gt;&lt;/font&gt; out of the consuming &lt;font face="Courier New"&gt;foreach&lt;/font&gt; loop before completing the iterations, you prevent wasteful code execution and memory use.&amp;#160; This feature prevents one piece of code from fully populating a potentially large collection of items, just to have another consuming piece of code iterate partially through the list and then prematurely exit.&amp;#160; Consider the savings especially when adding each item to the collection may be computationally intensive or if each item in the collection is itself a very large data structure.&amp;#160; In the Hot Potato analogy, this would be as if the kids in the circle who didn't touch the &amp;quot;hot potato&amp;quot; never existed in the game, saving floor space and unnecessary tosses to people you don't really want to target for humiliating removal from the game.&lt;/p&gt;  &lt;p&gt;For good sample code snippets of using the &lt;font face="Courier New"&gt;yield&lt;/font&gt; keyword, see the links provided above.&lt;/p&gt;  &lt;p&gt;I hope to identify situations in the near future where I could benefit from using this C# keyword.&amp;#160; Hopefully then I won't forget a year down the road from now and then have to re-search the internet for Joshua's blog post and the MSDN article to remind myself what I already learned.&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&lt;u&gt;FOLLOWUP (03/26/09)&lt;/u&gt;&lt;/strong&gt;:&amp;#160; So I'm not sure how I missed it, but it took reading a very recent article by &lt;a href="http://www.4guysfromrolla.com/ScottMitchell.shtml"&gt;Scott Mitchell&lt;/a&gt; of &lt;a href="http://www.4guysfromrolla.com/"&gt;4GuysFromRolla.com&lt;/a&gt; to understand the real reason the &lt;font face="Courier New"&gt;yield&lt;/font&gt; keyword was introduced.&amp;#160; The introduction of this keyword in .NET 2.0 was most helpful in the case of fulfilling the requirements of implementing the &lt;font face="Courier New"&gt;IEnumerable&lt;/font&gt; interface, which typically required you to create a sub-class that implemented &lt;font face="Courier New"&gt;IEnumerator&lt;/font&gt;.&amp;#160; In many cases, it allowed you to take about 50 lines of code and turn it into 2 lines of code using the &lt;font face="Courier New"&gt;yield&lt;/font&gt; keyword.&amp;#160; The introduction of LINQ brought heavy reliance on enumerating using the &lt;font face="Courier New"&gt;yield&lt;/font&gt; keyword in order to &lt;a href="http://en.wikipedia.org/wiki/Pipeline_(software)"&gt;pipeline&lt;/a&gt; &lt;a href="http://en.wikipedia.org/wiki/Language_Integrated_Query#Standard_Query_Operators"&gt;query operators&lt;/a&gt; together.&amp;#160; Scott Mitchell takes you through this whole journey, tying all of the loose ends together to create a complete history of this keyword and how it's most commonly utilized.&amp;#160; Please visit the following article to get the whole picture:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;&lt;a href="http://aspnet.4guysfromrolla.com/articles/032509-1.aspx"&gt;An Extensive Examination of LINQ: The Ins and Outs of Query Operators&lt;/a&gt;&lt;/li&gt; &lt;/ul&gt; &lt;/span&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1664217632350055880-2958618679460091764?l=murrayon.net' alt='' /&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://murrayon.net/feeds/2958618679460091764/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://murrayon.net/2009/03/keyword-in-c-aka-execution-control-hot.html#comment-form" title="1 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/1664217632350055880/posts/default/2958618679460091764?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/1664217632350055880/posts/default/2958618679460091764?v=2" /><link rel="alternate" type="text/html" href="http://murrayon.net/2009/03/keyword-in-c-aka-execution-control-hot.html" title="The &amp;quot;Yield&amp;quot; Keyword in C# (AKA Execution Control Hot Potato)" /><author><name>Mike Murray</name><uri>http://www.blogger.com/profile/01990150469958605173</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="15380857253844311568" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">1</thr:total></entry><entry gd:etag="W/&quot;D0YDQ30-cSp7ImA9WxVWEEs.&quot;"><id>tag:blogger.com,1999:blog-1664217632350055880.post-3770422546436181972</id><published>2009-02-19T10:36:00.000-07:00</published><updated>2009-02-19T10:39:32.359-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-02-19T10:39:32.359-07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Error" /><category scheme="http://www.blogger.com/atom/ns#" term=".NET" /><category scheme="http://www.blogger.com/atom/ns#" term="ASP.NET" /><category scheme="http://www.blogger.com/atom/ns#" term="Database" /><category scheme="http://www.blogger.com/atom/ns#" term="SQL" /><category scheme="http://www.blogger.com/atom/ns#" term="Microsoft" /><title>SQL Server Express 2005 Remote Connections</title><content type="html">&lt;p&gt;I developed an ASP.NET site connecting to a local SQL Server Express 2005 instance on my development box.&amp;#160; To further my informal testing, I wanted to host the site under IIS 7 on a Windows Server 2008 box, but I wanted to just use the same database remotely.&amp;#160; I got the following error message when the site tried to hit the database:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;&amp;quot;An error has occurred while establishing a connection to the server.&amp;#160; When connecting to SQL Server 2005, this failure may be caused by the fact that under the default settings SQL Server does not allow remote connections.&amp;#160; (provider: Named Pipes Provider, error: 40 - Could not open connection to SQL Server)&amp;quot;&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;Apparently SQL Server Express 2005 is not automatically configured for remote access during installation (which really isn't surprising as it is the Express version).&amp;#160; Remote connections can be enabled though with a few relatively painless steps.&amp;#160; See the following link for the procedure:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;&lt;a href="http://www.datamasker.com/SSE2005_NetworkCfg.htm"&gt;Configuring SQL Server Express 2005 for Remote Access when SQL Server does not allow remote connections&lt;/a&gt;&lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;Hope this is helpful.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1664217632350055880-3770422546436181972?l=murrayon.net' alt='' /&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://murrayon.net/feeds/3770422546436181972/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://murrayon.net/2009/02/sql-server-express-2005-remote.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/1664217632350055880/posts/default/3770422546436181972?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/1664217632350055880/posts/default/3770422546436181972?v=2" /><link rel="alternate" type="text/html" href="http://murrayon.net/2009/02/sql-server-express-2005-remote.html" title="SQL Server Express 2005 Remote Connections" /><author><name>Mike Murray</name><uri>http://www.blogger.com/profile/01990150469958605173</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="15380857253844311568" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total></entry><entry gd:etag="W/&quot;CUYAQ305eyp7ImA9WxNVGEg.&quot;"><id>tag:blogger.com,1999:blog-1664217632350055880.post-2050413284625674348</id><published>2009-02-17T17:38:00.000-07:00</published><updated>2009-10-29T15:52:22.323-06:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-10-29T15:52:22.323-06:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Error" /><category scheme="http://www.blogger.com/atom/ns#" term=".NET" /><category scheme="http://www.blogger.com/atom/ns#" term="Server 2008" /><category scheme="http://www.blogger.com/atom/ns#" term="ISAPI" /><category scheme="http://www.blogger.com/atom/ns#" term="IIS" /><category scheme="http://www.blogger.com/atom/ns#" term="ASP.NET Providers Series" /><category scheme="http://www.blogger.com/atom/ns#" term="ASP.NET" /><category scheme="http://www.blogger.com/atom/ns#" term="Windows" /><category scheme="http://www.blogger.com/atom/ns#" term="Vista" /><category scheme="http://www.blogger.com/atom/ns#" term="Microsoft" /><title>IIS 7 and ASP.NET Providers (Membership, Roles, and Profile)</title><content type="html">&lt;p&gt;I talked at length about the ASP.NET &lt;a href="http://en.wikipedia.org/wiki/Provider_model"&gt;Provider Model pattern&lt;/a&gt; and the ease of implementing several built-in services you can have for free with ASP.NET 2.0 in &lt;a title="ASP.NET Providers - Membership, Role, and Profile" href="http://murrayon.net/2009/01/aspnet-providers-membership-role-and.html"&gt;my previous series of posts&lt;/a&gt;.&amp;#160; In this post, I will be discussing the advantages of using the ASP.NET Provider system under IIS 7 found in Windows Vista and Server 2008.&amp;#160; I will also talk about an issue with using this Provider system to try and add authentication to an ASP.NET website that contains non-ASP.NET content, like static HTML pages.&amp;#160; I think I'll start with the discussion about non-ASP.NET content first.&lt;/p&gt; &lt;span class='fullpost'&gt; &lt;h3&gt;IIS 7.0 Integrated Pipeline&lt;/h3&gt;  &lt;p&gt;Since I don't really understand much about &lt;a title="Internet Server Application Programming Interface" href="http://en.wikipedia.org/wiki/ISAPI"&gt;ISAPI&lt;/a&gt; filters and such, I'm just going to quote stuff from random pages on the &lt;a href="http://www.iis.net/"&gt;official Microsoft IIS site&lt;/a&gt;:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;&amp;quot;IIS 6.0 and previous versions allowed the development of .NET application components via the ASP.NET platform. ASP.NET integrated with IIS via an ISAPI extension, and exposed its own application and request processing model. This effectively exposed two separate server pipelines, one for native ISAPI filters and extension components, and another for managed application components. ASP.NET components would execute entirely inside the ASP.NET ISAPI extension bubble and only for requests mapped to ASP.NET in the IIS script map configuration.&lt;/p&gt;    &lt;p&gt;&amp;quot;IIS 7.0 integrates the ASP.NET runtime with the core web server, providing a unified request processing pipeline that is exposed to both native and managed components known as modules.&amp;quot;&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;and...&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;&amp;quot;This allows developers to fully extend the IIS 7.0 server with the richness of ASP.NET 2.0 and the .NET Framework, instead of using the lower level IIS C++ APIs. Existing ASP.NET applications also immediately benefit from tighter integration using existing ASP.NET features like Forms Authentication, Roles, and Output Caching for all content.&amp;quot;&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;Note the last three words there:&amp;#160; &amp;quot;&lt;font face="Courier New"&gt;for all content.&lt;/font&gt;&amp;quot;&amp;#160; When I started this endeavor to implement the ASP.NET Provider system, I didn't realize that it would really only apply to ASP.NET content and pages.&amp;#160; I didn't realize on IIS 6 I would have to fiddle with ISAPI filters and content filters to make my implementation work.&amp;#160; And when I tried to doing a mapping (like &lt;font face="Courier New"&gt;*.html&lt;/font&gt; to the ASP.NET ISAPI DLL), I either didn't do it right or it just isn't very reliable and stable; here is a link to &lt;a title="IIS problems with forms authentication &amp;amp; HTML pages" href="http://forums.asp.net/t/1184547.aspx"&gt;the thread I followed in trying to make the appropriate changes in IIS 6&lt;/a&gt;.&amp;#160; I will note however that &lt;a href="http://www.ultidev.com/products/Cassini/index.htm"&gt;UltiDev's Cassini Web Server&lt;/a&gt; can host such a site with absolutely no extra modification, where even IIS 7 required a little configuration.&lt;/p&gt;  &lt;p&gt;By default in IIS 7, an &lt;a title="IIS and ASP.NET: The Application Pool" href="http://www.developer.com/net/asp/article.php/2245511"&gt;application pool&lt;/a&gt; runs using the &lt;font face="Courier ne"&gt;Integrated&lt;/font&gt; mode for the &lt;font face="Courier New"&gt;Managed Pipeline&lt;/font&gt; configuration.&amp;#160; But there is also the option of &lt;font face="Courier New"&gt;Classic&lt;/font&gt; mode, which is helpful if you are needing strict compatibility with how you ran a website under IIS 6.&amp;#160; In many cases, however, an existing ASP.NET website runs under &lt;font face="Courier New"&gt;Integrated&lt;/font&gt; mode without any problems.&lt;/p&gt;  &lt;h3&gt;Configuring an ASP.NET Website to Run on IIS 7&lt;/h3&gt;  &lt;p&gt;First, I think I will point you to a great video and document on Microsoft's official IIS site that explains everything you really need to know.&amp;#160; Then I will emphasize a few of the important points and also a gotcha or two.&amp;#160; Here are the links you should reference:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;&lt;a href="http://learn.iis.net/page.aspx/377/using-aspnet-forms-authentication/"&gt;Using ASP.NET Forms Authentication&lt;/a&gt; (video) &lt;/li&gt;    &lt;li&gt;&lt;a href="http://learn.iis.net/page.aspx/243/aspnet-integration-with-iis7/"&gt;ASP.NET Integration with IIS 7.0&lt;/a&gt; &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;The video above is also a terrific introduction to IIS 7.&amp;#160; Below is a screenshot of IIS's UI for configuring a website:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh6.ggpht.com/_rps657FzHZ0/SZtZDNleinI/AAAAAAAAACw/b2kq_6XIGD8/s1600-h/IIS_screenshot%5B5%5D.png"&gt;&lt;img style="border-right-width: 0px; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" border="0" alt="IIS_screenshot" src="http://lh5.ggpht.com/_rps657FzHZ0/SZtZDjlrIRI/AAAAAAAAAC0/cC29GwiAIhk/IIS_screenshot_thumb%5B3%5D.png?imgmax=800" width="475" height="368" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;Notice the &lt;font face="Courier New"&gt;ASP.NET&lt;/font&gt; section and how it's able to use your Providers to bring back Users, Roles, and Profile data back from the database.&amp;#160; This UI reads from and writes to your &lt;font face="Courier New"&gt;Web.config&lt;/font&gt; and is really slick in my opinion.&lt;/p&gt;  &lt;p&gt;The only real &amp;quot;breaking change&amp;quot; for running your website under IIS 7 is the fact that your &lt;font face="Courier New"&gt;Web.config&lt;/font&gt; might need a little migration to be compatible with &lt;font face="Courier New"&gt;Integrated&lt;/font&gt; mode.&amp;#160; Apparently IIS gives you helpful error messages if it detects you haven't run through the migration yet.&amp;#160; The two most common things that ASP.NET websites have that require this migration are if you have declared &lt;font face="Courier New"&gt;httpModules&lt;/font&gt; or &lt;font face="Courier New"&gt;httpHandlers&lt;/font&gt; in your &lt;font face="Courier New"&gt;Web.config&lt;/font&gt;.&amp;#160; The fix is to either copy or move these sections under &lt;font face="Courier New"&gt;system.web&lt;/font&gt; to their corresponding &lt;font face="Courier New"&gt;system.webServer&lt;/font&gt; sections.&amp;#160; If you duplicate the sections, then you should be able run under both &lt;font face="Courier New"&gt;Integrated&lt;/font&gt; and &lt;font face="Courier New"&gt;Classic&lt;/font&gt; modes without any problems.&amp;#160; You can even still run on IIS 6 I believe, as IIS 6 will ignore this new section called &lt;font face="Courier New"&gt;system.webServer&lt;/font&gt; which is IIS 7 specific.&amp;#160; IIS 7 even provides a utility that can perform this migration for you; here is the what you would type in a Command Prompt:&lt;/p&gt;  &lt;p&gt;&lt;font face="Courier New"&gt;%windir%\system32\inetsrv\APPCMD.EXE migrate config &amp;lt;Application Path&amp;gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;...where &lt;font face="Courier New"&gt;&amp;lt;Application Path&amp;gt;&lt;/font&gt; would be something like &lt;font face="Courier New"&gt;&amp;quot;Default Web Site/&amp;quot;&lt;/font&gt; or &lt;font face="Courier New"&gt;&amp;quot;Default Web Site/someApp&amp;quot;&lt;/font&gt;.&amp;#160; If you manually migrate your &lt;font face="Courier New"&gt;Web.config&lt;/font&gt; and are still getting migration error messages, here is a snippet you can add right under the &lt;font face="Courier New"&gt;system.webServer&lt;/font&gt; node to disable the error message:&lt;/p&gt;  &lt;p&gt;&lt;font face="Courier New"&gt;&amp;lt;validation validateIntegratedModeConfiguration=&amp;quot;false&amp;quot; /&amp;gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;Also, I want to make note of something I couldn't get to work that they showed in the tutorial video.&amp;#160; At about the &lt;font face="Courier New"&gt;13:50&lt;/font&gt; mark in the video, they go into the &lt;font face="Courier New"&gt;Modules&lt;/font&gt; section of the UI.&amp;#160; These are the modules of the IIS pipeline for both managed .NET code and unmanaged code.&amp;#160; In order to make their video file hidden behind ASP.NET Forms Authentication, they change a property on two authentication modules to allow these modules to execute on non-managed content as well.&amp;#160; However, this did not work for me for some reason when I was trying to secure HTML pages behind Forms Authentication.&amp;#160; What did work for me (and may have been a drastic solution) was to put the following attribute on the &lt;font face="Courier New"&gt;modules&lt;/font&gt; node under &lt;font face="Courier New"&gt;system.webServer&lt;/font&gt;:&lt;/p&gt;  &lt;p&gt;&lt;font face="Courier New"&gt;&amp;lt;modules runAllManagedModulesForAllRequests=&amp;quot;true&amp;quot; /&amp;gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;I believe the issue in my case was their was another few managed modules that I needed to clear that checkbox for in the UI.&amp;#160; But I didn't take the time to find out which ones I was missing and opted for the drastic solution.&amp;#160; I will also say there is a way to configure these managed modules through your &lt;font face="Courier New"&gt;Web.config&lt;/font&gt; so you don't have to have your IT Admin configure properties manually in the UI.&amp;#160; In fact, it seems that much of IIS 7 configuration for your website can be done this way.&lt;/p&gt;  &lt;h3&gt;A Few Error Messages (and Their Solutions)&lt;/h3&gt;  &lt;p&gt;If you get error messages while using the IIS Manager user interface like this...&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;&amp;quot;This feature cannot be used because the default provider type could not be determined to check whether it is a trusted provider.&lt;/p&gt;    &lt;p&gt;&amp;quot;You can use this feature only when the default provider is a trusted provider.&amp;#160; If you are a server administrator, you can make a provider a trusted provider by adding the provider type to the trusted providers list in the Administration.config file.&amp;#160; The provider has to be strongly typed and added to the GAC (Global Assembly Cache).&amp;quot;&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;...then you should visit the following article for detailed information about resolving the error message:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;&lt;a href="http://www.iis.net/ConfigReference/system.webServer/management/trustedProviders/add"&gt;Adding Management Trusted Providers &amp;lt;add&amp;gt;&lt;/a&gt; &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;Getting rid of this error message is really only for convenience in letting the IIS Manager UI be able to query your database using your providers and give you a basic view of your Membership, Roles, and Profile fields.&amp;#160; Also, if you are trying to find your &lt;font face="Courier New"&gt;Administration.config&lt;/font&gt; file, it is likely located under the &lt;font face="Courier New"&gt;C:\Windows\System32\inetsrv\config\&lt;/font&gt; folder.&lt;/p&gt;  &lt;p&gt;The other error message I received was not in the IIS Manager UI, but rather when you attempt to view your website in a browser (after you think you got all the configuration bugs out!).&amp;#160; A &lt;font face="Courier New"&gt;BadImageFormatException&lt;/font&gt; is thrown and the error details say something like this:&lt;/p&gt;  &lt;p&gt;&lt;font face="Courier New"&gt;Could not load file or assembly 'AssemlyNameHere' or one of its dependencies.&amp;#160; An attempt was made to load a program with an incorrect format.&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;The likely cause of this error is that the assembly referenced in the error message was compiled only for 32-bit machines and you are running a 64-bit operating system.&amp;#160; With Windows Server 2008 x64, the application pools in IIS have an &lt;font face="Courier New"&gt;Advanced Setting&lt;/font&gt; called &lt;font face="Courier New"&gt;Enable 32-Bit Applications&lt;/font&gt;, that is disabled by default.&amp;#160; Enable this setting and you're probably good to go.&amp;#160; See the following link for more detailed information and some nice screenshots:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;&lt;a href="http://blog.crowe.co.nz/archive/2007/11/05/Could-not-load-file-or-assembly-name-or-one-of.aspx"&gt;Could not load file or assembly 'name' or one of its dependencies&lt;/a&gt; &lt;/li&gt; &lt;/ul&gt;  &lt;h3&gt;Additional Reading&lt;/h3&gt;  &lt;p&gt;I just barely noticed that &lt;a href="http://www.4guysfromrolla.com/"&gt;4GuysFromRolla.com&lt;/a&gt; recently posted an article about the exact same stuff I was attempting to explain.&amp;#160; To read additional details about IIS 7's Integrated Pipeline and ASP.NET Forms Authentication with static content, check out the following link:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;&lt;a href="http://aspnet.4guysfromrolla.com/articles/122408-1.aspx"&gt;Apply ASP.NET Authentication and Authorization Rules to Static Content with IIS 7.0's Integrated Pipeline Feature&lt;/a&gt; &lt;/li&gt; &lt;/ul&gt;  &lt;h3&gt;Conclusion&lt;/h3&gt;  &lt;p&gt;I hope you've enjoyed &lt;a title="ASP.NET Providers - Membership, Role, and Profile" href="http://murrayon.net/2009/01/aspnet-providers-membership-role-and.html"&gt;this series on the ASP.NET Provider System&lt;/a&gt;.&amp;#160; My desire is that you've found these posts helpful in getting you started with implementing such a versatile and customizable model for adding common membership and authorization functionality to your new and existing websites.&amp;#160; There are quite a few advantages in hosting your site on IIS 7 in Windows Server 2008, as I've outlined in this specific post.&amp;#160; Hopefully these discussions about errors and gotchas will also help you get going in no time!&lt;/p&gt; &lt;/span&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1664217632350055880-2050413284625674348?l=murrayon.net' alt='' /&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://murrayon.net/feeds/2050413284625674348/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://murrayon.net/2009/02/iis-7-and-aspnet-providers-membership.html#comment-form" title="2 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/1664217632350055880/posts/default/2050413284625674348?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/1664217632350055880/posts/default/2050413284625674348?v=2" /><link rel="alternate" type="text/html" href="http://murrayon.net/2009/02/iis-7-and-aspnet-providers-membership.html" title="IIS 7 and ASP.NET Providers (Membership, Roles, and Profile)" /><author><name>Mike Murray</name><uri>http://www.blogger.com/profile/01990150469958605173</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="15380857253844311568" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">2</thr:total></entry><entry gd:etag="W/&quot;CE4FQXczfyp7ImA9WxNVGEg.&quot;"><id>tag:blogger.com,1999:blog-1664217632350055880.post-2039771211821386099</id><published>2009-02-11T15:08:00.001-07:00</published><updated>2009-10-29T15:48:30.987-06:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-10-29T15:48:30.987-06:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Web" /><category scheme="http://www.blogger.com/atom/ns#" term=".NET" /><category scheme="http://www.blogger.com/atom/ns#" term="Build" /><category scheme="http://www.blogger.com/atom/ns#" term="ASP.NET Providers Series" /><category scheme="http://www.blogger.com/atom/ns#" term="ASP.NET" /><category scheme="http://www.blogger.com/atom/ns#" term="Windows" /><category scheme="http://www.blogger.com/atom/ns#" term="MSBuild" /><category scheme="http://www.blogger.com/atom/ns#" term="C#" /><category scheme="http://www.blogger.com/atom/ns#" term="Visual Studio" /><category scheme="http://www.blogger.com/atom/ns#" term="Microsoft" /><title>ASP.NET Profile and Web Application Projects</title><content type="html">&lt;p&gt;I talked at length about the ASP.NET &lt;a href="http://en.wikipedia.org/wiki/Provider_model"&gt;Provider Model pattern&lt;/a&gt; and the ease of implementing several built-in services you can have for free with ASP.NET 2.0 in &lt;a title="ASP.NET Providers - Membership, Role, and Profile" href="http://murrayon.net/2009/01/aspnet-providers-membership-role-and.html"&gt;my previous series of posts&lt;/a&gt;.&amp;#160; In this post, I will be discussing a few issues I ran into using the Profile system with the &lt;font face="Courier New"&gt;Web Application&lt;/font&gt; project template instead of the &lt;font face="Courier New"&gt;Web Site&lt;/font&gt; project template as found in Visual Studio's list of default project templates.&lt;/p&gt;  &lt;p&gt;The crux of the issue is that Visual Studio doesn't automatically generate the &lt;font face="Courier New"&gt;Profile&lt;/font&gt; proxy class object when using the &lt;font face="Courier New"&gt;Web Application&lt;/font&gt; project template, like it does with the &lt;font face="Courier New"&gt;Web Site&lt;/font&gt; project template.&amp;#160; This proxy class can be used to obtain access to strongly-typed properties representing the custom Profile fields you specified in your &lt;font face="Courier New"&gt;Web.config&lt;/font&gt;.&amp;#160; This is a very convenient way to access a user's Profile data, both for authenticated and for anonymous users.&lt;/p&gt;  &lt;p&gt;Let's discuss the issue a little further and then I will present a workaround that I found and have successfully implemented in my own project.&lt;/p&gt; &lt;span class='fullpost'&gt; &lt;h3&gt;VS Project Templates:&amp;#160; Web Site vs. Web Application&lt;/h3&gt;  &lt;p&gt;It appears that Microsoft has tried to differentiate these two project templates as much as possible in Visual Studio 2008.&amp;#160; In 2005, you would go to the &lt;font face="Courier New"&gt;New Project&lt;/font&gt; dialog window and you would see these two &lt;font face="Courier New"&gt;Web&lt;/font&gt; project templates side-by-side, wondering what difference it would make if you chose one over the other.&amp;#160; However, in Visual Studio 2008, it appears they reworked this whole dialog and menu system for starting a new project so that you would never see these two project templates side-by-side.&amp;#160; In 2008, you have more than one option in the &lt;font face="Courier New"&gt;File&lt;/font&gt; menu for starting a project; those options are &lt;font face="Courier New"&gt;File | New | Project&lt;/font&gt; and &lt;font face="Courier New"&gt;File | New | Web Site&lt;/font&gt;.&amp;#160; The first option is the one that will get you to the &lt;font face="Courier New"&gt;ASP.NET Web Application&lt;/font&gt; template, while the second takes you to the &lt;font face="Courier New"&gt;ASP.NET Web Site&lt;/font&gt; project template.&lt;/p&gt;  &lt;p&gt;Now as for the differences between these two templates, I'll outline a few of the main differences and give a little bit of history of how these two templates came to coexist.&amp;#160; The history in a nutshell is that Visual Studio 2005 came out with the &lt;font face="Courier New"&gt;Web Site&lt;/font&gt; project template to replace the old, but proven project configuration used by ASP.NET 1.x.&amp;#160; In the opinion of many, the old template better encouraged Object-Oriented design practices.&amp;#160; The new template had no project file for explicitly delineating what files where included in the project and namespacing was quite cumbersome, as the only painless design was to let everything pile up into one big default namespace.&amp;#160; A few other changes involved taking ASP.NET back to compiling on the fly at the web server and also drastically changing the organization of UI template and code-behind files.&amp;#160; It appears the intention was to closely mimic the configuration and deployment practices of popular agile languages like PHP and Ruby on Rails.&lt;/p&gt;  &lt;p&gt;In the Service Pack 1 of Visual Studio 2005, Microsoft decided to resurrect the older project template under the name of &lt;font face="Courier New"&gt;Web Application&lt;/font&gt;.&amp;#160; There is evidence to suggest that Microsoft considers this latter project template an &amp;quot;enterprise&amp;quot; project type, as compared to the casual &lt;font face="Courier New"&gt;Web Site&lt;/font&gt; project template.&amp;#160; With the advent of Visual Studio 2008, it is apparent that Microsoft is committed to supporting both project types for at least a little while.&amp;#160; For a more detailed discussion of the history and differences of these two project templates, I suggest the following blog post by &lt;a href="http://reddnet.net/code/"&gt;Stephen M. Redd&lt;/a&gt;:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;&lt;a href="http://reddnet.net/code/aspnet-web-site-vs-web-application/"&gt;ASP.NET - Web Site vs. Web Application&lt;/a&gt;&lt;/li&gt; &lt;/ul&gt;  &lt;h3&gt;Web Profile Builder by Joe Wrobel&lt;/h3&gt;  &lt;p&gt;The ability to retrieve and update your custom Profile fields at design time via strongly-typed properties on the &lt;font face="Courier New"&gt;Profile&lt;/font&gt; proxy class is extremely convenient.&amp;#160; Unfortunately, you get no such compiler and intellisense love if you are using the &lt;font face="Courier New"&gt;Web Application&lt;/font&gt; project template for your site.&lt;/p&gt;  &lt;p&gt;In trying to find a workaround, I came across a &lt;a title="Web Profile Builder for Web Application Projects" href="http://weblogs.asp.net/joewrobel/archive/2008/02/03/web-profile-builder-for-web-application-projects.aspx"&gt;blog post by Joe Wrobel introducing a project he worked on to solve this issue&lt;/a&gt;.&amp;#160; It's called the &lt;font face="Courier New"&gt;Web Profile Builder&lt;/font&gt; (here's a &lt;a title="Web Profile Builder" href="http://code.msdn.microsoft.com/WebProfileBuilder/Release/ProjectReleases.aspx"&gt;link to it's project page on MSDN Code Gallery&lt;/a&gt;) and it was based on a project called the &lt;a href="http://www.codeplex.com/WebProfile"&gt;Web Profile Generator&lt;/a&gt;, which was a Visual Studio 2005 Add-In project found on &lt;a href="http://www.codeplex.com/"&gt;CodePlex&lt;/a&gt;.&amp;#160; The latter project seems to have not been worked on in over a year and a half, nor does it seem to be compatible with Visual Studio 2008.&amp;#160; Hence, Joe feeling the need to start up on his own project, with a few improvements on the side of course.&lt;/p&gt;  &lt;p&gt;In Joe's introductory post to the project, he mentions he changed the Visual Studio integration from being a plug-in to being an MSBuild Build Task.&amp;#160; The method for incorporating the Build Task into your project is to add a line into your project file (the one with file extension &lt;font face="Courier New"&gt;.csproj&lt;/font&gt;).&amp;#160; In case you weren't aware, Visual Studio project files are just &lt;a href="http://en.wikipedia.org/wiki/MSBuild"&gt;MSBuild&lt;/a&gt; build scripts.&amp;#160; For details about where to put this line in the file (and about a message Visual Studio pops up when it detects you've mucked with the project file), be sure to check out &lt;a title="Web Profile Builder for Web Application Projects" href="http://weblogs.asp.net/joewrobel/archive/2008/02/03/web-profile-builder-for-web-application-projects.aspx"&gt;Joe's post on the Web Profile Builder project&lt;/a&gt;.&lt;/p&gt;  &lt;p&gt;There are a couple of other things I need to point out about using the Build Task that weren't entirely clear to me beforehand.&amp;#160; The build task actually generates a C# code file that is intended to be included into your project; once it's generated, you need to go to the &lt;font face="Courier New"&gt;Solution Explorer&lt;/font&gt; and explicitly add it as a file in your project (one way is through the &lt;font face="Courier New"&gt;Add | Existing Item&lt;/font&gt; menu option).&amp;#160; One of the main things that helped me decide to use this solution and how to configure it was reading two blog posts from &lt;a href="http://www.codersbarn.com/"&gt;Anthony Grace&lt;/a&gt;; the second post below has a great excerpt apparently from the &lt;font face="Courier New"&gt;Web Profile Builder&lt;/font&gt; documentation that explains the process I outlined above in a bit more detail:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;&lt;a href="http://www.codersbarn.com/post/2008/06/ASPNET-Web-Site-versus-Web-Application-Project.aspx"&gt;ASP.NET: Web Site versus Web Application Project&lt;/a&gt;&lt;/li&gt;    &lt;li&gt;&lt;a href="http://www.codersbarn.com/post/2008/07/10/ASPNET-PayPal-Subscriptions-IPN.aspx"&gt;ASP.NET PayPal Subscription IPN&lt;/a&gt;&lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;Also, it is not necessary to do the steps in the &lt;font face="Courier New"&gt;Extended Usage&lt;/font&gt; section of Joe's blog post.&amp;#160; They are optional configuration points in the &lt;font face="Courier New"&gt;Web.config&lt;/font&gt; where you control the &lt;font face="Courier New"&gt;className&lt;/font&gt;, &lt;font face="Courier New"&gt;nameSpace&lt;/font&gt;, &lt;font face="Courier New"&gt;directory&lt;/font&gt;, and &lt;font face="Courier New"&gt;fileName&lt;/font&gt; of the auto-generated code file.&amp;#160; Most of the defaults are fine, but in my case I wanted the generated file to end up in an &lt;font face="Courier New"&gt;App_Code&lt;/font&gt; directory instead of in the root of the project folder.&amp;#160; If you decide to add in this custom configuration, you need to be aware that you must add the following XML namespace to the &lt;font face="Courier New"&gt;configuration&lt;/font&gt; root element of your &lt;font face="Courier New"&gt;Web.config&lt;/font&gt;:&lt;/p&gt;  &lt;p&gt;&lt;font face="Courier New"&gt;xmlns=&amp;quot;http://schemas.microsoft.com/.NetConfiguration/v2.0&amp;quot;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;Finally, it should be noted that if the website you are building is under source control, you will likely want to always keep this auto-generated code file checked out in order to prevent the file from having its &lt;font face="Courier New"&gt;Read-Only&lt;/font&gt; attribute set when it's checked in.&amp;#160; If you don't have it checked out, the build will throw out a warning and the generated code file will not be regenerated if changes in your &lt;font face="Courier New"&gt;Web.config&lt;/font&gt; need to be propagated to it.&lt;/p&gt;  &lt;h3&gt;Conclusion&lt;/h3&gt;  &lt;p&gt;With all of this in place, you should be able to use the Profile proxy class object in your ASPX code-behind files, just as I gave examples of in my &lt;a href="http://murrayon.net/2009/02/aspnet-providers-profile.html"&gt;previous post about the ASP.NET Profile system&lt;/a&gt;.&amp;#160; Although in my case, I mostly used the static method &lt;font face="Courier New"&gt;GetProfile&lt;/font&gt; from the auto-generated &lt;font face="Courier New"&gt;WebProfile&lt;/font&gt;&lt;font face="Verdana"&gt; class (the name the Visual Studio Build Task selects by default).&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;As I mentioned when &lt;a title="ASP.NET Providers - Membership, Role, and Profile" href="http://murrayon.net/2009/01/aspnet-providers-membership-role-and.html"&gt;I first started the ASP.NET Provider Series of posts&lt;/a&gt;, my next blog post will be about some advantages of using this Provider system on IIS 7 and a few issues when your ASP.NET website contains non-ASP.NET content:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;&lt;a href="http://murrayon.net/2009/02/iis-7-and-aspnet-providers-membership.html"&gt;IIS 7 and ASP.NET Providers (Membership, Roles, and Profile)&lt;/a&gt; &lt;/li&gt; &lt;/ul&gt; &lt;/span&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1664217632350055880-2039771211821386099?l=murrayon.net' alt='' /&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://murrayon.net/feeds/2039771211821386099/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://murrayon.net/2009/02/aspnet-profile-and-web-application.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/1664217632350055880/posts/default/2039771211821386099?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/1664217632350055880/posts/default/2039771211821386099?v=2" /><link rel="alternate" type="text/html" href="http://murrayon.net/2009/02/aspnet-profile-and-web-application.html" title="ASP.NET Profile and Web Application Projects" /><author><name>Mike Murray</name><uri>http://www.blogger.com/profile/01990150469958605173</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="15380857253844311568" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total></entry><entry gd:etag="W/&quot;CEEGQH45eyp7ImA9WxNVGEg.&quot;"><id>tag:blogger.com,1999:blog-1664217632350055880.post-2465533286377116597</id><published>2009-02-09T16:10:00.002-07:00</published><updated>2009-10-29T15:43:41.023-06:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-10-29T15:43:41.023-06:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Web" /><category scheme="http://www.blogger.com/atom/ns#" term=".NET" /><category scheme="http://www.blogger.com/atom/ns#" term="ASP.NET Providers Series" /><category scheme="http://www.blogger.com/atom/ns#" term="ASP.NET" /><category scheme="http://www.blogger.com/atom/ns#" term="Database" /><category scheme="http://www.blogger.com/atom/ns#" term="C#" /><category scheme="http://www.blogger.com/atom/ns#" term="Visual Studio" /><category scheme="http://www.blogger.com/atom/ns#" term="SQL" /><category scheme="http://www.blogger.com/atom/ns#" term="Microsoft" /><title>ASP.NET Providers - Profile</title><content type="html">&lt;p&gt;This blog post is part of a series about the ASP.NET Providers (namely Membership, Role Management, and Profile). The introductory post in the series can be found at the following link, which introduces the &lt;a href="http://en.wikipedia.org/wiki/Provider_model"&gt;Provider Model pattern&lt;/a&gt; and gives a personal example of an implementation I have been working on:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="http://murrayon.net/2009/01/aspnet-providers-membership-role-and.html"&gt;ASP.NET Providers - Membership, Role, and Profile&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;This post will deal with adding Profile properties to your user accounts (and apparently this can also be used with anonymous users as well).&amp;#160; However, I will suggest using a slightly different Profile Provider than what comes in ASP.NET by default.&amp;#160; This will show how easy it is to plug in a different implementation in this very flexible Provider Model.&lt;/p&gt; &lt;span class='fullpost'&gt; &lt;h3&gt;SqlProfileProvider vs. SqlTableProfileProvider&lt;/h3&gt;&lt;p&gt;The &lt;font face="Courier New"&gt;SqlProfileProvider&lt;/font&gt; is the built-in Profile Provider that ASP.NET comes with by default.&amp;#160; It allows you to define custom fields that make up profiling data you would want to collect and store about your users.&amp;#160; This could be demographics, preferences, or any other useful details.&amp;#160; This specific implementation is designed in a way where no matter what fields you define, your database schema will be compatible with any upgrade Microsoft could send down to patch the Provider system or ASP.NET in general.&amp;#160; The way this is accomplished is by storing a &lt;a title="Binary Large Object" href="http://en.wikipedia.org/wiki/Binary_large_object"&gt;blob&lt;/a&gt; of all the field names in one table column and a blob of all the field values in another column; it's similar to the concept of a &lt;a title="Associative Array" href="http://en.wikipedia.org/wiki/Associative_array"&gt;dictionary&lt;/a&gt; with key/value pairs.&amp;#160; The difficult part is that these blobs can contain clear-text, XML, and/or binary, depending on how the source data type serializes by default.&amp;#160; Unfortunately, this highly flexible solution is quite unusable if you need a clear view of the Profile data for reporting purposes or stored procedure needs.&lt;/p&gt;&lt;p&gt;When trying to find an already implemented custom provider that would allow to store each Profile field in its own table column, I came across a &lt;a title="ASP.NET 2.0 SQL Table Profile Provider Released Today" href="http://weblogs.asp.net/scottgu/archive/2006/01/10/435038.aspx"&gt;blog post from Scott Guthrie introducing such an implementation done by two Microsoft employees&lt;/a&gt;.&amp;#160; The name of this provider is the &lt;font face="Courier New"&gt;SqlTableProfileProvider&lt;/font&gt;, and it can be found at the following link:&lt;/p&gt;&lt;p&gt;&lt;a href="http://www.asp.net/downloads/sandbox/table-profile-provider-samples/"&gt;Table Profile Provider Samples&lt;/a&gt;&lt;/p&gt;&lt;p&gt;At the above location, you will find an MSI download that will install a sample project containing a few source code files you can include in your project; you will also find a download link for a &amp;quot;white paper&amp;quot; Word document that explains the usage of the &lt;font face="Courier New"&gt;SqlTableProfileProvider&lt;/font&gt; and the &lt;font face="Courier New"&gt;SqlStoredProcedureProfileProvider&lt;/font&gt; custom providers.&amp;#160; The nice thing about both of these providers is that their use in code and their configuration in the Web.config is extremely similar to how the original &lt;font face="Courier New"&gt;SqlProfileProvider&lt;/font&gt; is used and configured.&lt;/p&gt;&lt;h3&gt;Setting up the SqlTableProfileProvider&lt;/h3&gt;&lt;p&gt;As was done with the &lt;a title="ASP.NET Providers - Membership" href="http://murrayon.net/2009/01/aspnet-providers-membership.html"&gt;Membership&lt;/a&gt; and &lt;a title="ASP.NET Providers - Role Management" href="http://murrayon.net/2009/02/aspnet-providers-role-management.html"&gt;Role Management&lt;/a&gt; Providers, here is the XML fragment that would go in your &lt;font face="Courier New"&gt;Web.config&lt;/font&gt;:&lt;/p&gt;&lt;div style="border-right: gray 1px solid; padding-right: 4px; border-top: gray 1px solid; padding-left: 4px; font-size: 8pt; padding-bottom: 4px; margin: 20px 0px 10px; border-left: gray 1px solid; width: 97.5%; cursor: text; max-height: 325px; line-height: 12pt; padding-top: 4px; border-bottom: gray 1px solid; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; background-color: #f4f4f4"&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;configuration&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;
    &lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;connectionStrings&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;
        &lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;add&lt;/span&gt; &lt;span style="color: #ff0000"&gt;name&lt;/span&gt;&lt;span style="color: #0000ff"&gt;=&amp;quot;MyDB&amp;quot;&lt;/span&gt; &lt;span style="color: #ff0000"&gt;connectionString&lt;/span&gt;&lt;span style="color: #0000ff"&gt;=&amp;quot;...&amp;quot;&lt;/span&gt; &lt;span style="color: #0000ff"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span style="color: #0000ff"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000"&gt;connectionStrings&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;
    &lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;system.web&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;
        ... authentication &amp;amp; authorization settings ...
        &lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;profile&lt;/span&gt; &lt;span style="color: #ff0000"&gt;enabled&lt;/span&gt;&lt;span style="color: #0000ff"&gt;=&amp;quot;true&amp;quot;&lt;/span&gt;
                 &lt;span style="color: #ff0000"&gt;defaultProvider&lt;/span&gt;&lt;span style="color: #0000ff"&gt;=&amp;quot;ConfiguredProfileProvider&amp;quot;&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;
            &lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;providers&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;
                &lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;add&lt;/span&gt; &lt;span style="color: #ff0000"&gt;name&lt;/span&gt;&lt;span style="color: #0000ff"&gt;=&amp;quot;ConfiguredProfileProvider&amp;quot;&lt;/span&gt;
                     &lt;span style="color: #ff0000"&gt;type&lt;/span&gt;&lt;span style="color: #0000ff"&gt;=&amp;quot;Microsoft.Samples.SqlTableProfileProvider&amp;quot;&lt;/span&gt;
                     &lt;span style="color: #ff0000"&gt;connectionStringName&lt;/span&gt;&lt;span style="color: #0000ff"&gt;=&amp;quot;MyDB&amp;quot;&lt;/span&gt;
                     &lt;span style="color: #ff0000"&gt;table&lt;/span&gt;&lt;span style="color: #0000ff"&gt;=&amp;quot;custom_Profile&amp;quot;&lt;/span&gt;
                     &lt;span style="color: #ff0000"&gt;applicationName&lt;/span&gt;&lt;span style="color: #0000ff"&gt;=&amp;quot;SampleWebSite&amp;quot;&lt;/span&gt; &lt;span style="color: #0000ff"&gt;/&amp;gt;&lt;/span&gt;
            &lt;span style="color: #0000ff"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000"&gt;providers&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;
            ... properties section found in the next XML snippet ...
        &lt;span style="color: #0000ff"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000"&gt;profile&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;
    &lt;span style="color: #0000ff"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000"&gt;system.web&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;
&lt;span style="color: #0000ff"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000"&gt;configuration&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;&lt;u&gt;WARNING&lt;/u&gt;: &lt;/strong&gt;According to Microsoft, you should &lt;strong&gt;&lt;u&gt;never&lt;/u&gt;&lt;/strong&gt; use the default provider settings and should &lt;strong&gt;&lt;u&gt;always&lt;/u&gt;&lt;/strong&gt; add a new, configured provider; in addition you &lt;strong&gt;&lt;u&gt;must&lt;/u&gt;&lt;/strong&gt; be sure to specify the &lt;font face="Courier New"&gt;applicationName&lt;/font&gt; attribute! See &lt;a href="http://weblogs.asp.net/scottgu/archive/2006/04/22/Always-set-the-_2200_applicationName_2200_-property-when-configuring-ASP.NET-2.0-Membership-and-other-Providers.aspx"&gt;Scott Guthrie's blog post on this topic&lt;/a&gt; for more details. Apparently, you can also use a value of &lt;font face="Courier New"&gt;&amp;quot;/&amp;quot;&lt;/font&gt; for the &lt;font face="Courier New"&gt;applicationName&lt;/font&gt; and it will use the root application name.&lt;/p&gt;&lt;p&gt;You'll notice in the &lt;font face="Courier New"&gt;type&lt;/font&gt; attribute that we are not referencing the default &lt;font face="Courier New"&gt;SqlProfileProvider&lt;/font&gt; that ships with ASP.NET.&amp;#160; What you need to do is get this new class included or referenced in your solution so that this namespace reference can successfully resolve.&amp;#160; I opted to just include the code files in my solution as is; I chose to place them in my &lt;font face="Courier New"&gt;App_Code&lt;/font&gt; folder.&amp;#160; The code files you want to grab are likely in the default location that the MSI installed to, which is &lt;font face="Courier New"&gt;Program Files/Microsoft/ASP.NET 2.0 Table Profile Provider Samples&lt;/font&gt;.&amp;#160; The two files you need are &lt;font face="Courier New"&gt;SqlStoredProcedureProfileProvider.cs&lt;/font&gt; and &lt;font face="Courier New"&gt;SqlTableProfileProvider.cs&lt;/font&gt;&lt;font face="Verdana"&gt;, &lt;/font&gt;both of which are found in the &lt;font face="Courier New"&gt;App_Code&lt;/font&gt; folder of the sample project.&amp;#160; You need to copy both code files to your solution, as it appears that the &lt;font face="Courier New"&gt;SqlTableProfileProvider&lt;/font&gt; depends on some logic in the &lt;font face="Courier New"&gt;SqlStoredProcedureProfileProvider&lt;/font&gt; for some reason.&lt;/p&gt;&lt;p&gt;Also note the &lt;font face="Courier New"&gt;table&lt;/font&gt; attribute above (which is not present in the built-in &lt;font face="Courier New"&gt;SqlProfileProvider&lt;/font&gt;), which tells the provider which table in your database will be storing the custom Profile fields.&amp;#160; As for the &amp;quot;properties section&amp;quot; referenced near the end of the above snippet, this is where you specify the custom Profile fields and their mappings to column names in the specified database table.&amp;#160; The advantage of specifying this information in the &lt;font face="Courier New"&gt;Web.config&lt;/font&gt; is that you will be able to get programmatic access to these fields as strongly-typed properties on a proxy class named &lt;font face="Courier New"&gt;Profile&lt;/font&gt; in your code-behind.&amp;#160; Here is a sample &lt;font face="Courier New"&gt;properties&lt;/font&gt; configuration:&lt;/p&gt;&lt;div style="border-right: gray 1px solid; padding-right: 4px; border-top: gray 1px solid; padding-left: 4px; font-size: 8pt; padding-bottom: 4px; margin: 20px 0px 10px; border-left: gray 1px solid; width: 97.5%; cursor: text; max-height: 300px; line-height: 12pt; padding-top: 4px; border-bottom: gray 1px solid; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; background-color: #f4f4f4"&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;properties&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;
    &lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;add&lt;/span&gt; &lt;span style="color: #ff0000"&gt;name&lt;/span&gt;&lt;span style="color: #0000ff"&gt;=&amp;quot;FirstName&amp;quot;&lt;/span&gt;
         &lt;span style="color: #ff0000"&gt;type&lt;/span&gt;&lt;span style="color: #0000ff"&gt;=&amp;quot;string&amp;quot;&lt;/span&gt;
         &lt;span style="color: #ff0000"&gt;defaultValue&lt;/span&gt;&lt;span style="color: #0000ff"&gt;=&amp;quot;[null]&amp;quot;&lt;/span&gt;
         &lt;span style="color: #ff0000"&gt;customProviderData&lt;/span&gt;&lt;span style="color: #0000ff"&gt;=&amp;quot;FirstName;nvarchar&amp;quot;&lt;/span&gt; &lt;span style="color: #0000ff"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;add&lt;/span&gt; &lt;span style="color: #ff0000"&gt;name&lt;/span&gt;&lt;span style="color: #0000ff"&gt;=&amp;quot;Age&amp;quot;&lt;/span&gt;
         &lt;span style="color: #ff0000"&gt;type&lt;/span&gt;&lt;span style="color: #0000ff"&gt;=&amp;quot;int&amp;quot;&lt;/span&gt;
         &lt;span style="color: #ff0000"&gt;customProviderData&lt;/span&gt;&lt;span style="color: #0000ff"&gt;=&amp;quot;Age;int&amp;quot;&lt;/span&gt; &lt;span style="color: #0000ff"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;add&lt;/span&gt; &lt;span style="color: #ff0000"&gt;name&lt;/span&gt;&lt;span style="color: #0000ff"&gt;=&amp;quot;AccountExpiration&amp;quot;&lt;/span&gt;
         &lt;span style="color: #ff0000"&gt;type&lt;/span&gt;&lt;span style="color: #0000ff"&gt;=&amp;quot;DateTime&amp;quot;&lt;/span&gt;
         &lt;span style="color: #ff0000"&gt;defaultValue&lt;/span&gt;&lt;span style="color: #0000ff"&gt;=&amp;quot;[null]&amp;quot;&lt;/span&gt;
         &lt;span style="color: #ff0000"&gt;customProviderData&lt;/span&gt;&lt;span style="color: #0000ff"&gt;=&amp;quot;AccountExpiration;datetime&amp;quot;&lt;/span&gt; &lt;span style="color: #0000ff"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;add&lt;/span&gt; &lt;span style="color: #ff0000"&gt;name&lt;/span&gt;&lt;span style="color: #0000ff"&gt;=&amp;quot;CookieID&amp;quot;&lt;/span&gt;
         &lt;span style="color: #ff0000"&gt;type&lt;/span&gt;&lt;span style="color: #0000ff"&gt;=&amp;quot;System.Guid&amp;quot;&lt;/span&gt;
         &lt;span style="color: #ff0000"&gt;defaultValue&lt;/span&gt;&lt;span style="color: #0000ff"&gt;=&amp;quot;[null]&amp;quot;&lt;/span&gt;
         &lt;span style="color: #ff0000"&gt;customProviderData&lt;/span&gt;&lt;span style="color: #0000ff"&gt;=&amp;quot;CookieID;uniqueidentifier&amp;quot;&lt;/span&gt; &lt;span style="color: #0000ff"&gt;/&amp;gt;&lt;/span&gt;
&lt;span style="color: #0000ff"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000"&gt;properties&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The Profile system provides a configuration point for each Profile field called &lt;font face="Courier New"&gt;customProviderData&lt;/font&gt;.&amp;#160; It appears the default &lt;font face="Courier New"&gt;SqlProfileProvider&lt;/font&gt; doesn't even look at this additional attribute, but rather reserves this configuration point for use by custom implemented Profile providers.&amp;#160; The &lt;font face="Courier New"&gt;SqlTableProfileProvider &lt;/font&gt;utilizes this extra metadata field as a place to put mapping information for a column name and ADO.NET database type.&amp;#160; If you have questions about which ADO.NET and .NET types to use/specify in this configuration, there is helpful information in the accompanying white paper found on the download site.&amp;#160; Also found in that document is a great discussion you may want to read about the &lt;font face="Courier New"&gt;defaultValue&lt;/font&gt; attribute, what it configures, and how it might differ for value types (such as &lt;font face="Courier New"&gt;integer&lt;/font&gt;).&lt;/p&gt;&lt;h3&gt;Creating the Database Table&lt;/h3&gt;&lt;p&gt;Now that you have the code files in your solution and have configured the Profile fields, you need to create the custom table in the database that this provider will query and update.&amp;#160; Here is a sample SQL definition for our custom profile table:&lt;/p&gt;&lt;div style="border-right: gray 1px solid; padding-right: 4px; border-top: gray 1px solid; padding-left: 4px; font-size: 8pt; padding-bottom: 4px; margin: 20px 0px 10px; border-left: gray 1px solid; width: 97.5%; cursor: text; max-height: 200px; line-height: 12pt; padding-top: 4px; border-bottom: gray 1px solid; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; background-color: #f4f4f4"&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #0000ff"&gt;create&lt;/span&gt; &lt;span style="color: #0000ff"&gt;table&lt;/span&gt; dbo.custom_Profile
(
    UserId               uniqueidentifier &lt;span style="color: #0000ff"&gt;not&lt;/span&gt; &lt;span style="color: #0000ff"&gt;null&lt;/span&gt; &lt;span style="color: #0000ff"&gt;Primary&lt;/span&gt; &lt;span style="color: #0000ff"&gt;Key&lt;/span&gt;,
    FirstName            nvarchar(50) &lt;span style="color: #0000ff"&gt;null&lt;/span&gt;,
    Age                  &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; &lt;span style="color: #0000ff"&gt;null&lt;/span&gt;,
    AccountExpiration    datetime &lt;span style="color: #0000ff"&gt;null&lt;/span&gt;,
    CookieID             uniqueidentifier &lt;span style="color: #0000ff"&gt;null&lt;/span&gt;,
    LastUpdatedDate      datetime &lt;span style="color: #0000ff"&gt;not&lt;/span&gt; &lt;span style="color: #0000ff"&gt;null&lt;/span&gt;
)
go&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Note that the &lt;font face="Courier New"&gt;SqlTableProfileProvider&lt;/font&gt; requires two extra columns in addition to your custom defined Profile properties, namely &lt;font face="Courier New"&gt;UserId&lt;/font&gt; and &lt;font face="Courier New"&gt;LastUpdatedDate&lt;/font&gt;.&amp;#160; One other thing to be aware of is that if you use the Membership API to delete a user programmatically, this will remove all entries related to that user in the database &lt;strong&gt;&lt;u&gt;except&lt;/u&gt;&lt;/strong&gt; from your custom Profile table.&amp;#160; I believe this might be because the Profile system can apparently be used independently of the Membership system, even allowing you to store Profile data on anonymous, unauthenticated users.&amp;#160; I think the same caution would go for any utility that presumably uses this Membership API under the covers, such as the &lt;font face="Courier New"&gt;ASP.NET Website Administration Tool&lt;/font&gt; launched from Visual Studio that I referred to earlier in this series with a post titled &lt;a href="http://murrayon.net/2009/01/aspnet-providers-getting-started.html"&gt;ASP.NET Providers - Getting Started&lt;/a&gt;.&amp;#160; Up to this point, I have resorted to manually clearing out Profile table rows myself that are linked to the membership account being removed from the database.&lt;/p&gt;&lt;p&gt;Also, if your web site is using a Windows user or system account for the identity of the worker process, you'll want to make sure that set of credentials has &lt;font face="Courier New"&gt;SELECT&lt;/font&gt;, &lt;font face="Courier New"&gt;INSERT&lt;/font&gt;, &lt;font face="Courier New"&gt;UPDATE&lt;/font&gt;, and &lt;font face="Courier New"&gt;DELETE&lt;/font&gt; permissions granted to it for this new custom database table you created.&amp;#160; There are also some &lt;font face="Courier New"&gt;EXECUTE&lt;/font&gt;, &lt;font face="Courier New"&gt;SELECT&lt;/font&gt;, and &lt;font face="Courier New"&gt;UPDATE&lt;/font&gt; permissions required on a few of the already-existing stored procedures that the Provider system uses.&amp;#160; Again, check the accompanying white paper on the download site for a discussion about these procedure and for some SQL statements to help you automate the granting of these permissions.&lt;/p&gt;&lt;h3&gt;The Profile Proxy Class&lt;/h3&gt;&lt;p&gt;If you are using the &lt;font face="Courier New"&gt;Web Site&lt;/font&gt; project template in Visual Studio, then you are good to go with using the &lt;font face="Courier New"&gt;Profile&lt;/font&gt; proxy class that can be used anywhere in your code to retrieve and update Profile fields on the current user.&amp;#160; The availability of this &lt;font face="Courier New"&gt;Profile&lt;/font&gt; class is independent of whether you are using the built-in ASP.NET &lt;font face="Courier New"&gt;SqlProfileProvider&lt;/font&gt; or the custom &lt;font face="Courier New"&gt;SqlTableProfileProvider&lt;/font&gt; that I've been showcasing thus far.&amp;#160; However, if you are using the &lt;font face="Courier New"&gt;Web Application&lt;/font&gt; project template, this proxy object is not auto-generated for you by Visual Studio.&amp;#160; For a detailed discussion of the problem and a working solution, see my next post which is entitled &lt;a href="http://murrayon.net/2009/02/aspnet-profile-and-web-application.html"&gt;ASP.NET Profile and Web Application Projects&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;Use of this &lt;font face="Courier New"&gt;Profile&lt;/font&gt; class couldn't be easier and is exactly as you would expect it to be.&amp;#160; Here is a code snippet that both retrieves and updates strongly-typed Profile properties (exactly as they were defined in the &lt;font face="Courier New"&gt;Web.config&lt;/font&gt;) using this proxy object:&lt;/p&gt;&lt;div style="border-right: gray 1px solid; padding-right: 4px; border-top: gray 1px solid; padding-left: 4px; font-size: 8pt; padding-bottom: 4px; margin: 20px 0px 10px; border-left: gray 1px solid; width: 97.5%; cursor: text; max-height: 200px; line-height: 12pt; padding-top: 4px; border-bottom: gray 1px solid; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; background-color: #f4f4f4"&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #008000"&gt;// Set Profile property&lt;/span&gt;
Profile.FirstName = txtBoxFirstName.Text;

&lt;span style="color: #008000"&gt;// Retrieve Profile property&lt;/span&gt;
&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; age = Profile.Age;&lt;/pre&gt;&lt;/div&gt;&lt;h3&gt;Read On!&lt;/h3&gt;&lt;p&gt;This crash course of the ASP.NET Provider system is pretty much done I guess you could say, as far as a tutorial goes that is.&amp;#160; I still have another two posts on the radar that will be coming over the next few days regarding issues and workarounds that I encountered.&amp;#160; One post will deal with generating this &lt;font face="Courier New"&gt;Profile&lt;/font&gt; proxy class under the Visual Studio &lt;font face="Courier New"&gt;Web Application&lt;/font&gt; project template.&amp;#160; The other post will be about the advantages of using this system under IIS 7 found in Windows Vista and Server 2008; it will also include some issues with using this system if some of your content is static HTML instead of ASPX pages.&amp;#160; Here are the links to these two posts:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="http://murrayon.net/2009/02/aspnet-profile-and-web-application.html"&gt;ASP.NET Profile and Web Application Projects&lt;/a&gt; &lt;/li&gt;&lt;li&gt;&lt;a href="http://murrayon.net/2009/02/iis-7-and-aspnet-providers-membership.html"&gt;IIS 7 and ASP.NET Providers (Membership, Roles, and Profile)&lt;/a&gt; &lt;/li&gt;&lt;/ul&gt;&lt;p&gt;It has been a very pleasant experience overall to work with the ASP.NET Provider system because of it's highly customizable and flexible design.&amp;#160; If your &lt;a title="ASP.NET Providers - Membership" href="http://murrayon.net/2009/01/aspnet-providers-membership.html"&gt;Membership&lt;/a&gt;, &lt;a title="ASP.NET Providers - Role Management" href="http://murrayon.net/2009/02/aspnet-providers-role-management.html"&gt;Role Management&lt;/a&gt;, and Profile needs are fairly common and typical, this framework is a piece of cake to incorporate into your product (including your existing ones, no matter how out-of-date they are).&amp;#160; Hope you've enjoyed the series!&lt;/p&gt;
&lt;/span&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1664217632350055880-2465533286377116597?l=murrayon.net' alt='' /&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://murrayon.net/feeds/2465533286377116597/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://murrayon.net/2009/02/aspnet-providers-profile.html#comment-form" title="5 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/1664217632350055880/posts/default/2465533286377116597?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/1664217632350055880/posts/default/2465533286377116597?v=2" /><link rel="alternate" type="text/html" href="http://murrayon.net/2009/02/aspnet-providers-profile.html" title="ASP.NET Providers - Profile" /><author><name>Mike Murray</name><uri>http://www.blogger.com/profile/01990150469958605173</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="15380857253844311568" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">5</thr:total></entry><entry gd:etag="W/&quot;CEMERHs5cSp7ImA9WxNVGEg.&quot;"><id>tag:blogger.com,1999:blog-1664217632350055880.post-4763114250744436891</id><published>2009-02-05T16:45:00.002-07:00</published><updated>2009-10-29T15:40:05.529-06:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-10-29T15:40:05.529-06:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Web" /><category scheme="http://www.blogger.com/atom/ns#" term="Security" /><category scheme="http://www.blogger.com/atom/ns#" term=".NET" /><category scheme="http://www.blogger.com/atom/ns#" term="ASP.NET Providers Series" /><category scheme="http://www.blogger.com/atom/ns#" term="ASP.NET" /><category scheme="http://www.blogger.com/atom/ns#" term="C#" /><category scheme="http://www.blogger.com/atom/ns#" term="Visual Studio" /><category scheme="http://www.blogger.com/atom/ns#" term="Microsoft" /><title>ASP.NET Providers - Role Management</title><content type="html">&lt;p&gt;This blog post is part of a series about the ASP.NET Providers (namely Membership, Role Management, and Profile). The introductory post in the series can be found at the following link, which introduces the &lt;a href="http://en.wikipedia.org/wiki/Provider_model"&gt;Provider Model pattern&lt;/a&gt; and gives a personal example of an implementation I have been working on:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;&lt;a href="http://murrayon.net/2009/01/aspnet-providers-membership-role-and.html"&gt;ASP.NET Providers - Membership, Role, and Profile&lt;/a&gt; &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;This post will deal with adding Role Management to your website.&lt;/p&gt; &lt;span class='fullpost'&gt; &lt;h3&gt;Role Management&lt;/h3&gt;  &lt;p&gt;Creating roles and assigning users accounts to them is a great way to group users together under similar permissions and abilities.&amp;#160; The ASP.NET Roles Management service allows you to restrict page viewing (or even just certain regions of a page) based on roles you define; you can even apply roles security to specific methods or classes using &lt;a title="Introduction to Attributes (C#)" href="http://msdn.microsoft.com/en-us/library/aa288059(VS.71).aspx"&gt;attributes&lt;/a&gt;, which I will show an example of a little later.&lt;/p&gt;  &lt;p&gt;In order to add role management to your site, add an XML fragment like the one below; the process is much the same as it was with the &lt;a title="ASP.NET Providers - Membership" href="http://murrayon.net/2009/01/aspnet-providers-membership.html"&gt;Membership Provider&lt;/a&gt;:&lt;/p&gt;  &lt;div style="border-right: gray 1px solid; padding-right: 4px; border-top: gray 1px solid; padding-left: 4px; font-size: 8pt; padding-bottom: 4px; margin: 20px 0px 10px; border-left: gray 1px solid; width: 97.5%; cursor: text; max-height: 300px; line-height: 12pt; padding-top: 4px; border-bottom: gray 1px solid; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; background-color: #f4f4f4"&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;configuration&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;
    &lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;connectionStrings&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;
        &lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;add&lt;/span&gt; &lt;span style="color: #ff0000"&gt;name&lt;/span&gt;&lt;span style="color: #0000ff"&gt;=&amp;quot;MyDB&amp;quot;&lt;/span&gt; &lt;span style="color: #ff0000"&gt;connectionString&lt;/span&gt;&lt;span style="color: #0000ff"&gt;=&amp;quot;...&amp;quot;&lt;/span&gt; &lt;span style="color: #0000ff"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span style="color: #0000ff"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000"&gt;connectionStrings&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;
    &lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;system.web&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;
        ... authentication &amp;amp; authorization settings ...
        &lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;roleManager&lt;/span&gt; &lt;span style="color: #ff0000"&gt;enabled&lt;/span&gt;&lt;span style="color: #0000ff"&gt;=&amp;quot;true&amp;quot;&lt;/span&gt;
                     &lt;span style="color: #ff0000"&gt;defaultProvider&lt;/span&gt;&lt;span style="color: #0000ff"&gt;=&amp;quot;ConfiguredRoleProvider&amp;quot;&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;
            &lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;providers&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;
                &lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;add&lt;/span&gt; &lt;span style="color: #ff0000"&gt;name&lt;/span&gt;&lt;span style="color: #0000ff"&gt;=&amp;quot;ConfiguredRoleProvider&amp;quot;&lt;/span&gt;
                     &lt;span style="color: #ff0000"&gt;type&lt;/span&gt;&lt;span style="color: #0000ff"&gt;=&amp;quot;System.Web.Security.SqlRoleProvider&amp;quot;&lt;/span&gt;
                     &lt;span style="color: #ff0000"&gt;connectionStringName&lt;/span&gt;&lt;span style="color: #0000ff"&gt;=&amp;quot;MyDB&amp;quot;&lt;/span&gt;
                     &lt;span style="color: #ff0000"&gt;applicationName&lt;/span&gt;&lt;span style="color: #0000ff"&gt;=&amp;quot;SampleWebSite&amp;quot;&lt;/span&gt; &lt;span style="color: #0000ff"&gt;/&amp;gt;&lt;/span&gt;
            &lt;span style="color: #0000ff"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000"&gt;providers&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;
        &lt;span style="color: #0000ff"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000"&gt;roleManager&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;
    &lt;span style="color: #0000ff"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000"&gt;system.web&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;
&lt;span style="color: #0000ff"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000"&gt;configuration&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;&lt;u&gt;WARNING&lt;/u&gt;: &lt;/strong&gt;According to Microsoft, you should &lt;strong&gt;&lt;u&gt;never&lt;/u&gt;&lt;/strong&gt; use the default provider settings and should &lt;strong&gt;&lt;u&gt;always&lt;/u&gt;&lt;/strong&gt; add a new, configured provider; in addition you &lt;strong&gt;&lt;u&gt;must&lt;/u&gt;&lt;/strong&gt; be sure to specify the &lt;font face="Courier New"&gt;applicationName&lt;/font&gt; attribute! See &lt;a href="http://weblogs.asp.net/scottgu/archive/2006/04/22/Always-set-the-_2200_applicationName_2200_-property-when-configuring-ASP.NET-2.0-Membership-and-other-Providers.aspx"&gt;Scott Guthrie's blog post on this topic&lt;/a&gt; for more details. Apparently, you can also use a value of &lt;font face="Courier New"&gt;&amp;quot;/&amp;quot;&lt;/font&gt; for the &lt;font face="Courier New"&gt;applicationName&lt;/font&gt; and it will use the root application name.&lt;/p&gt;&lt;p&gt;Role names can be used in the &lt;font face="Courier New"&gt;Web.config&lt;/font&gt; in the same place we used the user class wildcard characters (namely, &lt;font face="Courier New"&gt;*&lt;/font&gt; for all users and &lt;font face="Courier New"&gt;?&lt;/font&gt; for anonymous users); the following sample fragment would go under the &lt;font face="Courier New"&gt;system.web&lt;/font&gt; node:&lt;/p&gt;&lt;div style="border-right: gray 1px solid; padding-right: 4px; border-top: gray 1px solid; padding-left: 4px; font-size: 8pt; padding-bottom: 4px; margin: 20px 0px 10px; border-left: gray 1px solid; width: 97.5%; cursor: text; max-height: 200px; line-height: 12pt; padding-top: 4px; border-bottom: gray 1px solid; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; background-color: #f4f4f4"&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;authorization&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;
    &lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;deny&lt;/span&gt; &lt;span style="color: #ff0000"&gt;users&lt;/span&gt;&lt;span style="color: #0000ff"&gt;=&amp;quot;BannedUsers,?&amp;quot;&lt;/span&gt; &lt;span style="color: #0000ff"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;allow&lt;/span&gt; &lt;span style="color: #ff0000"&gt;users&lt;/span&gt;&lt;span style="color: #0000ff"&gt;=&amp;quot;PremiumUsers&amp;quot;&lt;/span&gt; &lt;span style="color: #0000ff"&gt;/&amp;gt;&lt;/span&gt;
&lt;span style="color: #0000ff"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000"&gt;authorization&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Role names can be defined by using the &lt;font face="Courier New"&gt;ASP.NET Website Administration Tool&lt;/font&gt; launched from Visual Studio that I referred to earlier in this series with a post titled &lt;a href="http://murrayon.net/2009/01/aspnet-providers-getting-started.html"&gt;ASP.NET Providers - Getting Started&lt;/a&gt;.&amp;#160; You can also use this utility to assign users to one or more roles.&amp;#160; Roles can be programmatically assigned and verified in code as well, using the provided &lt;font face="Courier New"&gt;Roles&lt;/font&gt; .NET API.&lt;/p&gt;&lt;h3&gt;Attribute-based Role Management&lt;/h3&gt;&lt;p&gt;In order to put authorization rules on classes or methods, you use the attribute named &lt;font face="Courier New"&gt;PrincipalPermission&lt;/font&gt;.&amp;#160; Here is a sample that contains a method only accessible by a user with the username of &lt;font face="Courier New"&gt;administrator&lt;/font&gt;&amp;#160;&lt;u&gt;AND&lt;/u&gt; in the role group &lt;font face="Courier New"&gt;Admin&lt;/font&gt;:&lt;/p&gt;&lt;div style="border-right: gray 1px solid; padding-right: 4px; border-top: gray 1px solid; padding-left: 4px; font-size: 8pt; padding-bottom: 4px; margin: 20px 0px 10px; border-left: gray 1px solid; width: 97.5%; cursor: text; max-height: 200px; line-height: 12pt; padding-top: 4px; border-bottom: gray 1px solid; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; background-color: #f4f4f4"&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;[PrincipalPermission(SecurityAction.Demand, Name=&lt;span style="color: #006080"&gt;&amp;quot;administrator&amp;quot;&lt;/span&gt;, Role=&lt;span style="color: #006080"&gt;&amp;quot;Admin&amp;quot;&lt;/span&gt;)]
&lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;void&lt;/span&gt; SomeMethod(...)
{
    ...
}&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The &lt;u&gt;OR&lt;/u&gt; version of the above logic (meaning the user account being verified need only satisfy one of these authorization rules) would be represented like this:&lt;/p&gt;&lt;div style="border-right: gray 1px solid; padding-right: 4px; border-top: gray 1px solid; padding-left: 4px; font-size: 8pt; padding-bottom: 4px; margin: 20px 0px 10px; border-left: gray 1px solid; width: 97.5%; cursor: text; max-height: 200px; line-height: 12pt; padding-top: 4px; border-bottom: gray 1px solid; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; background-color: #f4f4f4"&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;[PrincipalPermission(SecurityAction.Demand, Name=&lt;span style="color: #006080"&gt;&amp;quot;administrator&amp;quot;&lt;/span&gt;)]
[PrincipalPermission(SecurityAction.Demand, Role=&lt;span style="color: #006080"&gt;&amp;quot;Admin&amp;quot;&lt;/span&gt;)]
&lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;void&lt;/span&gt; SomeOtherMethod(...)
{
    ...
}&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Here is an interesting sample that restricts a page to authenticated users (those not visiting anonymously); you would put the attribute on the code-behind of an ASPX page, like this example for &lt;font face="Courier New"&gt;SomePage.aspx&lt;/font&gt;:&lt;/p&gt;&lt;div style="border-right: gray 1px solid; padding-right: 4px; border-top: gray 1px solid; padding-left: 4px; font-size: 8pt; padding-bottom: 4px; margin: 20px 0px 10px; border-left: gray 1px solid; width: 97.5%; cursor: text; max-height: 200px; line-height: 12pt; padding-top: 4px; border-bottom: gray 1px solid; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; background-color: #f4f4f4"&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #0000ff"&gt;using&lt;/span&gt; System.Security.Permissions;

[PrincipalPermission(SecurityAction.Demand, Authenticated=&lt;span style="color: #0000ff"&gt;true&lt;/span&gt;)]
&lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;partial&lt;/span&gt; &lt;span style="color: #0000ff"&gt;class&lt;/span&gt; SomePage : System.Web.UI.Page
{
    ...
}&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;In all of these cases, if the authorization criteria is not met, a &lt;font face="Courier New"&gt;SecurityException&lt;/font&gt; is thrown.&amp;#160; You would want to catch that exception and perform alternate logic or display a more user-friendly error message.&lt;/p&gt;&lt;h3&gt;Read On!&lt;/h3&gt;&lt;p&gt;Continue onward by reading the next blog post in this series found at the following link:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="http://murrayon.net/2009/02/aspnet-providers-profile.html"&gt;ASP.NET Providers - Profile&lt;/a&gt; &lt;/li&gt;&lt;/ul&gt;
&lt;/span&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1664217632350055880-4763114250744436891?l=murrayon.net' alt='' /&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://murrayon.net/feeds/4763114250744436891/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://murrayon.net/2009/02/aspnet-providers-role-management.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/1664217632350055880/posts/default/4763114250744436891?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/1664217632350055880/posts/default/4763114250744436891?v=2" /><link rel="alternate" type="text/html" href="http://murrayon.net/2009/02/aspnet-providers-role-management.html" title="ASP.NET Providers - Role Management" /><author><name>Mike Murray</name><uri>http://www.blogger.com/profile/01990150469958605173</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="15380857253844311568" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total></entry><entry gd:etag="W/&quot;DUQDRXo_eSp7ImA9WxNVGE4.&quot;"><id>tag:blogger.com,1999:blog-1664217632350055880.post-5687902183083831396</id><published>2009-01-30T14:21:00.007-07:00</published><updated>2009-10-29T11:29:34.441-06:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-10-29T11:29:34.441-06:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Web" /><category scheme="http://www.blogger.com/atom/ns#" term="Security" /><category scheme="http://www.blogger.com/atom/ns#" term="Encryption" /><category scheme="http://www.blogger.com/atom/ns#" term=".NET" /><category scheme="http://www.blogger.com/atom/ns#" term="ASP.NET Providers Series" /><category scheme="http://www.blogger.com/atom/ns#" term="ASP.NET" /><category scheme="http://www.blogger.com/atom/ns#" term="C#" /><category scheme="http://www.blogger.com/atom/ns#" term="Visual Studio" /><category scheme="http://www.blogger.com/atom/ns#" term="SQL" /><category scheme="http://www.blogger.com/atom/ns#" term="Microsoft" /><title>ASP.NET Providers - Membership</title><content type="html">&lt;p&gt;This blog post is part of a series about the ASP.NET Providers (namely Membership, Role Management, and Profile). The introductory post in the series can be found at the following link, which introduces the &lt;a href="http://en.wikipedia.org/wiki/Provider_model" target="_blank"&gt;Provider Model pattern&lt;/a&gt; and gives a personal example of an implementation I have been working on:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="http://murrayon.net/2009/01/aspnet-providers-membership-role-and.html"&gt;ASP.NET Providers - Membership, Role, and Profile&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;This post will deal with adding the Membership functionality to your website.&lt;/p&gt; &lt;span class='fullpost'&gt; &lt;h3&gt;Membership Provider Configuration&lt;/h3&gt;&lt;p&gt;Now that your DB is set up, there are a few snippets that need to be added to your &lt;span style="font-family: courier new"&gt;Web.config&lt;/span&gt;. It involves adding a connection string and adding a new membership provider, as in the sample below:&lt;/p&gt;&lt;div style="border-right: gray 1px solid; padding-right: 4px; border-top: gray 1px solid; padding-left: 4px; font-size: 8pt; padding-bottom: 4px; margin: 20px 0px 10px; border-left: gray 1px solid; width: 97.5%; cursor: text; max-height: 350px; line-height: 12pt; padding-top: 4px; border-bottom: gray 1px solid; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; background-color: #f4f4f4"&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;configuration&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;connectionStrings&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;        &lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;add&lt;/span&gt; &lt;span style="color: #ff0000"&gt;name&lt;/span&gt;&lt;span style="color: #0000ff"&gt;=&amp;quot;MyDB&amp;quot;&lt;/span&gt; &lt;span style="color: #ff0000"&gt;connectionString&lt;/span&gt;&lt;span style="color: #0000ff"&gt;=&amp;quot;...&amp;quot;&lt;/span&gt; &lt;span style="color: #0000ff"&gt;/&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000"&gt;connectionStrings&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;system.web&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;        ... authentication &amp;amp; authorization settings ...&lt;br /&gt;&lt;br /&gt;        &lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;membership&lt;/span&gt; &lt;span style="color: #ff0000"&gt;defaultProvider&lt;/span&gt;&lt;span style="color: #0000ff"&gt;=&amp;quot;ConfiguredMembershipProvider&amp;quot;&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;            &lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;providers&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;                &lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;add&lt;/span&gt; &lt;span style="color: #ff0000"&gt;name&lt;/span&gt;&lt;span style="color: #0000ff"&gt;=&amp;quot;ConfiguredMembershipProvider&amp;quot;&lt;/span&gt;&lt;br /&gt;                     &lt;span style="color: #ff0000"&gt;type&lt;/span&gt;&lt;span style="color: #0000ff"&gt;=&amp;quot;System.Web.Security.SqlMembershipProvider&amp;quot;&lt;/span&gt;&lt;br /&gt;                     &lt;span style="color: #ff0000"&gt;connectionStringName&lt;/span&gt;&lt;span style="color: #0000ff"&gt;=&amp;quot;MyDB&amp;quot;&lt;/span&gt;&lt;br /&gt;                     &lt;span style="color: #ff0000"&gt;applicationName&lt;/span&gt;&lt;span style="color: #0000ff"&gt;=&amp;quot;SampleWebSite&amp;quot;&lt;/span&gt;&lt;br /&gt;                     &lt;span style="color: #ff0000"&gt;minRequiredPasswordLength&lt;/span&gt;&lt;span style="color: #0000ff"&gt;=&amp;quot;5&amp;quot;&lt;/span&gt;&lt;br /&gt;                     &lt;span style="color: #ff0000"&gt;minRequiredNonalphanumericCharacters&lt;/span&gt;&lt;span style="color: #0000ff"&gt;=&amp;quot;0&amp;quot;&lt;/span&gt; &lt;span style="color: #0000ff"&gt;/&amp;gt;&lt;/span&gt;&lt;br /&gt;            &lt;span style="color: #0000ff"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000"&gt;providers&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;        &lt;span style="color: #0000ff"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000"&gt;membership&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000"&gt;system.web&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #0000ff"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000"&gt;configuration&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;&lt;u&gt;WARNING&lt;/u&gt;: &lt;/strong&gt;According to Microsoft, you should &lt;strong&gt;&lt;u&gt;never&lt;/u&gt;&lt;/strong&gt; use the default provider settings and should &lt;strong&gt;&lt;u&gt;always&lt;/u&gt;&lt;/strong&gt; add a new, configured provider; in addition you &lt;strong&gt;&lt;u&gt;must&lt;/u&gt;&lt;/strong&gt; be sure to specify the &lt;span style="font-family: courier new"&gt;applicationName&lt;/span&gt; attribute! See &lt;a title="Always set the " href="http://weblogs.asp.net/scottgu/archive/2006/04/22/Always-set-the-_2200_applicationName_2200_-property-when-configuring-ASP.NET-2.0-Membership-and-other-Providers.aspx" other="other" and="and" configuring="configuring" when="when" property="property" membership="membership" net="ASP.NET" 0="2.0"&gt;Scott Guthrie's blog post on this topic&lt;/a&gt; for more details. Apparently, you can also use a value of &lt;span style="font-family: courier new"&gt;&amp;quot;/&amp;quot;&lt;/span&gt; for the &lt;span style="font-family: courier new"&gt;applicationName&lt;/span&gt; and it will use the root application name.&lt;/p&gt;&lt;p&gt;The last two attributes of the &lt;span style="font-family: courier new"&gt;add&lt;/span&gt; node are only a couple of several membership features you can configure. For a complete list of attributes you can configure, see &lt;a href="http://msdn.microsoft.com/en-us/library/whae3t94.aspx"&gt;&amp;lt;add&amp;gt; Element for Providers for Membership&lt;/a&gt;.&lt;/p&gt;&lt;h3&gt;Securing Site Content by Requiring Authentication&lt;/h3&gt;&lt;p&gt;With 5 more lines of configuration added to your &lt;span style="font-family: courier new"&gt;Web.config&lt;/span&gt;, you can have the whole site secured and accessible only by user account authentication. Even better, you can make that 6 lines added to the &lt;span style="font-family: courier new"&gt;Web.config&lt;/span&gt;, add a &lt;span style="font-family: courier new"&gt;Login.aspx&lt;/span&gt; page, and drop in a &lt;span style="font-family: courier new"&gt;Login&lt;/span&gt; control from the Toolbox and you will get auto-redirect to the login page if someone tries to hit any page you've now secured. The framework is even smart enough to return you to that desired page after successful login; it accomplishes this by redirecting you to the login page but by adding a &lt;span style="font-family: courier new"&gt;ReturnUrl&lt;/span&gt; query string attribute to know where to go after authentication.&lt;/p&gt;&lt;p&gt;Here are the additional lines for your &lt;span style="font-family: courier new"&gt;Web.config&lt;/span&gt; (put them under the &lt;span style="font-family: courier new"&gt;system.web&lt;/span&gt; node):&lt;/p&gt;&lt;div style="border-right: gray 1px solid; padding-right: 4px; border-top: gray 1px solid; padding-left: 4px; font-size: 8pt; padding-bottom: 4px; margin: 20px 0px 10px; border-left: gray 1px solid; width: 97.5%; cursor: text; max-height: 200px; line-height: 12pt; padding-top: 4px; border-bottom: gray 1px solid; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; background-color: #f4f4f4"&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;authorization&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;deny&lt;/span&gt; &lt;span style="color: #ff0000"&gt;users&lt;/span&gt;&lt;span style="color: #0000ff"&gt;=&amp;quot;?&amp;quot;&lt;/span&gt; &lt;span style="color: #0000ff"&gt;/&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #0000ff"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000"&gt;authorization&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;authentication&lt;/span&gt; &lt;span style="color: #ff0000"&gt;mode&lt;/span&gt;&lt;span style="color: #0000ff"&gt;=&amp;quot;Forms&amp;quot;&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;forms&lt;/span&gt; &lt;span style="color: #ff0000"&gt;defaultUrl&lt;/span&gt;&lt;span style="color: #0000ff"&gt;=&amp;quot;index.html&amp;quot;&lt;/span&gt; &lt;span style="color: #ff0000"&gt;loginUrl&lt;/span&gt;&lt;span style="color: #0000ff"&gt;=&amp;quot;Login.aspx&amp;quot;&lt;/span&gt; &lt;span style="color: #0000ff"&gt;/&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #0000ff"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000"&gt;authentication&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;u&gt;&lt;strong&gt;NOTE&lt;/strong&gt;&lt;/u&gt;: You will likely already have an &lt;span style="font-family: courier new"&gt;authentication&lt;/span&gt; node in your &lt;span style="font-family: courier new"&gt;Web.config&lt;/span&gt;, but it's &lt;span style="font-family: courier new"&gt;mode&lt;/span&gt; may be set to the default &lt;span style="font-family: courier new"&gt;&amp;quot;Windows&amp;quot;&lt;/span&gt; value. To use the Membership Provider for authentication, you must have this value set to &lt;span style="font-family: courier new"&gt;&amp;quot;Forms.&amp;quot;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;The optional 6th line I spoke of earlier is the &lt;span style="font-family: courier new"&gt;forms&lt;/span&gt; node under the &lt;span style="font-family: courier new"&gt;authentication&lt;/span&gt; node. The &lt;span style="font-family: courier new"&gt;defaultUrl&lt;/span&gt; attribute of this line is used to tell the framework where to go after successful login if there is no &lt;span style="font-family: courier new"&gt;ReturnUrl&lt;/span&gt; specified in the query string. The &lt;span style="font-family: courier new"&gt;loginUrl&lt;/span&gt; attribute is used to specify the page the user is redirected to if they are attempting to hit a page that requires authentication.&lt;/p&gt;&lt;p&gt;The &lt;span style="font-family: courier new"&gt;deny&lt;/span&gt; node is using the question mark (&lt;span style="font-family: courier new"&gt;?&lt;/span&gt;) wildcard character, which is used for anonymous users (or those that haven't been authenticated yet); the asterisk (&lt;span style="font-family: courier new"&gt;*&lt;/span&gt;) wildcard is used to signify all users browsing the site. Since we are dealing with the &lt;span style="font-family: courier new"&gt;Web.config&lt;/span&gt; at the root of the site, this &lt;span style="font-family: courier new"&gt;deny&lt;/span&gt; rule will apply to the whole site and it's subdirectories. You can either put a &lt;span style="font-family: courier new"&gt;Web.config&lt;/span&gt; in each subfolder that requires an overriding or more restrictive set of &lt;span style="font-family: courier new"&gt;allow&lt;/span&gt; and &lt;span style="font-family: courier new"&gt;deny&lt;/span&gt; rules, or you can actually specify &lt;span style="font-family: courier new"&gt;location&lt;/span&gt; elements in your &lt;span style="font-family: courier new"&gt;Web.config&lt;/span&gt;, as is shown in the following example (basically you could have several of these &lt;span style="font-family: courier new"&gt;location&lt;/span&gt; elements, each with their own &lt;span style="font-family: courier new"&gt;authorization&lt;/span&gt; rules):&lt;/p&gt;&lt;div style="border-right: gray 1px solid; padding-right: 4px; border-top: gray 1px solid; padding-left: 4px; font-size: 8pt; padding-bottom: 4px; margin: 20px 0px 10px; border-left: gray 1px solid; width: 97.5%; cursor: text; max-height: 200px; line-height: 12pt; padding-top: 4px; border-bottom: gray 1px solid; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; background-color: #f4f4f4"&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;configuration&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;location&lt;/span&gt; &lt;span style="color: #ff0000"&gt;path&lt;/span&gt;&lt;span style="color: #0000ff"&gt;=&amp;quot;Login.aspx&amp;quot;&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;        &lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;system.web&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;            &lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;authorization&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;                &lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;allow&lt;/span&gt; &lt;span style="color: #ff0000"&gt;users&lt;/span&gt;&lt;span style="color: #0000ff"&gt;=&amp;quot;?&amp;quot;&lt;/span&gt; &lt;span style="color: #0000ff"&gt;/&amp;gt;&lt;/span&gt;&lt;br /&gt;            &lt;span style="color: #0000ff"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000"&gt;authorization&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;        &lt;span style="color: #0000ff"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000"&gt;system.web&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000"&gt;location&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #0000ff"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000"&gt;configuration&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;As far as I can tell, this sample configuration above isn't necessary if you have specified your login page in the &lt;span style="font-family: courier new"&gt;loginUrl&lt;/span&gt; attribute of the &lt;span style="font-family: courier new"&gt;authentication/forms&lt;/span&gt; node like we did in the previous code snippet. But this sample is at least illustrative of the location-based authorization rules.&lt;/p&gt;&lt;p&gt;Personally, I decided to create a folder named&lt;span style="font-family: courier new"&gt; Public&lt;/span&gt; in my site and I give it its own &lt;span style="font-family: courier new"&gt;Web.config&lt;/span&gt; that allows all users (including anonymous ones) access to the containing web pages. This folder currently contains the login, user account registration, account activation (a link included in the email sent upon registration), and password retrieval pages, all of which would need unrestricted access for anonymous users.&lt;/p&gt;&lt;h3&gt;Test Your Membership Provider&lt;/h3&gt;&lt;p&gt;With all of this now in place, you should be able to use the &lt;span style="font-family: courier new"&gt;ASP.NET Website Administration Tool&lt;/span&gt; launched from Visual Studio to create a few new user accounts. I mentioned how to launch this utility earlier in this series with a post titled &lt;a href="http://murrayon.net/2009/01/aspnet-providers-getting-started.html"&gt;ASP.NET Providers - Getting Started&lt;/a&gt;. Then you can double-check your membership system is working by logging in with your newly created credentials. Also, you can now create a user account registration page (utilizing the &lt;span style="font-family: courier new"&gt;CreateUserWizard&lt;/span&gt; control) and a password retrieval/reset page (using the &lt;span style="font-family: courier new"&gt;PasswordRecovery&lt;/span&gt; control). All of the controls I have named throughout this post are highly skinable and configurable via numerous attributes and templates; they also contain flexible task workflows that you can override or plug into by registering to any of several event listeners.&lt;/p&gt;&lt;p&gt;One other thing that needs to be done if you want to enable the email notification capabilities is to set the SMTP settings in your &lt;font face="Courier New"&gt;Web.config&lt;/font&gt;.&amp;#160; Here is a snippet you would put right above the &lt;font face="Courier New"&gt;system.web&lt;/font&gt; node:&lt;/p&gt;&lt;div style="border-right: gray 1px solid; padding-right: 4px; border-top: gray 1px solid; padding-left: 4px; font-size: 8pt; padding-bottom: 4px; margin: 20px 0px 10px; border-left: gray 1px solid; width: 97.5%; cursor: text; max-height: 200px; line-height: 12pt; padding-top: 4px; border-bottom: gray 1px solid; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; background-color: #f4f4f4"&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;system.net&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;
    &lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;mailSettings&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;
        &lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;smtp&lt;/span&gt; &lt;span style="color: #ff0000"&gt;from&lt;/span&gt;&lt;span style="color: #0000ff"&gt;=&amp;quot;service@website.com&amp;quot;&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;
            &lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;network&lt;/span&gt; &lt;span style="color: #ff0000"&gt;host&lt;/span&gt;&lt;span style="color: #0000ff"&gt;=&amp;quot;mail.domain.com&amp;quot;&lt;/span&gt; &lt;span style="color: #ff0000"&gt;port&lt;/span&gt;&lt;span style="color: #0000ff"&gt;=&amp;quot;25&amp;quot;&lt;/span&gt;
                     &lt;span style="color: #ff0000"&gt;userName&lt;/span&gt;&lt;span style="color: #0000ff"&gt;=&amp;quot;...&amp;quot;&lt;/span&gt; &lt;span style="color: #ff0000"&gt;password&lt;/span&gt;&lt;span style="color: #0000ff"&gt;=&amp;quot;...&amp;quot;&lt;/span&gt; &lt;span style="color: #0000ff"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span style="color: #0000ff"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000"&gt;smtp&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;
    &lt;span style="color: #0000ff"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000"&gt;mailSettings&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;
&lt;span style="color: #0000ff"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000"&gt;system.net&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3&gt;Membership API and MembershipInfo Class&lt;/h3&gt;&lt;p&gt;There is also a &lt;span style="font-family: courier new"&gt;Membership&lt;/span&gt; API and an accompanying &lt;span style="font-family: courier new"&gt;MembershipInfo&lt;/span&gt; class that you can call in order to retrieve and update user info from the database if you wanted to create your own custom controls or page logic. For instance, the following is code that I adapted &lt;a title="Examining ASP.NET 2.0&amp;#39;s Membership, Roles, and Profile - Part 11" href="http://aspnet.4guysfromrolla.com/articles/062508-1.aspx"&gt;from Part 11 of the tutorial I mentioned earlier&lt;/a&gt; in the introductory post of this series; this code activates an account when a user clicks the link emailed to them during registration:&lt;/p&gt;&lt;div style="border-right: gray 1px solid; padding-right: 4px; border-top: gray 1px solid; padding-left: 4px; font-size: 8pt; padding-bottom: 4px; margin: 20px 0px 10px; border-left: gray 1px solid; width: 97.5%; cursor: text; max-height: 650px; line-height: 12pt; padding-top: 4px; border-bottom: gray 1px solid; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; background-color: #f4f4f4"&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;partial&lt;/span&gt; &lt;span style="color: #0000ff"&gt;class&lt;/span&gt; Verify : System.Web.UI.Page&lt;br /&gt;{&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;protected&lt;/span&gt; &lt;span style="color: #0000ff"&gt;void&lt;/span&gt; Page_Load(&lt;span style="color: #0000ff"&gt;object&lt;/span&gt; sender, EventArgs e)&lt;br /&gt;    {&lt;br /&gt;        &lt;span style="color: #008000"&gt;//Make sure valid querystring value was passed&lt;/span&gt;&lt;br /&gt;        &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (&lt;span style="color: #0000ff"&gt;string&lt;/span&gt;.IsNullOrEmpty(Request.QueryString[&lt;span style="color: #006080"&gt;&amp;quot;ID&amp;quot;&lt;/span&gt;]) ||&lt;br /&gt;            !Regex.IsMatch(Request.QueryString[&lt;span style="color: #006080"&gt;&amp;quot;ID&amp;quot;&lt;/span&gt;],&lt;br /&gt;                &lt;span style="color: #006080"&gt;@&amp;quot;[0-9a-f]{8}\-([0-9a-f]{4}\-){3}[0-9a-f]{12}&amp;quot;&lt;/span&gt;))&lt;br /&gt;        {&lt;br /&gt;            InformationLabel.Text = &lt;span style="color: #006080"&gt;&amp;quot;An invalid ID value was passed &amp;quot;&lt;/span&gt; +&lt;br /&gt;                &lt;span style="color: #006080"&gt;&amp;quot;in through the query string.&amp;quot;&lt;/span&gt;;&lt;br /&gt;        }&lt;br /&gt;        &lt;span style="color: #0000ff"&gt;else&lt;/span&gt;&lt;br /&gt;        {&lt;br /&gt;            &lt;span style="color: #008000"&gt;//ID exists and is kosher, approve user&lt;/span&gt;&lt;br /&gt;            &lt;span style="color: #008000"&gt;//Get the ID sent in on query string&lt;/span&gt;&lt;br /&gt;            Guid userId = &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; Guid(Request.QueryString[&lt;span style="color: #006080"&gt;&amp;quot;ID&amp;quot;&lt;/span&gt;]);&lt;br /&gt;&lt;br /&gt;            &lt;span style="color: #008000"&gt;//Get user object&lt;/span&gt;&lt;br /&gt;            MembershipUser userInfo = Membership.GetUser(userId);&lt;br /&gt;&lt;br /&gt;            &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (userInfo == &lt;span style="color: #0000ff"&gt;null&lt;/span&gt;)&lt;br /&gt;            {&lt;br /&gt;                &lt;span style="color: #008000"&gt;//Could not find user!&lt;/span&gt;&lt;br /&gt;                InformationLabel.Text = &lt;span style="color: #006080"&gt;&amp;quot;The user account could not &amp;quot;&lt;/span&gt; +&lt;br /&gt;                    &lt;span style="color: #006080"&gt;&amp;quot;be found in the membership database.&amp;quot;&lt;/span&gt;;&lt;br /&gt;            }&lt;br /&gt;            &lt;span style="color: #0000ff"&gt;else&lt;/span&gt;&lt;br /&gt;            {&lt;br /&gt;                &lt;span style="color: #008000"&gt;//User is valid, approve them&lt;/span&gt;&lt;br /&gt;                userInfo.IsApproved = &lt;span style="color: #0000ff"&gt;true&lt;/span&gt;;&lt;br /&gt;                Membership.UpdateUser(userInfo);&lt;br /&gt;&lt;br /&gt;                &lt;span style="color: #008000"&gt;//Display a message&lt;/span&gt;&lt;br /&gt;                InformationLabel.Text = &lt;span style="color: #006080"&gt;&amp;quot;Your account has been &amp;quot;&lt;/span&gt; +&lt;br /&gt;                    &lt;span style="color: #006080"&gt;&amp;quot;verified and you can now log into the site.&amp;quot;&lt;/span&gt;;&lt;br /&gt;            }&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;}&lt;/pre&gt;&lt;/div&gt;&lt;h3&gt;Read On!&lt;/h3&gt;&lt;p&gt;Continue onward by reading the next blog post in this series found at the following link:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="http://murrayon.net/2009/02/aspnet-providers-role-management.html"&gt;ASP.NET Providers - Role Management&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;
&lt;/span&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1664217632350055880-5687902183083831396?l=murrayon.net' alt='' /&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://murrayon.net/feeds/5687902183083831396/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://murrayon.net/2009/01/aspnet-providers-membership.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/1664217632350055880/posts/default/5687902183083831396?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/1664217632350055880/posts/default/5687902183083831396?v=2" /><link rel="alternate" type="text/html" href="http://murrayon.net/2009/01/aspnet-providers-membership.html" title="ASP.NET Providers - Membership" /><author><name>Mike Murray</name><uri>http://www.blogger.com/profile/01990150469958605173</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="15380857253844311568" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total></entry><entry gd:etag="W/&quot;DUUEQXg-fip7ImA9WxNVGE4.&quot;"><id>tag:blogger.com,1999:blog-1664217632350055880.post-8619883946092918827</id><published>2009-01-30T14:20:00.000-07:00</published><updated>2009-10-29T11:26:40.656-06:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-10-29T11:26:40.656-06:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Security" /><category scheme="http://www.blogger.com/atom/ns#" term="Encryption" /><category scheme="http://www.blogger.com/atom/ns#" term=".NET" /><category scheme="http://www.blogger.com/atom/ns#" term="ASP.NET Providers Series" /><category scheme="http://www.blogger.com/atom/ns#" term="ASP.NET" /><category scheme="http://www.blogger.com/atom/ns#" term="Database" /><category scheme="http://www.blogger.com/atom/ns#" term="Visual Studio" /><category scheme="http://www.blogger.com/atom/ns#" term="SQL" /><category scheme="http://www.blogger.com/atom/ns#" term="Microsoft" /><title>ASP.NET Providers - Getting Started</title><content type="html">&lt;p&gt;This blog post is part of a series about the ASP.NET Providers (namely Membership, Role Management, and Profile).&amp;#160; The introductory post in the series can be found at the following link, which introduces the &lt;a href="http://en.wikipedia.org/wiki/Provider_model" target="_blank"&gt;Provider Model pattern&lt;/a&gt; and gives a personal example of an implementation I have been working on:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;&lt;a href="http://murrayon.net/2009/01/aspnet-providers-membership-role-and.html"&gt;ASP.NET Providers - Membership, Role, and Profile&lt;/a&gt; &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;This post will deal with getting started using the ASP.NET Providers by setting up a database.&lt;/p&gt; &lt;span class='fullpost'&gt; &lt;h3&gt;Database Setup&lt;/h3&gt;  &lt;p&gt;First, you will need to configure a database to securely store all of the site's user data and activity info.&amp;#160; You'll most likely be content with the already provided SQL Providers (such as the &lt;font face="Courier New"&gt;SqlMembershipProvider&lt;/font&gt;&lt;font face="Verdan"&gt;), but Microsoft also provides you with other options in many cases.&amp;#160; For example in the case of Membership, &lt;/font&gt;you also have the option of having your site use the &lt;font face="Courier New"&gt;ActiveDirectoryMembershipProvider&lt;/font&gt; or you can even roll your own &lt;font face="Courier New"&gt;MembershipProvider&lt;/font&gt;.&amp;#160; The nice thing about using any of these Microsoft Providers is that they are already set up to store sensitive data like passwords in an encrypted format in the database.&lt;/p&gt;  &lt;p&gt;There are two tools you can use to automatically generate the necessary database tables needed for the SQL implementation.&amp;#160; The first tool is a web-based configuration tool launched from Visual Studio called the &lt;font face="Courier New"&gt;ASP.NET Website Administration Tool&lt;/font&gt;. It can not only create the database tables, but can also configure authorization rules, user roles, user accounts, and many other settings that go right into your &lt;font face="Courier New"&gt;Web.config&lt;/font&gt;.&amp;#160; It is launched by selecting the &lt;font face="Courier New"&gt;ASP.NET Configuration&lt;/font&gt; menu option in the &lt;font face="Courier New"&gt;Project&lt;/font&gt; menu (or &lt;font face="Courier New"&gt;Website&lt;/font&gt; menu, depending on which version of Visual Studio you have or the project template you selected).&amp;#160; However, this tool will create the database in a SQL Server file named &lt;font face="Courier New"&gt;ASPNETDB.mdf&lt;/font&gt; placed in the site's &lt;font face="Courier New"&gt;App_Data&lt;/font&gt; folder.&amp;#160; If you would prefer to create the database schema in an already existing install of SQL Server (likely on a different box), you need to use the &lt;font face="Courier New"&gt;aspnet_regsql.exe&lt;/font&gt; command-line tool.&amp;#160; The command-line tool's graphical interface can be launched by typing the name of the executable in a &lt;font face="Courier New"&gt;Visual Studio Command Prompt&lt;/font&gt; (located in the Start Menu under &lt;font face="Courier new"&gt;Visual Studio | Visual Studio Tools&lt;/font&gt;).&lt;/p&gt;  &lt;p&gt;The only other thing you need now is the connection string to this newly populated database.&amp;#160; I will show you where in your &lt;font face="Courier New"&gt;Web.config&lt;/font&gt; to put the connection string in the next post of this series.&lt;/p&gt;  &lt;h3&gt;Read On!&lt;/h3&gt;  &lt;p&gt;Continue onward by reading the next blog post in this series found at the following link:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;&lt;a href="http://murrayon.net/2009/01/aspnet-providers-membership.html"&gt;ASP.NET Providers - Membership&lt;/a&gt; &lt;/li&gt; &lt;/ul&gt; &lt;/span&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1664217632350055880-8619883946092918827?l=murrayon.net' alt='' /&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://murrayon.net/feeds/8619883946092918827/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://murrayon.net/2009/01/aspnet-providers-getting-started.html#comment-form" title="1 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/1664217632350055880/posts/default/8619883946092918827?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/1664217632350055880/posts/default/8619883946092918827?v=2" /><link rel="alternate" type="text/html" href="http://murrayon.net/2009/01/aspnet-providers-getting-started.html" title="ASP.NET Providers - Getting Started" /><author><name>Mike Murray</name><uri>http://www.blogger.com/profile/01990150469958605173</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="15380857253844311568" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">1</thr:total></entry><entry gd:etag="W/&quot;DE4HR3k_fCp7ImA9WxNVGE4.&quot;"><id>tag:blogger.com,1999:blog-1664217632350055880.post-2925799790519988941</id><published>2009-01-30T14:18:00.003-07:00</published><updated>2009-10-29T11:22:16.744-06:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-10-29T11:22:16.744-06:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Web" /><category scheme="http://www.blogger.com/atom/ns#" term="Security" /><category scheme="http://www.blogger.com/atom/ns#" term=".NET" /><category scheme="http://www.blogger.com/atom/ns#" term="IIS" /><category scheme="http://www.blogger.com/atom/ns#" term="ASP.NET Providers Series" /><category scheme="http://www.blogger.com/atom/ns#" term="ASP.NET" /><category scheme="http://www.blogger.com/atom/ns#" term="Windows" /><category scheme="http://www.blogger.com/atom/ns#" term="Visual Studio" /><category scheme="http://www.blogger.com/atom/ns#" term="Microsoft" /><title>ASP.NET Providers - Membership, Role, and Profile</title><content type="html">&lt;p&gt;Seems like any website you start nowadays involves creating the same common features we see all over the web.&amp;#160; These include creating user account functionality, storing profile information, implementing role-based access to content and features, instantiating SQL tables and data access repositories, and so on, so forth.&amp;#160; In most cases it would be a complete waste of time and money to roll your own implementation every time.&lt;/p&gt;  &lt;p&gt;There are plenty of frameworks out there that tackle this problem for you and abstract out details you shouldn't have to worry about.&amp;#160; If you are in the .NET world, there are a set of these services available to you that are baked right into the .NET 2.0 Framework.&amp;#160; I'm going to show you a personal example of how easy it is to add some of this functionality to an existing site, even one with an antique and cumbersome architecture.&amp;#160; Implementing these features using the ASP.NET 2.0 Provider Model on said architecture has convinced me that it couldn't be easier to add such functionality to a website, no matter what beast of a site you are dealing with.&lt;/p&gt; &lt;span class='fullpost'&gt; &lt;h3&gt;ASP.NET 2.0 Provider Model&lt;/h3&gt; &lt;p&gt;With the advent of ASP.NET 2.0, Microsoft introduced a set of configuration-driven services that adhere to the &lt;a href="http://en.wikipedia.org/wiki/Provider_model"&gt;Provider Model pattern&lt;/a&gt;.&amp;#160; These services focus on storing application state of a website using a very flexible and extensible data access strategy.&amp;#160; The available features that can be added to your website include Membership (which includes authentication and authorization), Role Management, Profile, Session State, Web Parts Personalization, and Site Map navigation.&amp;#160; The whole idea is to be able to secure and enhance an existing site by dropping in a few lines into the &lt;font face="Courier New"&gt;Web.config&lt;/font&gt;, using a Microsoft utility to automatically create database tables (most likely your chosen storage medium), and then dropping, configuring, and skinning a few controls into your existing pages.&amp;#160; To read a more thorough introduction to the Provider Model and these ASP.NET 2.0 Provider services (including a few helpful diagrams), check out the following link:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;&lt;a href="http://msdn.microsoft.com/en-us/library/aa479030.aspx"&gt;ASP.NET 2.0 Provider Model: Introduction to the Provider Model&lt;/a&gt; &lt;/li&gt; &lt;/ul&gt;  &lt;h3&gt;Personal Example&lt;/h3&gt;  &lt;p&gt;We currently maintain a series of desktop products that we have been entrusted with.&amp;#160; Under the covers, these &amp;quot;desktop&amp;quot; products were originally written in Java as locally-hosted websites using Apache's web server.&amp;#160; In order to be compatible with Windows Vista, we have since ported these products to .NET 2.0 and currently use &lt;a href="http://www.ultidev.com/products/Cassini/index.htm"&gt;UltiDev's free, light-weight, and redistributable web server named Cassini&lt;/a&gt; (essentially the same thing as the development web server found in Visual Studio and a great alternative to &lt;a title="Internet Information Services" href="http://en.wikipedia.org/wiki/Internet_Information_Services"&gt;IIS&lt;/a&gt;).&amp;#160; Many of the features are implemented in JavaScript and the content is almost entirely static HTML pages.&amp;#160; There were only a few Java Servlets that we ported to .NET HTTP Handlers and any database storage has been done using Microsoft Access databases.&amp;#160; This set of products also has other interaction requirements like the ability to view content from another product while staying in the context of the currently open product.&amp;#160; Finally, the installers for a few of these desktop products are getting to be nearly 600 MB in size, which has perpetuated the need for distributing the products to the users offline.&lt;/p&gt;  &lt;p&gt;We are in the process right now of exploring the cost benefits and customer experience improvements in moving this set of offerings to an online suite of websites.&amp;#160; The first step we are taking is to build an online version of one of the products where users can obtain a user account to view the content.&amp;#160; Building new applications is one thing, but upgrading and maintaining existing applications (especially ones you have inherited) is a whole different development experience.&amp;#160; This is where my appreciation for the ease and flexibility of what Microsoft is offering comes into play.&lt;/p&gt;  &lt;h3&gt;Read On!&lt;/h3&gt;  &lt;p&gt;The rest of the blog posts in this series can be found at the following links:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;&lt;a href="http://murrayon.net/2009/01/aspnet-providers-getting-started.html"&gt;ASP.NET Providers - Getting Started&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href="http://murrayon.net/2009/01/aspnet-providers-membership.html"&gt;ASP.NET Providers - Membership&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href="http://murrayon.net/2009/02/aspnet-providers-role-management.html"&gt;ASP.NET Providers - Role Management&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href="http://murrayon.net/2009/02/aspnet-providers-profile.html"&gt;ASP.NET Providers - Profile&lt;/a&gt; &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;In addition, I came across an issue when using the Profile system with the &lt;font face="Courier New"&gt;Web Application&lt;/font&gt; project template instead of the &lt;font face="Courier New"&gt;Web Site&lt;/font&gt; project template as found in Visual Studio's default set of project templates.&amp;#160; It has to do with the &lt;font face="Courier New"&gt;Profile&lt;/font&gt; proxy class object not being auto-generated by Visual Studio when using the &lt;font face="Courier New"&gt;Web Application&lt;/font&gt; project template.&amp;#160; Read the following blog post for a discussion of the problem and it's solution:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;&lt;a href="http://murrayon.net/2009/02/aspnet-profile-and-web-application.html"&gt;ASP.NET Profile and Web Application Projects&lt;/a&gt; &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;Also, I have another post discussing the advantages of using the ASP.NET Provider system under IIS 7 found in Windows Vista and Server 2008; it will also include some issues with using this system if some of your content is static HTML instead of ASPX pages.&amp;#160; You can find all of this goodness by following the link below:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;&lt;a href="http://murrayon.net/2009/02/iis-7-and-aspnet-providers-membership.html"&gt;IIS 7 and ASP.NET Providers (Membership, Roles, and Profile)&lt;/a&gt; &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;Finally, I based my implementation on a 13-part tutorial series by &lt;a href="http://www.4guysfromrolla.com/ScottMitchell.shtml"&gt;Scott Mitchell&lt;/a&gt; on &lt;a href="http://www.4guysfromrolla.com/"&gt;4GuysFromRolla.com&lt;/a&gt;, starting at this link:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;&lt;a href="http://aspnet.4guysfromrolla.com/articles/120705-1.aspx"&gt;Examining ASP.NET 2.0's Membership, Roles, and Profile - Part 1&lt;/a&gt; &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;Enjoy!&lt;/p&gt; &lt;/span&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1664217632350055880-2925799790519988941?l=murrayon.net' alt='' /&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://murrayon.net/feeds/2925799790519988941/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://murrayon.net/2009/01/aspnet-providers-membership-role-and.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/1664217632350055880/posts/default/2925799790519988941?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/1664217632350055880/posts/default/2925799790519988941?v=2" /><link rel="alternate" type="text/html" href="http://murrayon.net/2009/01/aspnet-providers-membership-role-and.html" title="ASP.NET Providers - Membership, Role, and Profile" /><author><name>Mike Murray</name><uri>http://www.blogger.com/profile/01990150469958605173</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="15380857253844311568" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total></entry><entry gd:etag="W/&quot;CkIMSXozfyp7ImA9WxVaGU0.&quot;"><id>tag:blogger.com,1999:blog-1664217632350055880.post-1304226192776498442</id><published>2008-12-16T11:48:00.001-07:00</published><updated>2009-04-16T10:49:48.487-06:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-04-16T10:49:48.487-06:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Personal" /><category scheme="http://www.blogger.com/atom/ns#" term="Humor" /><title>If Programming Languages Were Religions...</title><content type="html">&lt;p&gt;This is hilarious and really creative:&lt;/p&gt;  &lt;p&gt;&lt;a title="http://www.aegisub.net/2008/12/if-programming-languages-were-religions.html" href="http://www.aegisub.net/2008/12/if-programming-languages-were-religions.html"&gt;http://www.aegisub.net/2008/12/if-programming-languages-were-religions.html&lt;/a&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1664217632350055880-1304226192776498442?l=murrayon.net' alt='' /&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://murrayon.net/feeds/1304226192776498442/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://murrayon.net/2008/12/if-programming-languages-were-religions.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/1664217632350055880/posts/default/1304226192776498442?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/1664217632350055880/posts/default/1304226192776498442?v=2" /><link rel="alternate" type="text/html" href="http://murrayon.net/2008/12/if-programming-languages-were-religions.html" title="If Programming Languages Were Religions..." /><author><name>Mike Murray</name><uri>http://www.blogger.com/profile/01990150469958605173</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="15380857253844311568" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total></entry><entry gd:etag="W/&quot;Dk4MSHk9cCp7ImA9WxRbFE4.&quot;"><id>tag:blogger.com,1999:blog-1664217632350055880.post-8306371346213631939</id><published>2008-12-04T16:54:00.000-07:00</published><updated>2008-12-04T16:56:29.768-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2008-12-04T16:56:29.768-07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="New Technology" /><category scheme="http://www.blogger.com/atom/ns#" term="BizTalk" /><category scheme="http://www.blogger.com/atom/ns#" term=".NET" /><category scheme="http://www.blogger.com/atom/ns#" term="Microsoft" /><title>Which BAM is which?</title><content type="html">&lt;p&gt;I just watched a presentation that I thought would be about &lt;a title="BizTalk BAM" href="http://aspalliance.com/840_Business_Activity_Monitoring_BAM_with_BizTalk_Server_2006_from_Start_to_Finish"&gt;BAM (Business Activity Monitoring)&lt;/a&gt; from &lt;a href="http://www.microsoft.com/biztalk/en/us/default.aspx"&gt;BizTalk&lt;/a&gt;, but instead it was &lt;a title="Microsoft Research BAM" href="http://research.microsoft.com/~ejackson/bam.aspx"&gt;some new project that Microsoft Research cooked up that helps model cloud computing&lt;/a&gt;.&amp;#160; Interesting nonetheless, but not the BAM I thought I was getting.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1664217632350055880-8306371346213631939?l=murrayon.net' alt='' /&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://murrayon.net/feeds/8306371346213631939/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://murrayon.net/2008/12/which-bam-is-which.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/1664217632350055880/posts/default/8306371346213631939?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/1664217632350055880/posts/default/8306371346213631939?v=2" /><link rel="alternate" type="text/html" href="http://murrayon.net/2008/12/which-bam-is-which.html" title="Which BAM is which?" /><author><name>Mike Murray</name><uri>http://www.blogger.com/profile/01990150469958605173</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="15380857253844311568" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total></entry><entry gd:etag="W/&quot;CUIMSHYzcCp7ImA9WxNVF0o.&quot;"><id>tag:blogger.com,1999:blog-1664217632350055880.post-9213453600823522691</id><published>2008-12-01T17:13:00.000-07:00</published><updated>2009-10-28T17:46:29.888-06:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-10-28T17:46:29.888-06:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Error" /><category scheme="http://www.blogger.com/atom/ns#" term=".NET" /><category scheme="http://www.blogger.com/atom/ns#" term="Microsoft" /><category scheme="http://www.blogger.com/atom/ns#" term="Code Organization" /><category scheme="http://www.blogger.com/atom/ns#" term="Algorithms" /><title>Correctly Using Random Number Generators</title><content type="html">&lt;p&gt;Today I read another guy's blog post that reminded me of my own &amp;quot;Aha!&amp;quot; moment I had a while back with Random Number Generators.&amp;#160; It's something I will never forget about Random Number Generators but taken for granted, realizing that it might not be obvious to everyone how these objects are intended to be used.&amp;#160; Here is the blog entry that I read about creating and seeding a Random Number Generator once:&lt;/p&gt;  &lt;p&gt;&lt;a title="http://silverlight.net/blogs/msnow/archive/2008/12/01/silverlight-tip-of-the-day-77-creating-an-efficient-random-generator.aspx" href="http://silverlight.net/blogs/msnow/archive/2008/12/01/silverlight-tip-of-the-day-77-creating-an-efficient-random-generator.aspx"&gt;http://silverlight.net/blogs/msnow/archive/2008/12/01/silverlight-tip-of-the-day-77-creating-an-efficient-random-generator.aspx&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;However, I must admit that I think &lt;a title="Mike Snow" href="http://silverlight.net/blogs/msnow/about.aspx"&gt;Mike Snow&lt;/a&gt; should have titled his post something similar to the title of my post.&amp;#160; And I will tell you why...&lt;/p&gt; &lt;span class='fullpost'&gt; &lt;p&gt;In the MSDN documentation that Mike quotes, there is a key sentence everyone needs to take note of, as you can ignorantly introduce bugs into your code:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;&amp;quot;As a result, different Random objects that are created in close succession by a call to the default constructor will have identical default seed values and, therefore, will produce identical sets of random numbers.&amp;quot;&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;I have actually build a piece of code where this has happened.&amp;#160; I wrote a &lt;font face="Courier New"&gt;for&lt;/font&gt; loop that iterated quickly enough that the construction of the &lt;font face="Courier New"&gt;Random&lt;/font&gt; objects resulted in identical random number seeds.&amp;#160; The result was that I asked for several random numbers in quick succession and got the same exact &amp;quot;random&amp;quot; number across all my requests each time I ran the code.&amp;#160; So not only did I get &amp;quot;identical sets of random numbers,&amp;quot; but I got identical random numbers.&lt;/p&gt;  &lt;p&gt;As Mike Snow and the MSDN documentation states (and from my own experience), Random Number Generators are designed to be constructed once and intended to live long and prosper within your application.&amp;#160; It can serve &lt;u&gt;all&lt;/u&gt; of the random number needs within your application (i.e., you don't need a different Random Number Generator for different use cases or different object types).&amp;#160; All you need is a one-time created random number seed and then you can forever generate random numbers of any type and within any range of numbers.&amp;#160; I can't currently think of a situation when you may need to reseed your Random Number Generator.&amp;#160; Let me know if you think of one.&lt;/p&gt; &lt;/span&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1664217632350055880-9213453600823522691?l=murrayon.net' alt='' /&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://murrayon.net/feeds/9213453600823522691/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://murrayon.net/2008/12/correctly-using-random-number.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/1664217632350055880/posts/default/9213453600823522691?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/1664217632350055880/posts/default/9213453600823522691?v=2" /><link rel="alternate" type="text/html" href="http://murrayon.net/2008/12/correctly-using-random-number.html" title="Correctly Using Random Number Generators" /><author><name>Mike Murray</name><uri>http://www.blogger.com/profile/01990150469958605173</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="15380857253844311568" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total></entry><entry gd:etag="W/&quot;CEADRnY6eip7ImA9WxRWF0k.&quot;"><id>tag:blogger.com,1999:blog-1664217632350055880.post-8445030447281933556</id><published>2008-11-03T13:00:00.000-07:00</published><updated>2008-11-03T13:06:17.812-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2008-11-03T13:06:17.812-07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="New Technology" /><category scheme="http://www.blogger.com/atom/ns#" term=".NET" /><category scheme="http://www.blogger.com/atom/ns#" term="Visual Studio" /><category scheme="http://www.blogger.com/atom/ns#" term="Entity Framework" /><category scheme="http://www.blogger.com/atom/ns#" term="Microsoft" /><category scheme="http://www.blogger.com/atom/ns#" term="LINQ" /><title>Is LINQ to SQL Being Replaced Already?</title><content type="html">&lt;p&gt;The short answer is &amp;quot;kind of&amp;quot;; the push is for the &lt;a href="http://en.wikipedia.org/wiki/ADO.NET_Entity_Framework"&gt;ADO.NET Entity Framework&lt;/a&gt; to be the encouraged ORM approach from now on.&amp;#160; For the long-winded, thorough explanation of this answer (based on blog posts from Microsoft employees and managers), see the following blog post that someone pointed me toward:&lt;/p&gt;  &lt;p&gt;&lt;a title="http://www.infoq.com/news/2008/11/DLINQ-Future" href="http://www.infoq.com/news/2008/11/DLINQ-Future"&gt;http://www.infoq.com/news/2008/11/DLINQ-Future&lt;/a&gt;&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1664217632350055880-8445030447281933556?l=murrayon.net' alt='' /&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://murrayon.net/feeds/8445030447281933556/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://murrayon.net/2008/11/is-linq-to-sql-being-replaced-already.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/1664217632350055880/posts/default/8445030447281933556?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/1664217632350055880/posts/default/8445030447281933556?v=2" /><link rel="alternate" type="text/html" href="http://murrayon.net/2008/11/is-linq-to-sql-being-replaced-already.html" title="Is LINQ to SQL Being Replaced Already?" /><author><name>Mike Murray</name><uri>http://www.blogger.com/profile/01990150469958605173</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="15380857253844311568" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total></entry></feed>
