<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-2143318148319291738</id><updated>2012-02-16T21:41:43.088-05:00</updated><title type='text'>Hamlet Code</title><subtitle type='html'></subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://hamletcode.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2143318148319291738/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://hamletcode.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Jay Allard</name><uri>http://www.blogger.com/profile/15785084867572890025</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>61</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-2143318148319291738.post-1467215758683802221</id><published>2009-09-06T10:03:00.001-04:00</published><updated>2009-09-06T10:04:21.275-04:00</updated><title type='text'>NO MORE BLOGGER</title><content type='html'>Greetings&lt;br /&gt;&lt;br /&gt;I am now using WORDPRESS for my hamletcode blogging activity.&lt;br /&gt;&lt;br /&gt;Both of you, please update you RSS READERS to&lt;br /&gt;&lt;br /&gt;&lt;a href="http://hamletcode.wordpress.com/"&gt;http://hamletcode.wordpress.com&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Thank you!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2143318148319291738-1467215758683802221?l=hamletcode.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://hamletcode.blogspot.com/feeds/1467215758683802221/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2143318148319291738&amp;postID=1467215758683802221' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2143318148319291738/posts/default/1467215758683802221'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2143318148319291738/posts/default/1467215758683802221'/><link rel='alternate' type='text/html' href='http://hamletcode.blogspot.com/2009/09/no-more-blogger.html' title='NO MORE BLOGGER'/><author><name>Jay Allard</name><uri>http://www.blogger.com/profile/15785084867572890025</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2143318148319291738.post-6234075609217072246</id><published>2009-09-06T00:46:00.001-04:00</published><updated>2009-09-06T00:48:20.903-04:00</updated><title type='text'>Code Test</title><content type='html'>&lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;I’m switching to Wordpress.&lt;/p&gt;  &lt;p&gt;Trying a code sample….&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;div id="codeSnippetWrapper"&gt;   &lt;div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"&gt;     &lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum1"&gt;   1:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;namespace&lt;/span&gt; YaddaYadda&lt;/pre&gt;&lt;br /&gt;&lt;!--CRLF--&gt;&lt;br /&gt;&lt;br /&gt;    &lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum2"&gt;   2:&lt;/span&gt; {&lt;/pre&gt;&lt;br /&gt;&lt;!--CRLF--&gt;&lt;br /&gt;&lt;br /&gt;    &lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum3"&gt;   3:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;class&lt;/span&gt; Whatever&lt;/pre&gt;&lt;br /&gt;&lt;!--CRLF--&gt;&lt;br /&gt;&lt;br /&gt;    &lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum4"&gt;   4:&lt;/span&gt;     {&lt;/pre&gt;&lt;br /&gt;&lt;!--CRLF--&gt;&lt;br /&gt;&lt;br /&gt;    &lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum5"&gt;   5:&lt;/span&gt;         &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;void&lt;/span&gt; DoSomething()&lt;/pre&gt;&lt;br /&gt;&lt;!--CRLF--&gt;&lt;br /&gt;&lt;br /&gt;    &lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum6"&gt;   6:&lt;/span&gt;         {&lt;/pre&gt;&lt;br /&gt;&lt;!--CRLF--&gt;&lt;br /&gt;&lt;br /&gt;    &lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum7"&gt;   7:&lt;/span&gt;         }&lt;/pre&gt;&lt;br /&gt;&lt;!--CRLF--&gt;&lt;br /&gt;&lt;br /&gt;    &lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum8"&gt;   8:&lt;/span&gt;     }&lt;/pre&gt;&lt;br /&gt;&lt;!--CRLF--&gt;&lt;br /&gt;&lt;br /&gt;    &lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum9"&gt;   9:&lt;/span&gt; }&lt;/pre&gt;&lt;br /&gt;&lt;!--CRLF--&gt;&lt;/div&gt;&lt;br /&gt;&lt;/div&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2143318148319291738-6234075609217072246?l=hamletcode.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://hamletcode.blogspot.com/feeds/6234075609217072246/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2143318148319291738&amp;postID=6234075609217072246' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2143318148319291738/posts/default/6234075609217072246'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2143318148319291738/posts/default/6234075609217072246'/><link rel='alternate' type='text/html' href='http://hamletcode.blogspot.com/2009/09/code-test.html' title='Code Test'/><author><name>Jay Allard</name><uri>http://www.blogger.com/profile/15785084867572890025</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2143318148319291738.post-5550870595881092887</id><published>2009-09-02T23:09:00.001-04:00</published><updated>2009-09-02T23:09:47.171-04:00</updated><title type='text'>So what’s the deal with the thread blocking in vs2010/.net4?</title><content type='html'>&lt;p&gt;This was weird. I didn’t say anything in last night’s post because I wanted to make sure I wasn’t insane. I’m pretty sure I’m not.&lt;/p&gt;  &lt;p&gt;Anyhoo, I created a stupid little windows form application to host my Wcf Service and to also to create a client.&lt;/p&gt;  &lt;p&gt;The PAGE_LOAD calls a StartServer() method, which creates the service host.&lt;/p&gt;  &lt;p&gt;The form has a TEST button that creates a WCF client to the same service.&lt;/p&gt;  &lt;p&gt;That’s all pretty common stuff; start a server, create a client. But, the client kept reporting a Wcf timeout after 1 minute. I was able to connect to the service from another process, but not from within the windows form. It seemed like maybe a threading issue.&lt;/p&gt;  &lt;p&gt;So, I changed the client to run in another thread, and it worked. Why’s that?&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2143318148319291738-5550870595881092887?l=hamletcode.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://hamletcode.blogspot.com/feeds/5550870595881092887/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2143318148319291738&amp;postID=5550870595881092887' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2143318148319291738/posts/default/5550870595881092887'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2143318148319291738/posts/default/5550870595881092887'/><link rel='alternate' type='text/html' href='http://hamletcode.blogspot.com/2009/09/so-whats-deal-with-thread-blocking-in.html' title='So what’s the deal with the thread blocking in vs2010/.net4?'/><author><name>Jay Allard</name><uri>http://www.blogger.com/profile/15785084867572890025</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2143318148319291738.post-8615409576369128109</id><published>2009-09-02T00:17:00.001-04:00</published><updated>2009-09-02T10:31:42.039-04:00</updated><title type='text'>Injecting into a Wcf Service</title><content type='html'>&lt;h1&gt;&amp;#160;&lt;/h1&gt;  &lt;p&gt;&lt;strong&gt;Update 9/2/2009:&lt;/strong&gt; I forgot to include the service contract. Added it.&lt;/p&gt;  &lt;h1&gt;Overview&lt;/h1&gt;  &lt;p&gt;When you setup a Service Host, WCF manages the creation of your services. It requires there to be a default constructor so that it can just instantiate the thing and be done with it.&lt;/p&gt;  &lt;p&gt;I often find myself wishing to be able to pass something into the object when its created. For example: a unity container. I’d like to inject the unity container.&lt;/p&gt;  &lt;p&gt;Lacking that ability, we end up with a static container somewhere that the service calls.&lt;/p&gt;  &lt;pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;&lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;class&lt;/span&gt; TestService : ITestService&lt;br /&gt;&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;{&lt;br /&gt;&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;    &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;void&lt;/span&gt; DoSomething() &lt;br /&gt;&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;    {&lt;br /&gt;&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;        IWhatever whatever = StaticHelper.Container.Resolve&amp;lt;IWhatever&amp;gt;();&lt;br /&gt;&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;    }&lt;br /&gt;&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;&lt;/pre&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;What’s wrong with that? Statics are evil. Whenever you use a static, there should be a big red flag. Sure, its convenient, but its not very testable or flexible.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Sometime we can somewhat counter the testability limitation as follows&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;&lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;class&lt;/span&gt; TestService : ITestService&lt;br /&gt;&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;{&lt;br /&gt;&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;    &lt;span style="color: #0000ff"&gt;private&lt;/span&gt; &lt;span style="color: #0000ff"&gt;readonly&lt;/span&gt; IUnityContainer _unityContainer;&lt;br /&gt;&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;    &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; TestService() &lt;br /&gt;&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;    {&lt;br /&gt;&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;        &lt;span style="color: #008000"&gt;// wcf will use this constructor&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;        _unityContainer = StaticHelper.Container;&lt;br /&gt;&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;    }&lt;br /&gt;&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;    &lt;span style="color: #008000"&gt;// tests use this constructor&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;    &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; TestService(IUnityContainer container) &lt;br /&gt;&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;    {&lt;br /&gt;&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;        _unityContainer = container;&lt;br /&gt;&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;    }  &lt;br /&gt;&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;    &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;void&lt;/span&gt; DoSomething() &lt;br /&gt;&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;    {&lt;br /&gt;&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;        IWhatever whatever = _unityContainer.Resolve&amp;lt;IWhatever&amp;gt;();&lt;br /&gt;&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;    }&lt;br /&gt;&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;&lt;/pre&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;That works, but still smells kind of funny.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Tonight’s adventure was to figure out how to pass a unity container to the test service when instantiated. I didn’t really know where to start on this, so started at the ServiceHost, and googled the night away.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;There are a bunch of examples out there to use unity to determine the implementation type of the service. Two examples that I looked at rely on a static IOC container in order to determine the implementation type. In those cases, the statics can be easily eliminated just by passing the container through the layers as I do here. (Their goal’s were different. My goal is to get rid of the statics.)&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;&lt;strong&gt;UPDATE: &lt;/strong&gt;Now that I’ve gotten it all to work, and I’ve spent some time thinking about the conclusion, the fore mentioned approach is the best way. Rather than pulling objects from unity and assign it to properties, just define the service itself in the container. Then unity can handle all of the injection. I had to write this blog to come to that conclusion, so I’m not going to throw it all away. &lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Basic Steps&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;ol&gt;&lt;br /&gt;  &lt;br /&gt;&lt;br /&gt;&lt;br /&gt;  &lt;li&gt;Create a service host &lt;br /&gt;    &lt;br /&gt;&lt;br /&gt;&lt;br /&gt;    &lt;br /&gt;&lt;/li&gt;&lt;br /&gt;&lt;br /&gt;  &lt;li&gt;Create a behavior &lt;br /&gt;    &lt;br /&gt;&lt;br /&gt;&lt;br /&gt;    &lt;br /&gt;&lt;/li&gt;&lt;br /&gt;&lt;br /&gt;  &lt;li&gt;Create an instance provider – this is what we’re really interested in. This creates the service object. We need to get the IUnityContainer to this guy. &lt;br /&gt;    &lt;br /&gt;&lt;br /&gt;&lt;br /&gt;    &lt;br /&gt;&lt;/li&gt;&lt;br /&gt;&lt;br /&gt;  &lt;li&gt;Connect the host to the behavior &lt;br /&gt;    &lt;br /&gt;&lt;br /&gt;&lt;br /&gt;    &lt;br /&gt;&lt;/li&gt;&lt;br /&gt;&lt;br /&gt;  &lt;li&gt;Connect the behavior to the instance provider &lt;br /&gt;    &lt;br /&gt;&lt;/li&gt;&lt;br /&gt;&lt;/ol&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;I created a subclass of ServiceHost and added an IUnityContainer parameter to both of the constructors. The parameter value is saved to a local variable.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;The service behavior has no knowledge of the IUnityContainer. It just gives us the bridge between the instance provider.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;The instance provider has access to the service host. As you may recall, the service host has the IUnityContainer property. If the service object (implementation) has a IUnityContainer property, then we assign it.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;h1&gt;The Code&lt;/h1&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;&lt;strong&gt;DISCLAIMER:&lt;/strong&gt; This code is just enough to get it to work. Its not tied up nice and neat.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;An Interface for Services that require an IUnityContainer&lt;/h2&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;The instance provider, way down at the bottom, will see if the service implements this interface. If so, it assigns the property.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;&lt;span style="color: #0000ff"&gt;namespace&lt;/span&gt; AllardWorks.AwBus.Contracts&lt;br /&gt;&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;{&lt;br /&gt;&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;    &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;interface&lt;/span&gt; IUnityWcfService&lt;br /&gt;&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;    {&lt;br /&gt;&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;        IUnityContainer UnityContainer { &lt;span style="color: #0000ff"&gt;get&lt;/span&gt;; &lt;span style="color: #0000ff"&gt;set&lt;/span&gt;; }&lt;br /&gt;&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;    }&lt;br /&gt;&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;&lt;/pre&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;The Service Host&lt;/h2&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;    &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;class&lt;/span&gt; AwBusServiceHost : ServiceHost&lt;br /&gt;&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;    {&lt;br /&gt;&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;        &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; AwBusServiceHost(IUnityContainer container)&lt;br /&gt;&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;            : &lt;span style="color: #0000ff"&gt;base&lt;/span&gt;()&lt;br /&gt;&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;        {&lt;br /&gt;&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;            _container = container;&lt;br /&gt;&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;        }&lt;br /&gt;&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;        &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; AwBusServiceHost(IUnityContainer container, Type serviceType, &lt;span style="color: #0000ff"&gt;params&lt;/span&gt; Uri[] baseAddresses)&lt;br /&gt;&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;            : &lt;span style="color: #0000ff"&gt;base&lt;/span&gt;(serviceType, baseAddresses)&lt;br /&gt;&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;        {&lt;br /&gt;&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;            _container = container;&lt;br /&gt;&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;        }&lt;br /&gt;&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;        &lt;span style="color: #0000ff"&gt;protected&lt;/span&gt; &lt;span style="color: #0000ff"&gt;override&lt;/span&gt; &lt;span style="color: #0000ff"&gt;void&lt;/span&gt; OnOpening()&lt;br /&gt;&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;        {&lt;br /&gt;&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;            Description.Behaviors.Add(&lt;span style="color: #0000ff"&gt;new&lt;/span&gt; AwBusServiceBehavior());&lt;br /&gt;&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;            &lt;span style="color: #0000ff"&gt;base&lt;/span&gt;.OnOpening();&lt;br /&gt;&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;        }&lt;br /&gt;&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;        &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;readonly&lt;/span&gt; IUnityContainer _container;&lt;br /&gt;&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;        &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; IUnityContainer UnityContainer&lt;br /&gt;&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;        {&lt;br /&gt;&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;            &lt;span style="color: #0000ff"&gt;get&lt;/span&gt; { &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; _container; }&lt;br /&gt;&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;        }&lt;br /&gt;&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;    }&lt;br /&gt;&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;&lt;/pre&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;The Behavior&lt;/h2&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;We’re only interested in the ApplyDispatchBehavior method.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;This loops through all of the endpoint dispatchers and sets the instance provider to one of our own design. We pass it the type that is to be instantiated.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;    &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;class&lt;/span&gt; AwBusServiceBehavior : IServiceBehavior&lt;br /&gt;&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;    {&lt;br /&gt;&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;        &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;void&lt;/span&gt; ApplyDispatchBehavior(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)&lt;br /&gt;&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;        {&lt;br /&gt;&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;            &lt;span style="color: #0000ff"&gt;foreach&lt;/span&gt; (ChannelDispatcherBase cdb &lt;span style="color: #0000ff"&gt;in&lt;/span&gt; serviceHostBase.ChannelDispatchers)&lt;br /&gt;&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;            {&lt;br /&gt;&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;                ChannelDispatcher cd = cdb &lt;span style="color: #0000ff"&gt;as&lt;/span&gt; ChannelDispatcher;&lt;br /&gt;&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;                &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (cd == &lt;span style="color: #0000ff"&gt;null&lt;/span&gt;)&lt;br /&gt;&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;                {&lt;br /&gt;&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;                    &lt;span style="color: #0000ff"&gt;continue&lt;/span&gt;;&lt;br /&gt;&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;                }&lt;br /&gt;&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;                &lt;span style="color: #0000ff"&gt;foreach&lt;/span&gt; (EndpointDispatcher ed &lt;span style="color: #0000ff"&gt;in&lt;/span&gt; cd.Endpoints)&lt;br /&gt;&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;                {&lt;br /&gt;&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;                    ed.DispatchRuntime.InstanceProvider = &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; AwBusInstanceProvider(serviceDescription.ServiceType);&lt;br /&gt;&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;                }&lt;br /&gt;&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;            }&lt;br /&gt;&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;        }&lt;br /&gt;&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;        #region Not Used&lt;br /&gt;&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;        &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;void&lt;/span&gt; Validate(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)&lt;br /&gt;&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;        {&lt;br /&gt;&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;        }&lt;br /&gt;&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;        &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;void&lt;/span&gt; AddBindingParameters(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase, System.Collections.ObjectModel.Collection&amp;lt;ServiceEndpoint&amp;gt; endpoints, System.ServiceModel.Channels.BindingParameterCollection bindingParameters)&lt;br /&gt;&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;        {&lt;br /&gt;&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;        }&lt;br /&gt;&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;        #endregion&lt;br /&gt;&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;    }&lt;br /&gt;&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;&lt;/pre&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;The Instance Provider&lt;/h2&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;At last, we get to create an object. Yay.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;The interesting part here is the IUnityWcfService. If the new object implements that interface, then we set the UnityContainer property that the interface provides.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;    &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;class&lt;/span&gt; AwBusInstanceProvider : IInstanceProvider&lt;br /&gt;&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;    {&lt;br /&gt;&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;        &lt;span style="color: #0000ff"&gt;private&lt;/span&gt; &lt;span style="color: #0000ff"&gt;readonly&lt;/span&gt; Type _type;&lt;br /&gt;&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;        &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; AwBusInstanceProvider(Type type)&lt;br /&gt;&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;        {&lt;br /&gt;&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;            _type = type;&lt;br /&gt;&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;        }&lt;br /&gt;&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;        &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;object&lt;/span&gt; GetInstance(InstanceContext instanceContext)&lt;br /&gt;&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;        {&lt;br /&gt;&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;            &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; GetInstance(instanceContext, &lt;span style="color: #0000ff"&gt;null&lt;/span&gt;);&lt;br /&gt;&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;        }&lt;br /&gt;&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;        &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;object&lt;/span&gt; GetInstance(InstanceContext instanceContext, System.ServiceModel.Channels.Message message)&lt;br /&gt;&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;        {&lt;br /&gt;&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;            &lt;span style="color: #0000ff"&gt;object&lt;/span&gt; service = Activator.CreateInstance(_type);&lt;br /&gt;&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;            IUnityWcfService unityService = service &lt;span style="color: #0000ff"&gt;as&lt;/span&gt; IUnityWcfService;&lt;br /&gt;&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;            &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (unityService != &lt;span style="color: #0000ff"&gt;null&lt;/span&gt;)&lt;br /&gt;&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;            {&lt;br /&gt;&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;                unityService.UnityContainer = ((AwBusServiceHost)instanceContext.Host).UnityContainer;&lt;br /&gt;&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;            }&lt;br /&gt;&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;            &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; service;&lt;br /&gt;&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;        }&lt;br /&gt;&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;        &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;void&lt;/span&gt; ReleaseInstance(InstanceContext instanceContext, &lt;span style="color: #0000ff"&gt;object&lt;/span&gt; instance)&lt;br /&gt;&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;        {&lt;br /&gt;&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;        }&lt;br /&gt;&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;    }&lt;br /&gt;&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;&lt;/pre&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;h1&gt;Take it for a Test Drive&lt;/h1&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;A Test Service. (Hand coded on the spot. Should be mostly correct though)&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;[ServiceContract]&lt;br /&gt;  &lt;br /&gt;public interface IDoSomething&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;{&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;br /&gt;  &lt;p&gt;[OperationContract]&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;  &lt;p&gt;bool HasContainer();&lt;/p&gt;&lt;br /&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;}&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;&amp;#160;&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;public class DoSomething : IDoSomething, IUnityWcfService{&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;br /&gt;  &lt;p&gt;public IUnityContainer UnityContainer { get; set; }&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;  &lt;p&gt;public bool HasContainer()&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;  &lt;p&gt;{&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;  &lt;p&gt;return UnityContainer != null;&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;  &lt;p&gt;}&lt;/p&gt;&lt;br /&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;}&lt;br /&gt;  &lt;br /&gt;&lt;br /&gt;&lt;br /&gt;  &lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;The Server&lt;/h2&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;        &lt;span style="color: #0000ff"&gt;private&lt;/span&gt; IUnityContainer _unity;&lt;br /&gt;&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;        &lt;span style="color: #0000ff"&gt;private&lt;/span&gt; ServiceHost _host;&lt;br /&gt;&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;        &lt;span style="color: #0000ff"&gt;private&lt;/span&gt; &lt;span style="color: #0000ff"&gt;void&lt;/span&gt; StartServer()&lt;br /&gt;&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;        {&lt;br /&gt;&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;            _unity = &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; UnityContainer();&lt;br /&gt;&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;            _host = &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; AwBusServiceHost(_unity, &lt;span style="color: #0000ff"&gt;typeof&lt;/span&gt;(TestService), &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; Uri[] { });&lt;br /&gt;&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;            #region Mex&lt;br /&gt;&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;            BindingElement mexBindingElement = &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; TcpTransportBindingElement();&lt;br /&gt;&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;            CustomBinding mexBinding = &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; CustomBinding(mexBindingElement);&lt;br /&gt;&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;            ServiceMetadataBehavior metadataBehavior = _host.Description.Behaviors.Find&amp;lt;ServiceMetadataBehavior&amp;gt;();&lt;br /&gt;&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;            &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (metadataBehavior == &lt;span style="color: #0000ff"&gt;null&lt;/span&gt;)&lt;br /&gt;&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;            {&lt;br /&gt;&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;                metadataBehavior = &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; ServiceMetadataBehavior();&lt;br /&gt;&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;                _host.Description.Behaviors.Add(metadataBehavior);&lt;br /&gt;&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;            }&lt;br /&gt;&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;            _host.AddServiceEndpoint(&lt;span style="color: #0000ff"&gt;typeof&lt;/span&gt;(IMetadataExchange), mexBinding, ServiceUri + &amp;quot;&lt;span style="color: #8b0000"&gt;/MEX&lt;/span&gt;&amp;quot;);&lt;br /&gt;&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;            #endregion&lt;br /&gt;&lt;/pre&gt;&lt;h2&gt;&amp;#160;&lt;/h2&gt;&lt;strong&gt;&lt;font size="5"&gt;&lt;/font&gt;&lt;/strong&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;            #region NetTcp Endpoint&lt;br /&gt;&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;            c.Binding binding = &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; NetTcpBinding(SecurityMode.None);&lt;br /&gt;&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;            _host.AddServiceEndpoint(&lt;span style="color: #0000ff"&gt;typeof&lt;/span&gt;(ITestService), binding, &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; Uri(ServiceUri));&lt;br /&gt;&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;            #endregion&lt;br /&gt;&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;            _host.Open();&lt;br /&gt;&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;        }&lt;br /&gt;&lt;/pre&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;The Client&lt;/h2&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;                c.Binding binding = &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; NetTcpBinding(SecurityMode.None);&lt;br /&gt;&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;                EndpointAddress address = &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; EndpointAddress(ServiceUri);&lt;br /&gt;&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;                &lt;span style="color: #0000ff"&gt;using&lt;/span&gt; (ChannelFactory&amp;lt;ITestService&amp;gt; client = &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; ChannelFactory&amp;lt;ITestService&amp;gt;(binding, address))&lt;br /&gt;&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;                {&lt;br /&gt;&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;                    ITestService proxy = client.CreateChannel();&lt;br /&gt;&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;                    MessageBox.Show(proxy.HasContainer().ToString());&lt;br /&gt;&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;                }&lt;br /&gt;&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;&lt;/pre&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;h1&gt;Conclusion&lt;/h1&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;This is pretty neat. This solves an inconvenience we’ve had at work, though at work we need a different object. We have this thing we call “the factory”, which is our own IOC container. We wrote it before unity was released and before we realized that it already a name (IOC). &lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Once you understand that you can pass anything you want to the service host, and then eventually pass it down to the service object, there are a lot of other injection possibilities. Maybe rather than pass the entire container to the service, you just pull out the objects the service needs an inject them. There are a few ways to do that, but after a few seconds of thought, I think that using unity to construct the service object itself is the best idea. (I found a few examples of this, so its an established approach.)&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2143318148319291738-8615409576369128109?l=hamletcode.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://hamletcode.blogspot.com/feeds/8615409576369128109/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2143318148319291738&amp;postID=8615409576369128109' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2143318148319291738/posts/default/8615409576369128109'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2143318148319291738/posts/default/8615409576369128109'/><link rel='alternate' type='text/html' href='http://hamletcode.blogspot.com/2009/09/injecting-into-wcf-service.html' title='Injecting into a Wcf Service'/><author><name>Jay Allard</name><uri>http://www.blogger.com/profile/15785084867572890025</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2143318148319291738.post-8522430502533618490</id><published>2009-06-02T16:53:00.002-04:00</published><updated>2009-06-02T17:09:17.988-04:00</updated><title type='text'>Something more secure than Notepad</title><content type='html'>For years, I've stored all of my passwords in a TXT file. TXT files are inherently secure because you have to double click it in order to view it. Most people don't know that (until now). To further complicate things, I have obfuscated the file name by calling it "passwords.txt". Its a boring name that will not pique interest. As a computer professional, I'm sure you'll agree that I have taken all reasonable steps towards securing my personal information.&lt;br /&gt;&lt;br /&gt;But, the notepad file is inconvenient. I keep it on an external drive that's plugged into my home computer. I hardly use my home computer. So, when I need to lookup a password, its a pain. (I have most of them memorized, but Bank of America, for example, is just a bunch of numbers.)&lt;br /&gt;&lt;br /&gt;Last night, I started looking for an online notepad service where I can type in all of my information and save it on someone else's server preferably using the honor system. Surprisingly, such sites are not abundant, but I stumbled across the concept of "online password storage". There are several sites out there, obviously managed by paranoid maniacs, that think simply storing passwords in clear text is not the way to go. So, they do things like "encrypt" and require you to "login". Its pretty bizarre. These guys are taking security way too seriously. Honestly, what is someone really going to do if they get a list of all of my credit card numbers and pins and social security number?&lt;br /&gt;&lt;br /&gt;I looked at a few options, but ended up trying &lt;a href="http://passpack.com/"&gt;http://passpack.com&lt;/a&gt;. You can store 100 passwords for free. Each password record gives you plenty of fields, including a free form note field, to put in anything you need. This is good for the banks since I usually track more info than just the site's id and password. (Ie: cc number, expiration date, ccv, etc.). It gives you quick links to copy information from the record into the clipboard.&lt;br /&gt;&lt;br /&gt;You login to the site using your Id and password. But, before you can get to your needlessly encrypted highly personal data, you have to type in your UNPACK password. It seems that they're using this to hash the data. If you lose the UNPACK password, you're done. They can't provide you a new once (hence my speculation that it must be hashed.)&lt;br /&gt;&lt;br /&gt;The site is clean and makes good use of ajax. Pretty much every time you click a link, though, you get a fancy shmancy progress bar. I don't like that. The next page shouldn't take so long to load that it needs a progress bar.&lt;br /&gt;&lt;br /&gt;So far, I really like it. I have entered 4 passwords, which means I have less than 100 free passwords remaining because I already used four of them as I already stated at the beginning of this major run-on sentence. I'm not going to go nuts and figure out, exactly, how many more that leave me, but I have at least 20 more to go of the 100, which is enough for me.&lt;br /&gt;&lt;br /&gt;It offers many advanced features, such as sharing and messaging, but I haven't played with those. I'm really only interested in using it for personal uses.&lt;br /&gt;&lt;br /&gt;Check it out: &lt;a href="http://passpack.com/"&gt;http://passpack.com&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2143318148319291738-8522430502533618490?l=hamletcode.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://hamletcode.blogspot.com/feeds/8522430502533618490/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2143318148319291738&amp;postID=8522430502533618490' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2143318148319291738/posts/default/8522430502533618490'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2143318148319291738/posts/default/8522430502533618490'/><link rel='alternate' type='text/html' href='http://hamletcode.blogspot.com/2009/06/something-more-secure-than-notepad.html' title='Something more secure than Notepad'/><author><name>Jay Allard</name><uri>http://www.blogger.com/profile/15785084867572890025</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2143318148319291738.post-1161819320305270022</id><published>2009-05-29T20:19:00.001-04:00</published><updated>2009-05-29T20:32:33.474-04:00</updated><title type='text'>Serious memory leak with TRUE in .Net</title><content type='html'>&lt;p&gt;Greetings&lt;/p&gt;  &lt;p&gt;At work, we’ve been running PSR tests against our primary application. Last night, the application (which runs as a windows service), was on an obvious spiral into the drain of despair. The memory was steadily increasing. When it reached 1.5 gigs, the application stopped responding altogether.&lt;/p&gt;  &lt;p&gt;That’s not good.&lt;/p&gt;  &lt;p&gt;We were going to just not say anything and hope for the best, but the more level headed of us thought that maybe we should take a look. I was completely against it and wanted to sacrifice a goat instead, but I was overruled. (I seem to get overruled every time I want to sacrifice animals.)&lt;/p&gt;  &lt;p&gt;I started by reviewing the code. I found some connection objects that weren’t being properly cleaned up. I ordered 50 verbal lashes for the offending perps, but moved on. It wasn’t significant enough to be the memory leak, but did sprout an emotional leak in the bowels of my soul. (Please, just use the using clause. That’s all I ask.)&lt;/p&gt;  &lt;p&gt;But I digress. Today, we ran ANTS against it to see where all that memory was all going. It didn’t help, which is unusual.&lt;/p&gt;  &lt;p&gt;So, we did it the old fashion way. We started commenting things out of the main method to find which one was the problem. The object does:&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;Receives an xml message &lt;/li&gt;    &lt;li&gt;Removes duplicate nodes &lt;/li&gt;    &lt;li&gt;Calls a stored procedure to get more information for each of the nodes &lt;/li&gt;    &lt;li&gt;Does an Xslt Transform &lt;/li&gt;    &lt;li&gt;Publishes the message via WCF &lt;/li&gt; &lt;/ol&gt;  &lt;p&gt;Of all the things there, I was most suspicious of the WCF client and least suspicious of XSLT. Imagine my chagrin when it turned out to be the XSLT method.&lt;/p&gt; &lt;font size="2"&gt;   &lt;p&gt;&lt;/p&gt;   &lt;font color="#008000" size="2"&gt;&lt;font color="#008000" size="2"&gt;// XSLT&lt;/font&gt;&lt;/font&gt;&lt;/font&gt;&lt;font size="2"&gt;    &lt;p&gt;&lt;/p&gt;   &lt;font color="#2b91af" size="2"&gt;&lt;font color="#2b91af" size="2"&gt;XslCompiledTransform&lt;/font&gt;&lt;/font&gt;&lt;font size="2"&gt; transform = &lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;&lt;font color="#0000ff" size="2"&gt;new&lt;/font&gt;&lt;/font&gt;&lt;font size="2"&gt; &lt;/font&gt;&lt;font color="#2b91af" size="2"&gt;&lt;font color="#2b91af" size="2"&gt;XslCompiledTransform&lt;/font&gt;&lt;/font&gt;&lt;font size="2"&gt;(true);&lt;/font&gt;     &lt;p&gt;&lt;/p&gt;   &lt;font color="#0000ff" size="2"&gt;&lt;font color="#0000ff" size="2"&gt;using&lt;/font&gt;&lt;/font&gt;&lt;font size="2"&gt; (&lt;/font&gt;&lt;font color="#2b91af" size="2"&gt;&lt;font color="#2b91af" size="2"&gt;XmlReader&lt;/font&gt;&lt;/font&gt;&lt;font size="2"&gt; xmlReader = &lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;&lt;font color="#0000ff" size="2"&gt;new&lt;/font&gt;&lt;/font&gt;&lt;font size="2"&gt; &lt;/font&gt;&lt;font color="#2b91af" size="2"&gt;&lt;font color="#2b91af" size="2"&gt;XmlTextReader&lt;/font&gt;&lt;/font&gt;&lt;font size="2"&gt;(xsltFile))&lt;/font&gt;     &lt;p&gt;{&lt;/p&gt;    &lt;p&gt;transform.Load(xmlReader);&lt;/p&gt;    &lt;p&gt;}&lt;/p&gt;    &lt;p&gt;&amp;#160;&lt;/p&gt;    &lt;p&gt;The problem is the TRUE parameter when the object is instantiated. If you remove it, or change it to false, then everything is stable.&lt;/p&gt;    &lt;p&gt;This is a surprisingly large bug. How can something as fundamental as the boolean value TRUE take down an application like that? Shouldn’t someone have tested that the booleans work properly before shipping? The very foundations of computing are based on boolean values; bits are either on or off… yes or no… 1 or 0. This isn’t rocket science! How can Microsoft ship a product that doesn’t fully support the word true?&lt;/p&gt;    &lt;p&gt;I haven’t been this bothered about the .Net framework since I learned that the number 0 is also broken. Every time I try to divide any number by it, it breaks with some illogical math error (can’t divide by zero?). I can’t say that I’ve tried to divide every number, but&amp;#160; I did get the vast majority. .. let’s just say that I’ve tested the theory enough times to be convinced that it is a problem.&lt;/p&gt;    &lt;p&gt;I really love .NET and will continue to use it without reservation. But, the tough lesson is that you can’t take it for granted, especially if your logic is based on evaluations of some sort. Now that we’ve identified its limitations, we can use it more effectively.&lt;/p&gt;    &lt;p&gt;If the problem was elsewhere… let’s say, if the problem were in the XslCompiledTransform object rather than the word true, that would be more understandable. Then we might be able to conclude that “XslCompiledTransform in debug mode leaks more than the Bush administration”. That’s something we could get our head around and come to terms with... But a broken true!? Dissapointing.&lt;/p&gt;    &lt;p&gt;&lt;/p&gt; &lt;/font&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2143318148319291738-1161819320305270022?l=hamletcode.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://hamletcode.blogspot.com/feeds/1161819320305270022/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2143318148319291738&amp;postID=1161819320305270022' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2143318148319291738/posts/default/1161819320305270022'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2143318148319291738/posts/default/1161819320305270022'/><link rel='alternate' type='text/html' href='http://hamletcode.blogspot.com/2009/05/serious-memory-leak-with-true-in-net.html' title='Serious memory leak with TRUE in .Net'/><author><name>Jay Allard</name><uri>http://www.blogger.com/profile/15785084867572890025</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2143318148319291738.post-8422484388990029469</id><published>2009-05-25T01:16:00.003-04:00</published><updated>2009-05-25T01:41:23.477-04:00</updated><title type='text'>SpamArrest - You Got Me</title><content type='html'>I've been using SpamArrest.com for years now. I've been a big fan of the service, despite its flaws. But, as the years wane on and the flaws continue to persist uncontested, I have become less of a fan. In fact, I officially declare myself no longer a fan.&lt;br /&gt;&lt;br /&gt;Here is a big related post from April 2008: http://hamletcode.blogspot.com/2008/04/email-decision.html&lt;br /&gt;&lt;br /&gt;I was experiencing email turmoil at the time, and settled on SpamArrest. I would've liked to use Gmail, but could not (at least not the way intended).&lt;br /&gt;&lt;br /&gt;Since then, 2 significant things have happened with spam arrest:&lt;br /&gt;&lt;br /&gt;1 - I bought the lifetime subscription. At the time, I was still a fan. I've been using it for years and planned to use it for years more.&lt;br /&gt;&lt;br /&gt;2 - They introduced a javascript bug. I reported the bug to them on October 27th 2008 after waiting serveral weeks to see if they would correct it themselves.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;My Email to them&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;Greetings&lt;br /&gt;&lt;br /&gt;This has been happening for quite a while now, but I waited incase it was going to be fixed, but it hasn't.&lt;br /&gt;&lt;br /&gt;There's a bug on the login screen. It attempts to attach an event to the REMEMBER ME checkbox. But, if you're already logged in (because it remembered you), then the control doesn't exist, so it can't attach the event. This results in an error dialog:&lt;br /&gt;&lt;br /&gt;A runtime error has occurred.&lt;br /&gt;Do you wish to debug?&lt;br /&gt;Line 1726&lt;br /&gt;Error: 'addEventListener' is null or not an object.&lt;br /&gt;Its not a big deal, but after a few weeks its getting a little annoying. (I'm a developer, so I can't disable the alerts.)&lt;br /&gt;&lt;br /&gt;Jay &lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Rather than trying the steps listed, they instead suggested that my browser must be "acting up", and suggested that I install firefox or chrome. That's great... thanks. Great advice. I responded pointing out exactly where the javascript was failing and why, and showed that if fails in firefox 3 too. I listed 3 bulleted steps to reproduce. They responded saying "thank you, we'll forward that to our development team".&lt;br /&gt;&lt;br /&gt;That was nearly 7 months ago. They still haven't fixed it. Its going to fail in every browser because it's just bad logic. When you're already logged in, there isn't a "REMEMBER ME" checkbox. The javascript is looking for it anyway, then fails when it can't find it.&lt;br /&gt;&lt;br /&gt;Another of my favorite problems is REPLY ALL. If you click REPLY ALL, and forget to remove your own name from the address list, you get an onslaught of spam messages. Once you delete the messages, you don't get any more, so its not like it auto-approved them. Its just that you get a whole bunch that you have to cleanup before you're back to normal.&lt;br /&gt;&lt;br /&gt;In my previous blog post, I mentioned the searches I conducted in their help system to find simple things like IMAP and DISK QUOTA. To find DISK QUOTA information, you have to search for "SPACE". To find IMAP information, you have to read an article entitled "WHAT IS A POP SERVER?" Well, I already know what a pop server is. If I'm looking for IMAP server information, why would I click that?&lt;br /&gt;&lt;br /&gt;I strongly regret the life time subscription. I asked for a refund on it, and they responded saying no, but then asked me what the problems were. I didn't answer. How many times do I need to tell them what the problems are? At this point, I continue to use SPAM ARREST only out of laziness, despite the life time subscription. Maybe I can sell it on EBAY or something.&lt;br /&gt;&lt;br /&gt;Now, the webmail client has a REFER FRIEND tab on which they ask me to refer business to them for savings. I already have a strongly regretted life time subscription... how does refering a friend to spam arrest help me? Furthermore, even if I was still a fan, then that tab would be useless anyway. I've been referring people to SpamArrest for years, not because I want some type of credit, but because it's a good service. Only a few of those referrals have actually started using it, but that wasn't due to a lack of effort on my part. (Most people find GMAIL junk filters to be sufficient.)&lt;br /&gt;&lt;br /&gt;My official stance has changed. I will no longer recommend Spam Arrest. Infact, I will actively express dissapointment. Software is supposed to evolve; their web client continues to be stagnant (and broken) where it counts. The pages still say COPYRIGHT 2006!!! Has anyone looked at a calendar recently?&lt;br /&gt;&lt;br /&gt;Its ok to have flaws. Its not ok to never fix them. I'm dissapointed in them for not evolving, and I'm really annoyed that I fell for the "lifetime subscription" scam.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2143318148319291738-8422484388990029469?l=hamletcode.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://hamletcode.blogspot.com/feeds/8422484388990029469/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2143318148319291738&amp;postID=8422484388990029469' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2143318148319291738/posts/default/8422484388990029469'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2143318148319291738/posts/default/8422484388990029469'/><link rel='alternate' type='text/html' href='http://hamletcode.blogspot.com/2009/05/spamarrest-you-got-me.html' title='SpamArrest - You Got Me'/><author><name>Jay Allard</name><uri>http://www.blogger.com/profile/15785084867572890025</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2143318148319291738.post-2575944069782123338</id><published>2009-05-11T17:01:00.001-04:00</published><updated>2009-05-11T17:01:46.699-04:00</updated><title type='text'>Chewing</title><content type='html'>&lt;p&gt;In order to chew, you need teeth.&lt;/p&gt;  &lt;p&gt;Jack now has one that finally broke the gum line. This means that he can chew very small, very localized foods!&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2143318148319291738-2575944069782123338?l=hamletcode.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://hamletcode.blogspot.com/feeds/2575944069782123338/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2143318148319291738&amp;postID=2575944069782123338' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2143318148319291738/posts/default/2575944069782123338'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2143318148319291738/posts/default/2575944069782123338'/><link rel='alternate' type='text/html' href='http://hamletcode.blogspot.com/2009/05/chewing.html' title='Chewing'/><author><name>Jay Allard</name><uri>http://www.blogger.com/profile/15785084867572890025</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2143318148319291738.post-5339308872699416041</id><published>2009-05-05T23:51:00.001-04:00</published><updated>2009-05-05T23:54:12.827-04:00</updated><title type='text'>Linq, Attribute and Reflection, all in one</title><content type='html'>&lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;Greetings&lt;/p&gt;  &lt;p&gt;I was goofing around with some reflection stuff, and wanted to use LINQ to build an xml document for me. It started off as three different steps, and whittled its way down to one.&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;Gets a list of all of the properties in the current class that have the [ServiceProperty] attribute&lt;/li&gt;    &lt;li&gt;Creates an XDocument containing information about the property including the value, and all of the meta-data added by the [ServiceProperty] attribute&lt;/li&gt; &lt;/ol&gt;  &lt;p&gt;The only thing I don’t like is that it builds the entire wrapper, even if attribute is null. When the attribute is null, we don’t care about anything, and should just continue. But, as is, property.GetValue() executes even when we don’t need it.&lt;/p&gt;  &lt;div id="codeSnippetWrapper" style="border-right: silver 1px solid; padding-right: 4px; border-top: silver 1px solid; padding-left: 4px; font-size: 8pt; padding-bottom: 4px; margin: 20px 0px 10px; overflow: auto; border-left: silver 1px solid; width: 97.5%; cursor: text; direction: ltr; max-height: 200px; line-height: 12pt; padding-top: 4px; border-bottom: silver 1px solid; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; background-color: #f4f4f4; text-align: left"&gt;   &lt;div id="codeSnippet" style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; overflow: visible; width: 100%; color: black; direction: ltr; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; text-align: left; border-bottom-style: none"&gt;     &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; direction: ltr; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: white; text-align: left; border-bottom-style: none"&gt;&lt;span id="lnum1" style="color: #606060"&gt;   1:&lt;/span&gt; XDocument doc = &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; XDocument(&lt;/pre&gt;&lt;br /&gt;&lt;!--CRLF--&gt;&lt;br /&gt;&lt;br /&gt;    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; direction: ltr; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; text-align: left; border-bottom-style: none"&gt;&lt;span id="lnum2" style="color: #606060"&gt;   2:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; XDeclaration(&lt;span style="color: #006080"&gt;&amp;quot;1.0&amp;quot;&lt;/span&gt;, &lt;span style="color: #006080"&gt;&amp;quot;utf-8&amp;quot;&lt;/span&gt;, &lt;span style="color: #006080"&gt;&amp;quot;yes&amp;quot;&lt;/span&gt;),&lt;/pre&gt;&lt;br /&gt;&lt;!--CRLF--&gt;&lt;br /&gt;&lt;br /&gt;    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; direction: ltr; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: white; text-align: left; border-bottom-style: none"&gt;&lt;span id="lnum3" style="color: #606060"&gt;   3:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; XElement(&lt;span style="color: #006080"&gt;&amp;quot;properties&amp;quot;&lt;/span&gt;,&lt;/pre&gt;&lt;br /&gt;&lt;!--CRLF--&gt;&lt;br /&gt;&lt;br /&gt;    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; direction: ltr; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; text-align: left; border-bottom-style: none"&gt;&lt;span id="lnum4" style="color: #606060"&gt;   4:&lt;/span&gt;                  (&lt;/pre&gt;&lt;br /&gt;&lt;!--CRLF--&gt;&lt;br /&gt;&lt;br /&gt;    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; direction: ltr; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: white; text-align: left; border-bottom-style: none"&gt;&lt;span id="lnum5" style="color: #606060"&gt;   5:&lt;/span&gt;                      from property &lt;span style="color: #0000ff"&gt;in&lt;/span&gt; GetType().GetProperties(BindingFlags.Instance | BindingFlags.Public)&lt;/pre&gt;&lt;br /&gt;&lt;!--CRLF--&gt;&lt;br /&gt;&lt;br /&gt;    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; direction: ltr; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; text-align: left; border-bottom-style: none"&gt;&lt;span id="lnum6" style="color: #606060"&gt;   6:&lt;/span&gt;                      let wrapper = &lt;span style="color: #0000ff"&gt;new&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt;&lt;!--CRLF--&gt;&lt;br /&gt;&lt;br /&gt;    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; direction: ltr; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: white; text-align: left; border-bottom-style: none"&gt;&lt;span id="lnum7" style="color: #606060"&gt;   7:&lt;/span&gt;                                        {&lt;/pre&gt;&lt;br /&gt;&lt;!--CRLF--&gt;&lt;br /&gt;&lt;br /&gt;    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; direction: ltr; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; text-align: left; border-bottom-style: none"&gt;&lt;span id="lnum8" style="color: #606060"&gt;   8:&lt;/span&gt;                                            Property = property,&lt;/pre&gt;&lt;br /&gt;&lt;!--CRLF--&gt;&lt;br /&gt;&lt;br /&gt;    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; direction: ltr; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: white; text-align: left; border-bottom-style: none"&gt;&lt;span id="lnum9" style="color: #606060"&gt;   9:&lt;/span&gt;                                            Attribute =Attribute.GetCustomAttribute(property, &lt;span style="color: #0000ff"&gt;typeof&lt;/span&gt;(ServicePropertyAttribute)) &lt;span style="color: #0000ff"&gt;as&lt;/span&gt; ServicePropertyAttribute,&lt;/pre&gt;&lt;br /&gt;&lt;!--CRLF--&gt;&lt;br /&gt;&lt;br /&gt;    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; direction: ltr; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; text-align: left; border-bottom-style: none"&gt;&lt;span id="lnum10" style="color: #606060"&gt;  10:&lt;/span&gt;                                            Value = property.GetValue(&lt;span style="color: #0000ff"&gt;this&lt;/span&gt;, BindingFlags.Public | BindingFlags.Instance, &lt;span style="color: #0000ff"&gt;null&lt;/span&gt;, &lt;span style="color: #0000ff"&gt;null&lt;/span&gt;,&lt;/pre&gt;&lt;br /&gt;&lt;!--CRLF--&gt;&lt;br /&gt;&lt;br /&gt;    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; direction: ltr; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: white; text-align: left; border-bottom-style: none"&gt;&lt;span id="lnum11" style="color: #606060"&gt;  11:&lt;/span&gt;                                            CultureInfo.InvariantCulture)&lt;/pre&gt;&lt;br /&gt;&lt;!--CRLF--&gt;&lt;br /&gt;&lt;br /&gt;    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; direction: ltr; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; text-align: left; border-bottom-style: none"&gt;&lt;span id="lnum12" style="color: #606060"&gt;  12:&lt;/span&gt;                                        }&lt;/pre&gt;&lt;br /&gt;&lt;!--CRLF--&gt;&lt;br /&gt;&lt;br /&gt;    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; direction: ltr; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: white; text-align: left; border-bottom-style: none"&gt;&lt;span id="lnum13" style="color: #606060"&gt;  13:&lt;/span&gt;                      &lt;span style="color: #0000ff"&gt;where&lt;/span&gt; wrapper.Attribute != &lt;span style="color: #0000ff"&gt;null&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt;&lt;!--CRLF--&gt;&lt;br /&gt;&lt;br /&gt;    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; direction: ltr; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; text-align: left; border-bottom-style: none"&gt;&lt;span id="lnum14" style="color: #606060"&gt;  14:&lt;/span&gt;                      select&lt;/pre&gt;&lt;br /&gt;&lt;!--CRLF--&gt;&lt;br /&gt;&lt;br /&gt;    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; direction: ltr; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: white; text-align: left; border-bottom-style: none"&gt;&lt;span id="lnum15" style="color: #606060"&gt;  15:&lt;/span&gt;                          &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; XElement(&lt;span style="color: #006080"&gt;&amp;quot;property&amp;quot;&lt;/span&gt;,&lt;/pre&gt;&lt;br /&gt;&lt;!--CRLF--&gt;&lt;br /&gt;&lt;br /&gt;    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; direction: ltr; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; text-align: left; border-bottom-style: none"&gt;&lt;span id="lnum16" style="color: #606060"&gt;  16:&lt;/span&gt;                                       &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; XAttribute(&lt;span style="color: #006080"&gt;&amp;quot;name&amp;quot;&lt;/span&gt;, wrapper.Property.Name),&lt;/pre&gt;&lt;br /&gt;&lt;!--CRLF--&gt;&lt;br /&gt;&lt;br /&gt;    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; direction: ltr; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: white; text-align: left; border-bottom-style: none"&gt;&lt;span id="lnum17" style="color: #606060"&gt;  17:&lt;/span&gt;                                       &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; XElement(&lt;span style="color: #006080"&gt;&amp;quot;display-name&amp;quot;&lt;/span&gt;, wrapper.Attribute.DisplayName),&lt;/pre&gt;&lt;br /&gt;&lt;!--CRLF--&gt;&lt;br /&gt;&lt;br /&gt;    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; direction: ltr; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; text-align: left; border-bottom-style: none"&gt;&lt;span id="lnum18" style="color: #606060"&gt;  18:&lt;/span&gt;                                       &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; XElement(&lt;span style="color: #006080"&gt;&amp;quot;default-value&amp;quot;&lt;/span&gt;, wrapper.Attribute.DefaultValue),&lt;/pre&gt;&lt;br /&gt;&lt;!--CRLF--&gt;&lt;br /&gt;&lt;br /&gt;    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; direction: ltr; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: white; text-align: left; border-bottom-style: none"&gt;&lt;span id="lnum19" style="color: #606060"&gt;  19:&lt;/span&gt;                                       &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; XElement(&lt;span style="color: #006080"&gt;&amp;quot;description&amp;quot;&lt;/span&gt;, wrapper.Attribute.Description),&lt;/pre&gt;&lt;br /&gt;&lt;!--CRLF--&gt;&lt;br /&gt;&lt;br /&gt;    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; direction: ltr; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; text-align: left; border-bottom-style: none"&gt;&lt;span id="lnum20" style="color: #606060"&gt;  20:&lt;/span&gt;                                       &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; XElement(&lt;span style="color: #006080"&gt;&amp;quot;required&amp;quot;&lt;/span&gt;, wrapper.Attribute.Required),&lt;/pre&gt;&lt;br /&gt;&lt;!--CRLF--&gt;&lt;br /&gt;&lt;br /&gt;    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; direction: ltr; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: white; text-align: left; border-bottom-style: none"&gt;&lt;span id="lnum21" style="color: #606060"&gt;  21:&lt;/span&gt;                                       &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; XElement(&lt;span style="color: #006080"&gt;&amp;quot;value&amp;quot;&lt;/span&gt;, wrapper.Value),&lt;/pre&gt;&lt;br /&gt;&lt;!--CRLF--&gt;&lt;br /&gt;&lt;br /&gt;    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; direction: ltr; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; text-align: left; border-bottom-style: none"&gt;&lt;span id="lnum22" style="color: #606060"&gt;  22:&lt;/span&gt;                                       &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; XElement(&lt;span style="color: #006080"&gt;&amp;quot;data-type&amp;quot;&lt;/span&gt;, wrapper.Property.PropertyType.FullName)&lt;/pre&gt;&lt;br /&gt;&lt;!--CRLF--&gt;&lt;br /&gt;&lt;br /&gt;    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; direction: ltr; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: white; text-align: left; border-bottom-style: none"&gt;&lt;span id="lnum23" style="color: #606060"&gt;  23:&lt;/span&gt;                          )&lt;/pre&gt;&lt;br /&gt;&lt;!--CRLF--&gt;&lt;br /&gt;&lt;br /&gt;    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; direction: ltr; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; text-align: left; border-bottom-style: none"&gt;&lt;span id="lnum24" style="color: #606060"&gt;  24:&lt;/span&gt;                  )&lt;/pre&gt;&lt;br /&gt;&lt;!--CRLF--&gt;&lt;br /&gt;&lt;br /&gt;    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; direction: ltr; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: white; text-align: left; border-bottom-style: none"&gt;&lt;span id="lnum25" style="color: #606060"&gt;  25:&lt;/span&gt;         )&lt;/pre&gt;&lt;br /&gt;&lt;!--CRLF--&gt;&lt;br /&gt;&lt;br /&gt;    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; direction: ltr; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; text-align: left; border-bottom-style: none"&gt;&lt;span id="lnum26" style="color: #606060"&gt;  26:&lt;/span&gt;     );&lt;/pre&gt;&lt;br /&gt;&lt;!--CRLF--&gt;&lt;/div&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;&lt;a href="http://lh4.ggpht.com/_VTjiO7cQdSU/SgEJIVqBV8I/AAAAAAAAAKg/XZwpXCDL3Ps/s1600-h/image%5B2%5D.png"&gt;&lt;img title="image" style="border-right: 0px; border-top: 0px; display: inline; border-left: 0px; border-bottom: 0px" height="97" alt="image" src="http://lh5.ggpht.com/_VTjiO7cQdSU/SgEJIxEkZ_I/AAAAAAAAAKk/fFi17B8ksuk/image_thumb.png?imgmax=800" width="244" border="0" /&gt;&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/2143318148319291738-5339308872699416041?l=hamletcode.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://hamletcode.blogspot.com/feeds/5339308872699416041/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2143318148319291738&amp;postID=5339308872699416041' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2143318148319291738/posts/default/5339308872699416041'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2143318148319291738/posts/default/5339308872699416041'/><link rel='alternate' type='text/html' href='http://hamletcode.blogspot.com/2009/05/linq-attribute-and-reflection-all-in.html' title='Linq, Attribute and Reflection, all in one'/><author><name>Jay Allard</name><uri>http://www.blogger.com/profile/15785084867572890025</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh5.ggpht.com/_VTjiO7cQdSU/SgEJIxEkZ_I/AAAAAAAAAKk/fFi17B8ksuk/s72-c/image_thumb.png?imgmax=800' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2143318148319291738.post-7927753275118847818</id><published>2009-04-11T01:57:00.001-04:00</published><updated>2009-04-11T01:57:02.031-04:00</updated><title type='text'>Jts 3 Development Wiki</title><content type='html'>&lt;p&gt;I found an excellent free WIKI from screwturn. I was up and running in about 10 minutes. Excellent.&lt;/p&gt;  &lt;p&gt;Anyway, I created a wiki to document the Jts 3 development effort.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://www.allardworksdev.com/Wiki"&gt;http://www.allardworksdev.com/Wiki&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/2143318148319291738-7927753275118847818?l=hamletcode.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://hamletcode.blogspot.com/feeds/7927753275118847818/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2143318148319291738&amp;postID=7927753275118847818' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2143318148319291738/posts/default/7927753275118847818'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2143318148319291738/posts/default/7927753275118847818'/><link rel='alternate' type='text/html' href='http://hamletcode.blogspot.com/2009/04/jts-3-development-wiki.html' title='Jts 3 Development Wiki'/><author><name>Jay Allard</name><uri>http://www.blogger.com/profile/15785084867572890025</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2143318148319291738.post-6123937168090152194</id><published>2009-03-31T00:35:00.003-04:00</published><updated>2009-03-31T00:45:08.719-04:00</updated><title type='text'>Jack’s First SQL Query</title><content type='html'>&lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;Jack is just about 6 months old now. As anticipated, he has expressed an interest in programming. He was sitting on my lap yesterday as I was tweaking a query. He started to pound on the keyboard, so I opened up a fresh window for him so that he could express his programming desires uninhibited by my existing work.&lt;/p&gt;  &lt;p&gt;Here is what he came up with&lt;/p&gt;  &lt;p&gt;“&amp;#160; .&amp;quot;&lt;/p&gt;  &lt;p&gt;That’s 2 spaces, a period, and another space. Not only should you appreciate the query itself, but you should appreciate the manner in which it was written. Some people have a vague idea of what they are doing and they sit down to figure it out through a cycle of research/trial-and-error. Others know what has to be done and simply do it; Solving the problem takes exactly as long as it takes to type in the solution. I am of the latter classification, and it would seem that whichever gene enables that skill has been passed to the offspring. Jack was Picasso and the keyboard was his tapestry; There was no delay or thought, simply action. It was so natural that a casual observer may have perceived it as nothing more than the random flailing of his 2 topmost limbs.&lt;/p&gt;  &lt;p&gt;As a dad I proudly exclaim that this is a tremendous victory. While not completely void of issues, it is an excellent first step in solving many well known SQL puzzles. I love the initiative, the attitude, and the overall spirit of the effort. It takes more than skill to be a programmer; you need to love it. For that he gets an A+.&lt;/p&gt;  &lt;p&gt;But, as a software architect and a mentor, I must be fair and point out the very rare opportunities for improvement.&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Excessive white spaces – surely we don’t need spaces on both sides of the period. Perhaps he should consider a tab rather than consecutive leading spaces. I was going to suggest this to him, but he chose that moment to engage in massive crap. He was concentrating very hard on the pushing exercise, with his brow furrowed and his face turning red from the effort. Relative to his intestinal action and diaper trauma, the tab issue seemed trivial so was left unsaid.&lt;/li&gt;    &lt;li&gt;The period – in this context, it doesn’t actually do anything, which is OK. I see that the period is a solution; its just that we don’t understand the problem because we're dumb. I only mention it here because he didn’t comment it.&lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;Cleary Jack is on the road to programming greatness.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2143318148319291738-6123937168090152194?l=hamletcode.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://hamletcode.blogspot.com/feeds/6123937168090152194/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2143318148319291738&amp;postID=6123937168090152194' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2143318148319291738/posts/default/6123937168090152194'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2143318148319291738/posts/default/6123937168090152194'/><link rel='alternate' type='text/html' href='http://hamletcode.blogspot.com/2009/03/jacks-first-sql-query.html' title='Jack’s First SQL Query'/><author><name>Jay Allard</name><uri>http://www.blogger.com/profile/15785084867572890025</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2143318148319291738.post-6576592043079130457</id><published>2009-03-29T14:24:00.001-04:00</published><updated>2009-03-29T14:24:11.413-04:00</updated><title type='text'>XQuery – How ye disappoint</title><content type='html'>&lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;I’m updating a legacy app from VB6 to ASP and then to .NET. The ASP is a transitional step so that I can stop dealing with COM+ objects.&lt;/p&gt;  &lt;p&gt;Anyhoo… I picked one of the common pages. It prints a grid, basically.&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;page calls a vbscript function&lt;/li&gt;    &lt;li&gt;the vbscript function executes a query and gets back a recordset&lt;/li&gt;    &lt;li&gt;a series of nested loops covert the recordset to xml&lt;/li&gt;    &lt;li&gt;the xml is returned to the page&lt;/li&gt;    &lt;li&gt;the page uses XSLT to convert the XML to HTML&lt;/li&gt; &lt;/ol&gt;  &lt;p&gt;Sweet.&lt;/p&gt;  &lt;p&gt;Now that I’m converting it to .NET, though, I wanted to try exciting new possibilities. The application is on SQL 2000, but updating to 2005 is a reasonable expectation. (I won’t push my luck with 2008).&lt;/p&gt;  &lt;h1&gt;The Intent&lt;/h1&gt;  &lt;p&gt;The idea is to transform this data&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh6.ggpht.com/_VTjiO7cQdSU/Sc-8xR51BCI/AAAAAAAAAJw/_-HJ_DK03gE/s1600-h/image%5B2%5D.png"&gt;&lt;img title="image" style="border-right: 0px; border-top: 0px; display: inline; border-left: 0px; border-bottom: 0px" height="139" alt="image" src="http://lh4.ggpht.com/_VTjiO7cQdSU/Sc-8xmROEZI/AAAAAAAAAJ0/ORN7V1kYFps/image_thumb.png?imgmax=800" width="244" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;into this xml&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh4.ggpht.com/_VTjiO7cQdSU/Sc-8xwX92iI/AAAAAAAAAJ4/zmvSVXgwfUs/s1600-h/image%5B5%5D.png"&gt;&lt;img title="image" style="border-right: 0px; border-top: 0px; display: inline; border-left: 0px; border-bottom: 0px" height="244" alt="image" src="http://lh5.ggpht.com/_VTjiO7cQdSU/Sc-8yW0cyAI/AAAAAAAAAJ8/rA_3-RO9B2Y/image_thumb%5B1%5D.png?imgmax=800" width="207" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;In the current app, that transformation is done in ASP VbScript.&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;h1&gt;SQL XML&lt;/h1&gt;  &lt;p&gt;I’ve dabbled with some of the XML capabilities in 2005. I’ve used it to join to tables and to shred the xml. I’ve also used it to create xml documents without that pesky !TAG! syntax. But, they were all meager efforts.&lt;/p&gt;  &lt;p&gt;I started by hoping that such meagerness would be sufficient.&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;div id="codeSnippetWrapper" style="border-right: silver 1px solid; padding-right: 4px; border-top: silver 1px solid; padding-left: 4px; font-size: 8pt; padding-bottom: 4px; margin: 20px 0px 10px; overflow: auto; border-left: silver 1px solid; width: 97.5%; cursor: text; direction: ltr; max-height: 200px; line-height: 12pt; padding-top: 4px; border-bottom: silver 1px solid; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; background-color: #f4f4f4; text-align: left"&gt;   &lt;div id="codeSnippet" style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; overflow: visible; width: 100%; color: black; direction: ltr; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; text-align: left; border-bottom-style: none"&gt;     &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; direction: ltr; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: white; text-align: left; border-bottom-style: none"&gt;&lt;span id="lnum1" style="color: #606060"&gt;   1:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;declare&lt;/span&gt; @startDate datetime&lt;/pre&gt;&lt;br /&gt;&lt;!--CRLF--&gt;&lt;br /&gt;&lt;br /&gt;    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; direction: ltr; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; text-align: left; border-bottom-style: none"&gt;&lt;span id="lnum2" style="color: #606060"&gt;   2:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;declare&lt;/span&gt; @endDate datetime&lt;/pre&gt;&lt;br /&gt;&lt;!--CRLF--&gt;&lt;br /&gt;&lt;br /&gt;    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; direction: ltr; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: white; text-align: left; border-bottom-style: none"&gt;&lt;span id="lnum3" style="color: #606060"&gt;   3:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;declare&lt;/span&gt; @theaterId &lt;span style="color: #0000ff"&gt;int&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt;&lt;!--CRLF--&gt;&lt;br /&gt;&lt;br /&gt;    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; direction: ltr; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; text-align: left; border-bottom-style: none"&gt;&lt;span id="lnum4" style="color: #606060"&gt;   4:&lt;/span&gt;&amp;#160; &lt;/pre&gt;&lt;br /&gt;&lt;!--CRLF--&gt;&lt;br /&gt;&lt;br /&gt;    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; direction: ltr; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: white; text-align: left; border-bottom-style: none"&gt;&lt;span id="lnum5" style="color: #606060"&gt;   5:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;select&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt;&lt;!--CRLF--&gt;&lt;br /&gt;&lt;br /&gt;    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; direction: ltr; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; text-align: left; border-bottom-style: none"&gt;&lt;span id="lnum6" style="color: #606060"&gt;   6:&lt;/span&gt;     @startDate = &lt;span style="color: #006080"&gt;'10/31/2003'&lt;/span&gt;,&lt;/pre&gt;&lt;br /&gt;&lt;!--CRLF--&gt;&lt;br /&gt;&lt;br /&gt;    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; direction: ltr; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: white; text-align: left; border-bottom-style: none"&gt;&lt;span id="lnum7" style="color: #606060"&gt;   7:&lt;/span&gt;     @endDate = &lt;span style="color: #006080"&gt;'11/6/2003'&lt;/span&gt;,&lt;/pre&gt;&lt;br /&gt;&lt;!--CRLF--&gt;&lt;br /&gt;&lt;br /&gt;    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; direction: ltr; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; text-align: left; border-bottom-style: none"&gt;&lt;span id="lnum8" style="color: #606060"&gt;   8:&lt;/span&gt;     @theaterId = 170&lt;/pre&gt;&lt;br /&gt;&lt;!--CRLF--&gt;&lt;br /&gt;&lt;br /&gt;    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; direction: ltr; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: white; text-align: left; border-bottom-style: none"&gt;&lt;span id="lnum9" style="color: #606060"&gt;   9:&lt;/span&gt;&amp;#160; &lt;/pre&gt;&lt;br /&gt;&lt;!--CRLF--&gt;&lt;br /&gt;&lt;br /&gt;    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; direction: ltr; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; text-align: left; border-bottom-style: none"&gt;&lt;span id="lnum10" style="color: #606060"&gt;  10:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;select&lt;/span&gt; &lt;/pre&gt;&lt;br /&gt;&lt;!--CRLF--&gt;&lt;br /&gt;&lt;br /&gt;    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; direction: ltr; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: white; text-align: left; border-bottom-style: none"&gt;&lt;span id="lnum11" style="color: #606060"&gt;  11:&lt;/span&gt;         v.FilmId &amp;quot;film/@film-id&amp;quot;,&lt;/pre&gt;&lt;br /&gt;&lt;!--CRLF--&gt;&lt;br /&gt;&lt;br /&gt;    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; direction: ltr; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; text-align: left; border-bottom-style: none"&gt;&lt;span id="lnum12" style="color: #606060"&gt;  12:&lt;/span&gt;         v.FilmName &amp;quot;film/@film-name&amp;quot;,&lt;/pre&gt;&lt;br /&gt;&lt;!--CRLF--&gt;&lt;br /&gt;&lt;br /&gt;    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; direction: ltr; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: white; text-align: left; border-bottom-style: none"&gt;&lt;span id="lnum13" style="color: #606060"&gt;  13:&lt;/span&gt;         v.PrintId &amp;quot;film/&lt;span style="color: #0000ff"&gt;print&lt;/span&gt;/@&lt;span style="color: #0000ff"&gt;print&lt;/span&gt;-id&amp;quot;,&lt;/pre&gt;&lt;br /&gt;&lt;!--CRLF--&gt;&lt;br /&gt;&lt;br /&gt;    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; direction: ltr; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; text-align: left; border-bottom-style: none"&gt;&lt;span id="lnum14" style="color: #606060"&gt;  14:&lt;/span&gt;         dates.[&lt;span style="color: #0000ff"&gt;Date&lt;/span&gt;] &amp;quot;film/&lt;span style="color: #0000ff"&gt;print&lt;/span&gt;/&lt;span style="color: #0000ff"&gt;date&lt;/span&gt;/@&lt;span style="color: #0000ff"&gt;date&lt;/span&gt;&amp;quot;,&lt;/pre&gt;&lt;br /&gt;&lt;!--CRLF--&gt;&lt;br /&gt;&lt;br /&gt;    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; direction: ltr; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: white; text-align: left; border-bottom-style: none"&gt;&lt;span id="lnum15" style="color: #606060"&gt;  15:&lt;/span&gt;         a.AuditoriumName &amp;quot;film/&lt;span style="color: #0000ff"&gt;print&lt;/span&gt;/&lt;span style="color: #0000ff"&gt;date&lt;/span&gt;/auditorium/@auditorium-name&amp;quot;,&lt;/pre&gt;&lt;br /&gt;&lt;!--CRLF--&gt;&lt;br /&gt;&lt;br /&gt;    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; direction: ltr; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; text-align: left; border-bottom-style: none"&gt;&lt;span id="lnum16" style="color: #606060"&gt;  16:&lt;/span&gt;         a.AuditoriumId &amp;quot;film/&lt;span style="color: #0000ff"&gt;print&lt;/span&gt;/&lt;span style="color: #0000ff"&gt;date&lt;/span&gt;/auditorium/@auditorium-id&amp;quot;&lt;/pre&gt;&lt;br /&gt;&lt;!--CRLF--&gt;&lt;br /&gt;&lt;br /&gt;    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; direction: ltr; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: white; text-align: left; border-bottom-style: none"&gt;&lt;span id="lnum17" style="color: #606060"&gt;  17:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;from&lt;/span&gt; &lt;/pre&gt;&lt;br /&gt;&lt;!--CRLF--&gt;&lt;/div&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;But its not. That built the the hierarchy, but it repeats itself over and over. It doesn’t group itself the way I need. If there was/is a way to do everything I need by specifying the paths like that, then it would be a good day.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;h1&gt;SQL XQUERY&lt;/h1&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Next, I started dabbling with XQUERY. My only XQUERY experience has been via SQL Server 2005, and in its simplest form.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;I went Google-Crazy and read up on some stuff. I was able to write a query (albeit a crappy one) that does the job.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;div id="codeSnippetWrapper" style="border-right: silver 1px solid; padding-right: 4px; border-top: silver 1px solid; padding-left: 4px; font-size: 8pt; padding-bottom: 4px; margin: 20px 0px 10px; overflow: auto; border-left: silver 1px solid; width: 97.5%; cursor: text; direction: ltr; max-height: 200px; line-height: 12pt; padding-top: 4px; border-bottom: silver 1px solid; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; background-color: #f4f4f4; text-align: left"&gt;&lt;br /&gt;  &lt;div id="codeSnippet" style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; overflow: visible; width: 100%; color: black; direction: ltr; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; text-align: left; border-bottom-style: none"&gt;&lt;br /&gt;    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; direction: ltr; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: white; text-align: left; border-bottom-style: none"&gt;&lt;span id="lnum1" style="color: #606060"&gt;   1:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;select&lt;/span&gt; @&lt;span style="color: #0000ff"&gt;output&lt;/span&gt;.query(&lt;span style="color: #006080"&gt;'&lt;/pre&gt;&lt;br /&gt;&lt;!--CRLF--&gt;&lt;br /&gt;&lt;br /&gt;    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; direction: ltr; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; text-align: left; border-bottom-style: none"&gt;&lt;span id="lnum2" style="color: #606060"&gt;   2:&lt;/span&gt;     &amp;lt;theater&amp;gt;&lt;/pre&gt;&lt;br /&gt;&lt;!--CRLF--&gt;&lt;br /&gt;&lt;br /&gt;    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; direction: ltr; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: white; text-align: left; border-bottom-style: none"&gt;&lt;span id="lnum3" style="color: #606060"&gt;   3:&lt;/span&gt;         {&lt;/pre&gt;&lt;br /&gt;&lt;!--CRLF--&gt;&lt;br /&gt;&lt;br /&gt;    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; direction: ltr; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; text-align: left; border-bottom-style: none"&gt;&lt;span id="lnum4" style="color: #606060"&gt;   4:&lt;/span&gt;             for $filmId in distinct-values(/theater/film/@film-id)&lt;/pre&gt;&lt;br /&gt;&lt;!--CRLF--&gt;&lt;br /&gt;&lt;br /&gt;    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; direction: ltr; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: white; text-align: left; border-bottom-style: none"&gt;&lt;span id="lnum5" style="color: #606060"&gt;   5:&lt;/span&gt;             return &lt;/pre&gt;&lt;br /&gt;&lt;!--CRLF--&gt;&lt;br /&gt;&lt;br /&gt;    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; direction: ltr; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; text-align: left; border-bottom-style: none"&gt;&lt;span id="lnum6" style="color: #606060"&gt;   6:&lt;/span&gt;             &amp;lt;film&amp;gt;&lt;/pre&gt;&lt;br /&gt;&lt;!--CRLF--&gt;&lt;br /&gt;&lt;br /&gt;    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; direction: ltr; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: white; text-align: left; border-bottom-style: none"&gt;&lt;span id="lnum7" style="color: #606060"&gt;   7:&lt;/span&gt;                 { attribute id { $filmId }}&lt;/pre&gt;&lt;br /&gt;&lt;!--CRLF--&gt;&lt;br /&gt;&lt;br /&gt;    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; direction: ltr; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; text-align: left; border-bottom-style: none"&gt;&lt;span id="lnum8" style="color: #606060"&gt;   8:&lt;/span&gt;                 { attribute name { /theater/film [@film-id = $filmId][1]/@film-name }}&lt;/pre&gt;&lt;br /&gt;&lt;!--CRLF--&gt;&lt;br /&gt;&lt;br /&gt;    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; direction: ltr; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: white; text-align: left; border-bottom-style: none"&gt;&lt;span id="lnum9" style="color: #606060"&gt;   9:&lt;/span&gt;                 {&lt;/pre&gt;&lt;br /&gt;&lt;!--CRLF--&gt;&lt;br /&gt;&lt;br /&gt;    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; direction: ltr; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; text-align: left; border-bottom-style: none"&gt;&lt;span id="lnum10" style="color: #606060"&gt;  10:&lt;/span&gt;                     for $printId in distinct-values(/theater/film [@film-id=$filmId]/@print-id)&lt;/pre&gt;&lt;br /&gt;&lt;!--CRLF--&gt;&lt;br /&gt;&lt;br /&gt;    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; direction: ltr; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: white; text-align: left; border-bottom-style: none"&gt;&lt;span id="lnum11" style="color: #606060"&gt;  11:&lt;/span&gt;                         order by $printId&lt;/pre&gt;&lt;br /&gt;&lt;!--CRLF--&gt;&lt;br /&gt;&lt;br /&gt;    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; direction: ltr; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; text-align: left; border-bottom-style: none"&gt;&lt;span id="lnum12" style="color: #606060"&gt;  12:&lt;/span&gt;                         return &lt;/pre&gt;&lt;br /&gt;&lt;!--CRLF--&gt;&lt;br /&gt;&lt;br /&gt;    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; direction: ltr; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: white; text-align: left; border-bottom-style: none"&gt;&lt;span id="lnum13" style="color: #606060"&gt;  13:&lt;/span&gt;                         &amp;lt;print&amp;gt;&lt;/pre&gt;&lt;br /&gt;&lt;!--CRLF--&gt;&lt;br /&gt;&lt;br /&gt;    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; direction: ltr; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; text-align: left; border-bottom-style: none"&gt;&lt;span id="lnum14" style="color: #606060"&gt;  14:&lt;/span&gt;                             { attribute id { $printId }}&lt;/pre&gt;&lt;br /&gt;&lt;!--CRLF--&gt;&lt;br /&gt;&lt;br /&gt;    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; direction: ltr; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: white; text-align: left; border-bottom-style: none"&gt;&lt;span id="lnum15" style="color: #606060"&gt;  15:&lt;/span&gt;                             {&lt;/pre&gt;&lt;br /&gt;&lt;!--CRLF--&gt;&lt;br /&gt;&lt;br /&gt;    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; direction: ltr; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; text-align: left; border-bottom-style: none"&gt;&lt;span id="lnum16" style="color: #606060"&gt;  16:&lt;/span&gt;                                 for $date in distinct-values(/theater/film [@film-id=$filmId and @print-id=$printId]/@date)&lt;/pre&gt;&lt;br /&gt;&lt;!--CRLF--&gt;&lt;br /&gt;&lt;br /&gt;    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; direction: ltr; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: white; text-align: left; border-bottom-style: none"&gt;&lt;span id="lnum17" style="color: #606060"&gt;  17:&lt;/span&gt;                                     order by $date&lt;/pre&gt;&lt;br /&gt;&lt;!--CRLF--&gt;&lt;br /&gt;&lt;br /&gt;    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; direction: ltr; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; text-align: left; border-bottom-style: none"&gt;&lt;span id="lnum18" style="color: #606060"&gt;  18:&lt;/span&gt;                                     return &lt;/pre&gt;&lt;br /&gt;&lt;!--CRLF--&gt;&lt;br /&gt;&lt;br /&gt;    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; direction: ltr; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: white; text-align: left; border-bottom-style: none"&gt;&lt;span id="lnum19" style="color: #606060"&gt;  19:&lt;/span&gt;                                     &amp;lt;date&amp;gt;&lt;/pre&gt;&lt;br /&gt;&lt;!--CRLF--&gt;&lt;br /&gt;&lt;br /&gt;    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; direction: ltr; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; text-align: left; border-bottom-style: none"&gt;&lt;span id="lnum20" style="color: #606060"&gt;  20:&lt;/span&gt;                                         {attribute date { $date }}&lt;/pre&gt;&lt;br /&gt;&lt;!--CRLF--&gt;&lt;br /&gt;&lt;br /&gt;    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; direction: ltr; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: white; text-align: left; border-bottom-style: none"&gt;&lt;span id="lnum21" style="color: #606060"&gt;  21:&lt;/span&gt;                                         {&lt;/pre&gt;&lt;br /&gt;&lt;!--CRLF--&gt;&lt;br /&gt;&lt;br /&gt;    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; direction: ltr; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; text-align: left; border-bottom-style: none"&gt;&lt;span id="lnum22" style="color: #606060"&gt;  22:&lt;/span&gt;                                             for $auditoriumId in distinct-values(/theater/film [@film-id=$filmId and @print-id = $printId and @date=$date]/@auditorium-id)&lt;/pre&gt;&lt;br /&gt;&lt;!--CRLF--&gt;&lt;br /&gt;&lt;br /&gt;    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; direction: ltr; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: white; text-align: left; border-bottom-style: none"&gt;&lt;span id="lnum23" style="color: #606060"&gt;  23:&lt;/span&gt;                                             return&lt;/pre&gt;&lt;br /&gt;&lt;!--CRLF--&gt;&lt;br /&gt;&lt;br /&gt;    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; direction: ltr; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; text-align: left; border-bottom-style: none"&gt;&lt;span id="lnum24" style="color: #606060"&gt;  24:&lt;/span&gt;                                             &amp;lt;auditorium&amp;gt;&lt;/pre&gt;&lt;br /&gt;&lt;!--CRLF--&gt;&lt;br /&gt;&lt;br /&gt;    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; direction: ltr; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: white; text-align: left; border-bottom-style: none"&gt;&lt;span id="lnum25" style="color: #606060"&gt;  25:&lt;/span&gt;                                                 { attribute id { $auditoriumId }}&lt;/pre&gt;&lt;br /&gt;&lt;!--CRLF--&gt;&lt;br /&gt;&lt;br /&gt;    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; direction: ltr; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; text-align: left; border-bottom-style: none"&gt;&lt;span id="lnum26" style="color: #606060"&gt;  26:&lt;/span&gt;                                                 { attribute name { /theater/film [@film-id=$filmId and @print-id = $printId and @date=$date and @auditorium-id=$auditoriumId]/@auditorium-name }}&lt;/pre&gt;&lt;br /&gt;&lt;!--CRLF--&gt;&lt;br /&gt;&lt;br /&gt;    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; direction: ltr; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: white; text-align: left; border-bottom-style: none"&gt;&lt;span id="lnum27" style="color: #606060"&gt;  27:&lt;/span&gt;                                             &amp;lt;/auditorium&amp;gt;&lt;/pre&gt;&lt;br /&gt;&lt;!--CRLF--&gt;&lt;br /&gt;&lt;br /&gt;    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; direction: ltr; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; text-align: left; border-bottom-style: none"&gt;&lt;span id="lnum28" style="color: #606060"&gt;  28:&lt;/span&gt;                                         }                                            &lt;/pre&gt;&lt;br /&gt;&lt;!--CRLF--&gt;&lt;br /&gt;&lt;br /&gt;    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; direction: ltr; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: white; text-align: left; border-bottom-style: none"&gt;&lt;span id="lnum29" style="color: #606060"&gt;  29:&lt;/span&gt;                                     &amp;lt;/date&amp;gt;&lt;/pre&gt;&lt;br /&gt;&lt;!--CRLF--&gt;&lt;br /&gt;&lt;br /&gt;    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; direction: ltr; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; text-align: left; border-bottom-style: none"&gt;&lt;span id="lnum30" style="color: #606060"&gt;  30:&lt;/span&gt;                             }&lt;/pre&gt;&lt;br /&gt;&lt;!--CRLF--&gt;&lt;br /&gt;&lt;br /&gt;    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; direction: ltr; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: white; text-align: left; border-bottom-style: none"&gt;&lt;span id="lnum31" style="color: #606060"&gt;  31:&lt;/span&gt;                         &amp;lt;/print&amp;gt;&lt;/pre&gt;&lt;br /&gt;&lt;!--CRLF--&gt;&lt;br /&gt;&lt;br /&gt;    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; direction: ltr; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; text-align: left; border-bottom-style: none"&gt;&lt;span id="lnum32" style="color: #606060"&gt;  32:&lt;/span&gt;                 }&lt;/pre&gt;&lt;br /&gt;&lt;!--CRLF--&gt;&lt;br /&gt;&lt;br /&gt;    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; direction: ltr; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: white; text-align: left; border-bottom-style: none"&gt;&lt;span id="lnum33" style="color: #606060"&gt;  33:&lt;/span&gt;             &amp;lt;/film&amp;gt;&lt;/pre&gt;&lt;br /&gt;&lt;!--CRLF--&gt;&lt;br /&gt;&lt;br /&gt;    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; direction: ltr; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; text-align: left; border-bottom-style: none"&gt;&lt;span id="lnum34" style="color: #606060"&gt;  34:&lt;/span&gt;         }&lt;/pre&gt;&lt;br /&gt;&lt;!--CRLF--&gt;&lt;br /&gt;&lt;br /&gt;    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; direction: ltr; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: white; text-align: left; border-bottom-style: none"&gt;&lt;span id="lnum35" style="color: #606060"&gt;  35:&lt;/span&gt;     &amp;lt;/theater&amp;gt;&lt;/pre&gt;&lt;br /&gt;&lt;!--CRLF--&gt;&lt;br /&gt;&lt;br /&gt;    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; direction: ltr; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; text-align: left; border-bottom-style: none"&gt;&lt;span id="lnum36" style="color: #606060"&gt;  36:&lt;/span&gt; '&lt;/span&gt;)&lt;/pre&gt;&lt;br /&gt;&lt;!--CRLF--&gt;&lt;/div&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;How does this suck? Let me count the ways&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;ol&gt;&lt;br /&gt;  &lt;li&gt;4 levels of nesting. Its not pretty. But, the VbScript has the same layers. (The logic is different, but its just as nested)&lt;/li&gt;&lt;br /&gt;&lt;br /&gt;  &lt;li&gt;Each layer has to go back to the top and work its way back down based on the key information collected thus far&lt;/li&gt;&lt;br /&gt;&lt;br /&gt;  &lt;li&gt;In the loops, I can only order by the loop indexer. For example: Auditorium. I don’t want to sort on “auditorium id”. I want to sort on display order. I can’t, because “auditorium id” is a value, not a node. If it was a node, I’d be able to get to a sibling attribute.&lt;/li&gt;&lt;br /&gt;&lt;br /&gt;  &lt;li&gt;It offers a handy distinct-values, but does not offer a handy distinct-nodes. (there are example how to do distinct-nodes, but the few I’ve seen use the LET statement, which you can’t do in SQL 2005)&lt;/li&gt;&lt;br /&gt;&lt;/ol&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;What doesn’t suck&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Obviously I’m having problems with it, but that may just be due to my staggering 45 minutes of inexperience with it.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;ol&gt;&lt;br /&gt;  &lt;li&gt;I like the syntax of specifying the attributes (shown) and elements (not shown) through the {} syntax&lt;/li&gt;&lt;br /&gt;&lt;br /&gt;  &lt;li&gt;I like that the comments are smiley faces (not shown).&amp;#160; (: this is an xquery comment :)&lt;/li&gt;&lt;br /&gt;&lt;br /&gt;  &lt;li&gt;In principle, I like how you can do the layering.&lt;/li&gt;&lt;br /&gt;&lt;/ol&gt;&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;The Problem&lt;/h2&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;I got the XML that I want, but its slow.&amp;#160; The SQL XQUERY consists of 2 parts: the query to get the data as xml, and the xquery to transform it the way I’d like it.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;The first part comes back instantaneously. The 2nd part takes anywhere from 2 to 16 seconds. One time, it took a minute and 54 seconds?!. Its really inconsistent. I looked at the execution plan multiple times. Every time it says that the first query accounts for 0% of the time, and the 2nd query accounts for 100% of the time.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;The legacy app does all it needs to do, including rendering it on the page, in a 1/2 second or less. You don’t even see it happen; you just click the link and the page renders.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;I know that my xquery is amateur. If I can rewrite it the way it should be written and try again, maybe the results will be drastically improved. (At least I hope they are.)&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Things that Would Help&lt;/h2&gt;&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;  &lt;li&gt;SQL 2008 supports the LET statement. If I had that in 2005, then I could assign node sets at the various levels, and treat that as the root for that level. Then it wouldn’t have to go to the top of the document every time. (At least, it seems like I’d be able to do that)&lt;/li&gt;&lt;br /&gt;&lt;br /&gt;  &lt;li&gt;If I could do a distinct-nodes instead distinct-values, then as I loop through, I can get the other stuff I need relative to the attribute. IE: &lt;a href="mailto:$film-id/../@film-name"&gt;$film-id/../@film-name&lt;/a&gt;.&lt;/li&gt;&lt;br /&gt;&lt;br /&gt;  &lt;li&gt;Knowledge of XQuery would sure be helpful.&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;&lt;h1&gt;Next Steps / Conclusions&lt;/h1&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;I wanted the source doc to be hierarchical so that its would be an accurate representation of the data. Since the XQuery didn’t work, I may end up doing it in C#. Then, the page will use an XSLT to render it. (I’ll look into using XQUERY to render it, but I don’t think that’s a viable option yet).&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;I developed the original application starting in 2001. Over the first few years, I spent a lot of time performance testing the quickest way to get the data out of the database and onto a page. I always lean towards XML and XSLT so that you can easily render it different ways. I want to keep it transformable.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Of all the things I tried, the quickest thing has always been:&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;ol&gt;&lt;br /&gt;  &lt;li&gt;Run the query and get back a flat dataset&lt;/li&gt;&lt;br /&gt;&lt;br /&gt;  &lt;li&gt;Use code to convert the dataset to xml&lt;/li&gt;&lt;br /&gt;&lt;/ol&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Despite the repeating data, and despite the manual conversion, it wins every time.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Things I may try&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;ol&gt;&lt;br /&gt;  &lt;li&gt;Convert the SQL XML to my XML via XSLT&lt;/li&gt;&lt;br /&gt;&lt;br /&gt;  &lt;li&gt;Convert the SQL XML to my XML via C# code (the old fashioned way with a new language)&lt;/li&gt;&lt;br /&gt;&lt;br /&gt;  &lt;li&gt;Read more about XQuery to determine how off-target my query really is&lt;/li&gt;&lt;br /&gt;&lt;/ol&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2143318148319291738-6576592043079130457?l=hamletcode.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://hamletcode.blogspot.com/feeds/6576592043079130457/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2143318148319291738&amp;postID=6576592043079130457' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2143318148319291738/posts/default/6576592043079130457'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2143318148319291738/posts/default/6576592043079130457'/><link rel='alternate' type='text/html' href='http://hamletcode.blogspot.com/2009/03/xquery-how-ye-disappoint.html' title='XQuery – How ye disappoint'/><author><name>Jay Allard</name><uri>http://www.blogger.com/profile/15785084867572890025</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh4.ggpht.com/_VTjiO7cQdSU/Sc-8xmROEZI/AAAAAAAAAJ0/ORN7V1kYFps/s72-c/image_thumb.png?imgmax=800' height='72' width='72'/><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2143318148319291738.post-4958045562459476925</id><published>2009-03-27T00:51:00.001-04:00</published><updated>2009-03-27T00:51:08.460-04:00</updated><title type='text'>Adventures in SCM</title><content type='html'>&lt;p&gt;After a long hiatus, I am resuming work on JTS. JTS is a theater management system that &amp;lt;a href=’http://muvico.com’&amp;gt;Muvico&amp;lt;/a&amp;gt; has been using since 2001ish.&lt;/p&gt;  &lt;p&gt;2001. That was years ago. Those were the days of ASP and COM+. .NET was still called ASP+. I was still prefixing everything I did with the letter J.&lt;/p&gt;  &lt;p&gt;The application now spans all generations of development technologies from ASP to .NET 3.5 SP1. Swell.&lt;/p&gt;  &lt;p&gt;The first big effort is to downgrade all of the COM+ to ASP, because ASP is easier to work with these days. The second big effort will be to selectively convert the modules to the IN-DEVELOPMENT JTS 3 API.&lt;/p&gt;  &lt;p&gt;I started researching what I can use for SCM. Ideally, I want it to be an online repository so that it doubles as backup service. (I use MOZY, but the client is dreadfully bad. Its almost unusable at this point. They said they’re rewriting it, but we’ll see.)&lt;/p&gt;  &lt;p&gt;My googling lead me here &lt;a href="http://www.myversioncontrol.com"&gt;http://www.myversioncontrol.com&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;For $5/month, I get what I need. Its subversion based, which I never used before. The service is excellent and its very generously priced. I have a security concern about it, though. I sent an email and we’ll see what happens. (it never asks for an encryption key. I’d like to keep their eyes out of my code.)&lt;/p&gt;  &lt;p&gt;MyVersionControl recommends 2 SVN clients: RAPID SVD and TORTOISE SVN. &lt;/p&gt;  &lt;p&gt;I couldn’t get RAPID to do anything. I got a lot of exceptions. I then tried TORTOISE which is a set of windows explorer shell extensions. That worked out pretty well. It took a little getting used to, though. My SCM exposure has been limited to VSS and StarTeam. This subversion stuff is different.&lt;/p&gt;  &lt;p&gt;Finally, I tackled VS integration, which ended up being an easy task. I found this product:&amp;#160; &lt;a href="http://visualvsn.com"&gt;http://visualvsn.com&lt;/a&gt;. I installed it and started using it. Peace of cake. VisualVSN, like MyVersionControl, offers a 30 day trials.&lt;/p&gt;  &lt;p&gt;Everything went well. I spent some time adding some filters to weed out the files that I don’t need to control. I checked everything in. My repository is now 50% full. Now I have 30 days to see if this sense of joy is permanent or fleeting.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2143318148319291738-4958045562459476925?l=hamletcode.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://hamletcode.blogspot.com/feeds/4958045562459476925/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2143318148319291738&amp;postID=4958045562459476925' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2143318148319291738/posts/default/4958045562459476925'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2143318148319291738/posts/default/4958045562459476925'/><link rel='alternate' type='text/html' href='http://hamletcode.blogspot.com/2009/03/adventures-in-scm.html' title='Adventures in SCM'/><author><name>Jay Allard</name><uri>http://www.blogger.com/profile/15785084867572890025</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2143318148319291738.post-2636570936703880601</id><published>2009-03-02T00:49:00.001-05:00</published><updated>2009-03-02T00:50:59.353-05:00</updated><title type='text'>Getting back on the ball with the DvdFriend, RSS feeds etc.</title><content type='html'>&lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;Today, I decided that I wanted to get my RSS feeds under control. I’m not very RSS saavy… I just use internet explorer to subscribe to them; nothing fancy. I ventured out to find a good web solution. I came across this little startup called “Google” which has, among other things, a decent reader.&lt;/p&gt;  &lt;p&gt;I haven’t used any other readers, so when I say “decent”, its not relative to anything else. Its very functional, like Gmail. And, the user interface isn’t great, like Gmail. But, its pretty neat.&lt;/p&gt;  &lt;p&gt;I have to rebuild a list of RSS feeds. If you come across this post, please let me know of your own personal feeds, and any others that you recommend. Please don’t assume that I already have it, even if I should.&lt;/p&gt;  &lt;p&gt;Also, I downloaded and am currently using WINDOWS LIVE WRITER. Good stuff. This will greatly improve the readability for people who take offense to typos. (I’m thinking of someone particular. You know who you are.)&lt;/p&gt;  &lt;p&gt;In a related story: I spent today getting a lot of stuff organized. I have multiple drives with duplicate code, documents, databases, etc. I’ve sorted through most of that. I also have some VMs:&lt;/p&gt;  &lt;p&gt;1 – super secret side project that I dumped because it wasn’t respecting my time&lt;/p&gt;  &lt;p&gt;2 – JTS&lt;/p&gt;  &lt;p&gt;3 – Other development efforts, including DvdFriend&lt;/p&gt;  &lt;p&gt;I’m getting all of those ducks in a line. The VM for #3 exists, but I haven’t setup the DvdFriend stuff yet. I’d like to get that going; I haven’t touched DvdFriend in months, and I’m itching to do some stuff. I started putting some prices and links in this week; Amazon and Netflix still work. Everyone else has changed their html, so the parser isn’t working. Oh well. 2 is better than none.&lt;/p&gt;  &lt;p&gt;The last time I worked on DvdFriend, I made progress towards asking TV reviews at the SHOW, SEASON and EPISODE levels. Of course, that was months ago and I have no idea where I left off or how I did it. Lets hope that I can read my own code.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2143318148319291738-2636570936703880601?l=hamletcode.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://hamletcode.blogspot.com/feeds/2636570936703880601/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2143318148319291738&amp;postID=2636570936703880601' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2143318148319291738/posts/default/2636570936703880601'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2143318148319291738/posts/default/2636570936703880601'/><link rel='alternate' type='text/html' href='http://hamletcode.blogspot.com/2009/03/getting-back-on-ball-with-dvdfriend-rss.html' title='Getting back on the ball with the DvdFriend, RSS feeds etc.'/><author><name>Jay Allard</name><uri>http://www.blogger.com/profile/15785084867572890025</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2143318148319291738.post-7306007713210282292</id><published>2009-02-07T19:51:00.003-05:00</published><updated>2009-02-07T20:25:35.086-05:00</updated><title type='text'>There's nothing wrong with a test hitting the database</title><content type='html'>Let me preface this rant with a preface. I work at a company that's all about agile, TDD, Scrum, and other cool words. Personally, I am all for those things. On the rare occasions that I have code unaccompanied by tests, I feel guilty. There should always be tests.&lt;br /&gt;&lt;br /&gt;But, that's the extent of my opinion of it. Write tests that test the code you're about to write. I'm not into mock objects. I don't debate the validity or non-validity of any one approach vs any other approach. I do what I have to do to produce a test that proves the code works. I really try to keep it simple. If I need a dummy implementation of an interface to prove something, then I spend 6 seconds to write the implementation.&lt;br /&gt;&lt;br /&gt;But, being in a company where there are lots of people with much stronger opinions about it, I hear a lot of stuff. When is a unit test no longer a unit test but a functional test? Should unit tests be allowed to hit the database? What should tests do and not do? Yadda yadda. I do not doubt the importance of those conversations or the ramifications of the results, its just not something I participate in. I'm more about the code and proving the code works; not the philosophy or implementation behind it.&lt;br /&gt;&lt;br /&gt;One of thoe things that comes up quite a bit is "the tests should not hit the database". My response to most things is "well, it depends on the test". If you're writing tests that are implicity hitting the database, then sure, in that case the database component should be swapped out with something simpler and faster without the environmental requirements. Yippee.&lt;br /&gt;&lt;br /&gt;But, sooner or later, you come down to the object that actually does the writes to and/or reads from the database. I'm sure you can emulate it, but if the object is a db object, then I'm of the opinion that you should make sure it reads and writes to/from the db. I don't know where that opinion stands in the overall view of the agile/tdd community, but I have heard blanket statements that tests should not hit the database.&lt;br /&gt;&lt;br /&gt;Last night, I got a call after hours asking me to look at some tests that were failing. I immediately stated it was environmental since the tests were 2 years old and hadn't been touched in 6 months, and then I set out to prove it. The cause of the failure was a missing row of "system delivered data" from the database that was there prior to the related project, and should always be there. &lt;br /&gt;&lt;br /&gt;If my test mocked the db activity rather than run it against the real scenarios, then we wouldn't have learned that the data was gone until someone fired up the product for real and tried to use it. The missing row was an adverse affect of a major database effort of another team. I wasn't involved with the fix, but as soon as it was identified they had no problem fixing it, so it seems to have been minor.&lt;br /&gt;&lt;br /&gt;So is it a functional test or is it a unit test? I don't know, and it doesn't matter to me. I wrote a test to prove that the code works, and as soon as an environmental dependency vanished, the test failed. That's the imporant part.&lt;br /&gt;&lt;br /&gt;Maybe there should've been a fitenesse test or some other automated test that would've tested the functionality within the website. Maybe that test does exist and we just didn't get to it yet. That's possible. But, it never got that far. They did the build and they ran the mbunit tests, and we immediately knew there was a problem.&lt;br /&gt;&lt;br /&gt;There is one take away from this: As a developer, the exception message allowed me to quickly identify what the problem was. But, it was implicit; I mentally traced it to the actual cause. My take away is to proactively check for this condition and throw an explicit error message.&lt;br /&gt;&lt;br /&gt;To those who say "your tests shouldn't hit the db", I say nay. Maybe I won't get the Agile Developer of the Year award, or maybe some in the TDD community will frown upon me, but the db hitting test identified a problem.&lt;br /&gt;&lt;br /&gt;We (my team) have lots of tests that hit the db. This one is a bit different since its know system delivered data, but most of other tests are not. In those cases, they insert all the test data they need, run the tests, then clean all the test data. We achieve this, in part, by not using identity fields on our setup tables. All our test data gets inserted with ids &gt; 10,000,000. We have a db test harness that's a facade for all of the things we need to do. The finally of every test calls a method that clears out all of the test data. All of these tests are flagged as "long running"; we run them locally, but not as part of the nightly build. In fact, we have a unit test that stress tests certain procs for thread safety.&lt;br /&gt;&lt;br /&gt;That concludes tonight's rant.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2143318148319291738-7306007713210282292?l=hamletcode.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://hamletcode.blogspot.com/feeds/7306007713210282292/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2143318148319291738&amp;postID=7306007713210282292' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2143318148319291738/posts/default/7306007713210282292'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2143318148319291738/posts/default/7306007713210282292'/><link rel='alternate' type='text/html' href='http://hamletcode.blogspot.com/2009/02/theres-nothing-wrong-with-test-hitting.html' title='There&apos;s nothing wrong with a test hitting the database'/><author><name>Jay Allard</name><uri>http://www.blogger.com/profile/15785084867572890025</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2143318148319291738.post-895139685358037675</id><published>2008-11-01T00:00:00.003-04:00</published><updated>2008-11-01T00:02:44.126-04:00</updated><title type='text'>AZURE update</title><content type='html'>Greetings&lt;br /&gt;&lt;br /&gt;I've only seen my very simple project work twice. The first time was when I first built it; the 2nd time was some random success. Typically, it just times out after 3 minutes.&lt;br /&gt;&lt;br /&gt;I'm setting this aside from now. This has inspired me on a project I've often talked about doing but never took on. So, I'm working on that now. I tend to start a lot of stuff and never finish it. This may be such a project, but at least for the moment, I'm motivated, and I'm working hard on it.&lt;br /&gt;&lt;br /&gt;I'm going to use SQLCE as the default data store for the project. I haven't used it before, so it'll be neat. (Of couse, you can swap it out with any data store you want, but it'll be ready to run out of the box because of CE)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2143318148319291738-895139685358037675?l=hamletcode.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://hamletcode.blogspot.com/feeds/895139685358037675/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2143318148319291738&amp;postID=895139685358037675' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2143318148319291738/posts/default/895139685358037675'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2143318148319291738/posts/default/895139685358037675'/><link rel='alternate' type='text/html' href='http://hamletcode.blogspot.com/2008/11/azure-update.html' title='AZURE update'/><author><name>Jay Allard</name><uri>http://www.blogger.com/profile/15785084867572890025</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2143318148319291738.post-8727995850483976374</id><published>2008-10-31T23:47:00.003-04:00</published><updated>2008-11-01T00:00:01.658-04:00</updated><title type='text'>Resharper: "Use implicitly typed local variable declaration"</title><content type='html'>I've been using Reshaper for a couple weeks now. I like it a lot. When I was given the option to get a license for this, I responded that I would rather Code Rush. Afterall, I write more code than I refactor.&lt;br /&gt;&lt;br /&gt;That ended up being an over simplification, though. Resharper has lots of great goodies in it. Though I would still like Code Rush, Reshaper is great all by itself. I learn to appreciate it more any day.&lt;br /&gt;&lt;br /&gt;Except for the "Use implicitly typed local variable declaration" hint.&lt;br /&gt;&lt;br /&gt;As an example, I have this line of code:&lt;br /&gt;&lt;br /&gt;      ServiceDescription description = attribute as ServiceDescription;&lt;br /&gt;&lt;br /&gt;the type, ServiceDescription, is underlined with the fore-mentioned hint. Basically, its telling me to define the type as VAR and let the compiler figure it out for me.&lt;br /&gt;&lt;br /&gt;I'm not a fan of that suggestion at all. If I know what type it is, then I want to specify the type. I don't need the compiler to figure it out for me. If I end up specifying a less than optimistic type (ie: should've used XmlReader instead of XmlTextReader), then Resharper or FxCop will let me know, and I'll learn from my mistake rather than just let the compiler do its voodoo for me.&lt;br /&gt;&lt;br /&gt;However, I don't want to be irrational and just blindly shut off the hint. I wanted to find the justification for that hint, so I started poking around. It seems that there are 2 prevailing schools of though on this: Those that think you should use it for everything, and those that think you should only use it for anonymous types.&lt;br /&gt;&lt;br /&gt;After reading a few different things, I have committed to my opinion expressed above: If you don't know what type it will be (because its anonymous), the use var. Otherwise, specify the type.&lt;br /&gt;&lt;br /&gt;A guy from resharper justifies it here:&lt;br /&gt;&lt;br /&gt;    http://resharper.blogspot.com/2008/03/varification-using-implicitly-typed.html&lt;br /&gt;&lt;br /&gt;While interesting, it doesn't sell me. Some comments on some bullets:&lt;br /&gt;- Its is required to expres variables of anonymous type - no kidding. that's why it was invented.&lt;br /&gt;- It induces better naming for local variables - that's putting a square peg in a circle hole. Its handholding at best. If you name you're variable CURRENT then its scope should be so small as to always remain obvious what it is. If it isn't obvious, then you named it wrong, and declaring it of type var isn't going to make you name it any better.&lt;br /&gt;- It induces variable initialization. - Again, I don't need VAR to force me to do that.&lt;br /&gt;- It removes code noise. - Maybe. I'd like to see some samples before I buy it.&lt;br /&gt;- It doesn't require a using directive - so what? Are using directives troublesome to anyone? Heck, Resharper puts it in for you. If you don't have resharper, then CONTROL+. will put it in for you.&lt;br /&gt;&lt;br /&gt;That's my story.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2143318148319291738-8727995850483976374?l=hamletcode.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://hamletcode.blogspot.com/feeds/8727995850483976374/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2143318148319291738&amp;postID=8727995850483976374' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2143318148319291738/posts/default/8727995850483976374'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2143318148319291738/posts/default/8727995850483976374'/><link rel='alternate' type='text/html' href='http://hamletcode.blogspot.com/2008/10/resharper-use-implicitly-typed-local.html' title='Resharper: &quot;Use implicitly typed local variable declaration&quot;'/><author><name>Jay Allard</name><uri>http://www.blogger.com/profile/15785084867572890025</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2143318148319291738.post-3479007641108622275</id><published>2008-10-30T14:27:00.002-04:00</published><updated>2008-10-30T15:01:31.721-04:00</updated><title type='text'>Windows Azure - Cool</title><content type='html'>Greetings&lt;br /&gt;&lt;br /&gt;By recommendation of a co-worker who is at PDC, I immediately signed up for AZURE and download all of the associated files. I also had to update this machine to 3.5 SP1 and VS2008 SP1.&lt;br /&gt;&lt;br /&gt;The following is just running commentary on what I'm doing as I do it.&lt;br /&gt;&lt;br /&gt;Once everything was in, I opened up VS2008 and found the new CLOUD SERVICE project options. I can only guess what a worker is, so kept it simple and started with just a simple WEB CLOUD SERVICE.&lt;br /&gt;&lt;br /&gt;This creates 2 projects: The service itself and a webrole. Again, I can only speculate on how we'll use WEB ROLE based on the name. The service project has a ROLES folder with a refernece to the ROLE project. Swell.&lt;br /&gt;&lt;br /&gt;The role project looks like a website. It has a web.config, Default.aspx, Default.aspx.cs, and Default.aspx.designer.cs. (I think that last file is new too. If its been in 2008, then I never noticed it. Don't know if its an AZURE thing or a SP1 thing.) The service file has two configuration files: a csdef and a cscfg. One defines the service, the other configures it. The cscfg defines the endpoint name, port and protocol. It notes that the port must be 80 in the actual cloud environment, though you can use whatever you want in the dev environment.&lt;br /&gt;&lt;br /&gt;I didn't make any changes since I really have no idea what I'm doing yet. I hit the RUN button to see what happened.&lt;br /&gt;&lt;br /&gt;The status bar reports "Initializaing Local Development Service", or something like that. VS seems to hang for a while, then reports that it can't find .\SQLEXPRESS. That's fine. I don't have SQLEXPRESS. Then it hangs some more, and eventually says that the service timed out.&lt;br /&gt;&lt;br /&gt;For kicks, I started downloading sqlexpress 2008. I haven't used 2008 yet, so now's as good a time as any. In the meantime, though, there must be a way to switch the database info.&lt;br /&gt;&lt;br /&gt;I found the answer in C:\Program Files\Windows Azure SDK\v1.0\bin\DevelopmentStorage.exe.config. I changed the setting, then hit run in VS2008 again. It reports that DEVELOPMENT STORAGE IS ALREADY RUNNING. ONLY ONE INSTANCE OF THE APPLICATION CAN BE RUN AT THE SAME TIME. Then it hangs again, and eventually comes back the SERVICE TIME OUT ERROR.&lt;br /&gt;&lt;br /&gt;I looked in Task Manager/Processes, and services.msc for any sign of this thing. No luck. That's not to say its not there, but I didn't see it short of looking at each process individually. I checked for things like AZURE and DEVELOPMENT, etc. (In retrospect, I should have looked through the vs2008 menus and icons. There's probably something there)&lt;br /&gt;&lt;br /&gt;Oh well. Time to restart vs2008. This time, when clicking run, it asks me if its ok to do some initialization as an administrator. Fine with me; go for it.&lt;br /&gt;&lt;br /&gt;It reports this:&lt;br /&gt;Added reservation for 'http://127.0.0.1:10000/' for user account 'jayavst690\jaya'&lt;br /&gt;Added reservation for 'http://127.0.0.1:10001/' for user account 'jayavst690\jaya'&lt;br /&gt;Added reservation for 'http://127.0.0.1:10002/' for user account 'jayavst690\jaya'&lt;br /&gt;&lt;br /&gt;Checking if database 'DevelopmentStorageDb' exists on server '.\personal'&lt;br /&gt;Creating database DevelopmentStorageDb&lt;br /&gt;&lt;br /&gt;Granting database access to user 'jayavst690\jaya'&lt;br /&gt;The login already has an account under a different user name.&lt;br /&gt;Changed database context to 'DevelopmentStorageDb'.&lt;br /&gt;Adding database role for user jayavst690\jaya&lt;br /&gt;User or role 'jaya' does not exist in this database.&lt;br /&gt;Changed database context to 'DevelopmentStorageDb'.&lt;br /&gt;&lt;br /&gt;Initialization successful. The development storage is now ready for use.&lt;br /&gt;&lt;br /&gt;Now, there's a DEVELOPMENT STORAGE icon in my system tray. Was that there before? Didn't notice. This time, it gave me a baloon to let me know it was up and running. There wasn't one when it failed.&lt;br /&gt;&lt;br /&gt;The development storage app shows that there are 3 services: Blob, Queue, Table. Table is stopped, the other 2 are running. The menu bar doesn't gives us a whole lot to do.&lt;br /&gt;&lt;br /&gt;I closed it and ran it again. This time, vs2008 hung. It gave me the "vs2008 is waiting for an internal process" message. Swell. I see that in sql server management studio 2005 all the time (usually when working with diagrams), but this is the first time for vs2008.&lt;br /&gt;&lt;br /&gt;I got tired of waiting, so killed it from the task manager. While in there, guess what I noticed: DevelopmentStorage.exe. That definitely wasn't there when I checked earlier.&lt;br /&gt;&lt;br /&gt;I restarted vs2008, and ran the project again. Development Storage started, but vs2008 is hanging again.&lt;br /&gt;&lt;br /&gt;So far: Lots of hanging.&lt;br /&gt;&lt;br /&gt;Now I'm just trying to get it to do something. I read a blog entry that tells me WEB ROLE isn't what I thought it would be (I was guessing just based on the word role). My goal is to get a silly DvdFriend service going. I'll keep you posted.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2143318148319291738-3479007641108622275?l=hamletcode.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://hamletcode.blogspot.com/feeds/3479007641108622275/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2143318148319291738&amp;postID=3479007641108622275' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2143318148319291738/posts/default/3479007641108622275'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2143318148319291738/posts/default/3479007641108622275'/><link rel='alternate' type='text/html' href='http://hamletcode.blogspot.com/2008/10/windows-azure-cool.html' title='Windows Azure - Cool'/><author><name>Jay Allard</name><uri>http://www.blogger.com/profile/15785084867572890025</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2143318148319291738.post-3054317476157235658</id><published>2008-07-31T08:27:00.003-04:00</published><updated>2008-07-31T08:33:23.127-04:00</updated><title type='text'>Related Products</title><content type='html'>I added some support for "Related Products". If you select Dark Knight, for example, the product page will also show you Batman Begins.&lt;br /&gt;&lt;br /&gt;This involved three new tables:&lt;br /&gt;- ProductGroupType&lt;br /&gt;- ProductGroup&lt;br /&gt;- ProductGroupMembers&lt;br /&gt;&lt;br /&gt;Two new views:&lt;br /&gt;- vwProductGroups&lt;br /&gt;- vwProductGroupMembers&lt;br /&gt;&lt;br /&gt;Stored Procedure:&lt;br /&gt;- GetRelatedProducts&lt;br /&gt;&lt;br /&gt;I added a new object data source to the page, and a gridview. The ODS calls a method that calls the stored procedure and returns a datatable (keep it simple).&lt;br /&gt;&lt;br /&gt;Currently, it just lists them with links. That will improve. Also, a product may be associated to multiple groups. The page will have to improve to show the different groups. For now, they're all just merged into one distinct list.&lt;br /&gt;&lt;br /&gt;I'm not going to make an effort to backfill groups. But, as new movies come up, I'll create new groups as appropriate. So far, there are groups for Stargate, Lost Boys, Hellboy, and Batman.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2143318148319291738-3054317476157235658?l=hamletcode.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://hamletcode.blogspot.com/feeds/3054317476157235658/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2143318148319291738&amp;postID=3054317476157235658' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2143318148319291738/posts/default/3054317476157235658'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2143318148319291738/posts/default/3054317476157235658'/><link rel='alternate' type='text/html' href='http://hamletcode.blogspot.com/2008/07/related-products.html' title='Related Products'/><author><name>Jay Allard</name><uri>http://www.blogger.com/profile/15785084867572890025</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2143318148319291738.post-6790965786590773089</id><published>2008-07-30T00:30:00.003-04:00</published><updated>2008-07-30T00:32:15.937-04:00</updated><title type='text'>MVC Preview 4</title><content type='html'>Preview 4 came out yesterdayish (at least, that's when I first heard of it). I haven't updated my test site yet, but will. Tonight I got hung up writing some queries for my side-venture. I have another task to do for them, then I'll be back for MVC Preview 4, and new work on the DvdFriend site. (Next up, I think, is product level comments. Lets rants and speculate about movies and DVDs without actually seeing them!)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2143318148319291738-6790965786590773089?l=hamletcode.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://hamletcode.blogspot.com/feeds/6790965786590773089/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2143318148319291738&amp;postID=6790965786590773089' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2143318148319291738/posts/default/6790965786590773089'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2143318148319291738/posts/default/6790965786590773089'/><link rel='alternate' type='text/html' href='http://hamletcode.blogspot.com/2008/07/mvc-preview-4.html' title='MVC Preview 4'/><author><name>Jay Allard</name><uri>http://www.blogger.com/profile/15785084867572890025</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2143318148319291738.post-5232362782559445883</id><published>2008-07-28T23:29:00.002-04:00</published><updated>2008-07-28T23:33:42.791-04:00</updated><title type='text'>Added News and Feed</title><content type='html'>I added a NEWS section to the top of the main page. It will really be more than news, though... more like notices, perhaps.&lt;br /&gt;&lt;br /&gt;The News support was already in there. It was displayed on the page somewhere about a year ago, but it didn't look good or wasn't useful, so I got rid of it.&lt;br /&gt;&lt;br /&gt;Fortunately, the method to retrieve it is still there. Basically, I just call GetRecentEntries(5, "news", true).&lt;br /&gt;Last 5 entries; news zone; get the entire text rather than just the title.&lt;br /&gt;&lt;br /&gt;There's a news feed too, but its going to need work. The title of a blog entry may contain HTML (ie: the link to dark city), but a syndication title may not. I have to change the entry page to distinguish between the title and what the title links to (if anything). In the meantime, it tears the html out of the title if there is any. Then, for the permalink, it extracts the link. If the link it exists, it uses it. Otherwise, it just links to the main page.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2143318148319291738-5232362782559445883?l=hamletcode.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://hamletcode.blogspot.com/feeds/5232362782559445883/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2143318148319291738&amp;postID=5232362782559445883' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2143318148319291738/posts/default/5232362782559445883'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2143318148319291738/posts/default/5232362782559445883'/><link rel='alternate' type='text/html' href='http://hamletcode.blogspot.com/2008/07/added-news-and-feed.html' title='Added News and Feed'/><author><name>Jay Allard</name><uri>http://www.blogger.com/profile/15785084867572890025</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2143318148319291738.post-7807088815435938873</id><published>2008-07-27T23:29:00.002-04:00</published><updated>2008-07-27T23:36:57.123-04:00</updated><title type='text'>Web delay fixed</title><content type='html'>The production site, since moving to GoDaddy, has always taken a few seconds to load on the first hit. The problem is that the first hits are very frequent. Almost every time I go to the site, its a first hit. &lt;br /&gt;&lt;br /&gt;It never really bothered me much because there are only a few visitors a day, but now that the embedding is enabled, its more intrusive. The hamletcode blog would pause as it waited for the dvdfriend site to fire up to serve the demo embedded review.&lt;br /&gt;&lt;br /&gt;I poked around in the pool settings and found that the worker process was set to shut down after 5 minutes of being idle. I disabled that. I also saw that it was set to recycle ever 29 hours, so got rid of that. There's really no reason for the worker process to need to be recycled, but this will be a good test to make sure.&lt;br /&gt;&lt;br /&gt;Since I was in there anyway, I changed the session timeout from 20 to 60 minutes. Effectively, the timeout was 5 minutes anyway since there's rarely more than one person writing a review at any given time.&lt;br /&gt;&lt;br /&gt;This should resolve all the timing issues. Also, it will help coverup a bug with the review page; If session times out while you're writing the review, you lose it. That's definitely very bogus and I have no reason to avoid fixing it other than a complete lack of interest. In fact, that's the last thing that's stopping me from removing the "under construction" label.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;In conclusion&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2143318148319291738-7807088815435938873?l=hamletcode.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://hamletcode.blogspot.com/feeds/7807088815435938873/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2143318148319291738&amp;postID=7807088815435938873' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2143318148319291738/posts/default/7807088815435938873'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2143318148319291738/posts/default/7807088815435938873'/><link rel='alternate' type='text/html' href='http://hamletcode.blogspot.com/2008/07/web-delay-fixed.html' title='Web delay fixed'/><author><name>Jay Allard</name><uri>http://www.blogger.com/profile/15785084867572890025</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2143318148319291738.post-6982301481468818273</id><published>2008-07-27T21:49:00.004-04:00</published><updated>2008-07-27T22:08:27.479-04:00</updated><title type='text'>Reviews can now be embedded</title><content type='html'>I was going to make this feature available to only people that are logged in, but then realized that it probably doesn't make sense to limit my exposure. Embed away!&lt;br /&gt;&lt;br /&gt;&lt;script language='javascript' type='text/javascript' src='http://www.dvdfriend.us/Content.svc/review/44fb6cc2-1f07-46da-86e5-440bae340d25'&gt;&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;The code goodies follow. ReviewHtml.GetReview() simply builds a bunch of javacript document.write() methods.&lt;br /&gt;&lt;br /&gt;    [ServiceContract]&lt;br /&gt;    public interface IContentService&lt;br /&gt;    {&lt;br /&gt;        [OperationContract]&lt;br /&gt;        [WebGet(UriTemplate = "review/{reviewId}", BodyStyle = WebMessageBodyStyle.Bare, ResponseFormat=WebMessageFormat.Xml)]&lt;br /&gt;        Stream GetReview(string reviewId);&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public class ContentService : IContentService&lt;br /&gt;    {&lt;br /&gt;        public Stream GetReview(string reviewId)&lt;br /&gt;        {&lt;br /&gt;            return new MemoryStream(Encoding.UTF8.GetBytes(ReviewHtml.GetReview(new Guid(reviewId))));&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;Here are some interesting things I learned:&lt;br /&gt;- I had to return the text as a stream rather than as text. If you return it as just a string, then there's always sometype of serialization wrapper around it. Additionaly, the generated html tags get encoded. So, we get &amp;lt;td&amp;gt; instead &lt;td&gt;.&lt;br /&gt;&lt;br /&gt;- In the UriTemplate, you specify the parameters.&lt;br /&gt;&lt;br /&gt;      UriTemplate = "review/{reviewId}"&lt;br /&gt;&lt;br /&gt;Its maps the value in {reviewId} to the reviewId parameter of the method. That's cool; very MVCish. Unlike MVC, however, it must be a string. In this case, the ID is a guid, but the mthod must accept a string.&lt;br /&gt;&lt;br /&gt;I find this dissapointing and, if I had to guess, I'd say that will change. The framework is certainly capable of converting known types for us.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;I really just sort of tripped through the WCF stuff in this case. I have to read up on the new REST capabilities.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2143318148319291738-6982301481468818273?l=hamletcode.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://hamletcode.blogspot.com/feeds/6982301481468818273/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2143318148319291738&amp;postID=6982301481468818273' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2143318148319291738/posts/default/6982301481468818273'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2143318148319291738/posts/default/6982301481468818273'/><link rel='alternate' type='text/html' href='http://hamletcode.blogspot.com/2008/07/reviews-can-now-be-embedded.html' title='Reviews can now be embedded'/><author><name>Jay Allard</name><uri>http://www.blogger.com/profile/15785084867572890025</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2143318148319291738.post-7055398853982484088</id><published>2008-07-23T20:40:00.003-04:00</published><updated>2008-07-23T20:57:02.459-04:00</updated><title type='text'>Good bye faithful printer.... Good bye!</title><content type='html'>I have mixed feelings about the passing of my printer.&lt;br /&gt;&lt;br /&gt;Well, see... there. I've lied already. In the very first sentence I'm lying like a president. The printer isn't so much "passing" as it being put down.&lt;br /&gt;&lt;br /&gt;I have a Lexmark X125 all in one printer. It is AT LEAST 5 years old; possibly even more than 6, but I have definite milestones to peg it at least 5.&lt;br /&gt;&lt;br /&gt;Its a cool little printer that I got for cheap and has lasted, to some extent, all this time. It still works. In fact, shortly after I bought it, I bought one for my parents too. (Coincidentally, last night I received a call about a new printer they bought. I believe that they too were still using their X125 until recently, but unconfirmed.)&lt;br /&gt;&lt;br /&gt;So why the mixed feelings? On one hand, I bought a cheap printer and used it for 5 years. On the other hand, it annoyed me every time.&lt;br /&gt;&lt;br /&gt;Here's the thing: the drivers suck. They always have. Lexmark support was 0 help... I gave up years ago. The printer will work for a while, then you have to kill some processes in order to get it to print again. I exchanged many emails with them just trying to get them to come clean and say "sorry, we suck", but they wouldn't.&lt;br /&gt;&lt;br /&gt;The next logical question may be, "How did you put up with that for 5 years, you poor poor soul!?". The answer is simple: I don't do a heck of a lot of printing. I bought a box of paper years ago and I still have most of the reems (spelling?). I just don't have a need or a desire to print. If I want to read something from the computer, I just read it on the computer. It doesn't have to be paper. I keep all our digital images as digital images... I don't print them.&lt;br /&gt;&lt;br /&gt;Lately, I've had a need to print some stuff, for expense reports, on a monthly basis. My luck has been limited. I occasionaly go to the office with the intent of printing the stuff, but then it slips my mind and I leave empty handed. Ick. I also have to fax my receipts, an the X125 was being difficult. It would often say "replace cartridge" even though it was a new cartridge. After multiple attempts, I thought it was dead. Then, it finally worked.&lt;br /&gt;&lt;br /&gt;So now, at long last, we're at the point where it is essentially unusable. I want to be one of the cool kids that simply clicks "print" and the thing prints. Is that too much to ask? Am I being a snob by not wanting to fight to print for 5 minutes a page? I don't think so, but I value your opinion, so let me know.&lt;br /&gt;&lt;br /&gt;Due to the fact that I work from home, my esteemed employer found it in its heart (and wallet) to equip me with a brand new HP5610. I plugged it in and clicked print. Guess what... it printed! Now I feel like a king. Rejoice!&lt;br /&gt;&lt;br /&gt;I'll cart the ole X125 up to the recycling center on my next trip. When I dump it in the box, perhaps I will pause for just a moment and reflect on the times gone by, both good and bad, but I make no promises.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2143318148319291738-7055398853982484088?l=hamletcode.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://hamletcode.blogspot.com/feeds/7055398853982484088/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2143318148319291738&amp;postID=7055398853982484088' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2143318148319291738/posts/default/7055398853982484088'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2143318148319291738/posts/default/7055398853982484088'/><link rel='alternate' type='text/html' href='http://hamletcode.blogspot.com/2008/07/good-bye-faithful-printer-good-bye.html' title='Good bye faithful printer.... Good bye!'/><author><name>Jay Allard</name><uri>http://www.blogger.com/profile/15785084867572890025</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2143318148319291738.post-3214312611220403274</id><published>2008-07-23T00:19:00.005-04:00</published><updated>2008-07-23T00:52:30.430-04:00</updated><title type='text'>Coming Soon - Embedded Reviews</title><content type='html'>Chris has stated his desire to be able to embed his DvdFriend reviews elsewhere in the internet galaxy. Interesting idea. I haven't done that before. (For those of you just joining us, I'm not real big on building web pages. There are a lot of things I haven't done.)&lt;br /&gt;&lt;br /&gt;Anyway, I started looking into this. The first thing that jumped to mind was left over from 1995: Add an iframe. The second thing to jump to mind was: don't be ridiculous.&lt;br /&gt;&lt;br /&gt;I started searching on the current swell ways to do this. The goal, per normal, is keep it simple. I just want the user to drop a little piece of something on their page and have it work. I came across XSS pretty quick, then avoided it since XSS is often associated with bad mojo due to attacks. I looked at the object&lt;br /&gt;tag... Couldn't get it to work with external web pages.&lt;br /&gt;&lt;br /&gt;Eventually, I ended up back to XSS.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Created A Page called ReviewScript.aspx&lt;/strong&gt;&lt;br /&gt;I wiped out everything from the ASPX except for the server tags at the top.&lt;br /&gt;&lt;br /&gt;The PageLoad calls Response.Clear(). It then builds a big piece of javascript that, basically, generates some html then writes it to the document.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Add a script tag to the page that references ReviewScript.aspx&lt;/strong&gt;&lt;br /&gt;Every time I paste any type of tag into this stupid thing, it loses it. And I'm currently too lazy to deal with a screen shot. So, mentally fill in angle brackets.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;script language='javascript' type='text/javascript' src='http://www.dvdfriend.us/ReviewScript.aspx?id=xxx'&lt;br /&gt;/script&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Sweet. I started by including that on the dvdfriend main page (dev version) so that I can compare whats generated to what shows up on the page.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Templates / Make it look as it does on the main page&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;The generated html is based on a template. The default template is going to look exactly like a rewiew does on the main page. I started by embedding the script on the main page so that I could look at them next to each other. Once it was close, I moved it to another site altogether.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Create a new CSS&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;As soon as I imported the dvdfriend.css to the other site, it messed up the entire page. That was expected. I created a new css called external.css and copied over only the styles i needed. I renamed them all with a prefix of DF, just to keep them separated.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Incidentally, the css is included by document.writing a link tag.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;That pretty much did it.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Template - So Far&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;The template has these tokens so far:&lt;br /&gt;DvdFriendCss&lt;br /&gt;Rating&lt;br /&gt;Title&lt;br /&gt;ProductTypeImage&lt;br /&gt;ProductName&lt;br /&gt;ProductId&lt;br /&gt;CreateDate&lt;br /&gt;Author - pending. Have to populate this&lt;br /&gt;RatingClass&lt;br /&gt;AuthorLink&lt;br /&gt;ProductLink&lt;br /&gt;ReadLink&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;The list will grow. Most of them are just pieces of data so that you can build it anyway you want. Some of them are more generic to give you something to start with. the LINK tokens, for example, automatically create the links as you see them on the home page now.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;TODO&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;- See if there is a better way to include the CSS. If there are multiple embeds on the same page, it will import the css multiple times. Would rather do it through javascript.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;- Retrieve the author. The page is built from a datatable. The script is built from a blog object which, mysteriously, doesn't already have an AUTHOR property exposed.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;- Work out some additional css issues. It almost looks like it does on the site, but I still have some font issues to resolve.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;- Test in production environment. I've only used it on my local machine. Lets see if it actually works out there. Furthermore, lets see what types of things, if any, prevent the xss from firing.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;- LATER: Allow for users to create their own templates using the available tokens. I think that every template will be available to every user, but it can only be editted by the person who created it. We'll see.&lt;br /&gt;&lt;br /&gt;&lt;p&gt;- Brush my teeth and go to bed&lt;/p&gt;&lt;p&gt;- Server it as a WCF service rather than an aspx page. The aspx is a quick and dirty just to get it going. I will convert it to a WCF service much like the RSS feed. The one missing piece of info there is how to pass parameters. It shouldn't be a big deal; I just have to look into it.&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Screenshot&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;Here's what it looks like embedded on the now neglected Clan Friend site.&lt;/p&gt;&lt;p&gt;The background of the review is always white. Its not inheriting it from the parent element.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://2.bp.blogspot.com/_VTjiO7cQdSU/SIa3FM95UmI/AAAAAAAAAGM/XptwlEIP7pQ/s1600-h/embed.PNG"&gt;&lt;img id="BLOGGER_PHOTO_ID_5226065717618102882" style="CURSOR: hand" alt="" src="http://2.bp.blogspot.com/_VTjiO7cQdSU/SIa3FM95UmI/AAAAAAAAAGM/XptwlEIP7pQ/s320/embed.PNG" border="0" /&gt;&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/2143318148319291738-3214312611220403274?l=hamletcode.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://hamletcode.blogspot.com/feeds/3214312611220403274/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2143318148319291738&amp;postID=3214312611220403274' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2143318148319291738/posts/default/3214312611220403274'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2143318148319291738/posts/default/3214312611220403274'/><link rel='alternate' type='text/html' href='http://hamletcode.blogspot.com/2008/07/coming-soon-embedded-reviews.html' title='Coming Soon - Embedded Reviews'/><author><name>Jay Allard</name><uri>http://www.blogger.com/profile/15785084867572890025</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_VTjiO7cQdSU/SIa3FM95UmI/AAAAAAAAAGM/XptwlEIP7pQ/s72-c/embed.PNG' height='72' width='72'/><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2143318148319291738.post-814476612710304947</id><published>2008-07-20T21:57:00.002-04:00</published><updated>2008-07-20T22:04:03.928-04:00</updated><title type='text'>First RSS Feed is live</title><content type='html'>I deployed the first DvdFriend RSS feed. I kept it as a WCF service afterall. I'll keep it that way until i come up with a reason not to.&lt;br /&gt;&lt;br /&gt;The deployment wasn't painless. It didn't work in production as it did in development. It was because there are multiple sites on the server that are distinguished by host headers.  Ilearned in 3.0, you had to code around it. 3.5 makes it a little easier. I found this link:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://blogs.msdn.com/rampo/archive/2008/02/11/how-can-wcf-support-multiple-iis-binding-specified-per-site.aspx"&gt;http://blogs.msdn.com/rampo/archive/2008/02/11/how-can-wcf-support-multiple-iis-binding-specified-per-site.aspx&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;I added &lt;a href="http://www.dvdfriend.us/"&gt;http://www.dvdfriend.us&lt;/a&gt; as a prefix. I attempted to add &lt;a href="http://dvdfriend.us/"&gt;http://dvdfriend.us&lt;/a&gt; as a second prefix, but it went back to the orignal error. Go figure. I don't havea  good grasp on this stuff yet, but its working, so we're ok for now&lt;br /&gt;&lt;br /&gt;I think COMMENTS will be the next feed. I have to create a page for that anyway, so they'll have the same data source.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2143318148319291738-814476612710304947?l=hamletcode.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://hamletcode.blogspot.com/feeds/814476612710304947/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2143318148319291738&amp;postID=814476612710304947' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2143318148319291738/posts/default/814476612710304947'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2143318148319291738/posts/default/814476612710304947'/><link rel='alternate' type='text/html' href='http://hamletcode.blogspot.com/2008/07/first-rss-feed-is-live.html' title='First RSS Feed is live'/><author><name>Jay Allard</name><uri>http://www.blogger.com/profile/15785084867572890025</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2143318148319291738.post-8528086490782132736</id><published>2008-07-20T00:56:00.015-04:00</published><updated>2008-07-20T09:15:24.981-04:00</updated><title type='text'>RSS 2 / Atom 1 Feeds</title><content type='html'>.NET 3.5 adds a WebHttp WCF binding and Synidication support. I haven't tried anything with syndication yet. Now seemed like a good time.&lt;br /&gt;&lt;br /&gt;&lt;div&gt;The DvdFriend home page shows the most recent 50 ratings/reviews. I've received more than one request to make that, and comments, available as feeds. I started with the recent activity.&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;div&gt;Setting it up as a WCF service was pretty easy, though I'll probably end up dropping it. I'll probably just expose it as SYNDICATION.aspx or something. We'll see. Regardless, doing it as a WCF service was a good experience.&lt;/div&gt;&lt;br /&gt;&lt;div&gt;Once I had a test feed going, it was time to populate it with the actual data. I thought LINQ would be the way to go. I already have a static method that returns a list of the recent reviews as a data table. I thought I'd just write a linq query against that data table. No dice. LINQ doesn't work on data tables. Swell. (Well, not really).&lt;/div&gt;&lt;br /&gt;&lt;div&gt;I wrote a generic wrapper class to make things enumerable for linq. (Is this the best solution? I don't know. But it works.)&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;div&gt;&lt;a href="http://4.bp.blogspot.com/_VTjiO7cQdSU/SILHAA5_zwI/AAAAAAAAAFM/GBSxv39dCy8/s1600-h/linqwrapper.JPG"&gt;&lt;img id="BLOGGER_PHOTO_ID_5224957320760381186" style="CURSOR: hand" alt="" src="http://4.bp.blogspot.com/_VTjiO7cQdSU/SILHAA5_zwI/AAAAAAAAAFM/GBSxv39dCy8/s320/linqwrapper.JPG" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;strong&gt;NOTE:&lt;/strong&gt; Changed this code. See notes at the bottom. (Changed GetEnumerator to return _items.GetEnumerator rather than yield through it itself)&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Next, I had to write a Linq query that would return a List&lt;syndicationitem&gt;. In the process, I had to explore some of the properties and methods to see what was what. I set the basic stuff, but there were 2 things that I wanted to set, but couldn't during initialization:&lt;/div&gt;&lt;br /&gt;&lt;div&gt;- The author. SyndicationItem.Authors is a List&lt;syndicationauthor&gt;(), so you don't initialize it. You have to add to the existing list.&lt;/div&gt;&lt;br /&gt;&lt;div&gt;- The item link. At first, I figured this would be BASEURI, but it wasn't. You have to call item.AddPermaLink(new Uri("...")). Its a method; can't call it during initialization.&lt;/div&gt;&lt;br /&gt;&lt;div&gt;For author, I could loop through all the items after the initial query and update the individual items from the datatable. But, not interested. That didn't sound like a very good solution. I only want to hit the datatable once and be done with it. PermLink would require a loop too, but that's based on ID which is already a property of SyndicationItem, so no problem there.&lt;/div&gt;&lt;br /&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;I solved the author issue by creating a subclass of SynidcationItem called AllardWorksSyndicationItem. I added a property called AUTHOR, so that I can save the information during load. Then, I can loop through and update the AUTHORS collection without having to bother the data table.&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;div&gt;&lt;a href="http://1.bp.blogspot.com/_VTjiO7cQdSU/SILIkxOZJKI/AAAAAAAAAFU/CThygrPiyGs/s1600-h/AllardWorksSyndicationItem.JPG"&gt;&lt;img id="BLOGGER_PHOTO_ID_5224959051717747874" style="CURSOR: hand" alt="" src="http://1.bp.blogspot.com/_VTjiO7cQdSU/SILIkxOZJKI/AAAAAAAAAFU/CThygrPiyGs/s320/AllardWorksSyndicationItem.JPG" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The Linq query now returns a List&lt;allardworkssyndicationitem&gt;. After the query, I loop through the items and create the permalink (based on the ID, which I already have), and I add the value of the new AUTHOR property to the existing AUTHORS property.&lt;/div&gt;&lt;br /&gt;&lt;div&gt;&lt;/div&gt;&lt;br /&gt;&lt;div&gt;&lt;a href="http://2.bp.blogspot.com/_VTjiO7cQdSU/SILJgnafYTI/AAAAAAAAAFc/Kil2mP1ppQE/s1600-h/postloop.JPG"&gt;&lt;img id="BLOGGER_PHOTO_ID_5224960079876284722" style="CURSOR: hand" alt="" src="http://2.bp.blogspot.com/_VTjiO7cQdSU/SILJgnafYTI/AAAAAAAAAFc/Kil2mP1ppQE/s320/postloop.JPG" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;But wait. There's more. The SyndicationFeed object has a property called Items. You set it to a IEnumerable of SyndicationObject&lt;syndicationitem&gt;, not IEnumerable of AllardWorksSyndicationItem&lt;allardworkssyndicationitem&gt;. The list needs to be converted. I achieved this by another Linq query which does the cast&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;a href="http://3.bp.blogspot.com/_VTjiO7cQdSU/SILJxx6_eCI/AAAAAAAAAFk/Vb2jrriMQ24/s1600-h/listconvert.JPG"&gt;&lt;img id="BLOGGER_PHOTO_ID_5224960374754736162" style="CURSOR: hand" alt="" src="http://3.bp.blogspot.com/_VTjiO7cQdSU/SILJxx6_eCI/AAAAAAAAAFk/Vb2jrriMQ24/s320/listconvert.JPG" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;Then, you return a formatter for the type of feed (I chose atom), and that's a wrap for tonight.&lt;/div&gt;&lt;br /&gt;&lt;div&gt;&lt;strong&gt;Final Code&lt;/strong&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;a href="http://2.bp.blogspot.com/_VTjiO7cQdSU/SILKT74aXVI/AAAAAAAAAFs/T0__JO5IHCI/s1600-h/fullcode.JPG"&gt;&lt;img id="BLOGGER_PHOTO_ID_5224960961543822674" style="CURSOR: hand" alt="" src="http://2.bp.blogspot.com/_VTjiO7cQdSU/SILKT74aXVI/AAAAAAAAAFs/T0__JO5IHCI/s320/fullcode.JPG" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;div&gt;&lt;strong&gt;Rendered in IE&lt;/strong&gt;&lt;/div&gt;&lt;a href="http://4.bp.blogspot.com/_VTjiO7cQdSU/SILL3JhfPaI/AAAAAAAAAF0/NkmhZRWwbKg/s1600-h/result.JPG"&gt;&lt;/a&gt;&lt;a href="http://2.bp.blogspot.com/_VTjiO7cQdSU/SILN5fOoTEI/AAAAAAAAAF8/-nQfi9CEgtI/s1600-h/result.JPG"&gt;&lt;img id="BLOGGER_PHOTO_ID_5224964905222294594" style="CURSOR: hand" alt="" src="http://2.bp.blogspot.com/_VTjiO7cQdSU/SILN5fOoTEI/AAAAAAAAAF8/-nQfi9CEgtI/s320/result.JPG" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;div&gt;Coming soon!&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;strong&gt;UPDATES&lt;/strong&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;I revisited some of this.&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;I realized that LinqWrapper.GetEnumerator was silly, because DataRowCollection is already IEnumerable. All you have to do it &lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;span style="color:#ff0000;"&gt;return (IEnumerator&lt;t&gt;)_items.GetEnumerator();&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;rather than yield through it yourself.&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;Then I was bothered by the fact that DataRowCollection is already IEnumerable, so why do I need this stupid wrapper class?&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;The reason is that DataRowCollection is IEnumerable. Linq requires IEnumerable&lt;t&gt;, so the wrapper converts it. I tried finding other&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2143318148319291738-8528086490782132736?l=hamletcode.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://hamletcode.blogspot.com/feeds/8528086490782132736/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2143318148319291738&amp;postID=8528086490782132736' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2143318148319291738/posts/default/8528086490782132736'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2143318148319291738/posts/default/8528086490782132736'/><link rel='alternate' type='text/html' href='http://hamletcode.blogspot.com/2008/07/rss-2-atom-1-feeds.html' title='RSS 2 / Atom 1 Feeds'/><author><name>Jay Allard</name><uri>http://www.blogger.com/profile/15785084867572890025</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_VTjiO7cQdSU/SILHAA5_zwI/AAAAAAAAAFM/GBSxv39dCy8/s72-c/linqwrapper.JPG' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2143318148319291738.post-5998336790994186396</id><published>2008-07-14T22:52:00.001-04:00</published><updated>2008-07-14T22:53:26.673-04:00</updated><title type='text'>Email Problems</title><content type='html'>Greetings&lt;br /&gt;&lt;br /&gt;People on my mail server haven't received any email since 7/10/2008. That's a problem. I took a look at the server, and as far as I can see, its ok. I put in a request with support.&lt;br /&gt;&lt;br /&gt;If you'd like, you can contact me at &lt;a href="mailto:hamletcode@gmail.com"&gt;hamletcode@gmail.com&lt;/a&gt; in the meantime.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2143318148319291738-5998336790994186396?l=hamletcode.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://hamletcode.blogspot.com/feeds/5998336790994186396/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2143318148319291738&amp;postID=5998336790994186396' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2143318148319291738/posts/default/5998336790994186396'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2143318148319291738/posts/default/5998336790994186396'/><link rel='alternate' type='text/html' href='http://hamletcode.blogspot.com/2008/07/email-problems.html' title='Email Problems'/><author><name>Jay Allard</name><uri>http://www.blogger.com/profile/15785084867572890025</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2143318148319291738.post-1468333287114337724</id><published>2008-07-07T23:36:00.002-04:00</published><updated>2008-07-07T23:38:41.786-04:00</updated><title type='text'>Prologue Complete</title><content type='html'>The final tally for the prologue draft is just over 9 pages. Chapter 1, so far, is about a third of a page. I expect that to get larger, even if I have to resort to increasing the font size.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2143318148319291738-1468333287114337724?l=hamletcode.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://hamletcode.blogspot.com/feeds/1468333287114337724/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2143318148319291738&amp;postID=1468333287114337724' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2143318148319291738/posts/default/1468333287114337724'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2143318148319291738/posts/default/1468333287114337724'/><link rel='alternate' type='text/html' href='http://hamletcode.blogspot.com/2008/07/prologue-complete.html' title='Prologue Complete'/><author><name>Jay Allard</name><uri>http://www.blogger.com/profile/15785084867572890025</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2143318148319291738.post-2838206754274577907</id><published>2008-07-06T00:22:00.002-04:00</published><updated>2008-07-06T00:28:24.468-04:00</updated><title type='text'>Lack of direction</title><content type='html'>I'm spinning my wheels trying to find something good to do. I watched a web cast on Dynamic Data, which was great. I'm going to start reading up on Ado.Net entitites. But, I really can't come up with a project that I'm interested enough in to really pursue.&lt;br /&gt;&lt;br /&gt;I keep thinking about a pubsub project, but haven't been able to comit. I've worked on the DVD site here and there, but nothing ground breaking. I'm lacking a sense of purpose.&lt;br /&gt;&lt;br /&gt;Lacking anything useful to do, I've spent some time trying to write a sci-fi story. I used to write a lot more when I was younger. Now, I usually find it more rewarding to code. Since that hasn't been working out lately, I'll give writing another shot.&lt;br /&gt;&lt;br /&gt;I've been thinking about this story for quite a while. So far, its called Savior, but I just made that up a minute ago and it probably won't stick. The prologue is mostly complete, and I should start on Chapter 1 tomorrow. It'll end up being a pretty short story; A lot of stories take 5 pages to say hello. In mine, I just say "hello". I don't know enough words to drag it out much longer than that. It certainly won't be novel length.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2143318148319291738-2838206754274577907?l=hamletcode.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://hamletcode.blogspot.com/feeds/2838206754274577907/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2143318148319291738&amp;postID=2838206754274577907' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2143318148319291738/posts/default/2838206754274577907'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2143318148319291738/posts/default/2838206754274577907'/><link rel='alternate' type='text/html' href='http://hamletcode.blogspot.com/2008/07/lack-of-direction.html' title='Lack of direction'/><author><name>Jay Allard</name><uri>http://www.blogger.com/profile/15785084867572890025</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2143318148319291738.post-4154913273423260916</id><published>2008-06-18T00:12:00.003-04:00</published><updated>2008-06-18T00:24:44.748-04:00</updated><title type='text'>Indecision results in Netflix</title><content type='html'>For the last couple weeks, I've been torn about what to work on.&lt;br /&gt;&lt;br /&gt;I got bored with the clan site. Once I worked through all of the MVC.NET stuff, I lost interest.&lt;br /&gt;&lt;br /&gt;Last week, I went to a SOA / ESB conference. For several days, I thought about writing a .NET pubsub system.&lt;br /&gt;&lt;br /&gt;I've also been thinking about writing a validation component. Every one I've seen (not many) requires tight coupling between the validator and the object being validated.&lt;br /&gt;&lt;br /&gt;I've also been thinking about JTS, which is a pretty big piece of software that I wrote. (Muvico uses it). I started rewriting part of it in .net 3.5 with the intention of, perhaps, renting it out to other theater chains. I still might do that.&lt;br /&gt;&lt;br /&gt;Then, I came back to DvdFriend. When all else fails, work on DvdFriend.&lt;br /&gt;&lt;br /&gt;I added NETFLIX to the list of vendors. Unfortunately, it didn't play nicely with the existing vendor framework. Netflix requires you to be logged in in order to see the full product page. I had to put in a piece of custom code to handle that.&lt;br /&gt;&lt;br /&gt;- changed the scraper to use httpwebrequest instead of webclient&lt;br /&gt;&lt;br /&gt;- added a netflix hack to handle the netflix specific stuff. (The next time this happens, I'll have to refactor to an OOP friendly solution. This is just one, though, so no pattern yet. My goal was to implement netflix, not write tons of new code.&lt;br /&gt;&lt;br /&gt;- Added a RentalOnly bit field to the vendor table.&lt;br /&gt;&lt;br /&gt;- Changed the user control to show RENT when its a rental product.&lt;br /&gt;&lt;br /&gt;- Much code is ignoring prices where the price &lt;= 0. Rather than deal with that, set netflix to set the price to 999.00 (which never shows up anyway). Added a FIXED method to the parser to support this.&lt;br /&gt;&lt;br /&gt;- Changed the save price stored procedure, for admin convenience. Normally, you would select a product type of RENTAL, then search for the product. Since DVD and BluRay is already there, the new check will make it a rental regardless of the selected product type.&lt;br /&gt;&lt;br /&gt;I don't plan on backfilling all of the products, though I did go through most of products in the left and center columns. I'll probably do the right as well. Going forward, I'll keep up with it, and maybe do a few others here and there, but it won't be a big effort.&lt;br /&gt;&lt;br /&gt;Now that the netflix product id is collected, the next logical step is "ADD TO QUEUE", and related.&lt;br /&gt;&lt;br /&gt;After that... who knows. Amazon Unboxed? (Unlike netflix, I think Amazon Unboxed probably has a commission.&lt;br /&gt;&lt;br /&gt;As always, if you would like to support the site, please consider using it for your product purchases.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2143318148319291738-4154913273423260916?l=hamletcode.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://hamletcode.blogspot.com/feeds/4154913273423260916/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2143318148319291738&amp;postID=4154913273423260916' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2143318148319291738/posts/default/4154913273423260916'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2143318148319291738/posts/default/4154913273423260916'/><link rel='alternate' type='text/html' href='http://hamletcode.blogspot.com/2008/06/indecision-results-in-netflix.html' title='Indecision results in Netflix'/><author><name>Jay Allard</name><uri>http://www.blogger.com/profile/15785084867572890025</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2143318148319291738.post-1984927374565949694</id><published>2008-06-10T13:17:00.002-04:00</published><updated>2008-06-10T13:30:13.657-04:00</updated><title type='text'>DOOM 4</title><content type='html'>It takes a while for me to get to the point. Hang in there.&lt;br /&gt;&lt;br /&gt;Chris mentioned that "Hitman is the best video game movie to date" on the DVDFriend website. I countered by suggesting that Doom, Mortal Kombat, and all 3 Resident Evil movies, and possibly the first Tomb Raider movie were all better. He agreed with a lot of that, but disagreed on doom. (It seems that he was zoning in on a particular director rather than cover the full spectrum of video game movies).&lt;br /&gt;&lt;br /&gt;I liked the first Doom movie. It's in the "crappy but good" category. I love how they didn't bother with a PG13... they just went for the R, and did anything they want.&lt;br /&gt;&lt;br /&gt;Anyway, that got me thinking about the Doom games. I never beat Doom 3. I suppose I should play it again, but I didn't have fun with it. Doom 1 and 2 were in big open areas with lots of monsters. You could kill a lot of the monsters with a single shot.&lt;br /&gt;&lt;br /&gt;I didn't get very far in Doom 3. It seemed that you had to shoot everything 50 times, and you were always in these tightly enclosed areas. I think I read that there could only be 3 baddies on the screen at a time. And, the infamous flashlight.... apparently your first-person self can't hold a flashlight and a gun at the same time. (There was change for that after... don't know if it was a 3rd party mod or a IDSoftware change). Half Life 2 came out about the same time. Its a FAR superior game. I later update to Doom 3 ripped off the Half Life 2 gravity gun.&lt;br /&gt;&lt;br /&gt;Great... right. But what does this have to do with a tech'ish blog? I'm getting there.&lt;br /&gt;&lt;br /&gt;After pondering the failure of Doom 3 for a bit, I jumped on google to find Doom 4. I learned that, at the beginning of May, IDSoftware announced that production on Doom 4 has begun.&lt;br /&gt;&lt;br /&gt;"Swell", I thought (in first person). "it'd be great if I could post a link to that on the website".&lt;br /&gt;&lt;br /&gt;The development project name for DVDFriend is "DVDBlog". So is the database. I approached the new design (which really isn't new anymore) in a completely different way. Everything is "blog" entries, which is to day, just a bunch of text. There's no real hierarch of data. There are other tables to bring the data together in  meaningful ways, with more to come eventually.)&lt;br /&gt;&lt;br /&gt;The DVDFriend site is broken up into zones. I can specify different things go into different zones, though I have never actually done that. Its functionality that I have to revisit, because the database and API both support my wish to show a list of NEWS links in the right margin. However, the admin site does not. Rather than jump in and manually insert the data, I'd rather write about not doing it, as  I am now.&lt;br /&gt;&lt;br /&gt;Actually, though, it would require a new zone. The right zone is currently occupied by the DVD list. I'll have to put it outside the margin. It'll give it a certain symmetry.&lt;br /&gt;&lt;br /&gt;When will I actually get to this? I feel that simply acknowledging it is sufficient. I don't know when I'll actually end up doing it. The way this usually works is that, as I type this, I'm really not in the mood. But, it will fester, then I'll finally commit to it while watching tv one night. Will the patter repeat? We'll see.&lt;br /&gt;&lt;br /&gt;In the meantime, I'm thinking about other things. In particular, I'm thinking about SOA, ESB, and the possibility of writing a .NET pubsub. Stay tuned.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2143318148319291738-1984927374565949694?l=hamletcode.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://hamletcode.blogspot.com/feeds/1984927374565949694/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2143318148319291738&amp;postID=1984927374565949694' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2143318148319291738/posts/default/1984927374565949694'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2143318148319291738/posts/default/1984927374565949694'/><link rel='alternate' type='text/html' href='http://hamletcode.blogspot.com/2008/06/doom-4.html' title='DOOM 4'/><author><name>Jay Allard</name><uri>http://www.blogger.com/profile/15785084867572890025</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2143318148319291738.post-4995543867134378513</id><published>2008-06-08T10:14:00.004-04:00</published><updated>2008-06-08T10:25:36.176-04:00</updated><title type='text'>Cardspace, Rounds 1 and 2</title><content type='html'>&lt;strong&gt;ROUND 1&lt;/strong&gt;&lt;br /&gt;One day last week, I figured it was time to learn some stuff about CardSpace. I read some articles and found some good startup guides. I learned about EV certificates.&lt;br /&gt;&lt;br /&gt;I installed a test EV certificate on my local development machine, and created a secondary login page for DVDFriend. I put the cardspace object tag on the new page.&lt;br /&gt;&lt;br /&gt;Everything went pretty smooth until that point. Then, I hit the button, and dissapointment ensued. The applet popped up and asked me for a card. Then there was flash, and it and the IE instance both froze. I went into process manager and killed ICARDAGT.exe and INFOCARD.EXE that freed it up. That happened a bunch of times.&lt;br /&gt;&lt;br /&gt;The event log revealed that it was a WS TRUST failure. I didn't look into it anymore at the time, but it was dissapointing that it kept crashing rather than handle it gracefully. It was a bad first impression, but oh well, things go wrong. I put it off for another day.&lt;br /&gt;&lt;strong&gt;&lt;br /&gt;ROUND 2&lt;/strong&gt;&lt;br /&gt;I didn't change anything. I just came back to it a few days later, and everything worked as advertised. I wonder if that WS error was due to a remote service being down somewhere. Its probably still in the event log, so maybe I'll revisit.&lt;br /&gt;&lt;br /&gt;I'm going to be in a conference for the next 3 days, so I should have plenty of down time at night. Time permitting, I'll implement CardSpace as an alternative login to DvdFriend. Once in place, I can check CardSpace off my "things to do" list.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2143318148319291738-4995543867134378513?l=hamletcode.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://hamletcode.blogspot.com/feeds/4995543867134378513/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2143318148319291738&amp;postID=4995543867134378513' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2143318148319291738/posts/default/4995543867134378513'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2143318148319291738/posts/default/4995543867134378513'/><link rel='alternate' type='text/html' href='http://hamletcode.blogspot.com/2008/06/cardspace-rounds-1-and-2.html' title='Cardspace, Rounds 1 and 2'/><author><name>Jay Allard</name><uri>http://www.blogger.com/profile/15785084867572890025</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2143318148319291738.post-8998693387086686761</id><published>2008-06-02T20:46:00.000-04:00</published><updated>2008-06-02T20:47:03.207-04:00</updated><title type='text'>Enterprise 4.0 is out</title><content type='html'>Cool.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2143318148319291738-8998693387086686761?l=hamletcode.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://hamletcode.blogspot.com/feeds/8998693387086686761/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2143318148319291738&amp;postID=8998693387086686761' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2143318148319291738/posts/default/8998693387086686761'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2143318148319291738/posts/default/8998693387086686761'/><link rel='alternate' type='text/html' href='http://hamletcode.blogspot.com/2008/06/enterprise-40-is-out.html' title='Enterprise 4.0 is out'/><author><name>Jay Allard</name><uri>http://www.blogger.com/profile/15785084867572890025</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2143318148319291738.post-7903352382640484646</id><published>2008-05-31T19:47:00.003-04:00</published><updated>2008-05-31T19:49:38.419-04:00</updated><title type='text'>Python Strings</title><content type='html'>Oh yea... i forgot to mention a Python string feature that I liked.&lt;br /&gt;&lt;br /&gt;You can have a string with quotes without having to escape the quotes. You start and end the string with triple quotes, and quotes in the middle are fine.&lt;br /&gt;&lt;br /&gt;IE:&lt;br /&gt;&lt;br /&gt;"""&lt;img src="whatever.gif"&gt;"I like to be quoted!". swell, right?"""&lt;br /&gt;&lt;br /&gt;That should make life easier as long as you don't frequently include """ as part of your string literals.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2143318148319291738-7903352382640484646?l=hamletcode.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://hamletcode.blogspot.com/feeds/7903352382640484646/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2143318148319291738&amp;postID=7903352382640484646' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2143318148319291738/posts/default/7903352382640484646'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2143318148319291738/posts/default/7903352382640484646'/><link rel='alternate' type='text/html' href='http://hamletcode.blogspot.com/2008/05/python-strings.html' title='Python Strings'/><author><name>Jay Allard</name><uri>http://www.blogger.com/profile/15785084867572890025</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2143318148319291738.post-2153615939503136603</id><published>2008-05-31T19:35:00.005-04:00</published><updated>2008-05-31T19:46:16.497-04:00</updated><title type='text'>Did some work on DvdFriend</title><content type='html'>It's been a long time, but I finally did some work on DvdFriend.&lt;br /&gt;&lt;br /&gt;There are now LISTS in the left column, one for Dvd and one for In Theaters. This is to bring attention to particular movies of interest. These are managed on a per-product basis in the product editor.&lt;br /&gt;&lt;br /&gt;The product editor now has 3 checkboxes&lt;br /&gt;- Show on COMING SOON - the right margin. Without this, movies would only show up if they're have a rating. But, since I want to show some Direct to DVD movies (ie: stargate continuum), they need to show up even if they're not rated yet.&lt;br /&gt;&lt;br /&gt;- Also in the product editor, I added a text box so that image urls can be manually entered. This is for cases where the image doesn't exist on amazon yet, usually theatrical releases. I have to find other image sources that I can safely use. (The "Set Image" link opens a browser that allows you to search amazon images. That's been there all along.)&lt;br /&gt;&lt;br /&gt;&lt;a href="http://4.bp.blogspot.com/_VTjiO7cQdSU/SEHigIwguRI/AAAAAAAAAD8/GSp_UCiOkoY/s1600-h/EditProduct.JPG"&gt;&lt;img style="cursor:pointer; cursor:hand;" src="http://4.bp.blogspot.com/_VTjiO7cQdSU/SEHigIwguRI/AAAAAAAAAD8/GSp_UCiOkoY/s320/EditProduct.JPG" border="0" alt=""id="BLOGGER_PHOTO_ID_5206691685951650066" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;The new lists on the left aren't very manageable yet. It'd be nice to be able to order them how I want, but I'm not that ambitious today.&lt;br /&gt;&lt;br /&gt;Now for the bad news. In order to get that list on the left, I had to modify the CSS. Previously, everything was centered. I used absolute positioning for the list, so if you resized the window there was a very good chance the list would overlap the main page. So, I attempted to fix it, but didn't do so 100%. The header and body aren't lining up exactly right.&lt;br /&gt;&lt;br /&gt;On the bright side, though, it looks MUCH better in firefox than it did before.&lt;br /&gt;&lt;br /&gt;I changes JAY'S BLOG from a link to a navigation button so that it would render better in fire fox.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2143318148319291738-2153615939503136603?l=hamletcode.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://hamletcode.blogspot.com/feeds/2153615939503136603/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2143318148319291738&amp;postID=2153615939503136603' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2143318148319291738/posts/default/2153615939503136603'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2143318148319291738/posts/default/2153615939503136603'/><link rel='alternate' type='text/html' href='http://hamletcode.blogspot.com/2008/05/did-some-work-on-dvdfriend.html' title='Did some work on DvdFriend'/><author><name>Jay Allard</name><uri>http://www.blogger.com/profile/15785084867572890025</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_VTjiO7cQdSU/SEHigIwguRI/AAAAAAAAAD8/GSp_UCiOkoY/s72-c/EditProduct.JPG' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2143318148319291738.post-2533534442311787125</id><published>2008-05-31T11:02:00.003-04:00</published><updated>2008-05-31T11:11:31.561-04:00</updated><title type='text'>Google App Engine</title><content type='html'>I just went through the GOOGLE APP ENGINE "Getting Started" guide. Neat stuff.&lt;br /&gt;&lt;br /&gt;http://code.google.com/appengine/docs/gettingstarted/&lt;br /&gt;&lt;br /&gt;The runtime is Python, which I haven't used before. I installed python, then just used notepad to write the code.&lt;br /&gt;&lt;br /&gt;The fun thing about python is that spacing counts. You block code by tabbing them out the same distance.&lt;br /&gt;&lt;br /&gt;Google currently allows everyone to have 3 applications online, while they're still in preview mode. Througout the guide, it mentions how you can use any python library for doing different types of things, but it comes with "Django" stuff already bundled. IE: Templates. (In asp.net world, a template is a master page)&lt;br /&gt;&lt;br /&gt;The benefit of using the google app engine is that it has a bunch of stuff built in, such as a datastore. The data store is not a relational database, though they expose a GQL language, which is very sql like. &lt;br /&gt;&lt;br /&gt;greetings = db.GqlQuery("SELECT * FROM Greeting ORDER BY date DESC LIMIT 10")&lt;br /&gt;&lt;br /&gt;You can also do it programtically.&lt;br /&gt;&lt;br /&gt;greetings = Greeting.all()      &lt;br /&gt;greetings.filter("author =", users.get_current_user())      &lt;br /&gt;greetings.order("-date")&lt;br /&gt;&lt;br /&gt;You never actually have to create any data store objects to hold your data. That happens automatically when you save stuff. It looks to be an object database. Once you save an object of type GREETING, then you use GQL to query for types of GREETING. (I wonder what will happen as you modify GREETING)&lt;br /&gt;&lt;br /&gt;I'm definitely not a python guy, but it was fun to play with the language a little bit. Google App Engine is trying to make development/hosting a lot faster. The SDK gives you everything you need to get started (local web server and data store), and deploying the application to production is a snap... you just execute a python script that takes care of it for you. The setup is minimal. Everything pretty much works right out of the box.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2143318148319291738-2533534442311787125?l=hamletcode.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://hamletcode.blogspot.com/feeds/2533534442311787125/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2143318148319291738&amp;postID=2533534442311787125' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2143318148319291738/posts/default/2533534442311787125'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2143318148319291738/posts/default/2533534442311787125'/><link rel='alternate' type='text/html' href='http://hamletcode.blogspot.com/2008/05/google-app-engine.html' title='Google App Engine'/><author><name>Jay Allard</name><uri>http://www.blogger.com/profile/15785084867572890025</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2143318148319291738.post-3517259547373024286</id><published>2008-05-27T23:20:00.003-04:00</published><updated>2008-05-27T23:23:25.997-04:00</updated><title type='text'>Membership Update</title><content type='html'>When you create a new profile, it sends you an email.&lt;br /&gt;The details of the email are recorded in the EmailHistory table.&lt;br /&gt;The activation codes and userid are stored in the Activation table.&lt;br /&gt;&lt;br /&gt;I changed the approach slightly. The actual activation part isn't done yet, but the plan is:&lt;br /&gt;When activate via the website, you must specify Email Address, Password, and Activation code.&lt;br /&gt;If you just click the link in the email (which is the easier way to go), it will pass two activation codes.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://localhost/clanfriend/membership/activate/code1/code2"&gt;http://localhost/clanfriend/membership/activate/code1/code2&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;That results in an ugly url, which is swell.&lt;br /&gt;&lt;br /&gt;The email is sent and recorded, and the activation codes are recorded. Next, I have to implement the actual activation.&lt;br /&gt;&lt;br /&gt;Getting closer, but there are still a lot of loose ends before I can put it up.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2143318148319291738-3517259547373024286?l=hamletcode.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://hamletcode.blogspot.com/feeds/3517259547373024286/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2143318148319291738&amp;postID=3517259547373024286' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2143318148319291738/posts/default/3517259547373024286'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2143318148319291738/posts/default/3517259547373024286'/><link rel='alternate' type='text/html' href='http://hamletcode.blogspot.com/2008/05/membership-update.html' title='Membership Update'/><author><name>Jay Allard</name><uri>http://www.blogger.com/profile/15785084867572890025</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2143318148319291738.post-4306711155275736345</id><published>2008-05-27T23:10:00.003-04:00</published><updated>2008-05-27T23:19:54.637-04:00</updated><title type='text'>Mvc.Net mapping / Preview 3</title><content type='html'>I said in an earlier post that I would like to have a mapping feature so that you can indicate actions via configuration rather than code. My tenative plan was to create a new subclass of Controller called MapController. It would have a method like&lt;br /&gt;&lt;br /&gt;MapAction(string actionName)&lt;br /&gt;&lt;br /&gt;In my login example, I'd change my action to:&lt;br /&gt;&lt;br /&gt;    MapAction("Membership.LoginSuccess");&lt;br /&gt;which would redirect to the Home&lt;br /&gt;&lt;br /&gt;    MapAction.("Membership.LoginFailed")&lt;br /&gt;which would render the LoginFailed view.&lt;br /&gt;&lt;br /&gt;MapAction would do a lookup from the configuration store then do a render or RedirectToAction.&lt;br /&gt;&lt;br /&gt;Preview 3 actually makes this a lot easier, because the acton methods now return an ActionResult object.&lt;br /&gt;&lt;br /&gt;The subclasses of ActionResult (that I can find) are:&lt;br /&gt;- ContentResult&lt;br /&gt;- EmptyResult ?? (do nothing?)&lt;br /&gt;- JSonResult&lt;br /&gt;- RedirectResult&lt;br /&gt;- RedirectToRouteResult&lt;br /&gt;- ViewResult&lt;br /&gt;&lt;br /&gt;So far, I've used implicitly used RedirectToRouteResult and ViewResult. (Controller has a RedirectToAction method and a View method which genereates the appropriate result object automatically).&lt;br /&gt;&lt;br /&gt;This means that all I'd really need to do is create the appropriate type of ActionResult object and populate it from configuration. The saving is that the objects already exist; in Preview2, I would've had to create my own objects. (I'm glad I didn't waste time on it, then).&lt;br /&gt;&lt;br /&gt;Now, I'd do:&lt;br /&gt;return MapAction("LoginMembership.Success")&lt;br /&gt;&lt;br /&gt;It'd be neat, but I'm not in a huge rush to do it. We'll see if it magically appears.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2143318148319291738-4306711155275736345?l=hamletcode.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://hamletcode.blogspot.com/feeds/4306711155275736345/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2143318148319291738&amp;postID=4306711155275736345' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2143318148319291738/posts/default/4306711155275736345'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2143318148319291738/posts/default/4306711155275736345'/><link rel='alternate' type='text/html' href='http://hamletcode.blogspot.com/2008/05/mvcnet-mapping-preview-3.html' title='Mvc.Net mapping / Preview 3'/><author><name>Jay Allard</name><uri>http://www.blogger.com/profile/15785084867572890025</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2143318148319291738.post-6594850357583871427</id><published>2008-05-27T21:17:00.005-04:00</published><updated>2008-05-28T12:41:54.787-04:00</updated><title type='text'>Preview 3</title><content type='html'>Woo hoo!&lt;br /&gt;&lt;br /&gt;&lt;a href="http://weblogs.asp.net/scottgu/archive/2008/05/27/asp-net-mvc-preview-3-release.aspx"&gt;http://weblogs.asp.net/scottgu/archive/2008/05/27/asp-net-mvc-preview-3-release.aspx&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;I just updated the test site to use it. Other than 1 case of me not following instructions, it went smooth.&lt;br /&gt;&lt;br /&gt;The HTML helpers have been changed. I was using an Html.Textbox signature that's no longer valid. Apparently, they'd rather you build the htmlAttributes collection and pass that in. For now, I merely simplified the call losing the SIZE and MAXLENGTH properties.&lt;br /&gt;&lt;br /&gt;There's a major change to the ACTIONS, which I like a lot. Previously, the methods were of type VOID, and you'd do things like:&lt;br /&gt;&lt;br /&gt;RenderView("Index")&lt;br /&gt;or&lt;br /&gt;RedirectToAction("Logout")&lt;br /&gt;&lt;br /&gt;Now, you change the VOID to ActionResult, and change the actions to:&lt;br /&gt;&lt;br /&gt;return View("Index")&lt;br /&gt;or&lt;br /&gt;return RedirectToAction("Logout")&lt;br /&gt;&lt;br /&gt;Now, rather than instructing it to do something, you're returning an object that tells it what to do. So, now its more testable. You can write a test for the action and make sure that it returns the ActionResult that it should. Sweet.&lt;br /&gt;&lt;br /&gt;Also, the ViewData object has changed. It used to be ViewData&amp;lt;T&amp;gt; where T is the type of the object passed to the view. That has changed to ViewData.Model&amp;lt;T&amp;gt;. This allows ViewData to provide other types of things such as...ummmm... Hang on a sec. I was really excited about that until just now. I pulled up the intellisense and didn't get what I expected. I'll have to look into that more, though I like the approach in intent. It is a place where a lot more things can be exposed other than just your view data object. As the framework grows, they can keep adding new things to ViewData.&lt;br /&gt;&lt;br /&gt;Back to the grind.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2143318148319291738-6594850357583871427?l=hamletcode.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://hamletcode.blogspot.com/feeds/6594850357583871427/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2143318148319291738&amp;postID=6594850357583871427' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2143318148319291738/posts/default/6594850357583871427'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2143318148319291738/posts/default/6594850357583871427'/><link rel='alternate' type='text/html' href='http://hamletcode.blogspot.com/2008/05/preview-3.html' title='Preview 3'/><author><name>Jay Allard</name><uri>http://www.blogger.com/profile/15785084867572890025</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2143318148319291738.post-5232306195419660663</id><published>2008-05-27T07:14:00.002-04:00</published><updated>2008-05-27T07:17:00.934-04:00</updated><title type='text'>Activation Codes</title><content type='html'>I'm starting to test the site pretending to be a brand new user. I want to make sure someone can sign up, get verified via an email activation code, then function. There will be two types of new users: those who aren't associated to any families, and those who are.&lt;br /&gt;&lt;br /&gt;You'll be able to activate your account either by clicking the link in the email, or by typing in Email Address, Password and Activation code on the activation page. I'm pretty sure that will bet two different actions.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2143318148319291738-5232306195419660663?l=hamletcode.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://hamletcode.blogspot.com/feeds/5232306195419660663/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2143318148319291738&amp;postID=5232306195419660663' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2143318148319291738/posts/default/5232306195419660663'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2143318148319291738/posts/default/5232306195419660663'/><link rel='alternate' type='text/html' href='http://hamletcode.blogspot.com/2008/05/activation-codes.html' title='Activation Codes'/><author><name>Jay Allard</name><uri>http://www.blogger.com/profile/15785084867572890025</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2143318148319291738.post-2649750497279798449</id><published>2008-05-25T19:31:00.003-04:00</published><updated>2008-05-26T19:11:31.919-04:00</updated><title type='text'>MVC.Net update</title><content type='html'>Greetings&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Just an update to let you know that I am still very active with the MVC.NET and LINQ SQL stuff, its just that there hasn't been anything terribly new to report. I continue to use LINQ SQL for everything, even where it feels incorrect.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;I added a bunch of permissions. They are represented as, basically, name value pairs. There isn't a table storing these permissions yet; there's just a view that infers the permissions.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Whoever creates a clan becomes the clan owner.&lt;br /&gt;&lt;br /&gt;Whoever creates a family becomes the family owner.&lt;br /&gt;&lt;br /&gt;Clan owners can edit their clans, the family in their clans, and the people in their family.&lt;br /&gt;&lt;br /&gt;Family owners can edit their family, and the people in their family.&lt;br /&gt;&lt;br /&gt;People can edit themselves.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Those rules are all brought together in a view. I have a permissions class with three properties: People, Clan, Family. Each of those subclasses has a property or method to represent the permission from the database. The properties/methods are really for convenience. If there isn't a property for a particular permission, there's a method that you call to pass the parameters.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;The permissions are setup as&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;ObjectType - People, Clan, Family&lt;br /&gt;ObjectId - PeopleId or ClanId or FamilyId&lt;br /&gt;Objectname - Clan Name, Family Name, or People Id&lt;br /&gt;User Name&lt;br /&gt;Permission Name&lt;br /&gt;&lt;p&gt;&lt;br /&gt;IE:&lt;/p&gt;&lt;p&gt;Clan, 33, 'Jay and Gina', 'Jay', 'CanAddPeopleToFamily'&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;I have a static reference to an instance of the permissions class. It uses a ReaderWriterLockSlim to wrap up the reader methods and the load method. Each time a family or clan is created, the permissions cache is reloaded.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;That's really a brute force approach, and its definitely temporary. The permissions should be lazy loaded per-object-per-user.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;I built it so that families can belong to multiple clans. When you create a new clan, it gives you the option of bringing existing families to the new clan. That's going to need an approval process... maybe the family doesn't want to be copied. At the very least, they need the flexibility to decide for themselves.&lt;br /&gt;&lt;br /&gt;The more I use MVC.NET, the more I think that it really needs  a mapping layer. That may be an ill-informed opinion, but so far, that's what I've come up with. I have the MEMBERSHIP controller redirecting the the HOME controller after logging in. That should be configurable at some other level. I'm thinking about writing that level to test it out. We'll see.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2143318148319291738-2649750497279798449?l=hamletcode.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://hamletcode.blogspot.com/feeds/2649750497279798449/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2143318148319291738&amp;postID=2649750497279798449' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2143318148319291738/posts/default/2649750497279798449'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2143318148319291738/posts/default/2649750497279798449'/><link rel='alternate' type='text/html' href='http://hamletcode.blogspot.com/2008/05/mvcnet-update.html' title='MVC.Net update'/><author><name>Jay Allard</name><uri>http://www.blogger.com/profile/15785084867572890025</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2143318148319291738.post-9123190916897444738</id><published>2008-05-15T00:11:00.003-04:00</published><updated>2008-05-15T00:24:07.911-04:00</updated><title type='text'>Logging in with MVC.net</title><content type='html'>&lt;div&gt;The test site has been coming along pretty well, though not a lot of new stuff to speak of recently. I learned some new LINQ stuff, but nothing revolutionary.&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;br /&gt;&lt;div&gt;At last, its time to add login capabilities. I installed the aspnet membership tables into the database, and setup the web.config. Then I created a new controller called LOGIN, and changed the LOGIN button (previously a dummy) to use it.&lt;/div&gt;&lt;br /&gt;&lt;div&gt;&lt;/div&gt;&lt;br /&gt;&lt;a href="http://3.bp.blogspot.com/_VTjiO7cQdSU/SCu5GGCRKvI/AAAAAAAAADI/81le9cAb-mw/s1600-h/Login.JPG"&gt;&lt;img id="BLOGGER_PHOTO_ID_5200453709079849714" style="CURSOR: hand" alt="" src="http://3.bp.blogspot.com/_VTjiO7cQdSU/SCu5GGCRKvI/AAAAAAAAADI/81le9cAb-mw/s320/Login.JPG" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;ShowLoginPage - I originally had a condition on the page that indicated which action to use depending on the current user's authenticated state. But, the point of this is to not do that kind of logic on the page, so I moved it to the ShowLoginPage action. If the user is authenticated, it redirects to the Logout action. Otherwise, it shows the login page.&lt;br /&gt;&lt;br /&gt;Logout - Easy enough... Logout, then redirect to the home page. This shows that the controllers are aware of each other. I'm not sure if that's correct, but I don't know of another way to do it, so there you go.&lt;br /&gt;&lt;br /&gt;Login - Users will login by email address. They'll have a username too, but that'll be for display purposes. The membership provider supports login by username, so I have to find the username by searching on the email address. The Find returns a collection of users. You can retrieve from the collection by username, but we don't have a username, so we have to enumerate to the first one. That was inconvenient. users[0] would've been swell.&lt;br /&gt;&lt;br /&gt;I haven't handled a failed login yet. Essentially, I want it to load the same view but pass it an error message. That'll be new.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2143318148319291738-9123190916897444738?l=hamletcode.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://hamletcode.blogspot.com/feeds/9123190916897444738/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2143318148319291738&amp;postID=9123190916897444738' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2143318148319291738/posts/default/9123190916897444738'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2143318148319291738/posts/default/9123190916897444738'/><link rel='alternate' type='text/html' href='http://hamletcode.blogspot.com/2008/05/logging-in-with-mvcnet.html' title='Logging in with MVC.net'/><author><name>Jay Allard</name><uri>http://www.blogger.com/profile/15785084867572890025</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_VTjiO7cQdSU/SCu5GGCRKvI/AAAAAAAAADI/81le9cAb-mw/s72-c/Login.JPG' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2143318148319291738.post-1184744744272895106</id><published>2008-05-11T00:29:00.005-04:00</published><updated>2008-05-11T00:50:36.549-04:00</updated><title type='text'>So much for that idea</title><content type='html'>The whole "swappable dal" thing didn't work out. It could've, but it would've been too much work, so I dropped it. I can play with SubSonic and the entity framework some other times.&lt;br /&gt;&lt;strong&gt;&lt;/strong&gt;&lt;br /&gt;&lt;strong&gt;Selecting into a new object&lt;/strong&gt;&lt;br /&gt;I created a couple view in the database and added them to the dbml. Reading is not a problem, but I'm curious how it handles attempted updates. (It is a view, afterall).&lt;br /&gt;&lt;br /&gt;I ran into a new LINQ situation. So far, all queries have been like:&lt;br /&gt;&lt;br /&gt;from p in this.TableName&lt;br /&gt;select p&lt;br /&gt;&lt;br /&gt;&lt;a href="http://4.bp.blogspot.com/_VTjiO7cQdSU/SCZ4Fb9G7EI/AAAAAAAAACw/DMTPPgDbW-Q/s1600-h/fm.JPG"&gt;&lt;img id="BLOGGER_PHOTO_ID_5198974854644558914" style="CURSOR: hand" alt="" src="http://4.bp.blogspot.com/_VTjiO7cQdSU/SCZ4Fb9G7EI/AAAAAAAAACw/DMTPPgDbW-Q/s320/fm.JPG" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;&lt;/p&gt;&lt;br /&gt;But, I only wanted a few fields from the view. How do you do that? It can't return a known object because you're specifying the fields on fly. I determined that I have to create a new object that has properties for just the fields I want, and return a list&lt;&gt; of those. So, I created a FamilyMember object.&lt;br /&gt;&lt;br /&gt;I don't know if that's the right way to do it, but it works. I read a LINQ book several months ago. I'll have to get back to it. I'll absorb a lot more on the second pass due to the rudimentary hands on.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Extend the View Object &lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;I added a new method to the vwClanFamily class.&lt;strong&gt;&lt;br /&gt;&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://3.bp.blogspot.com/_VTjiO7cQdSU/SCZ4_L9G7FI/AAAAAAAAAC4/Xff1RUGqlQo/s1600-h/vwClanFamily.JPG"&gt;&lt;img id="BLOGGER_PHOTO_ID_5198975846782004306" style="CURSOR: hand" alt="" src="http://3.bp.blogspot.com/_VTjiO7cQdSU/SCZ4_L9G7FI/AAAAAAAAAC4/Xff1RUGqlQo/s320/vwClanFamily.JPG" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Its used on the page in the inner loop.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://3.bp.blogspot.com/_VTjiO7cQdSU/SCZ5tL9G7GI/AAAAAAAAADA/ozNNzjovW80/s1600-h/loops.JPG"&gt;&lt;img id="BLOGGER_PHOTO_ID_5198976637055986786" style="CURSOR: hand" alt="" src="http://3.bp.blogspot.com/_VTjiO7cQdSU/SCZ5tL9G7GI/AAAAAAAAADA/ozNNzjovW80/s320/loops.JPG" border="0" /&gt;&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2143318148319291738-1184744744272895106?l=hamletcode.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://hamletcode.blogspot.com/feeds/1184744744272895106/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2143318148319291738&amp;postID=1184744744272895106' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2143318148319291738/posts/default/1184744744272895106'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2143318148319291738/posts/default/1184744744272895106'/><link rel='alternate' type='text/html' href='http://hamletcode.blogspot.com/2008/05/so-much-for-that-idea.html' title='So much for that idea'/><author><name>Jay Allard</name><uri>http://www.blogger.com/profile/15785084867572890025</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_VTjiO7cQdSU/SCZ4Fb9G7EI/AAAAAAAAACw/DMTPPgDbW-Q/s72-c/fm.JPG' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2143318148319291738.post-5558902022828176434</id><published>2008-05-07T23:30:00.002-04:00</published><updated>2008-05-07T23:45:24.020-04:00</updated><title type='text'>MVC / LINQ / SubSonic / Entity Framework</title><content type='html'>When I first started goofing around with MVC.NET a few days ago, I considered looking at the entity framework at the same time. Then I figured that LINQ and MVC.NET would be enough to keep me busy&lt;br /&gt;&lt;br /&gt;Tonight, while looking around to find answers to some mvc questions, I came across this:&lt;br /&gt;&lt;a href="http://subsonicproject.com/"&gt;http://subsonicproject.com/&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;I watched one of the videos, and its pretty neat. SubSonic generates the DAL layer for you. It can also be setup to regenerate the DAL every time the web site starts. (You wouldn't want to do that in production, but convenient for development). I haven't played with at all; I just watched the video, but its interesting. It looks like PRE-LINQ LINQ. I wonder if LINQ is going to be  problem for them.&lt;br /&gt;&lt;br /&gt;One nice feature of SubSonic is scripting. It creates an external tool that will script the entire db, including data, so that you can check it in. Cool.&lt;br /&gt;&lt;br /&gt;I thought about using SubSonic for some portion of the demo site, but that'd be a pain. Rather than mentally battle over LINQ, Entities, and SubSonic, I'm going to refactor the stuff so it can use any of the three. If it works (it should), it'll allow me to play with all three. (Honestly, though, I don't plan on digging into the entity framework just yet).&lt;br /&gt;&lt;br /&gt;I noticed one thing in SubSonic that I wasn't able to do in LINQ (at least not on the first attempt. I only spent 3 seconds on it): Partial classes. In LINQ, as shown in a previous post, I can create a partial class for the dataContext object.&lt;br /&gt;&lt;br /&gt;I did this:&lt;br /&gt;&lt;br /&gt;List&lt;people&gt; people = _db.GetAllPeople(); //or something like that&lt;br /&gt;&lt;br /&gt;I wanted to do:&lt;br /&gt;&lt;br /&gt;List&lt;popele&gt; people  _db.People.GetAllPeople();&lt;br /&gt;&lt;br /&gt;As shown, it would have to be a static method, which isn't what I want. So, obviously, its not going to work as intended. But, the subsonic api works differently, and you can create a partial class at the table level.&lt;br /&gt;&lt;br /&gt;So, my next task is to create an interface, a factory, and multiple implementations of the interface so that I can play with multiple DAL technologies. Stay tuned.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2143318148319291738-5558902022828176434?l=hamletcode.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://hamletcode.blogspot.com/feeds/5558902022828176434/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2143318148319291738&amp;postID=5558902022828176434' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2143318148319291738/posts/default/5558902022828176434'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2143318148319291738/posts/default/5558902022828176434'/><link rel='alternate' type='text/html' href='http://hamletcode.blogspot.com/2008/05/mvc-linq-subsonic-entity-framework.html' title='MVC / LINQ / SubSonic / Entity Framework'/><author><name>Jay Allard</name><uri>http://www.blogger.com/profile/15785084867572890025</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2143318148319291738.post-5351297867189778351</id><published>2008-05-05T23:26:00.009-04:00</published><updated>2008-05-05T23:51:07.590-04:00</updated><title type='text'>Tonight's MVC progress</title><content type='html'>Yesterday's post didn't go so well. The code and HTML isn't rendering correctly. Lets try screenshots.&lt;br /&gt;&lt;br /&gt;I have the edit functionality working. I ran into one glitch along the way. The edit page is a form. I set the action attribute using Url.ActionLink, but it didn't do anything. It kept posting back to the view page. "View Source" revealed that there are 2 form tags: 1 for the master page, plus the one I added. I removed the one from the master page, and it started working. (If I wasn't able to remove the parent form tag, what would I have to do? Maybe change the parent's action instead?)&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Here's the main page. Its using the master page and css provided by the template. Its nicer than anything I could've done, so I'll keep it.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://1.bp.blogspot.com/_VTjiO7cQdSU/SB_Q3LAnOWI/AAAAAAAAAB4/92aJM8fwf9I/s1600-h/MainPage.JPG"&gt;&lt;img id="BLOGGER_PHOTO_ID_5197102141275584866" style="CURSOR: hand" alt="" src="http://1.bp.blogspot.com/_VTjiO7cQdSU/SB_Q3LAnOWI/AAAAAAAAAB4/92aJM8fwf9I/s320/MainPage.JPG" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;The MVC links are:&lt;br /&gt;Clan Admin - &lt;a href="http://localhost:1653/ClanAdmin/Index"&gt;http://localhost:1653/ClanAdmin/Index&lt;/a&gt;&lt;br /&gt;Home - &lt;a href="http://localhost:1653/Home/Index"&gt;http://localhost:1653/Home/Index&lt;/a&gt;&lt;br /&gt;About - &lt;a href="http://localhost:1653/Home/About"&gt;http://localhost:1653/Home/About&lt;/a&gt;&lt;br /&gt;Login - &lt;a href="http://localhost:1653/Home/Login"&gt;http://localhost:1653/Home/Login&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;When you click Clan Admin, you get the really ugly list of people.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;&lt;a href="http://4.bp.blogspot.com/_VTjiO7cQdSU/SB_SI7AnOYI/AAAAAAAAACI/3YjyKLJFAUk/s1600-h/list.JPG"&gt;&lt;img id="BLOGGER_PHOTO_ID_5197103545729890690" style="CURSOR: hand" alt="" src="http://4.bp.blogspot.com/_VTjiO7cQdSU/SB_SI7AnOYI/AAAAAAAAACI/3YjyKLJFAUk/s320/list.JPG" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;The Edit page url is http://localhost:1653/ClanAdmin/EditPerson/3. The last segment is the people id.&lt;br /&gt;&lt;a href="http://3.bp.blogspot.com/_VTjiO7cQdSU/SB_SorAnOZI/AAAAAAAAACQ/yY3lRMtvY_4/s1600-h/edit.JPG"&gt;&lt;img id="BLOGGER_PHOTO_ID_5197104091190737298" style="CURSOR: hand" alt="" src="http://3.bp.blogspot.com/_VTjiO7cQdSU/SB_SorAnOZI/AAAAAAAAACQ/yY3lRMtvY_4/s320/edit.JPG" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;&lt;br /&gt;&lt;p&gt;When you click save, it submits to /ClanAdmin/UpdatePerson/3.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;Here's the UpdatePerson action.&lt;br /&gt;&lt;a href="http://3.bp.blogspot.com/_VTjiO7cQdSU/SB_TZrAnOaI/AAAAAAAAACY/h0s3eAE4CA0/s1600-h/code-updateaction.JPG"&gt;&lt;img id="BLOGGER_PHOTO_ID_5197104933004327330" style="CURSOR: hand" alt="" src="http://3.bp.blogspot.com/_VTjiO7cQdSU/SB_TZrAnOaI/AAAAAAAAACY/h0s3eAE4CA0/s320/code-updateaction.JPG" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;BindingHelperExtensions.UpdateFrom is neat. It looks at the posted form and maps the element names to the object property names. So, name your controls the same as the properties, and you can do the update in one swoop. It also provides measures to prevent certain properties form being updated, but I'm not using that here.&lt;/p&gt;&lt;p&gt;Yesterday I mentioned that I would need to create a partial class to add more specific functionality to ClanContextData. I was going to add a class to APP_CODE, but that doesn't exist in ASP.NET. Its been removed from the ADD ASP.NET FOLDER menu. So, I put it in the controller folder, which I now think is the correct place. (The REAL right place would be a separate assembly that contains all of the business logic. But, I don't have that piece. It's all in Controllers).&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;a href="http://4.bp.blogspot.com/_VTjiO7cQdSU/SB_VX7AnOcI/AAAAAAAAACo/WZk3v9KNfjg/s1600-h/code-db+extensions.JPG"&gt;&lt;img id="BLOGGER_PHOTO_ID_5197107101962811842" style="CURSOR: hand" alt="" src="http://4.bp.blogspot.com/_VTjiO7cQdSU/SB_VX7AnOcI/AAAAAAAAACo/WZk3v9KNfjg/s320/code-db+extensions.JPG" border="0" /&gt;&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2143318148319291738-5351297867189778351?l=hamletcode.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://hamletcode.blogspot.com/feeds/5351297867189778351/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2143318148319291738&amp;postID=5351297867189778351' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2143318148319291738/posts/default/5351297867189778351'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2143318148319291738/posts/default/5351297867189778351'/><link rel='alternate' type='text/html' href='http://hamletcode.blogspot.com/2008/05/tonights-mvc-progress.html' title='Tonight&apos;s MVC progress'/><author><name>Jay Allard</name><uri>http://www.blogger.com/profile/15785084867572890025</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_VTjiO7cQdSU/SB_Q3LAnOWI/AAAAAAAAAB4/92aJM8fwf9I/s72-c/MainPage.JPG' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2143318148319291738.post-6467806144311050194</id><published>2008-05-05T22:24:00.002-04:00</published><updated>2008-05-05T22:25:57.740-04:00</updated><title type='text'>Load / Modify / Reload / Save</title><content type='html'>I just read through part 4 of one of tutorials I've been using to go through the MVC stuff.&lt;br /&gt;&lt;br /&gt;http://weblogs.asp.net/scottgu/archive/2007/12/09/asp-net-mvc-framework-part-4-handling-form-edit-and-post-scenarios.aspx&lt;br /&gt;&lt;br /&gt;Unfortunately, it suggests that to do an update, you need to reload the object, update it, then save it. So, if the values have changed since you populated the page, then you'll just overwrite them.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2143318148319291738-6467806144311050194?l=hamletcode.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://hamletcode.blogspot.com/feeds/6467806144311050194/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2143318148319291738&amp;postID=6467806144311050194' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2143318148319291738/posts/default/6467806144311050194'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2143318148319291738/posts/default/6467806144311050194'/><link rel='alternate' type='text/html' href='http://hamletcode.blogspot.com/2008/05/load-modify-reload-save.html' title='Load / Modify / Reload / Save'/><author><name>Jay Allard</name><uri>http://www.blogger.com/profile/15785084867572890025</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2143318148319291738.post-8259162745407757017</id><published>2008-05-04T22:42:00.004-04:00</published><updated>2008-05-04T23:47:13.294-04:00</updated><title type='text'>MVC.Net and Linq to SQL</title><content type='html'>I was up until 4:30am Friday night working on a database thing for work. I spent most of the day Saturday, on and off, doing the same thing. The good news is I learned all that I needed to learn, solved the problem, and built a pretty thorough test harness and MbUnit tests for it. Swell. It violated my "don't work on weekends" rule, but it was for a good cause. I had to learn new stuff, so it was to my benefit.&lt;br /&gt;&lt;br /&gt;Anyhoo, that's a different story for another day.&lt;br /&gt;&lt;br /&gt;When Sunday evening rolled around, we sat down to watch an Indiana Jones movie or 2 (or 3). I'm mentally unable to simply sit there and watch a movie that I've already seen, unless I'm tired or uncharacteristically mentally lazy. Typically, I need something to work on at the same time. (Well, it depends on the movie too, I suppose).&lt;br /&gt;&lt;br /&gt;Furthermore, I've been slacking for a long time. Over the last few months, I've played A LOT of Burnout Paradise. For a while, I was feeling guilty about gaming instead of something productive, but I quickly came to terms with it. If I want to take a break, I can take a break. This one just happened to be longer than usual. Oh well.&lt;br /&gt;&lt;br /&gt;So, now that i've thoroughly beat Burnout Paradise, and I've done enough "work" work, its time for something new. I decided to jump on this MVC.NET thing that I've been hearing so much about. And, at the same time, I might as well start using LINQ for SQL. (I dabbled with LING for collections a bit, but nothing serious).&lt;br /&gt;&lt;br /&gt;The MVC.NET web template gets you going pretty good. It creates the MODELS, VIEWS, and CONTROLLERS folders.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Create Database&lt;/strong&gt;&lt;br /&gt;I have a vague about the website I'm going to build from this stuff, but its not real important. I started with an empty database and created a single table: PEOPLE. It has the following fields;&lt;br /&gt;- PeopleId (PK int identity)&lt;br /&gt;- FirstName&lt;br /&gt;- LastName&lt;br /&gt;- EmailAddress (nullable)&lt;br /&gt;- BirthDate (nullable)&lt;br /&gt;Simple... no big deal.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Create DBML &lt;/strong&gt;&lt;br /&gt;I ended up using VS2008 to crate the DBML file. Before that, I used SQLMetal just for kicks. It worked swell.&lt;br /&gt;&lt;br /&gt;I then ran a couple quick tests on the DBML file just to get a feel for ole betsy.&lt;br /&gt;&lt;br /&gt;ClanDataContext db = new ClanDataContext();&lt;br /&gt;People people = new People();&lt;br /&gt;people.FirstName = "first";&lt;br /&gt;people.LastName = "last";&lt;br /&gt;people.EmailAddress = "jay@allardworks.com";&lt;br /&gt;people.Birthday = new DateTime(1972, 7, 2);&lt;br /&gt;//PeopleId deafults to 0&lt;br /&gt;db.Peoples.InsertOnSubmit(people);&lt;br /&gt;db.SubmitChanges();&lt;br /&gt;//PeopleId is now the new identity value&lt;br /&gt;&lt;br /&gt;Sweet. LINQ is cool.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Modify the MasterPage&lt;/strong&gt;&lt;br /&gt;The MVC site template comes with a master page. I added an admin link to the left margin.&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;br /&gt;&lt;li&gt;&lt;%= Html.ActionLink("Clan Admin", "Index", "ClanAdmin") %&gt;&lt;/li&gt;&lt;/blockquote&gt;&lt;br /&gt;Parameter 1 is the text that appears in the link.&lt;br /&gt;Parameter 2 is the name of the action.&lt;br /&gt;Parameter 3 is the controller.&lt;br /&gt;&lt;br /&gt;The existing links on the page did not specify the controller, because there was only one to start with. Once I added my ClanController, I had to change the existing links to specify the third parameter.&lt;br /&gt;&lt;br /&gt;The link renders as: &lt;a href="http://localhost:1653/ClanAdmin/Index"&gt;http://localhost:1653/ClanAdmin/Index&lt;/a&gt; (Controller/Action)&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Controller Class&lt;/strong&gt;&lt;br /&gt;Next, create a controller class. The controller specified is ClanAdmin. The name of the specified action was Index, so create a method called Index.&lt;br /&gt;&lt;code&gt;&lt;br /&gt;using System;&lt;br /&gt;using System.Collections.Generic;&lt;br /&gt;using System.Linq;&lt;br /&gt;using System.Web;&lt;br /&gt;using System.Web.Mvc;&lt;br /&gt;using MvcTest1.Models;&lt;br /&gt;namespace MvcTest1.Controllers&lt;br /&gt;{&lt;br /&gt;public class ClanAdminController : Controller&lt;br /&gt;{&lt;br /&gt;public void Index()&lt;br /&gt;{&lt;br /&gt;ClanDataContext db = new ClanDataContext();List&lt;people&gt; people = (from p in db.Peoples select p).ToList&lt;people&gt;();&lt;br /&gt;RenderView("Index", people);}&lt;br /&gt;&lt;br /&gt;public void EditPerson(int peopleId)&lt;br /&gt;{&lt;br /&gt;RenderView("EditPerson", peopleId);&lt;br /&gt;}&lt;br /&gt;}&lt;br /&gt;}&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;That's the full Controller class. Index is the action we've already mentioned. It uses the linq entity class to get a list of all of the people. It passes it to the view via the second parameter of the RenderView method.&lt;br /&gt;&lt;br /&gt;The first parameter is the name of the view. So far, it seems that view names may commonly match action names, at least for navigation purposes. We have an action called index that loads a view called index.&lt;br /&gt;&lt;br /&gt;The second action, EditPerson, comes into play later.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Index View&lt;/strong&gt;&lt;br /&gt;Thew view page goes into VIEWS/CLANADMIN. VIEWS is a fixed name. CLANADMIN is the name of the controller. (What if you want multiple controllers to share the same view? Is that practical and/or possible?)&lt;br /&gt;&lt;br /&gt;By default, a view is just an ASPX page. However, you can change that behavior somewhere. (I'm not there yet).&lt;br /&gt;&lt;br /&gt;Here comes an inconvenience: When you add the MVC view page, it doesn't give you the option to select a master page. You have to create the page, assign the master page, and lop off the junk you no longer need.&lt;br /&gt;&lt;br /&gt;If you look back to the controller code, you'll see that the second parameter of RenderView is a List&lt;people&gt;. That parameter is called ViewData, and it may be anything type you desire. In order to make the view page aware of it, you must make it a generic of that type.&lt;br /&gt;&lt;br /&gt;&lt;em&gt;Controller / Action Method&lt;/em&gt;&lt;br /&gt;&lt;code&gt;&lt;br /&gt;ClanDataContext db = new ClanDataContext();List&lt;people&gt; people = (from p in db.Peoples select p).ToList&lt;people&gt;();&lt;br /&gt;RenderView("Index", people);}&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;NOTE: Will create a partial class to add a new method to ClanDataContext: GetPeople();&lt;br /&gt;&lt;br /&gt;&lt;em&gt;View Page&lt;/em&gt;&lt;br /&gt;&lt;code&gt;&lt;br /&gt;public partial class Index : &lt;strong&gt;ViewPage&lt;list&lt;people&gt;&gt;&lt;br /&gt;&lt;/strong&gt;{&lt;br /&gt;}&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;Now, the ViewData property is a List&lt;people&gt;.&lt;br /&gt;&lt;br /&gt;Lets recap. The controller retrieves the list of people and passes it to the view. Now, to keep the name VIEW honest, we must display the data.&lt;br /&gt;&lt;br /&gt;It looks like that while the use of ServerControls is allowed, its not encouraged. Instinct is to drop a DataGrid on the page and bind it to the list. But, all examples so far just use inline code. We end up with smaller more precise html, but we lose the flexibility of the grid control. I'm eager to see how that pans out. (I tried creating a Table object manually in code behind, but the namespace isn't included by default. I took that as a hint to not use it. For now, I'm keeping it simple. Its my first night.)&lt;br /&gt;&lt;br /&gt;I went with the flow and added inline code to the ASPX page.&lt;br /&gt;&lt;br /&gt;&lt;table&gt;&lt;br /&gt;&lt;% foreach (var p in ViewData) { %&gt;&lt;br /&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;%= p.PeopleId %&gt;&lt;/td&gt;&lt;td&gt;&lt;%= p.LastName %&gt;, &lt;%= p.FirstName %&gt;&lt;/td&gt;&lt;td&gt;&lt;%= p.EmailAddress %&gt;&lt;/td&gt;&lt;td&gt;&lt;%= Html.ActionLink("test", "EditPerson", new { controller = "ClanAdmin", peopleId = p.PeopleId }) %&gt;&lt;/td&gt;&lt;/tr&gt;&lt;% } %&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;I really don't like that. It brings me back to ASP. The difference, though, is that it'll all be compiled so you don't have context switching like ASP, but its still ugly. Not very OOPish, is it?&lt;br /&gt;&lt;br /&gt;I had a problem with Html.ActionLink. The second parameter is the action. Nothing I've found via google shows that parameter being specified. The anonymous third parameter becomes a RouteValueCollection. All samples I've seen specify the action there. But, when I do it, I get a method overload exception. Its trying to use the (string, string) signature, which is invalid. (This may be due to the fact that I'm using Preview 2. Most samples are Preview 1).&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Edit View&lt;/strong&gt;&lt;br /&gt;Now that we have a list of people from the database, I'd like to edit a person. Notice the Html.ActionLink in the last cell. It creates a link with text of "test". It'd be better to use p.LastName or something, but its junk code. The second parameter is the name of the action. Earlier, we saw the action defined in the controller class as shown:&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;public void EditPerson(int peopleId)&lt;br /&gt;{&lt;br /&gt;RenderView("EditPerson", peopleId);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;That's not how it will end up looking. The second parameter should be a PEOPLE object, but for now, I'm just passing the PEOPLEID to show that it works.&lt;br /&gt;&lt;br /&gt;To support this, I created a second view called Edit&lt;int&gt;, then simply print the ID (stored in ViewData)&lt;br /&gt;&lt;br /&gt;Class: public partial class EditPerson : ViewPage&lt;int&gt;&lt;br /&gt;ASPX Code:&lt;br /&gt;&lt;h1&gt;ID: &lt;%= ViewData %&gt;&lt;/h1&gt;&lt;br /&gt;&lt;br /&gt;Super. But, as I expected, it didn't work. The existing routes all treat ID as string, so there was a data type problem. I added a new route.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;routes.Add(new Route("{controller}/{action}/{peopleId}", new MvcRouteHandler())&lt;br /&gt;{&lt;br /&gt;Defaults = new RouteValueDictionary(new { peopleId = -1 })&lt;br /&gt;});&lt;br /&gt;&lt;br /&gt;I thought that would work, but it didn't. Then I remembered that the first matching route found wins. So, I moved that route to the top of the list, and now it wins. (I'm not 100% convinced this is all correct yet. This new route may be getting picked up in other scenarios when it shouldn't be. We'll see.)&lt;br /&gt;&lt;br /&gt;Now, when you click the TEST link, it goes to the EDIT page and displays the PeopleId.&lt;br /&gt;&lt;br /&gt;The URL to the edit page is:&lt;br /&gt;&lt;a href="http://localhost:1653/ClanAdmin/EditPerson/3"&gt;http://localhost:1653/ClanAdmin/EditPerson/3&lt;/a&gt;&lt;br /&gt;The page then shows the #3.&lt;br /&gt;Because nothing is implemented yet, you can change 3 to any integer that you want, and it will display.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;That's it for Tonight&lt;/strong&gt;&lt;br /&gt;The next steps are:&lt;br /&gt;- Use Linq to retrieve the people object. (Create the partial class mentioned earlier, and add a GetPerson(int peopleId)&lt;br /&gt;- Create the edit page. MVC.NET has some stuff to make this easier. I need to learn the details.&lt;br /&gt;- Figure out how to save. When saving, do I have to load the People object, change values, then save? Does MVC have a standard approach to this? (The People object will most likely be persisted somewhere. I don't know if that's my task, or something MVC helps with. If we do the reload/modify/save, then we lose Linq's conflict resolution capabilities. We want to keep that.)&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2143318148319291738-8259162745407757017?l=hamletcode.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://hamletcode.blogspot.com/feeds/8259162745407757017/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2143318148319291738&amp;postID=8259162745407757017' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2143318148319291738/posts/default/8259162745407757017'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2143318148319291738/posts/default/8259162745407757017'/><link rel='alternate' type='text/html' href='http://hamletcode.blogspot.com/2008/05/mvcnet-and-linq-to-sql.html' title='MVC.Net and Linq to SQL'/><author><name>Jay Allard</name><uri>http://www.blogger.com/profile/15785084867572890025</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2143318148319291738.post-3302719600301831224</id><published>2008-04-16T19:58:00.002-04:00</published><updated>2008-04-16T20:27:31.743-04:00</updated><title type='text'>Email Decision</title><content type='html'>Greetings&lt;br /&gt;&lt;br /&gt;I love IMAP. Its great.. I can use the webclient when I'm away, and any other client when I'm at home. Everything stays in sync. No hassel. With POP, each client is only aware of the messages it created. If one downloads a message without saving a copy on the server, then the other doesn't get it. Its a pain.&lt;br /&gt;&lt;br /&gt;IMAP good.&lt;br /&gt;&lt;br /&gt;Here's my setup: I have a hosted mail server for AllardWorks.com. I've been using Spam Arrest for years to filter out the spam. (Incidentally, SPAM ARREST is the best spam product I've ever seen). SPAM ARREST downloads the messages from allardworks.com and does its thing. I used to use the SPAM ARREST web page and use Outlook Express as my at-home client. They both connect to SPAM ARRESTS servers rather than the allardworks servers.&lt;br /&gt;&lt;br /&gt;Here's the problem with Spam Arrest: The spam arrest web client is minimal at best. It really hasn't improved much in the years I've been using it. Its really simplistic and ugly. Seriously guys, update the CSS once in a while! I jest. But really! No, I'm kidding. Or am I?&lt;br /&gt;&lt;br /&gt;GMAIL, on the other hand, is a lot nicer. I don't think it looks great, but its a lot more functional. The label feature is neat. (Its the equivalent of putting the same message in multiple folders). Several months ago I changed to the GMAIL client. GMAIL -&gt; SPAM ARREST -&gt; ALLARDWORKS.COM. That's a roundabout way of getting there, but it works well.&lt;br /&gt;&lt;br /&gt;Here's the problem with GMail: My gmail address is HamletCode@gmail.com. When I send a message from GMAIL, I don't want anyone to know it. I want the message to appear as FROM JAY@ALLARDWORKS.COM. But, there's no way to do that. You can set the reply to address, and the from address, but underneath it all, it still sends a hamletcode header. Its received as "from hamletcode@gmail.com on behalf of jay@allardworks.com". That might be backards, but either way, its not what I want. People keep asking me what hamletcode is when, really, that's just my account name. I've been using jay@allardorks.com for probably 12 years. I'm not interested in changing it.&lt;br /&gt;&lt;br /&gt;I put up with that for a few months, then decided against it. Last night, I moved all of my messages from GMAIL back to SPAMARREST via OUTLOOK EXPRESS. Spam Arrest offers 1 gig of storage, which should last a while. Gmail offers 6 gigs.&lt;br /&gt;&lt;br /&gt;Points&lt;br /&gt;- The SPAM ARREST web mail interface is crappy, but the spam service is unmatched.&lt;br /&gt;- SPAM ARREST offers only a gig of disk space. I suggested a feature to allow users to buy more space. We'll see if that happens when the time comes. (I'm now of the mindset that I'd like my email stored on a server, not just locally)&lt;br /&gt;- GMAIL has a better interface, but I wouldn't call it top-notch.&lt;br /&gt;- GMAIL is very generous with its drive space allotments.&lt;br /&gt;- GMAIL messes everything up by revealing that the message is coming from a gmail address.&lt;br /&gt;- YAHOO MAIL has the best interface I've seen, but they don't offer IMAP (I haven't seen many interface though)&lt;br /&gt;- I put in a feature request to ask SPAM ARREST to offer increased disk space&lt;br /&gt;- I put in a feature request to ask SPAM ARREST to show how much space is in use&lt;br /&gt;- Hotmail is a pain... I couldn't get into it with my existing windows live ID. It kept throwing exceptions. It looks like a pretty serious bug, which surprises me. It would be nice to actually see it to determine if it helps me at all.&lt;br /&gt;&lt;br /&gt;In the interest of full disclosure, I must fully disclose that my track record with Spam Arrest hasn't been perfect. One time I asked them how to delete a contact (or something like that). They directed me to the "delete contact" button. That was embarassing, though anyone who knows me would probably find it suprising that I couldn't find it on my own. Last night I asked them if they had plans to offer IMAP. They said "yes, we already do". That was embarassing too. I don't fully blame myself, though. I'm computer saavy. Clearly its not working the way I'm accustomed to, though I'm not spending enough time researching stuff. Also, the search engine (or the content) leaves a lot to be desired.&lt;br /&gt;&lt;br /&gt;Example 1: Search for DISK, then QUOTA on spam arrest. It doesn't come up with anything. Then search for SPACE, and you finally find what I was looking for: The disk limit.&lt;br /&gt;&lt;br /&gt;Example 2: Search for IMAP. The three results are:&lt;br /&gt;1 - Multiple Protected Mailboxes - accessing other mailboxes outside of spam arrest&lt;br /&gt;2 - What is a pop server? - If you open that, it gives you some IMAP information, but if the name of the article is POP, why would I open it if I'm looking for IMAP?&lt;br /&gt;3 - Options page - does that answer my question? I didn't ask about options, I asked about IMAP.&lt;br /&gt;&lt;br /&gt;Search #2 is what prompted me to ask them if/when they were going to going to offer IMAP, so I don't feel guilty about it. I searched. The results were dissapointing.&lt;br /&gt;&lt;br /&gt;One may ask why I don't just use my own mail server rather than jump through all these hoops&lt;br /&gt;- First of all, I'm not really an email administrator. I've had to fight through some issues for other clients of the server, but its not my cup of tea. I learned a lot, but that doesn't make me qualified.&lt;br /&gt;- I have space restrictions. Its not very generous, either. I don't want to waste space when other services offer more space for free or for fee. (I pay for spam arrest).&lt;br /&gt;- I'm responsible for backing up the mail server, which I don't do. None of the clients (other domains, same server) use the server to persist their messages; they download them and delete them from the server. I make no claims for redundancy, etc. Since I want redundancy for my own email, I clearly can't count on my own server.&lt;br /&gt;&lt;br /&gt;Then, you may ask why not host allardworks.com elsewhere where responsible people can take care of all the details for me?&lt;br /&gt;Mainly, I don't want to incur the cost of the non-jay users. I have a few friends and family at allardworks.com. To relocate, I'd have to pick a plan that allows for multiple mailboxes, which I'm not prepared to do. Nor am I willing to tell them that they can't use AllardWorks.com anymore. I spoke to TUFFMAIL.COM, which has potential if the spam arrest approach doesn't work. They assured me that even if I leave allardworks.com right where it is and use them just for storage/web client, TUFFMAIL will never show up in the headers. Also, there's a 30 day free trial, so I can check it out first. (The disk limits aren't generous, though, which is why I'm not going to do it until I need to.)&lt;br /&gt;&lt;br /&gt;Fun, right?&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2143318148319291738-3302719600301831224?l=hamletcode.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://hamletcode.blogspot.com/feeds/3302719600301831224/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2143318148319291738&amp;postID=3302719600301831224' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2143318148319291738/posts/default/3302719600301831224'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2143318148319291738/posts/default/3302719600301831224'/><link rel='alternate' type='text/html' href='http://hamletcode.blogspot.com/2008/04/email-decision.html' title='Email Decision'/><author><name>Jay Allard</name><uri>http://www.blogger.com/profile/15785084867572890025</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2143318148319291738.post-409657843618316756</id><published>2008-04-01T11:26:00.002-04:00</published><updated>2008-04-01T11:31:51.522-04:00</updated><title type='text'>Static variables and singletons</title><content type='html'>I planned on putting this online Saturday night, but I got lazy. The laziness lasted longer than expected, but at long last, here we go.&lt;br /&gt;&lt;br /&gt;This is just a paste of a word document. If you want a copy of the doc, let me know and I'll email it to you.&lt;br /&gt;&lt;br /&gt;Next task: Figure out how to more effectively use blogger to post this sort of thing.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Jay’s Current Stance on Singletons and Static Variables&lt;br /&gt;3/29/2008&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;"I hate being quoted" - Jay Allard&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Overview&lt;br /&gt;Singletons are really convenient. I’ve used them for many things over the years. As I’ve evolved, I’ve changed my stance on them several times. The changes range from minor tweaks to “why in god’s name did I ever think that was a good idea?”&lt;br /&gt;&lt;br /&gt;This rant describes where I currently stand with singletons, static variables, and how I came to my current opinion.&lt;br /&gt;&lt;br /&gt;Mixing Static and Instance State&lt;br /&gt;Just a quick blurb based on some object I’ve seen. An object should not, in most circumstances, have any static data.&lt;br /&gt;&lt;br /&gt;I ran into a situation on a side project a while back. I had to add new functionality to an existing object. I created unit tests for the object to define the new functionality.&lt;br /&gt;&lt;br /&gt;In each test, I instantiated the object and tested whatever I wanted to test. The tests were working apparently randomly, but not really. Sometimes things passed, sometimes they failed.&lt;br /&gt;&lt;br /&gt;It turns out that even though I was instantiating the object, it was driven by a lot of static data. So, instantiating a new instance gave you a new instance, but everything driving the object was static. Once the first instance was created, the static data was populated, so the subsequent tests didn’t behave as expected. Instantiating the object didn’t actually do anything. The instance was just exposing static data.&lt;br /&gt;&lt;br /&gt;If you instantiate an object, you should get a fresh new object. If that object loads a bunch of stuff and you only want to load it once, then use another pattern. Either use a singleton so that it’s clear that it’s shared data. Or, don’t bother giving it a constructor at all. Make it a static object.&lt;br /&gt;&lt;br /&gt;I only advise the creation of a static object, or singleton, as a better alternative to an insignificant instance. The better solution follows.&lt;br /&gt;&lt;br /&gt;What is a Singleton?&lt;br /&gt;A singleton is an instance of an object that is shared in the app domain. Rather than recreating the same type of object multiple times, just create it once, and allow everyone to use it.&lt;br /&gt;&lt;br /&gt;Lets use a new cache object as an example. We’re going to ignore the fact that there are plenty of caches available, and build our own.&lt;br /&gt;&lt;br /&gt;Cache cache = new Cache();&lt;br /&gt;cache.Add("test", new object());&lt;br /&gt;cache.Add("test 2", new object());&lt;br /&gt;&lt;br /&gt;Now, you can retrieve things from the cache by key.&lt;br /&gt;&lt;br /&gt;string hello = cache["test"];&lt;br /&gt;string world = cache["test 2"];&lt;br /&gt;&lt;br /&gt;Simple, right? Realistically, though, you only want to create the cache once then make it globally available. If you converted the cache object to a singleton, in its simplest form you would get:&lt;br /&gt;&lt;br /&gt;Cache.GetCache().Add("test 3", new object());&lt;br /&gt;Cache.GetCache().Add("test 4", new object());&lt;br /&gt;&lt;br /&gt;You could alternatively change GetCache() to be a property name. Technically, that would work, but I disapprove. The method approach is, logistically, more accurate. You’re telling the object to do something. (It can be argued either way, but I’ll always use a method)&lt;br /&gt;&lt;br /&gt;You may also see that we can achieve the same thing by exposing a public static variable. That’s smarts. Statics are the basis of the singletons, and a lot of times that may be the way you go, though I won’t.&lt;br /&gt;&lt;br /&gt;By the time you get to the end of this document, you’ll learn that I no longer do singletons as described above. I do it with a slight design driven variation. But, the concepts are the same, so lets work through it.&lt;br /&gt;&lt;br /&gt;Candidates for a Singleton&lt;br /&gt;No State&lt;br /&gt;A singleton is basically a server object. It can’t maintain state between calls because its getting hit by multiple threads at once, all with their own agenda.&lt;br /&gt;&lt;br /&gt;Pay pay = new Pay();&lt;br /&gt;pay.Hours = 3;&lt;br /&gt;pay.PayPerHours = 375.00;&lt;br /&gt;decimal myMoney = pay.Pay;&lt;br /&gt;&lt;br /&gt;The Pay object cannot be a singleton. Multiple threads would overwrite the properties. By the time you got to “pay.Pay”, the state is completely unpredictable.&lt;br /&gt;&lt;br /&gt;If you converted Pay to be method driven, you could then make a singleton of it.&lt;br /&gt;&lt;br /&gt;int myMoney = pay.CalculatePay(3, 375.00);&lt;br /&gt;&lt;br /&gt;Thread Safety&lt;br /&gt;Thread safety becomes very important. If your object supports read and writes, then you have to manage the threads to make sure they don’t step all over each other.&lt;br /&gt;For example, suppose the object checks a cache for a value. If the value is there, it returns it. Otherwise, it does a db lookup, populates the cache, then returns it. What if that happens twice simultaneously? Does the object end up on the cache twice?&lt;br /&gt;Creating a Singleton&lt;br /&gt;A singleton is an instance of an object assigned to a static variable.&lt;br /&gt;&lt;br /&gt;Initialization&lt;br /&gt;Option 1 – Inline Initialization – Jay’s Preference&lt;br /&gt;&lt;br /&gt;In most cases, this is how I go about it.&lt;br /&gt;&lt;br /&gt;public class Cache&lt;br /&gt;{&lt;br /&gt;private static Cache _cache = new Cache();&lt;br /&gt;&lt;br /&gt;That will get compiled into to the constructor anyway, so its not much different from #1. I just like the syntax better.&lt;br /&gt;&lt;br /&gt;In option #1, you saw that I added some initialization statements. How would you do that here?&lt;br /&gt;&lt;br /&gt;public class Cache&lt;br /&gt;{&lt;br /&gt;private static Cache _cache = CreateCache();&lt;br /&gt;private static Cache CreateCache()&lt;br /&gt;{&lt;br /&gt;Cache cache = new Cache();&lt;br /&gt;cache.GetCache().Add("test 7", new object());&lt;br /&gt;cache.GetCache().Add("test 8", new object());&lt;br /&gt;return cache;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;Note: This is only prudent when the object doesn’t have anything else to do. It’s just a cache; it doesn’t have any other functionality. That should usually be the case, but if you have a helper class with lots of stuff in it, then you may inadvertently create the cache when you do something irrelevant.&lt;br /&gt;&lt;br /&gt;The static constructor is thread safe, so you don’t have to worry about thread management. It will only get hit once.&lt;br /&gt;Option 2 - Static constructor&lt;br /&gt;For some reason, I used to like using the static constructor. For some reason, I don’t like it anymore.&lt;br /&gt;&lt;br /&gt;static Cache()&lt;br /&gt;{&lt;br /&gt;_cache = new Cache();&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;This gives you the opportunity to do some initialization right after you create it.&lt;br /&gt;&lt;br /&gt;_cache = new Cache();&lt;br /&gt;_cache.Add("test 5", new object());&lt;br /&gt;_cache.Add("test 6", new object());&lt;br /&gt;&lt;br /&gt;When an object has a static constructor, a flag is checked each time the object is hit to make sure that it has already been called. Regardless of how we do this, something is going to have to be checked on each visit anyway, so don’t get hung up on that.&lt;br /&gt;&lt;br /&gt;Repeat Note: This is only prudent when the object doesn’t have anything else to do. It’s just a cache; it doesn’t have any other functionality. That should usually be the case, but if you have a helper class with lots of stuff in it, then you may inadvertently create the cache when you do something irrelevant.&lt;br /&gt;&lt;br /&gt;The static constructor is thread safe, so you don’t have to worry about thread management. It will only get hit once.&lt;br /&gt;Option 3 – Lazy Load&lt;br /&gt;Back when I was a boy, this was my preferred approach. I did it this way to make sure that it only got created as needed, not when the class was used for any other reason. Since objects should only do one thing, that shouldn’t be a concern, so I don’t do this anymore. But, here you go.&lt;br /&gt;&lt;br /&gt;private static object _singletonLock = new object();&lt;br /&gt;public static Cache GetCache()&lt;br /&gt;{&lt;br /&gt;if (_cache != null)&lt;br /&gt;{&lt;br /&gt;return _cache;&lt;br /&gt;}&lt;br /&gt;lock (_singletonLock)&lt;br /&gt;{&lt;br /&gt;if (_cache != null)&lt;br /&gt;{&lt;br /&gt;return _cache;&lt;br /&gt;}&lt;br /&gt;_cache = new Cache();&lt;br /&gt;return _cache;&lt;br /&gt;}&lt;br /&gt;}&lt;br /&gt;Since this is a method, we’re responsible for the thread safety.&lt;br /&gt;First, check to see if _cache already exists. If so, return it.&lt;br /&gt;If not, lock the next chunk of code. We want to make sure only one thread hits this at any given time.&lt;br /&gt;&lt;br /&gt;Check _cache again. It may have been created, by another thread, since the last time we checked. If it exists, then return it. Otherwise, create it then return it.&lt;br /&gt;&lt;br /&gt;This Lock/Check/Lock approach doesn’t work in java. I read a bunch of stuff a few years ago. It was a hot topic, and it was proven that regardless of how logical the code is, it didn’t compile as you’d expect, so it wouldn’t work.&lt;br /&gt;&lt;br /&gt;I only know it works in .Net based on experience. I should compile it and look at the IL to make sure its doing what I think its doing. It would be a great exercise. But, thus far, I have no reason to suspect that its not working.&lt;br /&gt;&lt;br /&gt;A lesser approach is to lock the entire method. I don’t like that at all, though, because it only needs to be locked once, yet you’re locking it every time. Crazy, right?&lt;br /&gt;&lt;br /&gt;Constructors&lt;br /&gt;Once you’ve created an instance of your singleton object and assigned it to a static variable, are you done?&lt;br /&gt;&lt;br /&gt;Possible Answers:&lt;br /&gt;A: No&lt;br /&gt;B: No&lt;br /&gt;&lt;br /&gt;The correct answer is B: No. You are not done; at least, not if you want to enforce the SINGLE INSTANCE ONLY part of the singleton.&lt;br /&gt;&lt;br /&gt;public class Cache&lt;br /&gt;{&lt;br /&gt;private static Cache _cache = CreateCache();&lt;br /&gt;private static Cache GetCache()&lt;br /&gt;{&lt;br /&gt;return _cache;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;Now, you can quite easily use the singleton.&lt;br /&gt;&lt;br /&gt;Cache.GetCache().Add("Test 9", new object());&lt;br /&gt;Cache.GetCache().Add("Test 10", new object());&lt;br /&gt;&lt;br /&gt;Smashing. But, what’s to stop you from doing this?&lt;br /&gt;&lt;br /&gt;Cache myLocalCache = new Cache();&lt;br /&gt;myLocalCache.Add("Test 11", new object());&lt;br /&gt;myLocalCache.Add("Test 12", new object());&lt;br /&gt;&lt;br /&gt;Nothing is stopping you. By the definition of Singleton, you should stop it. You stop it by adding a private constructor. The private constructor will prevent any other object from instantiating cache&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Final Product&lt;br /&gt;public class Cache&lt;br /&gt;{&lt;br /&gt;private static Cache _cache = CreateCache();&lt;br /&gt;public static Cache GetCache()&lt;br /&gt;{&lt;br /&gt;return _cache;&lt;br /&gt;}&lt;br /&gt;private static Cache CreateCache()&lt;br /&gt;{&lt;br /&gt;return new Cache();&lt;br /&gt;}&lt;br /&gt;private Cache()&lt;br /&gt;{&lt;br /&gt;}&lt;br /&gt;public void Add(string key, object value)&lt;br /&gt;{&lt;br /&gt;//do someting&lt;br /&gt;}&lt;br /&gt;public object this[string key]&lt;br /&gt;{&lt;br /&gt;get&lt;br /&gt;{&lt;br /&gt;// do lookup&lt;br /&gt;return null;&lt;br /&gt;}&lt;br /&gt;}&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;Now we’re sitting pretty. The only way anyone can use your cache object is by calling Cache.GetCache(). In order for this to work properly, your implementation must be thread safe. Your methods may get hit multiple times simultaneously.&lt;br /&gt;&lt;br /&gt;That’s All Great, But Don’t Do It!&lt;br /&gt;Did I just waste 5 pages? No, its all valid information. And I’m being over dramatic when I say “don’t do it”. That’s your choice go for it.&lt;br /&gt;&lt;br /&gt;None of my business&lt;br /&gt;I’ve come to the determination that it should be up to the application to decide what is a singleton and what is not. Who am I to say that there should be one and exactly one Cache object? Maybe the application would like to create 5 cache objects for different things. (Please keep in mind that this cache object is an ambiguous example. The question applies to anything that you want to make a singleton.)&lt;br /&gt;&lt;br /&gt;If you come to the conclusion that you, as an object developer, have specific reasons to make sure that there is only one instance in any app domain, then it is your prerogative to make it a singleton yourself. What are some examples?&lt;br /&gt;Maybe your object opens up a specific TCP port and listens on it. You can’t do that more than once. (Though, if the port was a parameter, then you could).&lt;br /&gt;The Windows Workflow engine can only be started once per app domain. Somethine like that is a good candidate. (For the record, I don’t think WF should be a singleton for the reasons described in this section. But, it could be.)&lt;br /&gt;I’m out of examples, but just 2 bullets is a waste of bullets. A list needs at least 3 bullets to be respectable.&lt;br /&gt;&lt;br /&gt;I’m sure there are plenty of other examples, but in my experience, I’ve used singletons for convenience rather than necessity. I wanted my application to share one cache in an easily accessible way.&lt;br /&gt;&lt;br /&gt;It comes down to this: Build objects. Let the consumer of the objects decide what they want to do with them. Its none of your business.&lt;br /&gt;&lt;br /&gt;Testing&lt;br /&gt;TDD is one of the primary forces that drove me to stop doing singletons.&lt;br /&gt;In practicality, if you decided that you wanted something to be a singleton, then for most purposes its fine as a singleton. But, when you add testing to the equation, it becomes more problematic.&lt;br /&gt;&lt;br /&gt;For example: As I develop my cache object, I’m going to write a ton of unit tests. Each of those tests should be stand alone (ie: not victim of anything that happened before it; won’t influence anything that happens after it?) How do you do that with a singleton?&lt;br /&gt;&lt;br /&gt;For example, the test may be to add three items to the cache, then make sure the cache has three items.&lt;br /&gt;&lt;br /&gt;The next test may be to make sure the cache initializes to empty. If the cache exposes a Clear() or Remove() method, then you can do it. If it doesn’t, then you’re stuck. The singleton instance is already populated. Test #2 will fail.&lt;br /&gt;&lt;br /&gt;That’s only one minor example. We can invent plenty more.&lt;br /&gt;Evolution Step 1: Default Singleton and Instantiate a Class&lt;br /&gt;&lt;br /&gt;The previous conclusions were formed over time. Along the way, I took an incremental step towards supporting them. This worked out well since we already had existing singletons, but I wouldn’t do it for anything new.&lt;br /&gt;&lt;br /&gt;One of the key parts of the singleton is the private constructor. The private constructor prevents anyone from instantiating the object. It remains entirely in your control, not the consumer’s.&lt;br /&gt;&lt;br /&gt;Step 1 of the evolution was to eliminate that contructor, and change the getter to GetDefaultInstance.&lt;br /&gt;&lt;br /&gt;public class Cache&lt;br /&gt;{&lt;br /&gt;private static Cache _cache = CreateCache();&lt;br /&gt;public static Cache GetDefaultInstance()&lt;br /&gt;{&lt;br /&gt;return _cache;&lt;br /&gt;}&lt;br /&gt;private static Cache CreateCache()&lt;br /&gt;{&lt;br /&gt;return new Cache();&lt;br /&gt;}&lt;br /&gt;//private Cache()&lt;br /&gt;//{&lt;br /&gt;//}&lt;br /&gt;public void Add(string key, object value)&lt;br /&gt;{&lt;br /&gt;//do someting&lt;br /&gt;}&lt;br /&gt;public object this[string key]&lt;br /&gt;{&lt;br /&gt;get&lt;br /&gt;{&lt;br /&gt;// do lookup&lt;br /&gt;return null;&lt;br /&gt;}&lt;br /&gt;}&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;Now, you can either use the default instance (the singleton), or create your own. Technically, though, this is no longer a singleton. A problem with this approach is that the singleton is created even if you never use it. This could be a good place to use the Lazy Loading approach&lt;br /&gt;&lt;br /&gt;Evolution Step 2: Have your application do it.&lt;br /&gt;You have created a cache object and made it available to your applications. Its up to your application how to use it. If your application decides that there should be one and only one instance of the cache object for the entire application, then it can manage it.&lt;br /&gt;&lt;br /&gt;public static class ApplicationCache&lt;br /&gt;{&lt;br /&gt;private static Cache _cache = new Cache();&lt;br /&gt;public static Cache GetCache()&lt;br /&gt;{&lt;br /&gt;return _cache;&lt;br /&gt;}&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;Now you can use ApplicationCache.GetCache() to get to your single instance of the cache object. (Of course, that doesn’t stop anyone from creating their own Cache if they’d like to).&lt;br /&gt;&lt;br /&gt;If you have a few things like that, you could have one static class to expose them all to your application.&lt;br /&gt;Conclusion&lt;br /&gt;Going forward, I don’t see myself creating any objects that are automatically singletons. If I need a singleton, it will be at the application level.&lt;br /&gt;&lt;br /&gt;The singleton is a very basic pattern that’s probably not worth 9 pages of information. But I did it anyway. I hope you find it useful.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2143318148319291738-409657843618316756?l=hamletcode.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://hamletcode.blogspot.com/feeds/409657843618316756/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2143318148319291738&amp;postID=409657843618316756' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2143318148319291738/posts/default/409657843618316756'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2143318148319291738/posts/default/409657843618316756'/><link rel='alternate' type='text/html' href='http://hamletcode.blogspot.com/2008/04/static-variables-and-singletons.html' title='Static variables and singletons'/><author><name>Jay Allard</name><uri>http://www.blogger.com/profile/15785084867572890025</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2143318148319291738.post-9112115054234015277</id><published>2008-03-10T22:57:00.004-04:00</published><updated>2008-03-10T23:25:17.910-04:00</updated><title type='text'>MAC and no cheese</title><content type='html'>For some unexplainable reason, I was wondering how I would go about manually changing the MAC address of my wireless network card. I was just curious if it could be done incase I ever happened to go to a hotel that charges $13/day/laptop, and I didn't want to spend $26/day in addition to the hundreds of dollars already being spent.&lt;br /&gt;&lt;br /&gt;My research revealed that you could theoretically signup for the internet service with one laptop, then change the macaddress on the second laptop so that the hosting service doesn't know the difference. The one problem that I might someday theoretically run into is that perhaps the hypothetical service always issues the same IP address to the laptop with the recognized mac address. That would mean that while both computers could both connect to isp, only one can do it at a time. That would be ok, right? Better than $26/day, should the situation ever arise.&lt;br /&gt;&lt;br /&gt;If this were to ever come up, I would search google for a means of changing the mac address when the NIC properties doesn't allow for it. Maybe I'd find a program called MACSHIFT to help out. We may never know.&lt;br /&gt;&lt;br /&gt;I believe the moral of the story is: pack a router.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2143318148319291738-9112115054234015277?l=hamletcode.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://hamletcode.blogspot.com/feeds/9112115054234015277/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2143318148319291738&amp;postID=9112115054234015277' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2143318148319291738/posts/default/9112115054234015277'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2143318148319291738/posts/default/9112115054234015277'/><link rel='alternate' type='text/html' href='http://hamletcode.blogspot.com/2008/03/mac-and-no-cheese.html' title='MAC and no cheese'/><author><name>Jay Allard</name><uri>http://www.blogger.com/profile/15785084867572890025</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2143318148319291738.post-7156485497150532371</id><published>2008-03-04T22:41:00.002-05:00</published><updated>2008-03-04T22:46:55.359-05:00</updated><title type='text'>Added TV SHOW and REVIEW COMMENTS</title><content type='html'>As part of the continuing effort to keep Chris satisified with the forward progress of the site, I have added two new features:&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;TV Show Season&lt;/strong&gt;&lt;br /&gt;Actually, this isn't really a feature. Its just a new type of product that you can review. Its intended for an entire season of a show. The immediate example is THE SARAH CONNOR CHORNICLES. As far as individual episodes: That's a whole other thing that I haven't started yet.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Comments&lt;/strong&gt;&lt;br /&gt;Yet another feature that was on the old site and is now, at last, on the new site. I actually attempted to do this a couple times before. I wanted to use an ajax dialog control, but I couldn't get the ajax toolkit to work in VS2008, and I wasn't in the mood to fight with it. I think its clashing with an old version that the GAC util won't let me delete. Another fight for another day. In the meantime, I tossed in a plain-old textbox on the page. It only shows up if you're logged in.&lt;br /&gt;&lt;br /&gt;Unlike the review page, the comment box doesn't care if your session times out while you type your comments. It tracks who you are in viewstate so that it can always get to your id. The review page has a pretty major bug... if your session times out, the review won't save. I made it a habit to copy it before clicking save. I'll get to it.&lt;br /&gt;&lt;br /&gt;Enjoy&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2143318148319291738-7156485497150532371?l=hamletcode.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://hamletcode.blogspot.com/feeds/7156485497150532371/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2143318148319291738&amp;postID=7156485497150532371' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2143318148319291738/posts/default/7156485497150532371'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2143318148319291738/posts/default/7156485497150532371'/><link rel='alternate' type='text/html' href='http://hamletcode.blogspot.com/2008/03/added-tv-show-and-review-comments.html' title='Added TV SHOW and REVIEW COMMENTS'/><author><name>Jay Allard</name><uri>http://www.blogger.com/profile/15785084867572890025</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2143318148319291738.post-3676727754114507377</id><published>2008-02-24T17:39:00.003-05:00</published><updated>2008-02-24T17:49:18.856-05:00</updated><title type='text'>ASP.NET - Client Side List Box</title><content type='html'>We needed to create a dropdown list that would allows us to reorder items on the list. Piece o' cake, right? We created a composite web control with a drop down list and 3 client side buttons. A bunch of javascript managed adding the items and sorting the list. No big deal.&lt;br /&gt;&lt;br /&gt;The interesting part didn't happen until post back. Asp:ListBox doesn't recognize things that are added from the client, only from the server. I thought it would work because you can do that type of things with, for example, a textbox. The different is that a textbox is an input control and a listbox is just a select control.&lt;br /&gt;&lt;br /&gt;I created a new composite control called ClientListBox. I have know idea if I did it correctly, but it works. (I have minimal web control experience. I'm more about all of the other tiers. The composite control contains a listbox and a hidden field. As you add items to the list, the text and values are saved to the hidden field. On post back, it wipes out the list times, then creates new ones based on the contents of the hidden field.&lt;br /&gt;&lt;br /&gt;The hidden fields stores the values as:&lt;br /&gt;value&lt;strong&gt;\t&lt;/strong&gt;text&lt;strong&gt;\n&lt;/strong&gt;&lt;br /&gt;&lt;strong&gt;&lt;/strong&gt;&lt;br /&gt;The IDs of the listbox and hidden fields are set dynamically based on the id of the composite control. So, if the control id is TEST, then the listbox is TEST_LB, and the hidden is TEST_HIDDEN.&lt;br /&gt;&lt;br /&gt;Its intended use is client side script, so it gives you a known method name to retrieve the object.&lt;br /&gt;&lt;br /&gt;If the control name is TEST, then in javascript, you can call getTEST() to obtain a reference to the object. You can then all methods like Add(text, value), etc. Conceivably, there would be MoveUp and MoveDown methods too, but we didn't bring it that far.&lt;br /&gt;&lt;br /&gt;ie: alert(getTEST().getCount());&lt;br /&gt;&lt;br /&gt;getTest() is created on the server side.&lt;br /&gt;&lt;br /&gt;function getTEST() { return new ClientSideListbox(hiddenId, listboxId); }&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Is that the proper way to write a webcontrol? I have no idea. But its clean and it works.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2143318148319291738-3676727754114507377?l=hamletcode.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://hamletcode.blogspot.com/feeds/3676727754114507377/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2143318148319291738&amp;postID=3676727754114507377' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2143318148319291738/posts/default/3676727754114507377'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2143318148319291738/posts/default/3676727754114507377'/><link rel='alternate' type='text/html' href='http://hamletcode.blogspot.com/2008/02/aspnet-client-side-list-box.html' title='ASP.NET - Client Side List Box'/><author><name>Jay Allard</name><uri>http://www.blogger.com/profile/15785084867572890025</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2143318148319291738.post-5022229042619114553</id><published>2008-02-24T17:32:00.003-05:00</published><updated>2008-02-24T17:39:06.944-05:00</updated><title type='text'>DvdFriend - Added the RECENT RELEASES section</title><content type='html'>For a site that would like to sell some DVDs, there certainly has been a lack of price listings.&lt;br /&gt;&lt;br /&gt;In all 87 versions of the site that I've built to date, I've always struggled with determining what information to show where. Movies are coming out on DVD... should I list the date? The average rating? The Image? How many should I show? Should it be a number or by date range?&lt;br /&gt;&lt;br /&gt;I refused to engage my self in those debates this time. Its showing 50 releases ranging from TODAY + 21 days, to whenever it runs out of movies. They're listed on the right side of the main page. this will eventually evolve into a more detailed page. I'd like to add a mouse-over dialog to it (like netflix does). I can easily do that, but as always, making it pretty will be the difficult part.&lt;br /&gt;&lt;br /&gt;A key thing I did tackle is determining which titles to show. There may be a ton of movies in there, but not all of them are interesting enough to put on the front page. So, its only showing DVDs of movies that someone on the site has reviewed. Additionaly, there's a mechanism in there to flag movies that I want to show up. I haven't added the page functionality yet, but the back end is ready to go.&lt;br /&gt;&lt;br /&gt;Later, the date headings will become hyperlinks that will show all of the releases for that day, without any filters. At the rate I'm going though, I'll spend 4 minutes doing it in 3 months.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2143318148319291738-5022229042619114553?l=hamletcode.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://hamletcode.blogspot.com/feeds/5022229042619114553/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2143318148319291738&amp;postID=5022229042619114553' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2143318148319291738/posts/default/5022229042619114553'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2143318148319291738/posts/default/5022229042619114553'/><link rel='alternate' type='text/html' href='http://hamletcode.blogspot.com/2008/02/dvdfriend-added-recent-releases-section.html' title='DvdFriend - Added the RECENT RELEASES section'/><author><name>Jay Allard</name><uri>http://www.blogger.com/profile/15785084867572890025</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2143318148319291738.post-6839387109324572092</id><published>2008-02-09T17:24:00.001-05:00</published><updated>2008-02-09T17:45:25.160-05:00</updated><title type='text'>DvdFriend - User Review Page</title><content type='html'>In the other blog, Chris requested a page that shows all of the reviews he has written. I estimated it would take 14 seconds. It took 50 minutes to build and deploy.&lt;br /&gt;&lt;br /&gt;Example: &lt;a href="http://www.dvdfriend.us/UserReviews.aspx?un=DVDFriend"&gt;http://www.dvdfriend.us/UserReviews.aspx?un=DVDFriend&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;1 - Create a page Called UserReviews.aspx. It uses the normal site master page. Loaded this page into the browser passing it ?un=DvdFriend. The page loaded without any content.&lt;br /&gt;&lt;br /&gt;2 - Created a stored procedure called DFGetUserBlogs(@userName). There's an existing view, DFvwBlogEntries, that already has all of the information I need. The stored procedure queries some fields for that where &lt;a href="mailto:UserName=@userName"&gt;UserName=@userName&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;3 - Expose the query as a method in one of the business objects. There's an existing class called BlogFactory that has lots of similar methods. I created the new method:&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;public static DataTable GetUserBlogs(string userName)&lt;br /&gt;{&lt;br /&gt;const string STORED_PROCEDURE = "DFGetUserBlogs";&lt;br /&gt;return AWDatabase.GetReadonly().ExecuteDataSet(STORED_PROCEDURE, userName).Tables[0];&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;4 - Added an object data source to the new page. Pointed it to the new method. Added a query string parameter for un.&lt;br /&gt;&lt;br /&gt;5 - Added a datagrid to the page. Wired it up to the object data source. Loaded the page.. it's good!&lt;br /&gt;&lt;br /&gt;6 - Tweaked the grid. Shut off AUTO GENERATE COLUMNS, then added the fields in the order I wanted. Formatted the date field.&lt;br /&gt;&lt;br /&gt;7 - Added the SortExpression for each of the columns.&lt;br /&gt;&lt;br /&gt;8 - Added a server-side H1 to the page. Assigned its value from the UserName property, which returns the value of Request.Querystring["un"];&lt;br /&gt;&lt;br /&gt;9 - Changed Default.aspx and P.aspx: converted the USERNAME display fields to hyperlinks for the new page.&lt;br /&gt;&lt;br /&gt;10 - Tested&lt;br /&gt;&lt;br /&gt;11 - Deployed&lt;br /&gt;&lt;br /&gt;Using out-of-the-box asp.net controls, and a little custom code, I was able to create this page pretty quick, but there's a lot more that can be done.&lt;br /&gt;&lt;br /&gt;The page is a dump of everything the user has. Currently, DVFriend is the worse-case-scenario, wich isn't so bad. Once the list reaches a certain unknown size, it will be time to add paging.&lt;br /&gt;&lt;br /&gt;Adding paging is easy enough; just have to enable it in the grid. However, the problem is that even if you're only showing one page of data, it would still query for all of the rows. I wouldn't be able to sleep if I did that (other than as, maybe, a transitional step).&lt;br /&gt;&lt;br /&gt;I had a problem with the sort description. I set the Rating column to Rating,ProductName. I thought that would work, but it didn't. It always sorted by rating ASC. DESC wouldn't work, so I took off product name for now. The sorts will have to be revisited.&lt;br /&gt;&lt;br /&gt;Other TO DOs&lt;br /&gt;- I'd also like to add a summary grid and some filters on the top. IE: Pick a particular rating, and or date range; and/or reviews only. The summary would show how many ratings and reviews the user has, how long they have been active, etc.&lt;br /&gt;&lt;br /&gt;- Show a list of other users on the right side so you can browser all reviews from all users. As long as the active user list is short, that will work... i can drop it in quick. Once the site conquers the world and the list is bigger, it won't hold.&lt;br /&gt;&lt;br /&gt;- Put the grid in an asp.net update panel. I would've done this to begin with if I thought of it at the time.&lt;br /&gt;&lt;br /&gt;So, the asp.net controls are pretty powerful; quick and easy. I'm not a huge fan of the final result, though. Its super quick and easy, but each SORT operation is a post back. I'd rather use the querystring so that you can bookmark the page and get back to it in the same state you left it. As is, you can bookmark it, but it will go to its original state.&lt;br /&gt;&lt;br /&gt;Prior to asp.net, I created a ton of reports in JTS that needed this functionality. It was all done by adding attributes to the html tags, and javascript would create the new url and request it. In the end, I ended up with one generic ASP page and a bunch of XLSTs and data sources. To sort, you'd add a SORT="" attribute to the corresponding TH. There'd be some notation for asc, desc, etc (I forget the details). That worked out pretty well.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2143318148319291738-6839387109324572092?l=hamletcode.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://hamletcode.blogspot.com/feeds/6839387109324572092/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2143318148319291738&amp;postID=6839387109324572092' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2143318148319291738/posts/default/6839387109324572092'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2143318148319291738/posts/default/6839387109324572092'/><link rel='alternate' type='text/html' href='http://hamletcode.blogspot.com/2008/02/dvdfriend-user-review-page.html' title='DvdFriend - User Review Page'/><author><name>Jay Allard</name><uri>http://www.blogger.com/profile/15785084867572890025</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2143318148319291738.post-3910290157000988395</id><published>2008-02-09T00:57:00.001-05:00</published><updated>2008-02-09T01:39:53.889-05:00</updated><title type='text'>Pet Peeve 277: Ordinals vs key name</title><content type='html'>Pet Peeve #277&lt;br /&gt;&lt;br /&gt;select FirstName, LastName, ShoeSize from MyFavoriteTable&lt;br /&gt;&lt;br /&gt;... get a reader ...&lt;br /&gt;&lt;br /&gt;while (reader.Read()) {&lt;br /&gt;Console.WriteLine("First Name: " + (string)reader["firstname"]);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;Per my previous post, I prefer (string)reader["firstname"] over reader["firstname"].ToString(). But it doesn't stop there. Oh no. There's more. I don't like that approach at all. I'd much rather see reader.GetString(FIRST_NAME) but more on that later.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Notice that the select statement queries for FirstName, but we're looking for "firstname" in our reader. The reader is going to do a case-sensitive search for "firstname". When that fails, it will do a case-insensitive search. Why search twice? In fact, why search at all? Just tell it the index number.&lt;br /&gt;&lt;p&gt;string firstName = reader.GetString(0);&lt;br /&gt;string lastName = reader.GetString(1);&lt;br /&gt;Int32 shoeSize = reader.GetInt32(2);&lt;/p&gt;&lt;p&gt;That's more efficient. Its going right to where it needs to go. But, 0, 1 and 2 aren't very readable, are they? Gosh no.&lt;/p&gt;&lt;p&gt;I use constants.&lt;/p&gt;&lt;p&gt;const int FIRST_NAME = 0;&lt;br /&gt;const int LAST_NAME = 1;&lt;br /&gt;const int SHOE_SIZE = 2;&lt;/p&gt;&lt;p&gt;get reader... create while loop, etc&lt;/p&gt;&lt;p&gt;string firstName = reader.GetString(FIRST_NAME);&lt;br /&gt;string lastName = reader.GetString(LAST_NAME);&lt;br /&gt;Int32 shoeSize = reader.GetInt32(SHOE_SIZE);&lt;/p&gt;&lt;p&gt;Of course, for this to work the fields need to be in a known predictable order, which in my experience is usually the case. Maybe it wouldn't fit if you have multiple existing procedures that return similar fields in different orders all going through the same method, but what are the odds of that? I've always been able to define the order.&lt;/p&gt;&lt;p&gt;Reader has another method called GetOrdinal() that you can use to look up the ordinals up front. So, if you really don't know the ordinal, you can do this:&lt;/p&gt;&lt;p&gt;int firstNameOrdinal = reader.GetOrdinal("FirstName");&lt;br /&gt;int lastNameOrdinal = reader.GetOrdinal("LastName");&lt;br /&gt;while (reader.Read()) {&lt;br /&gt;string firstName = reader.GetString(firstNameOrdinal);&lt;br /&gt;string firstName = reader.GetString(lastNameOrdinal);&lt;br /&gt;...&lt;br /&gt;}&lt;/p&gt;&lt;p&gt;That way, you only do the lookups once rather than at every iteration of the loop.&lt;/p&gt;&lt;p&gt;If you know they'll never change, then maybe you assign them to statics. I used to have a pattern to cover that scenario, but I quickly learned to dislike it because of the comingling of static/non-statics. Basically, when it got to the reader, it would check the value of one of the static ordinals. If it was -1, it would assign all of the statics. From there on, it wouldn't have to do it again. I don't like it.&lt;/p&gt;&lt;p&gt;The GetOrdinal follows the same steps as reader["fieldName"]. First it does a case-insensitive search, then a case sensitive search if necessary. So, if you don't have the ordinal, then hopefully you at least have the proper column name.&lt;/p&gt;&lt;p&gt;My position is clear: know the ordinals upfront and use them.&lt;/p&gt;&lt;p&gt;In order to do that effectively, you have to rely on the column order. If you do "select *", that's not reliable or portable. Always explicitly specify your select wether you're hitting a table or view directly, or when a proc does it for you.&lt;/p&gt;&lt;p&gt;&lt;span style="font-size:180%;"&gt;Reader Source Code&lt;/span&gt;&lt;/p&gt;&lt;p&gt;I took a look at the reader source code to compare reader["string"] to reader.GetString(0). The by-ordinal approach doesn't immediately return the value... it does a little legwork first. By-string does the same legwork, plus the additional work of looking up the ordinal to get it started.&lt;/p&gt;&lt;p&gt; &lt;/p&gt;&lt;p&gt; &lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2143318148319291738-3910290157000988395?l=hamletcode.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://hamletcode.blogspot.com/feeds/3910290157000988395/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2143318148319291738&amp;postID=3910290157000988395' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2143318148319291738/posts/default/3910290157000988395'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2143318148319291738/posts/default/3910290157000988395'/><link rel='alternate' type='text/html' href='http://hamletcode.blogspot.com/2008/02/pet-peeve-277-ordinals-vs-key-name.html' title='Pet Peeve 277: Ordinals vs key name'/><author><name>Jay Allard</name><uri>http://www.blogger.com/profile/15785084867572890025</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2143318148319291738.post-7904194423240314158</id><published>2008-02-09T00:18:00.000-05:00</published><updated>2008-02-09T13:07:43.112-05:00</updated><title type='text'>Pet Peeve 318: (string) vs ToString()</title><content type='html'>I'm trying to make it a point to blog entries on a regular basis. I've been told its a good idea, and I like good ideas, but at this time of the day, I don't have much to talk about.&lt;br /&gt;&lt;br /&gt;So, I'm going to fall back to Jay Pet Peeve #318 (I just made that up, but I'll start keeping track.)&lt;br /&gt;&lt;br /&gt;Let me be upfront about Pet Peeve #318: It is superceded by Pet Peeve #277. If you have to do a lookup by string, then its covered by #277. However, I feel you should do the lookups by ordinal, which is covered by the next post.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:180%;"&gt;ToString()&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;select FirstName, ShoeSize from SomeStupidTableThatDoesntActuallyExist&lt;br /&gt;&lt;br /&gt;The name is a varchar, and the shoesize is an integer.&lt;br /&gt;&lt;br /&gt;You write some code to execute the query, and you end up with a data reader. Then you start looping through the reader.&lt;br /&gt;&lt;br /&gt;while (reader.Read()) {&lt;br /&gt;Console.WriteLine("First Name: " + reader["firstname"].ToString());&lt;br /&gt;Console.WriteLine("Shoe Size: " + reader["shoesize"].ToString());&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;An alternative for first name is:&lt;br /&gt;Console.WriteLine("First Name: " + (string)reader["firstname"]);&lt;br /&gt;&lt;br /&gt;The first approach is technically sound, though I prefer the second simply for semantics. ToString() is used to provide the string representation of an object. When your object is already a string, you're essentially saying "convert my string to a string". Whereas, the 2nd approach says "here's my string". You wouldn't do "hello".ToString(), would you?&lt;br /&gt;&lt;br /&gt;Does it matter? No. Its a pet peeve. I tried to be upfront about that. Pardon me if I wasn't clear.&lt;br /&gt;&lt;br /&gt;As for the "shoesize", that's a different story. That's an integer, but you want to display it as a string, so ToString() doesn't offend my delicate sensibilities in that case.&lt;br /&gt;&lt;br /&gt;NOTE: I don't like "firstname" and "lastname" in the reader calls either... that's covered in the next post.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2143318148319291738-7904194423240314158?l=hamletcode.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://hamletcode.blogspot.com/feeds/7904194423240314158/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2143318148319291738&amp;postID=7904194423240314158' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2143318148319291738/posts/default/7904194423240314158'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2143318148319291738/posts/default/7904194423240314158'/><link rel='alternate' type='text/html' href='http://hamletcode.blogspot.com/2008/02/string-vs-tostring.html' title='Pet Peeve 318: (string) vs ToString()'/><author><name>Jay Allard</name><uri>http://www.blogger.com/profile/15785084867572890025</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2143318148319291738.post-1265086829783091803</id><published>2008-02-06T08:49:00.001-05:00</published><updated>2008-02-06T08:57:14.581-05:00</updated><title type='text'>More string silliness</title><content type='html'>Lets convert that previous example into a C# 3.0 extension method.&lt;br /&gt;&lt;br /&gt;It would be cool if we could add static extension methods instead.&lt;br /&gt;IE:   string.IsNullOrTrimmedEmpty();&lt;br /&gt;rather than&lt;br /&gt;x == null || x.IsTrimmedEmpty()&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Test Class&lt;/h3&gt;&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;br /&gt;using MbUnit.Framework;&lt;br /&gt;using System;&lt;br /&gt;using System.Collections.Generic;&lt;br /&gt;using System.Linq;&lt;br /&gt;using System.Text;&lt;br /&gt;&lt;br /&gt;namespace YaddaYadda&lt;br /&gt;{&lt;br /&gt;    class Program&lt;br /&gt;    {&lt;br /&gt;        public static bool IsNullOrTrimmedEmpty(string s)&lt;br /&gt;        {&lt;br /&gt;            return s == null || &lt;b style='color:blue'&gt;s.IsTrimmedEmpty();&lt;/b&gt;&lt;br /&gt;        }&lt;br /&gt;        static void Main(string[] args)&lt;br /&gt;        {&lt;br /&gt;            Assert.IsTrue(IsNullOrTrimmedEmpty(null));&lt;br /&gt;            Assert.IsTrue(IsNullOrTrimmedEmpty(""));&lt;br /&gt;            Assert.IsTrue(IsNullOrTrimmedEmpty("   "));&lt;br /&gt;            Assert.IsFalse(IsNullOrTrimmedEmpty(" a "));&lt;br /&gt;            Assert.IsFalse(IsNullOrTrimmedEmpty("a "));&lt;br /&gt;            Assert.IsFalse(IsNullOrTrimmedEmpty(" a"));&lt;br /&gt;            Assert.IsFalse(IsNullOrTrimmedEmpty("a"));&lt;br /&gt;            Console.ReadLine();&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;The class with the extension method&lt;/h3&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;br /&gt;using System;&lt;br /&gt;using System.Collections.Generic;&lt;br /&gt;using System.Linq;&lt;br /&gt;using System.Text;&lt;br /&gt;&lt;br /&gt;namespace YaddaYadda&lt;br /&gt;{&lt;br /&gt;    public static class StringExtensions&lt;br /&gt;    {&lt;br /&gt;        &lt;b style='color:blue'&gt;public static bool IsTrimmedEmpty(this string s)&lt;br /&gt;        {&lt;br /&gt;            return s.Trim().Length == 0;           &lt;br /&gt;        }&lt;/b&gt;&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;/blockquote&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2143318148319291738-1265086829783091803?l=hamletcode.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://hamletcode.blogspot.com/feeds/1265086829783091803/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2143318148319291738&amp;postID=1265086829783091803' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2143318148319291738/posts/default/1265086829783091803'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2143318148319291738/posts/default/1265086829783091803'/><link rel='alternate' type='text/html' href='http://hamletcode.blogspot.com/2008/02/more-string-silliness.html' title='More string silliness'/><author><name>Jay Allard</name><uri>http://www.blogger.com/profile/15785084867572890025</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2143318148319291738.post-1000248240290373417</id><published>2008-02-06T07:24:00.000-05:00</published><updated>2008-02-06T08:49:04.914-05:00</updated><title type='text'>String silliness</title><content type='html'>Yesterday at work, Carlos and I had a silly converstation about the best way to check if a trimmed string is NULL or EMPTY.&lt;br /&gt;&lt;br /&gt;I usually do this:&lt;br /&gt;&lt;blockquote&gt;&lt;br /&gt;if (string.IsNullOrEmpty(x)  x.Trim().Length == 0)&lt;br /&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;Carlos liked this better because its prettier:&lt;br /&gt;&lt;blockquote&gt;&lt;br /&gt;if (x == null || x.Trim().Length == 0)&lt;br /&gt;&lt;/blockquote&gt;&lt;br /&gt;Of course, I took offense to that because I find my version to be quite attractive as well. So, instead of settling on which one is prettier, we broke it down into basic operations to see which one would be (theoretically) quicker.&lt;br /&gt;&lt;br /&gt;In most cases, x will be a valid string.&lt;br /&gt;&lt;blockquote&gt;&lt;br /&gt;string x = "123";&lt;br /&gt;if (string.IsNullOrEmpty(x) || x.Trim().Length == 0)&lt;br /&gt;&lt;/blockquote&gt;&lt;br /&gt;1 - Check for null&lt;br /&gt;2 - Check for empty (.Length == 0)&lt;br /&gt;3 - Trim the string&lt;br /&gt;4 - Check the length&lt;br /&gt;Under normal circumstances, there are 4 things to do&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;br /&gt;string x = "123";&lt;br /&gt;if (x == null || x.Trim().Length == 0)&lt;br /&gt;&lt;/blockquote&gt;&lt;br /&gt;1 - Check for null&lt;br /&gt;2 - Trim&lt;br /&gt;3 - Check the length&lt;br /&gt;Under normal circumstances, there are 3 things to do.&lt;br /&gt;&lt;br /&gt;So, the second choice is the better one, and we will use that going forward.&lt;br /&gt;&lt;br /&gt;Out of curiosity, I took a look at the string source code to see how it was doing some things. &lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;br /&gt;if (x.Trim().Length == 0)&lt;br /&gt;or&lt;br /&gt;if (x.Trim() == string.Empty)&lt;br /&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;.Length has been my means of choice. Its just a property value as opposed to a comparison. The string source code does it the same way.&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;br /&gt;System.String.IsNullOrEmpty()&lt;br /&gt;if (value != null) { return value.Length == 0;} return true;&lt;br /&gt;&lt;/blockquote&gt;&lt;br /&gt;I think we've made a lot of progress towards solving some insignificant problems. Super.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2143318148319291738-1000248240290373417?l=hamletcode.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://hamletcode.blogspot.com/feeds/1000248240290373417/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2143318148319291738&amp;postID=1000248240290373417' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2143318148319291738/posts/default/1000248240290373417'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2143318148319291738/posts/default/1000248240290373417'/><link rel='alternate' type='text/html' href='http://hamletcode.blogspot.com/2008/02/yesterday-at-work-carlos-and-i-had.html' title='String silliness'/><author><name>Jay Allard</name><uri>http://www.blogger.com/profile/15785084867572890025</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2143318148319291738.post-3708993353066846939</id><published>2008-02-03T09:29:00.000-05:00</published><updated>2008-02-03T10:15:39.435-05:00</updated><title type='text'>Code Camp 2008 recap</title><content type='html'>Code Camp 2008 is an excellent programming event sponsored by a variety of companies (including the one one I work for) in South Floida. Its a day of 72 classes at 70 minues each. This year's agenda is here:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://codecamp08.fladotnet.com/agenda.aspx"&gt;http://codecamp08.fladotnet.com/agenda.aspx&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Its a great event. Its completely free, and you can get exposure to a lot of stuff.&lt;br /&gt;&lt;br /&gt;7:30 -8:00 - Registration&lt;br /&gt;This was chaotic. There several copies of sign in sheets spewed about. You had to find a page with your name on it, and sign. Presumbably someone later consolidated the lists. After that, we were given the goody package. The goody packages was assembled on demand rather than prepackaged, so the line was pretty backed up.&lt;br /&gt;&lt;br /&gt;8:00 - 8:30 - Keynote&lt;br /&gt;There were 600 people crammed into a cafeteria that felt as if it were only intended for 1/2 that number. I fell asleep for 10 minutes and didn't fall over.&lt;br /&gt;&lt;br /&gt;At 8:15, there was a very brief welcome, and code camp officially began.&lt;br /&gt;&lt;br /&gt;8:30 - 9:40&lt;br /&gt;I went to "Essential of the Architect and Architecture". I didn't have any expectations for this, because that's how I roll, but if I came up with some, I would've been way off. Ron Jacobs from Microsoft was the presenter. He's a pretty significant character in the great northwest, so it was good to get his view of things.&lt;br /&gt;&lt;br /&gt;He described the roll of an architect by breaking it down in to three major components and comparing them to the roles of real people such as Christopher Columbus (explorer) and OJ Simpson's layer (advocate). It was interesting. I have several take aways from that session.&lt;br /&gt;&lt;br /&gt;There were 2 other sessions at the time that would've been intresting: Dynamic Data Fields and Tools&lt;br /&gt;&lt;br /&gt;9:15 - 11:00&lt;br /&gt;I've already mastered the "Science of Great UI" as clearly demonstrated by the multitude of 3 color sites that I have assembled. Its real simple: Use a table for layout, then make everything look ad boring as possible within the cells of the table. Clearly I don't need a class.&lt;br /&gt;&lt;br /&gt;I went to the Web Service Software Factory Modeling Edition. The software factories are basically code generators. It gets you started, you fill in the blanks. The modeling edition is more than that because you can work with the designer and regenerate from the model as you need to. I'm going to have to become more familiar with this.&lt;br /&gt;&lt;br /&gt;Stan Schultes was the presenter&lt;br /&gt;&lt;a href="http://www.vbnetexpert.com/"&gt;http://www.vbnetexpert.com/&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;11:10 - 12:20&lt;br /&gt;From C# to F# in 60 minutes&lt;br /&gt;This was a good introduction to F#. The gist of it was this: "We can't make light got any faster". Computer power has stopped doubleing every 18 months, so we have to make better us of multicores, etc. F# is a functional, scripting, and OOP language all rolled into one. Its great for list based stuff, and it makes it very easy to fire off stuff asychronously. It was nostalgic to watch it in action because most of the commands were issued from a command line. Good stuff.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://cs.jaxdug.com/blogs/eugene_chuvyrov/"&gt;http://cs.jaxdug.com/blogs/eugene_chuvyrov/&lt;/a&gt;&lt;br /&gt;I just went to the presenters Blog, and the top entry is "VB.NET Must Die". I love it.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;12:20 to 1:20 - Lunch&lt;br /&gt;Once again, 600+ people crammed into the cafeteria. There were rumors of pizza going througout the crowd. I wasn't keen on the idea of waiting in another line and trying to find somewhere to sit, so Carlos, Steve and I went to Chilis instead.&lt;br /&gt;&lt;br /&gt;1:20 - 2:30&lt;br /&gt;High Speed Development in Visual Studio with Code Rush and refactor.&lt;br /&gt;This was great. I installed CodeRush a few weeks ago, but haven't really used it. I didn't take the time to learn it. It turns out that there's a TRAINING window for inflight training. I'm going to turn that on, then most likely buy it when the trial expires.&lt;br /&gt;&lt;a href="http://www.devexpress.com/Products/NET/IDETools/CodeRush/"&gt;http://www.devexpress.com/Products/NET/IDETools/CodeRush/&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;2:40 - 3:50&lt;br /&gt;For Love or More Money, Developing Your IT Career&lt;br /&gt;I initially thought this was a poor choice, but it worked out. I figured that by "Developing your IT Career", it would cover how to grow as an IT professional. There was some of that, but mostly it was "how to interview for another job". It was presented by &lt;a href="http://www.sherstaff.com/"&gt;http://www.sherstaff.com/&lt;/a&gt;, a company I haven't worked with before. (I've only changed jobs twice, so I don't get around a lot.) Despite my initial trepidation, I did get some pointers out of it. (IE: Keep a technical blog).&lt;br /&gt;&lt;br /&gt;I've always had trouble with the interview process. There's a lot of etiquette. There are things you should and shouldn't say, should and shouldn't do. I have a very hard time accepting that. I like putting my forks AND spoons on the same side of the plate. I don't care where the wine glass is or the accessibility of my cloth napkin. Just give me food. I'm the same way with the interviews which, amittedly, isn't good. I want to get a job based on my experience with technology and people, and I would prefer to do that without rehearsing lines in front of the mirror. Thankfully, I don't interview often.&lt;br /&gt;&lt;br /&gt;4:00 - 5:10&lt;br /&gt;"Orcas for Architects" - I think its time to update the presentation name.&lt;br /&gt;This was a 70 minute crash course in all things VS 2008 and beyond. I got a kick out of it. Most was stuff I'm already familiar with, but there were some gold nuggets in there such as ParallelFX. This reminded me of the "can't make light go any faster" comment earlier in the day. ParallelFX offers some new contructs that will automatically perform certain operations in parallel. It will use the other cores on your CPU to finish things faster.&lt;br /&gt;&lt;br /&gt;The first set of example was mostly linear: on a dual core, it was twice as fast. On a quad core, it was 4 times as fast. The second one was graphic based. A quad core was 53% faster.&lt;br /&gt;&lt;br /&gt;I told a couple guys about this later that night, and messed it up. I thought it was called PLINQ, but it looks like PLINQ is just part of it.&lt;br /&gt;&lt;br /&gt;I'm looking forward to that one.&lt;br /&gt;&lt;br /&gt;5:10&lt;br /&gt;Wrapup. We once again assembled in the fire-hazard cafeteria. There were some nice raffle items, and closing comments from several of the sponsors. Some of the sponsors put together an after party, but I was unable to attend due to other plans.&lt;br /&gt;&lt;br /&gt;It was a great day. I can't say I learned a lot of detail about anything in particular, but I got a lot of exposure to a lot of cool things, which is important.&lt;br /&gt;&lt;br /&gt;Most of my takeaways came from the first Architecture session and the "For Love or Money" session.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2143318148319291738-3708993353066846939?l=hamletcode.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://hamletcode.blogspot.com/feeds/3708993353066846939/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2143318148319291738&amp;postID=3708993353066846939' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2143318148319291738/posts/default/3708993353066846939'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2143318148319291738/posts/default/3708993353066846939'/><link rel='alternate' type='text/html' href='http://hamletcode.blogspot.com/2008/02/code-camp-2008-recap.html' title='Code Camp 2008 recap'/><author><name>Jay Allard</name><uri>http://www.blogger.com/profile/15785084867572890025</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2143318148319291738.post-198616234469693321</id><published>2008-02-03T09:21:00.000-05:00</published><updated>2008-02-03T09:29:18.209-05:00</updated><title type='text'>Hamlet Code</title><content type='html'>"Hamlet Code" is a piece of foolishness that I came up while trying to find a new XBOX Live ID. My original ID was "DvdFriend", and ode to my website, but after a while I realized it was a lame handle.&lt;br /&gt;&lt;br /&gt;I tried a variety of different code related user names, but they were all taken. A thought process that I don't recall came up with "to code or not to code", which is too big, so I rounded it down to "Hamlet Code". I only hope that my recollection of 9th grade literature is accurate.&lt;br /&gt;&lt;br /&gt;So anyway. I have another blog at &lt;a href="http://jayallard.blogspot.com/"&gt;http://jayallard.blogspot.com/&lt;/a&gt;. I occasionaly add some foolishness there, and every once in a while I toss in some technical stuff. Quite honestly, its a disaster. However, I call the blog "Jay's Rants", so I'm being upfront about the kind of attention I apply to it. I just go in, type whatever I want to type, then hit save. More than one person has commented on typos and grammatical whoopsies.&lt;br /&gt;&lt;br /&gt;This new blog is strictly for technical foolishness. If you want to read about how our community flooded, or the affect of the 1986 Transformers animated movie on my relationship with my nephew, or how I feed my dogs, then go to the other one. If you want to read about code related stuff, then read this one. In the end, there's something for everyone (or, at least for me).&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2143318148319291738-198616234469693321?l=hamletcode.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://hamletcode.blogspot.com/feeds/198616234469693321/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2143318148319291738&amp;postID=198616234469693321' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2143318148319291738/posts/default/198616234469693321'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2143318148319291738/posts/default/198616234469693321'/><link rel='alternate' type='text/html' href='http://hamletcode.blogspot.com/2008/02/hamlet-code.html' title='Hamlet Code'/><author><name>Jay Allard</name><uri>http://www.blogger.com/profile/15785084867572890025</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry></feed>
