<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/atom10full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><feed xmlns="http://www.w3.org/2005/Atom" xmlns:openSearch="http://a9.com/-/spec/opensearch/1.1/" xmlns:georss="http://www.georss.org/georss" xmlns:gd="http://schemas.google.com/g/2005" xmlns:thr="http://purl.org/syndication/thread/1.0" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" gd:etag="W/&quot;CEEBSHYyfSp7ImA9WhRaGUU.&quot;"><id>tag:blogger.com,1999:blog-3980660135707078299</id><updated>2012-02-23T09:37:39.895+02:00</updated><category term="Mocks" /><category term="Reading" /><category term="Approvals" /><category term="Hackatone" /><category term="Social" /><category term="Code Kata" /><category term="MVC" /><category term="Trackyt.net" /><category term="CSS" /><category term="REST" /><category term="Continuous" /><category term="GitSVN" /><category term="AJAX" /><category term="UI" /><category term="Design" /><category term="Tips" /><category term="BeerNCode" /><category term="ITJam" /><category term="Candidate" /><category term="Refactoring" /><category term="KievAltNet" /><category term="ELMAH.MVC" /><category term="Mind" /><category term="Life" /><category term="Retrospective" /><category term="GitHub" /><category term="Open source" /><category term="TDD" /><category term="NuGet" /><category term="Git" /><category term="Agile" /><category term="Linq" /><category term="Conference" /><category term="HTML" /><category term="InsideMVC" /><category term="Tools" /><category term="asp.net" /><category term="CSharp" /><category term="DDD" /><category term="Applications" /><category term="Clean Code" /><category term="JavaScript" /><category term="Video" /><category term="DAL" /><category term="Cloud" /><title>Alexander Beletsky's Development Blog</title><subtitle type="html">Issues of development, testing, maintenance and &lt;a href="http://trackyt.net"&gt;management&lt;/a&gt;</subtitle><link rel="http://schemas.google.com/g/2005#feed" type="application/atom+xml" href="http://www.beletsky.net/feeds/posts/default" /><link rel="alternate" type="text/html" href="http://www.beletsky.net/" /><link rel="next" type="application/atom+xml" href="http://www.blogger.com/feeds/3980660135707078299/posts/default?start-index=26&amp;max-results=25&amp;redirect=false&amp;v=2" /><author><name>Alexander Beletsky</name><uri>https://profiles.google.com/104123427697898813533</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh5.googleusercontent.com/-WqHPxmC8QfM/AAAAAAAAAAI/AAAAAAAAHi4/tX9CTF-Dzy8/s512-c/photo.jpg" /></author><generator version="7.00" uri="http://www.blogger.com">Blogger</generator><openSearch:totalResults>133</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/atom+xml" href="http://feeds.feedburner.com/abeletskyblog" /><feedburner:info uri="abeletskyblog" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><entry gd:etag="W/&quot;D0ABQ3wyfyp7ImA9WhRaGEw.&quot;"><id>tag:blogger.com,1999:blog-3980660135707078299.post-2658070700940330598</id><published>2012-02-21T11:15:00.001+02:00</published><updated>2012-02-21T11:15:52.297+02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-02-21T11:15:52.297+02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Tools" /><category scheme="http://www.blogger.com/atom/ns#" term="Open source" /><category scheme="http://www.blogger.com/atom/ns#" term="CSS" /><category scheme="http://www.blogger.com/atom/ns#" term="UI" /><category scheme="http://www.blogger.com/atom/ns#" term="HTML" /><title>Foundation Framework for Web Sites Production</title><content type="html">&lt;p&gt;The &lt;a href="http://foundation.zurb.com/"&gt;Foundation&lt;/a&gt; framework is something I discovered by accident browsing through some github project pages. I really liked how one of the sites looked on my iPad. I was also pleased to see how HTML crafted, using clear names for classes and HTML5 semantics. As it turned out, that site was using Foundation Framework by &lt;a href="http://www.zurb.com/"&gt;Zurb&lt;/a&gt; - design agency in San Francisco Bay area.&lt;br /&gt;
&lt;/p&gt;&lt;p&gt;I checked out the &lt;a href="http://foundation.zurb.com/docs/"&gt;documentation&lt;/a&gt; and Foundation appears to be pretty solid framework for web applications prototyping and production. It contained everything needed: &lt;a href="http://foundation.zurb.com/docs/grid.php"&gt;Grid Layouts&lt;/a&gt;, &lt;a href="http://foundation.zurb.com/docs/buttons.php"&gt;Buttons&lt;/a&gt;, &lt;a href="http://foundation.zurb.com/docs/forms.php"&gt;Forms&lt;/a&gt; and &lt;a href="http://foundation.zurb.com/docs/ui.php"&gt;UI&lt;/a&gt;. And of cause, all of that is open source hosted on github.&lt;br /&gt;
&lt;/p&gt;&lt;p&gt;During my preparation of project page for &lt;a href="http://alexanderbeletsky.github.com/candidate/"&gt;candidate&lt;/a&gt; I decided to try it out. I was really happy of the experience. &lt;br /&gt;
&lt;/p&gt;&lt;h2&gt;Object Oriented CSS&lt;/h2&gt;&lt;p&gt;Have you heard of &lt;a href="https://github.com/stubbornella/oocss/wiki"&gt;OOCSS&lt;/a&gt;? Initially I thought that idea is almost non-sense, but I'm changing my opinion now. I think Foundation fully conforms to OOCSS style of development - each behavior or UI you want to apply to HTML element is done by applying of corresponding class. &lt;br /&gt;
&lt;/p&gt;&lt;p&gt;Great thing is that you see how it's done in framework and do same in your code as well. I remember the times I started to do HTML/CSS and I higly used #id's, applying the styles by element Id. The code was awful and styles applied on #id's were not re-usable at all, so if I needed the same margin/padding or text color I have to copy the section of CSS and move it into next &lt;code&gt;#some-id { ... }&lt;/code&gt;.&lt;br /&gt;
&lt;/p&gt;&lt;p&gt;With OOCSS you rely on classed. Here some example,&lt;br /&gt;
&lt;/p&gt;&lt;pre class="brush: html"&gt;&amp;lt;div class=&amp;quot;container darker-grey light-border small-padding&amp;quot;&amp;gt;
 &amp;lt;div class=&amp;quot;row smaller-fonts&amp;quot;&amp;gt;
  &amp;lt;div class=&amp;quot;four columns&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;
  &amp;lt;div class=&amp;quot;four columns&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;
  &amp;lt;div class=&amp;quot;four columns&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;
 &amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&lt;/pre&gt;&lt;p&gt;Look, no #id's - classes only. With classes I control: position, colors, borders and margin/paddings. This is really cool, since all of that classes are easy reusable in any part of page.&lt;br /&gt;
&lt;/p&gt;&lt;h2&gt;Grid system&lt;/h2&gt;&lt;p&gt;Grid systems is really cool concept and allows to develop much faster. Instead of writing own CSS that would position elements, you stick to Grid System. The classical grid system is probably &lt;a href="http://960.gs/"&gt;960.gs&lt;/a&gt;. It's really great and blown my mind as I first time tried it, but currently it little outdated: 960px wide is small for modern monitor and it is not adaptive. Modern web design demands site looks great both on PC and Mobile devices, adapt it's content based on screen size.&lt;br /&gt;
&lt;/p&gt;&lt;p&gt;Here is a quote of Foundation documentation.&lt;br /&gt;
&lt;/p&gt;&lt;blockquote&gt;The grid is built around three key elements: containers, rows, and columns. Containers create base padding for the page; rows create a max-width and contain the columns; and columns create the final structure. Everything on your page that you don't give a specific structural style to should be within a container, row and column.&lt;br /&gt;
&lt;/blockquote&gt;&lt;p&gt;You develop the layout based on planned number of row and columns that compose the row. Again, code is done in OOCSS way with clean classes names, so you write almost "plain" English in HTML.&lt;br /&gt;
&lt;/p&gt;&lt;pre class="brush: html"&gt;&amp;lt;div class=&amp;quot;container&amp;quot;&amp;gt;
  &amp;lt;div class=&amp;quot;row&amp;quot;&amp;gt;
    &amp;lt;div class=&amp;quot;eight columns&amp;quot;&amp;gt;
      Eight columns
    &amp;lt;/div&amp;gt;
    &amp;lt;div class=&amp;quot;four columns&amp;quot;&amp;gt;
      Four columns     
    &amp;lt;/div&amp;gt;
  &amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&lt;/pre&gt;&lt;p&gt;After design is ready, you just open it on iPad and.. Surprise, it looks great there! Text and columns are adaptively fits the screen size. &lt;br /&gt;
&lt;/p&gt;&lt;h2&gt;Buttons and Forms&lt;/h2&gt;&lt;p&gt;Buttons and Forms are same important as Colors and Fonts in your web site. You can't get good site appearance if buttons and forms are ugly. I usually spend a lot of time on "beautifying" those, but still unhappy with results at the end of the day. With Foundation it's easier. You got nice styles from the box. &lt;br /&gt;
&lt;/p&gt;&lt;p&gt;Forms:&lt;br /&gt;
&lt;/p&gt;&lt;a href="https://lh5.googleusercontent.com/-r0XbF8NN5Zo/T0NfEXYwg6I/AAAAAAAAH4Q/4yZ8y3OqCMM/s620/image-1.jpg"&gt;&lt;br /&gt;
&lt;img src="https://lh5.googleusercontent.com/-r0XbF8NN5Zo/T0NfEXYwg6I/AAAAAAAAH4Q/4yZ8y3OqCMM/s620/image-1.jpg" alt="foundation forms" /&gt;&lt;br /&gt;
&lt;/a&gt;&lt;br /&gt;
&lt;p&gt;Buttons:&lt;br /&gt;
&lt;/p&gt;&lt;a href="https://lh6.googleusercontent.com/-TNxDQv_m1Oc/T0NfGrGMXDI/AAAAAAAAH4Y/HYjq_XxDbGs/s620/image-2.jpg"&gt;&lt;br /&gt;
&lt;img src="https://lh6.googleusercontent.com/-TNxDQv_m1Oc/T0NfGrGMXDI/AAAAAAAAH4Y/HYjq_XxDbGs/s620/image-2.jpg" alt="foundation buttons" /&gt;&lt;br /&gt;
&lt;/a&gt;&lt;br /&gt;
&lt;p&gt;Recently, I've &lt;a href="https://github.com/zurb/foundation/pull/313"&gt;submitted&lt;/a&gt; green button style, so I hope it will be available soon.&lt;br /&gt;
&lt;/p&gt;&lt;h2&gt;UI stuff&lt;/h2&gt;&lt;p&gt;Besides those primary things you got nice bonus. That's different UI elements commonly used through different web sites. It includes: Alerts, Labels, Warnings, Tooltips, Tabs etc. &lt;br /&gt;
&lt;/p&gt;&lt;p&gt;For &lt;a href="http://alexanderbeletsky.github.com/candidate/"&gt;candidate&lt;/a&gt; site I successfully used Pagination UI element. &lt;br /&gt;
&lt;/p&gt;&lt;a href="https://lh3.googleusercontent.com/-_5240sOGkko/T0NfHuydwUI/AAAAAAAAH4g/jE3ft2nAAeM/s620/image-3.jpg"&gt;&lt;br /&gt;
&lt;img src="https://lh3.googleusercontent.com/-_5240sOGkko/T0NfHuydwUI/AAAAAAAAH4g/jE3ft2nAAeM/s620/image-3.jpg" alt="foundation ui" /&gt;&lt;br /&gt;
&lt;/a&gt;&lt;br /&gt;
&lt;h2&gt;Conclusions&lt;/h2&gt;&lt;p&gt;Currently &lt;a href="http://twitter.github.com/bootstrap"&gt;Bootstrap&lt;/a&gt; from Twitter is obvious leader in that niche. But I really think Foundation will get it's place. Easy to use, great documentation &lt;a href="https://github.com/zurb/foundation"&gt;repository&lt;/a&gt; is very active, so we might expected further great features in Foundation.&lt;br /&gt;
&lt;/p&gt;&lt;p&gt;And by the way.. To payback Foundation, I got idea for small product: inspired by &lt;a href="http://bootswatch.com/"&gt;Bootswatch&lt;/a&gt; I'm about to create bunch of "ready-to-use" Foundation themes, that you just download and start to use immediately. It will work great for people who are about to create one page product presentation or simple blog. Hope it will go fine and I release it soon.&lt;br /&gt;
&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3980660135707078299-2658070700940330598?l=www.beletsky.net' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/abeletskyblog?a=8Gm_UHMpDUI:tYJ0Mip8jWo:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/abeletskyblog?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/abeletskyblog?a=8Gm_UHMpDUI:tYJ0Mip8jWo:63t7Ie-LG7Y"&gt;&lt;img src="http://feeds.feedburner.com/~ff/abeletskyblog?d=63t7Ie-LG7Y" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/abeletskyblog?a=8Gm_UHMpDUI:tYJ0Mip8jWo:-BTjWOF_DHI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/abeletskyblog?i=8Gm_UHMpDUI:tYJ0Mip8jWo:-BTjWOF_DHI" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/abeletskyblog/~4/8Gm_UHMpDUI" height="1" width="1"/&gt;</content><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/3980660135707078299/posts/default/2658070700940330598?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/3980660135707078299/posts/default/2658070700940330598?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/abeletskyblog/~3/8Gm_UHMpDUI/foundation-framework-for-web-sites.html" title="Foundation Framework for Web Sites Production" /><author><name>Alexander Beletsky</name><uri>https://profiles.google.com/104123427697898813533</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh5.googleusercontent.com/-WqHPxmC8QfM/AAAAAAAAAAI/AAAAAAAAHi4/tX9CTF-Dzy8/s512-c/photo.jpg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://lh5.googleusercontent.com/-r0XbF8NN5Zo/T0NfEXYwg6I/AAAAAAAAH4Q/4yZ8y3OqCMM/s72-c/image-1.jpg" height="72" width="72" /><feedburner:origLink>http://www.beletsky.net/2012/02/foundation-framework-for-web-sites.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DU8CQXo-fCp7ImA9WhRaEUQ.&quot;"><id>tag:blogger.com,1999:blog-3980660135707078299.post-9068944886551298648</id><published>2012-02-14T07:37:00.000+02:00</published><updated>2012-02-14T07:37:40.454+02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-02-14T07:37:40.454+02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Continuous" /><category scheme="http://www.blogger.com/atom/ns#" term="Candidate" /><category scheme="http://www.blogger.com/atom/ns#" term="Open source" /><title>Candidate v.0.0.1rc - Released</title><content type="html">&lt;p&gt;  You may notice that I stick to original project name at the end of the day, even thought I wish to change it. That happened for 2 reasons: first, I really get used to candidate and it's good enough project name.. second, I spent some hours of brainstorming but found out nothing better that existing.&lt;br /&gt;
 &lt;/p&gt; &lt;p&gt;  This weekend I also finally concluded project web site and hosted it as github pages - &lt;a href="http://alexanderbeletsky.github.com/candidate/"&gt;http://alexanderbeletsky.github.com/candidate/&lt;/a&gt;. So, ladies and gentlemen - please welcome, &lt;a href="https://github.com/downloads/alexanderbeletsky/candidate/candidate-v.0.0.1rc.zip"&gt;Candidate v0.0.1rc&lt;/a&gt; is ready to be shown to the world. &lt;br /&gt;
 &lt;/p&gt; &lt;a href="http://alexanderbeletsky.github.com/candidate/"&gt;&lt;br /&gt;
  &lt;img src="https://lh5.googleusercontent.com/-WIUMqyz3naI/TznyBp-dQbI/AAAAAAAAH4A/exqlfJUQr8o/s1024/screenshot-1.jpg" alt="candidate web site" style="width: 620px;" /&gt;&lt;br /&gt;
 &lt;/a&gt;&lt;br /&gt;
 &lt;h2&gt;  What's the goal?&lt;br /&gt;
 &lt;/h2&gt; &lt;p&gt;  Thinking about nearest "competitors" in this area I would re-call &lt;a href="http://www.paulstovell.com/octopus/intro"&gt;Octopus&lt;/a&gt; by &lt;a href="https://twitter.com/#!/paulstovell"&gt;Paul Stovell&lt;/a&gt;. Octopus uses Build Server / Tentacle (Agent) architecture principal, while Candidate is simple Agent architecture - you host it the same machine as your environment is (stage, production) providing both integration and deployment functionality.&lt;br /&gt;
 &lt;/p&gt; &lt;p&gt;  My goal is stabilize and improve Candidate through this year, so it fulfill different requirements including performance and scalability. I switched all my projects to use Candidate now, so it would give me some initial feedback.&lt;br /&gt;
 &lt;/p&gt; &lt;p&gt;  Nevertheless, Candidate may turn out to be a powerful deployment application I'm still thinking about "Deployement as Service" product like &lt;a href="https://appharbor.com/"&gt;AppHabor&lt;/a&gt; and &lt;a href="http://www.heroku.com/"&gt;Heroku&lt;/a&gt; or &lt;a href="http://travis-ci.org/"&gt;Travis-CI&lt;/a&gt; as it was &lt;a href=
  "http://www.beletsky.net/2011/06/candidatenet-application-i-made-on.html"&gt;original&lt;/a&gt; idea.&lt;br /&gt;
 &lt;/p&gt; &lt;h2&gt;  What's next?&lt;br /&gt;
 &lt;/h2&gt; &lt;p&gt;  Following the principle "Build product X to learn technology Y" I'm going to proceed with Candidate to shape following areas that I wish to improve now:&lt;br /&gt;
 &lt;/p&gt; &lt;ul&gt;  &lt;li&gt;Processes, threads, synchronization in .NET&lt;/li&gt;
  &lt;li&gt;Async, Tasks library&lt;/li&gt;
  &lt;li&gt;Robust applications architecture&lt;/li&gt;
  &lt;li&gt;Different deployment scenarios for .NET platform&lt;/li&gt;
 &lt;/ul&gt; &lt;p&gt;  Technological stack is still ASP.NET MVC3 / C#/ jQuery. Currently application requires to be hosted on IIS, with application pool Process Identity equals to Admin. This does not suite all users. So, I'm looking forward to create self-hosted version using &lt;a href="https://github.com/NancyFx/Nancy"&gt;NancyFX&lt;/a&gt;. &lt;br /&gt;
 &lt;/p&gt; &lt;p&gt;  I also try to target UI / UX issues as much as possible.&lt;br /&gt;
 &lt;/p&gt; &lt;h2&gt;Wanna join?&lt;/h2&gt; &lt;p&gt;  I would be happy to. I'll much encourage you to download application, install it, perform simple testing (scenario could be found &lt;a href="https://github.com/alexanderbeletsky/candidate/wiki/Quick-start-instructions"&gt;here&lt;/a&gt;). Let me know what you think, that would be great initial contribution. As for any github hosted project, you are absolutely free to fork, hack it out and send pull request.&lt;br /&gt;
 &lt;/p&gt; &lt;p&gt;  Thanks for you help.&lt;br /&gt;
 &lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3980660135707078299-9068944886551298648?l=www.beletsky.net' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/abeletskyblog?a=DrtxY95HrhM:yJYmGXS3oig:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/abeletskyblog?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/abeletskyblog?a=DrtxY95HrhM:yJYmGXS3oig:63t7Ie-LG7Y"&gt;&lt;img src="http://feeds.feedburner.com/~ff/abeletskyblog?d=63t7Ie-LG7Y" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/abeletskyblog?a=DrtxY95HrhM:yJYmGXS3oig:-BTjWOF_DHI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/abeletskyblog?i=DrtxY95HrhM:yJYmGXS3oig:-BTjWOF_DHI" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/abeletskyblog/~4/DrtxY95HrhM" height="1" width="1"/&gt;</content><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/3980660135707078299/posts/default/9068944886551298648?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/3980660135707078299/posts/default/9068944886551298648?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/abeletskyblog/~3/DrtxY95HrhM/candidate-v001rc-released.html" title="Candidate v.0.0.1rc - Released" /><author><name>Alexander Beletsky</name><uri>https://profiles.google.com/104123427697898813533</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh5.googleusercontent.com/-WqHPxmC8QfM/AAAAAAAAAAI/AAAAAAAAHi4/tX9CTF-Dzy8/s512-c/photo.jpg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://lh5.googleusercontent.com/-WIUMqyz3naI/TznyBp-dQbI/AAAAAAAAH4A/exqlfJUQr8o/s72-c/screenshot-1.jpg" height="72" width="72" /><feedburner:origLink>http://www.beletsky.net/2012/02/candidate-v001rc-released.html</feedburner:origLink></entry><entry gd:etag="W/&quot;C0EHQH48fip7ImA9WhRbGEw.&quot;"><id>tag:blogger.com,1999:blog-3980660135707078299.post-8102180680633602498</id><published>2012-02-09T20:20:00.000+02:00</published><updated>2012-02-09T20:20:31.076+02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-02-09T20:20:31.076+02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Applications" /><category scheme="http://www.blogger.com/atom/ns#" term="GitHub" /><category scheme="http://www.blogger.com/atom/ns#" term="Open source" /><title>Few Things I Learned From IdeaStrike Project</title><content type="html">&lt;p&gt;First of all, I have to say &lt;a href=""&gt;Code52&lt;/a&gt; team is doing just amazing job. It's very original initiative, cool ideas and highly productive team. Each time they announce next thing to build I have "product envy" inside me. Check out their &lt;a href=""&gt;blog&lt;/a&gt; or &lt;a href=""&gt;github&lt;/a&gt; account to be updated.&lt;br /&gt;
&lt;/p&gt;&lt;p&gt;My attention this time was attracted by &lt;a href=""&gt;IdeaStrike&lt;/a&gt; project. It suppose to be analog of &lt;a href=""&gt;uservoice&lt;/a&gt; for OS community. As always, first release was very fast and I was very curious what's inside. So, I cloned the &lt;a href="https://github.com/Code52/Ideastrike"&gt;repo&lt;/a&gt; and did small hacker session. I've spend some hours with it and would like to share some initial thoughts.&lt;br /&gt;
&lt;/p&gt;&lt;h2&gt;Build script is small and clean&lt;/h2&gt;&lt;p&gt;Project contains &lt;code&gt;build.cmd&lt;/code&gt; as I run it downloaded all dependencies by NuGet, build web site and run all unit test. Basically, all you need for any small project. Then I looked inside, it turns out like:&lt;br /&gt;
&lt;/p&gt;&lt;pre class="brush: plain"&gt;@echo Off
set config=%1
if "%config%" == "" (
   set config=Debug
)

%WINDIR%\Microsoft.NET\Framework\v4.0.30319\msbuild build.proj /p:Configuration="%config%" /t:AppHarbor /m /v:M /fl /flp:LogFile=msbuild.log;Verbosity=Normal /nr:false
&lt;/pre&gt;&lt;p&gt;At the time I first looked in it also contained small script for running tests, but later they moved that to .csproj as separate target. &lt;br /&gt;
&lt;/p&gt;&lt;h2&gt;Use NuGet without committing to SCM&lt;/h2&gt;&lt;p&gt;I was amazed, how fast git repository was cloned and as I checked out &lt;code&gt;packages&lt;/code&gt; folder with all dependencies were just empty. How can it be? As I said in #1 as I run build script they just automatically downloaded for me. As it turns out, this is feature of NuGet that allows to work with dependencies, without real necessity of committing those to SCM. This is very cool, especially if you have big project, so cloning and branching appears to be prolonged operations. The implementation details is on &lt;a href="http://docs.nuget.org/docs/workflows/using-nuget-without-committing-packages"&gt;nuget&lt;/a&gt; site.&lt;br /&gt;
&lt;/p&gt;&lt;h2&gt;Deploy application DB at first launch&lt;/h2&gt;&lt;p&gt;IdeaStrike is based on &lt;a href="http://blogs.msdn.com/b/adonet/archive/2012/01/12/ef-4-3-beta-1-released.aspx"&gt;EF 4.3 Beta 1&lt;/a&gt; currently, using Code First approach. EF Code First also includes very cool feature called Migrations. This is something I really lack first time I tried EF Code First approach. You define the  &lt;a href="https://github.com/alexanderbeletsky/Ideastrike/blob/master/src/Ideastrike.Nancy/Models/IdeastrikeContext.cs"&gt;Context&lt;/a&gt;, &lt;a href="https://github.com/alexanderbeletsky/Ideastrike/blob/master/src/Ideastrike.Nancy/Migrations/IdeastrikeDbConfiguration.cs"&gt;DbConfiguration&lt;/a&gt; class and &lt;a href="https://github.com/alexanderbeletsky/Ideastrike/tree/master/src/Ideastrike.Nancy/Migrations"&gt;migration scripts&lt;/a&gt; (that's also, just a C# code), so at application bootstrap you call the code like:&lt;br /&gt;
&lt;/p&gt;&lt;pre class="brush: csharp"&gt;private static void DoMigrations()
{
    var settings = new IdeastrikeDbConfiguration();
    var migrator = new DbMigrator(settings);
    migrator.Update();
}
&lt;/pre&gt;&lt;p&gt;The database and schema will be automatically deployed on first application run.&lt;br /&gt;
&lt;/p&gt;&lt;h2&gt;Social login with Janrain&lt;/h2&gt;&lt;p&gt;As I clicked to Sign In button, I've been showed nice dialog to select my existing social account to login. &lt;br /&gt;
&lt;/p&gt;&lt;a href="https://lh6.googleusercontent.com/-eJTIkFUrCtA/TzQNiXlAayI/AAAAAAAAH34/gFt_Gn8vAME/s620/image-1.jpg"&gt;&lt;br /&gt;
&lt;img src="https://lh6.googleusercontent.com/-eJTIkFUrCtA/TzQNiXlAayI/AAAAAAAAH34/gFt_Gn8vAME/s620/image-1.jpg" alt="social login" /&gt;&lt;br /&gt;
&lt;/a&gt;&lt;br /&gt;
&lt;p&gt;&lt;a href="http://www.janrain.com/products/engage/engage-introduction?utm_source=login.janrain.com&amp;utm_medium=partner&amp;utm_campaign=attribution"&gt;JanRain&lt;/a&gt; is very cool solution. I remember I tried to investigate something like that for ASP.NET MVC and was really disappointed, because I actually found nothing. For all of existing solutions you have to read OAuth spec and write own code. JanRain does all dirty job for you. As user authorized you receive POST on given URL, with a special token. By given token you request the details about the user, like name and email and so on (see &lt;a href="https://github.com/alexanderbeletsky/Ideastrike/blob/master/src/Ideastrike.Nancy/Modules/LoginModule.cs"&gt;LoginModule.cs&lt;/a&gt;). It has fair &lt;a href="http://www.janrain.com/products/engage/pricing"&gt;plans&lt;/a&gt; for hobby projects and bloggers.&lt;br /&gt;
&lt;/p&gt;&lt;h2&gt;Bootstrap your CSS and HTML&lt;/h2&gt;&lt;p&gt;&lt;a href="http://twitter.github.com/bootstrap/"&gt;Bootstrap&lt;/a&gt; neither new nor very unique, at least I know several good CSS/HTML frameworks. But IdeaStrike proved one more time - it has no sense to invent the wheel. Take advantage of results produced by people who are smarter than you, that's the rule of pragmatic programmer.&lt;br /&gt;
&lt;/p&gt;&lt;p&gt; Dear future me, please never ever again start your application with HTML/CSS from scratch, you can build nothing more as shit. Bootstrap is great for different kind of projects and prototypes. Taking into account number of watches and forks on &lt;a href="https://github.com/twitter/bootstrap/"&gt;github&lt;/a&gt; I expect even more improvements and features in future. &lt;br /&gt;
&lt;/p&gt;&lt;h2&gt;Nancy as web framework&lt;/h2&gt;&lt;p&gt;I've heard about Nancy many times, but it's only now I got a change to touch it. For me it's just alternative reality comparing to ASP.NET MVC. It is not hard to understand what the code does. It is not hard to apply changes there. You are very explicit of what you are doing, by specifying HTTP verb, route and action as lambda. First class citizen in Nancy is Module, all module's logic is placed inside the constructor:&lt;br /&gt;
&lt;/p&gt;&lt;pre class="brush: csharp"&gt;public FeatureModule(IIdeaRepository ideas, IFeatureRepository features, IUserRepository users)
    : base("/idea")
{
    _ideas = ideas;
    _features = features;

    this.RequiresAuthentication();

    Post["/{idea}/feature"] = _ =&gt;
    {
        int id = _.Idea;
        var feature = new Feature
                        {
                            Time = DateTime.UtcNow,
                            Text = Request.Form.feature,
                            User = Context.GetCurrentUser(users)
                        };
        _features.Add(id, feature);

        return Response.AsRedirect(string.Format("/idea/{0}#{1}", id, feature.Id));
    };
}
&lt;/pre&gt;&lt;p&gt;Nancy application could be hosted as ASP.NET / WCF / Self hosted runtimes, it supports different View Engines (including Razor). In short, it is great ALT.NET tool and will find a lot of applications in different projects. More details on &lt;a href="https://github.com/NancyFx/Nancy"&gt;Nancy&lt;/a&gt; github account.&lt;br /&gt;
&lt;/p&gt;&lt;h2&gt;Conclusions&lt;/h2&gt;&lt;p&gt;IdeaStrike is great example of open source project you can learn something from. I would not say I got only positive impressions, moreover there are some obstacles that block me from my normal development flow. I'll try to share my observations on next blog posts.&lt;br /&gt;
&lt;/p&gt;&lt;p&gt;NancyFX, probably be my next web framework to learn, since I need to move out of ASP.NET MVC which is comfortable zone for me now. I'll be keep looking for IdeaStrike and hope to do some pull requests as well.&lt;br /&gt;
&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3980660135707078299-8102180680633602498?l=www.beletsky.net' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/abeletskyblog?a=ceOdTiB-f2Q:7_drDDsTE8U:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/abeletskyblog?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/abeletskyblog?a=ceOdTiB-f2Q:7_drDDsTE8U:63t7Ie-LG7Y"&gt;&lt;img src="http://feeds.feedburner.com/~ff/abeletskyblog?d=63t7Ie-LG7Y" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/abeletskyblog?a=ceOdTiB-f2Q:7_drDDsTE8U:-BTjWOF_DHI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/abeletskyblog?i=ceOdTiB-f2Q:7_drDDsTE8U:-BTjWOF_DHI" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/abeletskyblog/~4/ceOdTiB-f2Q" height="1" width="1"/&gt;</content><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/3980660135707078299/posts/default/8102180680633602498?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/3980660135707078299/posts/default/8102180680633602498?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/abeletskyblog/~3/ceOdTiB-f2Q/few-things-i-learned-from-ideastrike.html" title="Few Things I Learned From IdeaStrike Project" /><author><name>Alexander Beletsky</name><uri>https://profiles.google.com/104123427697898813533</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh5.googleusercontent.com/-WqHPxmC8QfM/AAAAAAAAAAI/AAAAAAAAHi4/tX9CTF-Dzy8/s512-c/photo.jpg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://lh6.googleusercontent.com/-eJTIkFUrCtA/TzQNiXlAayI/AAAAAAAAH34/gFt_Gn8vAME/s72-c/image-1.jpg" height="72" width="72" /><feedburner:origLink>http://www.beletsky.net/2012/02/few-things-i-learned-from-ideastrike.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CkUMSXwyeip7ImA9WhRbFUg.&quot;"><id>tag:blogger.com,1999:blog-3980660135707078299.post-6050812006309126471</id><published>2012-02-02T11:36:00.000+02:00</published><updated>2012-02-06T19:44:48.292+02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-02-06T19:44:48.292+02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Tools" /><category scheme="http://www.blogger.com/atom/ns#" term="Mocks" /><category scheme="http://www.blogger.com/atom/ns#" term="Clean Code" /><category scheme="http://www.blogger.com/atom/ns#" term="TDD" /><title>New Tools in My TDD Arsenal</title><content type="html">&lt;p&gt;Recently my TDD arsenal has been enhanced with 3 new cool tools, which I'm about to share with you. More precisely it one tool and two frameworks. Let's go for it.&lt;br /&gt;
&lt;/p&gt;&lt;h2&gt;NCrunch&lt;br /&gt;
&lt;/h2&gt;&lt;p&gt;&lt;a href="http://www.ncrunch.net/"&gt;NCrunch&lt;/a&gt; is just amazing extension for Visual Studio created by &lt;a href="https://twitter.com/#!/remcomulder"&gt;@remcomulder&lt;/a&gt;. It automatically detects all your tests and re-running those as soon as source code changes happen. Forget about manual test re-running, it's just waste of time. You even do not need to press Ctrl + S, just continue coding as you usually do. &lt;br /&gt;
&lt;/p&gt;&lt;p&gt;Initially I had big doubts about such kind of tools, but NCrunch changed my mind. It supports major unit test frameworks NUnit, XUnit, MSpec etc. Besides of that it allows to collect code coverage metrics (and show it just in VS editor), run tests under debugger, supports multi-core systems etc.&lt;br /&gt;
&lt;/p&gt;&lt;p&gt;In short, NCruch is something that makes your TDD very smooth, allowing to focusing on important things and forgot about some routine.&lt;br /&gt;
&lt;/p&gt;&lt;a href="https://lh3.googleusercontent.com/-SG_xDY5wvDo/TypXmx-VFGI/AAAAAAAAH3o/S46jODLRr5Q/s620/image-1.jpg"&gt;&lt;br /&gt;
&lt;img src="https://lh3.googleusercontent.com/-SG_xDY5wvDo/TypXmx-VFGI/AAAAAAAAH3o/S46jODLRr5Q/s620/image-1.jpg" alt="ncrunch" /&gt;&lt;br /&gt;
&lt;/a&gt;&lt;br /&gt;
&lt;h2&gt;NSubstitute&lt;br /&gt;
&lt;/h2&gt;&lt;p&gt;I stick to &lt;a href="http://code.google.com/p/moq/"&gt;Moq&lt;/a&gt; for quite awhile and saw no reason to switch it.. Till I saw &lt;a href="http://nsubstitute.github.com/"&gt;NSubsitute&lt;/a&gt;. I hardly could imagine someone who staring "yet another mocking framework project", it looks like absolute non-sense.. But &lt;a href="https://github.com/nsubstitute"&gt;those&lt;/a&gt; guys proves me wrong.&lt;br /&gt;
&lt;/p&gt;&lt;p&gt;Well, what's so new there? First of all it have very clean API. No more &lt;code&gt;new Mock()&lt;/code&gt; or &lt;code&gt;MockGenerator.GenerateMock()&lt;/code&gt;, creation of test doubles are nothing more as &lt;code&gt;Substitute.For&amp;lt;IEntityToMock&amp;gt;()&lt;/code&gt;. Mocking properties, multiple return values, events etc. in very easy fashion. Check out their &lt;a href="http://nsubstitute.github.com/help/getting-started/"&gt;getting started&lt;/a&gt; materials for further info. &lt;br /&gt;
&lt;/p&gt;&lt;p&gt;Best feature as for me, that by using extension methods they got rid of lambdas for setting up mocks. It makes test code more readable and clean. See this small &lt;a href="https://gist.github.com/1722396"&gt;gist&lt;/a&gt; there I placed just some Moq and NSubstitue tests together.&lt;br /&gt;
&lt;/p&gt;&lt;p&gt;I would not say that Rhino or Moq is now much worse that NSubstitute.. No, I would just say NSubstitute is a little better. Even same functionality, with less amount of code is already big argument for me.&lt;br /&gt;
&lt;/p&gt;&lt;pre class="brush: csharp"&gt;[Test]
public void should_send_an_email_if_users_signs_up_nsub()
{ 
 // arrange
 var emailService = Substitute.For&amp;lt;IEMailService&amp;gt;();
 var controller = new LoginController(emailService);

 // act
 controller.SignUp(new SignUpModel { Email = &amp;quot;a@a.com&amp;quot;, Password = &amp;quot;xxx&amp;quot; });

 // assert
 emailService.Received().SendEmail(Arg.Any&amp;lt;EmailMessage&amp;gt;(), &amp;quot;current&amp;quot;);
}
&lt;/pre&gt;&lt;h2&gt;FluentAssertions&lt;br /&gt;
&lt;/h2&gt;&lt;p&gt;Again, for years I followed classic NUnit's &lt;code&gt;Assert.That()&lt;/code&gt; method. I also played a bit with &lt;a href="http://sharptestex.codeplex.com/"&gt;SharpTestsEx&lt;/a&gt;, but FluentAssertions by &lt;a href="https://twitter.com/#!/ddoomen"&gt;@ddoomen&lt;/a&gt; is going to change that.&lt;br /&gt;
&lt;/p&gt;&lt;p&gt;FluentAssertions are based on extension methods and allows you to get rid of Assert.That call and just wrote your assertion directly to object. Here some example: &lt;br /&gt;
&lt;/p&gt;&lt;pre class="brush: csharp"&gt;{
    // NUnit.Assert style..
    Assert.That(result, Is.EqualTo(3));

    // FluentAssert style..
    result.Should().Be(3);
}
&lt;/pre&gt;&lt;p&gt;This is very simple example. The power of FluentAssertions arise then you need to have either multiple assertions or assertions on complex objects. Multiple assertion could be combined by &lt;code&gt;And&lt;/code&gt;, like:&lt;br /&gt;
&lt;/p&gt;&lt;pre class="brush: csharp"&gt;{
    "somestring".Should().Contain("some").And.HaveLength(10);
}
&lt;/pre&gt;&lt;p&gt;It also provides great support for working with Collections, DateTimes, Guids, Exceptions, XML etc. Project is hosted on codeplex, here is &lt;a href="http://fluentassertions.codeplex.com/documentation"&gt;documentation&lt;/a&gt;. Easy start, easy go.&lt;br /&gt;
&lt;/p&gt;&lt;h2&gt;Conclusions&lt;/h2&gt;&lt;p&gt;Now, I'm sharpening my axe on those tools and have very nice impressions so far. Special thanks goes to &lt;a href="https://twitter.com/#!/skalinets"&gt;@skalinets&lt;/a&gt; who introduced me with those tools.&lt;br /&gt;
&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3980660135707078299-6050812006309126471?l=www.beletsky.net' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/abeletskyblog?a=7Mti79Nqfpg:MTpkx0t3KnY:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/abeletskyblog?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/abeletskyblog?a=7Mti79Nqfpg:MTpkx0t3KnY:63t7Ie-LG7Y"&gt;&lt;img src="http://feeds.feedburner.com/~ff/abeletskyblog?d=63t7Ie-LG7Y" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/abeletskyblog?a=7Mti79Nqfpg:MTpkx0t3KnY:-BTjWOF_DHI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/abeletskyblog?i=7Mti79Nqfpg:MTpkx0t3KnY:-BTjWOF_DHI" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/abeletskyblog/~4/7Mti79Nqfpg" height="1" width="1"/&gt;</content><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/3980660135707078299/posts/default/6050812006309126471?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/3980660135707078299/posts/default/6050812006309126471?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/abeletskyblog/~3/7Mti79Nqfpg/new-tools-in-my-tdd-arsenal.html" title="New Tools in My TDD Arsenal" /><author><name>Alexander Beletsky</name><uri>https://profiles.google.com/104123427697898813533</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh5.googleusercontent.com/-WqHPxmC8QfM/AAAAAAAAAAI/AAAAAAAAHi4/tX9CTF-Dzy8/s512-c/photo.jpg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://lh3.googleusercontent.com/-SG_xDY5wvDo/TypXmx-VFGI/AAAAAAAAH3o/S46jODLRr5Q/s72-c/image-1.jpg" height="72" width="72" /><feedburner:origLink>http://www.beletsky.net/2012/02/new-tools-in-my-tdd-arsenal.html</feedburner:origLink></entry><entry gd:etag="W/&quot;A0ENQ3g6eSp7ImA9WhRUGUk.&quot;"><id>tag:blogger.com,1999:blog-3980660135707078299.post-2703396961247537333</id><published>2012-01-30T20:54:00.000+02:00</published><updated>2012-01-30T20:54:52.611+02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-01-30T20:54:52.611+02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Continuous" /><category scheme="http://www.blogger.com/atom/ns#" term="Conference" /><title>Agile Base Camp 2012</title><content type="html">&lt;p&gt;Past Saturday I was a part of big Ukrainian event &lt;a href="http://agilebasecamp.org/"&gt;Agile Base Camp: From Idea to Product&lt;/a&gt;. It's been organized by &lt;a href="http://www.scrumguides.com/"&gt;ScrumGuides&lt;/a&gt;, pioneers on Agile in Ukraine and organizers of famous &lt;a href="http://www.beletsky.net/search/label/Agile"&gt;Agilee&lt;/a&gt; series of conferences.&lt;br /&gt;
&lt;/p&gt;&lt;p&gt;The conference named "From Idea to Product" and focused on product development issues. There was 3 stages there: Main, XP, UX. Main is for more or less common topics as budgeting, motivation etc.. XP is practical stage for developers and UX for user experience engineers. The program of conference was really interesting, but I spend all my day on XP stage (no surprise).&lt;br /&gt;
&lt;/p&gt;&lt;p&gt;There were great speeches by &lt;a href="http://twitter.com/dmytromindra"&gt;Dmytro Mindra&lt;/a&gt;, &lt;a href="http://twitter.com/skaninets"&gt;Sergey Kalinets&lt;/a&gt;. Probably most valuable for me were ones by &lt;a href="http://twitter.com/vitaliystakhov"&gt;Vitaliy Stakhov&lt;/a&gt; and &lt;a href="http://twitter.com/_TLK"&gt;Anatoly Kolesnik&lt;/a&gt;, Vitaliy shared Hypermedia concepts of RESTfull systems and that looks very promising. Anatoly did great NoSQL introduction that is very actual at the moment. I also enjoyed &lt;a href="https://twitter.com/defimenko"&gt;Dmitry Efimenko&lt;/a&gt; speech about testing in product company. He did it in quite tough style, so crowd was a little shocked and kept silence till the last words. I got some interesting points for myself.     &lt;br /&gt;
&lt;/p&gt;&lt;p&gt;I did a talk about - Continues Delivery / Deployment / Production. This practical field is very interesting to me not only because I'm trying to &lt;a href="http://www.beletsky.net/2012/01/pre-announce-of-release-candidate.html"&gt;build a product&lt;/a&gt; for that and I want to adapt for all project I work to.   &lt;br /&gt;
&lt;/p&gt;&lt;a href="https://lh3.googleusercontent.com/-pNWAtW5oWu8/TybgzFR4zWI/AAAAAAAAH3g/HxLkTCyvV1A/s720/395323_283771048348762_248481618544372_777581_1168321183_n.jpg"&gt;&lt;br /&gt;
&lt;img src="https://lh3.googleusercontent.com/-pNWAtW5oWu8/TybgzFR4zWI/AAAAAAAAH3g/HxLkTCyvV1A/s620/395323_283771048348762_248481618544372_777581_1168321183_n.jpg" alt="alexander beletsky" /&gt;&lt;br /&gt;
&lt;/a&gt;&lt;br /&gt;
&lt;p&gt;I've got very nice feedback and questions after my speech, totally collected 15 donuts (a special cards that listeners give to speaker if they like the speech), so I was quite happy about. If you interested, here is my &lt;a href="http://speakerdeck.com/u/alexanderbeletsky/p/when"&gt;slides&lt;/a&gt; on speaker deck.&lt;br /&gt;
&lt;/p&gt;&lt;script src="http://speakerdeck.com/embed/4f225b72a0a84d001f019c7b.js" type="text/javascript"&gt;&lt;/script&gt;&lt;br /&gt;
&lt;p&gt;I really much enjoyed after party and evening we spent in Work'N'Roll, the co-working office of &lt;a href="http://www.scrumguides.com/"&gt;ScrumGuides&lt;/a&gt;. Appreciate organizers for that job and wish you good luck of all next events.&lt;br /&gt;
&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3980660135707078299-2703396961247537333?l=www.beletsky.net' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/abeletskyblog?a=L_6sZ0Isvu8:svMdvxn031A:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/abeletskyblog?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/abeletskyblog?a=L_6sZ0Isvu8:svMdvxn031A:63t7Ie-LG7Y"&gt;&lt;img src="http://feeds.feedburner.com/~ff/abeletskyblog?d=63t7Ie-LG7Y" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/abeletskyblog?a=L_6sZ0Isvu8:svMdvxn031A:-BTjWOF_DHI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/abeletskyblog?i=L_6sZ0Isvu8:svMdvxn031A:-BTjWOF_DHI" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/abeletskyblog/~4/L_6sZ0Isvu8" height="1" width="1"/&gt;</content><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/3980660135707078299/posts/default/2703396961247537333?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/3980660135707078299/posts/default/2703396961247537333?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/abeletskyblog/~3/L_6sZ0Isvu8/agile-base-camp-2012.html" title="Agile Base Camp 2012" /><author><name>Alexander Beletsky</name><uri>https://profiles.google.com/104123427697898813533</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh5.googleusercontent.com/-WqHPxmC8QfM/AAAAAAAAAAI/AAAAAAAAHi4/tX9CTF-Dzy8/s512-c/photo.jpg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://lh3.googleusercontent.com/-pNWAtW5oWu8/TybgzFR4zWI/AAAAAAAAH3g/HxLkTCyvV1A/s72-c/395323_283771048348762_248481618544372_777581_1168321183_n.jpg" height="72" width="72" /><feedburner:origLink>http://www.beletsky.net/2012/01/agile-base-camp-2012.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DE8MQXc5fCp7ImA9WhRUFEw.&quot;"><id>tag:blogger.com,1999:blog-3980660135707078299.post-7565023621434170797</id><published>2012-01-24T16:54:00.000+02:00</published><updated>2012-01-24T16:54:40.924+02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-01-24T16:54:40.924+02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Tools" /><category scheme="http://www.blogger.com/atom/ns#" term="Tips" /><category scheme="http://www.blogger.com/atom/ns#" term="Clean Code" /><title>Convention based IoC configuration</title><content type="html">&lt;p&gt;What's your favorite IoC container framework? For quite long time I stick to &lt;a href=""&gt;Ninject&lt;/a&gt;. First time I read about it in Steve Sanders ASP.NET MVC2 book and it's my favorite container since then. But this blog post does not aim particular IoC framework, rather approach you can use. For code examples I'll still be using Ninject, through.&lt;br /&gt;
&lt;/p&gt;&lt;h2&gt;What's are conventions?&lt;br /&gt;
&lt;/h2&gt;&lt;p&gt;&lt;a href="http://en.wikipedia.org/wiki/Convention_over_configuration"&gt;Convention over configuration&lt;/a&gt; is very popular trend nowadays. Many frameworks trying to adopt it, including ASP.NET MVC. In short, that means you are relying on some front-know conventions, like names of files, folder or classes and system does something meaningful, based on those conventions. Like, all controllers in ASP.NET MVC should have "Controller" postfix, so the framework is able to find and &lt;a href="http://www.beletsky.net/2011/12/inside-aspnet-mvc-instantiation-of.html"&gt;instantiate&lt;/a&gt; it. &lt;br /&gt;
&lt;/p&gt;&lt;p&gt;Conventions make a developer's life a little easier, you are no longer spending efforts on configuration, instead following some simple rules. &lt;br /&gt;
&lt;/p&gt;&lt;h2&gt;What we have for IoC?&lt;br /&gt;
&lt;/h2&gt;&lt;p&gt;My &lt;a href="http://en.wikipedia.org/wiki/Shuhari"&gt;"Shu"&lt;/a&gt; level of IoC containers learning was configuration based. This is something you learn at very beginning. So, in case of Ninject, sooner of later you have huge file with dependencies configuration: &lt;br /&gt;
&lt;/p&gt;&lt;pre class="brush: csharp"&gt;/// &amp;lt;summary&amp;gt;
/// Load your modules or register your services here!
/// &amp;lt;/summary&amp;gt;
/// &amp;lt;param name=&amp;quot;kernel&amp;quot;&amp;gt;The kernel.&amp;lt;/param&amp;gt;
private static void RegisterServices(IKernel kernel)
{
 kernel.Bind&amp;lt;ISettingsManager&amp;gt;().To&amp;lt;SettingsManager&amp;gt;();
 kernel.Bind&amp;lt;IDirectoryProvider&amp;gt;().To&amp;lt;DirectoryProvider&amp;gt;().InSingletonScope();
 kernel.Bind&amp;lt;ISetupFactory&amp;gt;().To&amp;lt;SetupFactory&amp;gt;();
 kernel.Bind&amp;lt;ITargetsObjectBuilder&amp;gt;().To&amp;lt;DefaultTargetsObjectBuilder&amp;gt;();
 kernel.Bind&amp;lt;ITargetsBuilder&amp;gt;().To&amp;lt;TargetsBuilder&amp;gt;();
 kernel.Bind&amp;lt;IBounceFactory&amp;gt;().To&amp;lt;BounceFactory&amp;gt;();
 kernel.Bind&amp;lt;ITargetsRetriever&amp;gt;().To&amp;lt;TargetsRetriever&amp;gt;();
 kernel.Bind&amp;lt;IConfigObjectBuilder&amp;gt;().To&amp;lt;ConfigObjectBuilder&amp;gt;();
 kernel.Bind&amp;lt;ILoggerFactory&amp;gt;().To&amp;lt;LoggerFactory&amp;gt;();
 kernel.Bind&amp;lt;IHashService&amp;gt;().To&amp;lt;HashService&amp;gt;();
 kernel.Bind&amp;lt;IAuthentication&amp;gt;().To&amp;lt;Authentication&amp;gt;();
 kernel.Bind&amp;lt;IConfigurationsFactory&amp;gt;().To&amp;lt;ConfigurationsFactory&amp;gt;();
 
 // More, more, more...
}
&lt;/pre&gt;&lt;p&gt;As more your application grows, as more services, repositories, factories you have. As long &lt;code&gt;RegisterServices&lt;/code&gt; method becomes longer, as more you forgot to correct correct it after some new dependency added, so you see YSOD during application run.&lt;br /&gt;
&lt;/p&gt;&lt;p&gt;But please, put your attention to interface and class names. What we have here - &lt;code&gt;ISettingsManager&lt;/code&gt; and &lt;code&gt;SettingsManager&lt;/code&gt;; &lt;code&gt;IDirectoryProvider&lt;/code&gt; and &lt;code&gt;DirectoryProvider&lt;/code&gt;.. &lt;code&gt;ILoggerFactory&lt;/code&gt; and &lt;code&gt;LoggerFactory&lt;/code&gt;. Do you see pattern here? Exactly, it is ["I" + entity name] for interfaces and [entity name] for implementation.&lt;br /&gt;
&lt;/p&gt;&lt;p&gt;Here we go for &lt;a href="http://en.wikipedia.org/wiki/Shuhari"&gt;"Ha"&lt;/a&gt; level of IoC and apply convention based configuration.&lt;br /&gt;
&lt;/p&gt;&lt;h2&gt;Convention over configuration&lt;/h2&gt;&lt;p&gt;Let's take an advance of the fact above and shrink our configuration code. First of all, you need to get great extension for Ninject, called &lt;a href="http://nuget.org/packages/ninject.extensions.conventions/2.2.0.5"&gt;ninject.extensions.conventions&lt;/a&gt;.&lt;br /&gt;
&lt;/p&gt;&lt;p&gt;After the package is installed, the simples Ninject start-up code ever would be:&lt;br /&gt;
&lt;/p&gt;&lt;pre class="brush: csharp"&gt;/// &amp;lt;summary&amp;gt;
/// Load your modules or register your services here!
/// &amp;lt;/summary&amp;gt;
/// &amp;lt;param name=&amp;quot;kernel&amp;quot;&amp;gt;The kernel.&amp;lt;/param&amp;gt;
private static void RegisterServices(IKernel kernel)
{
 kernel.Scan(scanner =&amp;gt;
     {
      scanner.FromCallingAssembly();
      scanner.BindWithDefaultConventions();
     }
  );
}
&lt;/pre&gt;&lt;p&gt;What it does? It has an abstraction called "scanner". You instruct scanner what to do. In this example, I said - take calling assembly and bind all interfaces to implementation class having Default conventions. The default conventions are ones that I shown above. &lt;br /&gt;
&lt;/p&gt;&lt;p&gt;That's it, all those lines of code are simply gone away, since we rely on conventions and Ninject is aware how to deal with those conventions. If you added new dependency and followed convention, nothing you should do manually any more.&lt;br /&gt;
&lt;/p&gt;&lt;h2&gt;I have some questions!?&lt;/h2&gt;&lt;p&gt;Ok, typically you have something little more complex. I'll try to predict some questions you might have.&lt;br /&gt;
&lt;/p&gt;&lt;h3&gt;I have a lot of assemblies in my application, but want only particular ones to be scanned?&lt;/h3&gt;&lt;p&gt;You can easily use only assemblies that matches particular patterns, like:&lt;br /&gt;
&lt;/p&gt;&lt;pre class="brush: csharp"&gt;private static void RegisterServices(IKernel kernel)
{
 kernel.Scan(scanner =&amp;gt;
     {
      scanner.FromAssembliesMatching("Candidate.*");
      scanner.BindWithDefaultConventions();
     }
  );
}
&lt;/pre&gt;&lt;h3&gt;Is it only default conventions I can use?&lt;/h3&gt;&lt;p&gt;No, you can specify your own rules. Scanner has &lt;code&gt;BindWith&lt;/code&gt; method, that receives &lt;code&gt;IBindingGenerator&lt;/code&gt; type. You can implement your own binding generator for custom conventions.&lt;br /&gt;
&lt;/p&gt;&lt;pre class="brush: csharp"&gt;private static void RegisterServices(IKernel kernel)
{
 kernel.Scan(scanner =&amp;gt;
     {
      scanner.FromAssembliesMatching("Candidate.*");
      scanner.BindWith&amp;lt;MyCustomConventionsGenerator&amp;gt;();
     }
  );
}
&lt;/pre&gt;&lt;h3&gt;What if I have several cases of convention violations?&lt;/h3&gt;&lt;p&gt;You are still able to bind in exactly same way as before:&lt;br /&gt;
&lt;/p&gt;&lt;pre class="brush: csharp"&gt;private static void RegisterServices(IKernel kernel)
{
 kernel.Scan(scanner =&amp;gt;
     {
      scanner.FromAssembliesMatching("Candidate.*");
      scanner.BindWith&amp;lt;MyCustomConventionsGenerator&amp;gt;();
     }
  );

    // classes that violates conventions
    kernel.Bind&amp;lt;IMyInterface&amp;gt;().To&amp;lt;MyImpl&amp;gt;();
}
&lt;/pre&gt;&lt;h3&gt;What is I have dependencies in different assemblies?&lt;/h3&gt;&lt;p&gt;Best thing is to go with Ninject modules. First, correct the scanner:&lt;br /&gt;
&lt;/p&gt;&lt;pre class="brush: csharp"&gt;private static void RegisterServices(IKernel kernel)
{
 kernel.Scan(scanner =&amp;gt;
     {
      scanner.FromAssembliesMatching("Candidate.*");
                        scanner.AutoLoadModules();
      scanner.BindWith&amp;lt;MyCustomConventionsGenerator&amp;gt;();
     }
  );
}
&lt;/pre&gt;&lt;p&gt;Now, each assembly should include module instance:&lt;br /&gt;
&lt;/p&gt;&lt;pre class="brush: csharp"&gt;namespace Candidate.Core
{
    public class CoreModule : NinjectModule
    {
        public override void Load()
        {
            // place convention-violation classes here
   // Bind&amp;amp;lt;IMyInterface&amp;amp;gt;().To&amp;amp;lt;MyImpl&amp;amp;gt;();
        }
    }
}
&lt;/pre&gt;&lt;p&gt;Another one good feature of Convention based IoC is - "Config and forget". Once done, use always and forget about manual binding once and for all.&lt;br /&gt;
&lt;/p&gt;&lt;p&gt;I've heard about this on &lt;a href="http://www.beletsky.net/2011/12/xp-days-ukraine-2011.html"&gt;XP Days 2011&lt;/a&gt; conference, by &lt;a href="https://twitter.com/#!/ploeh"&gt;Mark Seemann&lt;/a&gt;. I think it's nice approach.. I adopt it and going to use in my projects.&lt;br /&gt;
&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3980660135707078299-7565023621434170797?l=www.beletsky.net' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/abeletskyblog?a=WycQ58x8FJE:A4zJfhhPGyI:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/abeletskyblog?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/abeletskyblog?a=WycQ58x8FJE:A4zJfhhPGyI:63t7Ie-LG7Y"&gt;&lt;img src="http://feeds.feedburner.com/~ff/abeletskyblog?d=63t7Ie-LG7Y" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/abeletskyblog?a=WycQ58x8FJE:A4zJfhhPGyI:-BTjWOF_DHI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/abeletskyblog?i=WycQ58x8FJE:A4zJfhhPGyI:-BTjWOF_DHI" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/abeletskyblog/~4/WycQ58x8FJE" height="1" width="1"/&gt;</content><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/3980660135707078299/posts/default/7565023621434170797?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/3980660135707078299/posts/default/7565023621434170797?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/abeletskyblog/~3/WycQ58x8FJE/convention-based-ioc-configuration.html" title="Convention based IoC configuration" /><author><name>Alexander Beletsky</name><uri>https://profiles.google.com/104123427697898813533</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh5.googleusercontent.com/-WqHPxmC8QfM/AAAAAAAAAAI/AAAAAAAAHi4/tX9CTF-Dzy8/s512-c/photo.jpg" /></author><feedburner:origLink>http://www.beletsky.net/2012/01/convention-based-ioc-configuration.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CkYMRHs9fSp7ImA9WhRaEEk.&quot;"><id>tag:blogger.com,1999:blog-3980660135707078299.post-8950891082615796390</id><published>2012-01-13T10:01:00.000+02:00</published><updated>2012-02-12T11:49:45.565+02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-02-12T11:49:45.565+02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Candidate" /><title>Pre-announce of Release "Candidate"</title><content type="html">&lt;p&gt;For those, who already forgot what the candidate is I'll do a small reminder :). This is an &lt;a href="https://github.com/alexanderbeletsky/candidate"&gt;application&lt;/a&gt; for Continues Deployment for .NET projects. I started the project at &lt;a href="http://www.beletsky.net/2011/06/candidatenet-application-i-made-on.html"&gt;Hackatone&lt;/a&gt; that took place in summer 2011, in Kyiv. I liked the results I got there, so I didn't throw it away after the contest, but slowly progressed on that through last several months. &lt;br /&gt;
&lt;/p&gt;&lt;a href="https://lh6.googleusercontent.com/-LDlYwfKzvKQ/Tw_ji4BzopI/AAAAAAAAH3A/-SwXb_g_oYo/s621/image-1.png"&gt;&lt;br /&gt;
&lt;img src="https://lh6.googleusercontent.com/-LDlYwfKzvKQ/Tw_ji4BzopI/AAAAAAAAH3A/-SwXb_g_oYo/s621/image-1.png" alt="welcome"/&gt;&lt;br /&gt;
&lt;/a&gt;&lt;br /&gt;
&lt;p&gt;The goal of application is very simple. Provide you with easy to setup and use tool Continues Deployment. I'm still very confused now with all those terms - Continuous Deployment/Delivery/Production/Release.. but in general it is nothing more as next step of Continues Integration. Rebuild and retest the application and deploy it in case of successful results.&lt;br /&gt;
&lt;/p&gt;&lt;a href="https://lh4.googleusercontent.com/-FfsyUPLA5ek/Tw_jirfuETI/AAAAAAAAH24/PX-apdvN2Rw/s1024/image-2.png"&gt;&lt;br /&gt;
&lt;img src="https://lh4.googleusercontent.com/-FfsyUPLA5ek/Tw_jirfuETI/AAAAAAAAH24/PX-apdvN2Rw/s1024/image-2.png" style="width: 620px" alt="welcome"/&gt;&lt;br /&gt;
&lt;/a&gt;&lt;br /&gt;
&lt;p&gt;I'm building that in mind of my own needs, how I see it might work for my projects. My own projects are really simple ones, so the candidate is really simple now. Of cause, I would like to be as general as possible, to cover common needs. I'm pretty much sure it would be rewritten hundred of times to reach the level of mass adoption and I'm looking forward to that.&lt;br /&gt;
&lt;/p&gt;&lt;a href="https://lh3.googleusercontent.com/-1pTIk_M6Z0s/Tw_jilnpwhI/AAAAAAAAH28/Zog53hBf1kY/s1019/image-3.png"&gt;&lt;br /&gt;
&lt;img src="https://lh3.googleusercontent.com/-1pTIk_M6Z0s/Tw_jilnpwhI/AAAAAAAAH28/Zog53hBf1kY/s1019/image-3.png" style="width: 620px" alt="config"/&gt;&lt;br /&gt;
&lt;/a&gt;&lt;br /&gt;
&lt;p&gt;Yesterday, I reached very important milestone of candidate.net. It is now feature completed. I would like to stop on current functionality and show it to you. It would take some time to prepare website and instructions, but please stay tuned for official release of project!&lt;br /&gt;
&lt;/p&gt;&lt;a href="https://lh6.googleusercontent.com/-2QDjpa8ic7c/Tw_jie0ltoI/AAAAAAAAH20/k6g2qmCxGj0/s982/image-4.png"&gt;&lt;br /&gt;
&lt;img src="https://lh6.googleusercontent.com/-2QDjpa8ic7c/Tw_jie0ltoI/AAAAAAAAH20/k6g2qmCxGj0/s982/image-4.png" style="width: 620px" alt="config"/&gt;&lt;br /&gt;
&lt;/a&gt;&lt;br /&gt;
&lt;p&gt;By the way, I'm still looking for new name! It turns out that finding the good name, could be even harder than finding process running &lt;a href="http://stackoverflow.com/questions/7666423/iis-7-5-with-process-idenity-set-to-user-has-wrong-userprofile"&gt;bugs&lt;/a&gt;. I would be really happy if you do such early contribution proposing some nice name. Please do not hesitate and share your ideas just in comments.&lt;br /&gt;
&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3980660135707078299-8950891082615796390?l=www.beletsky.net' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/abeletskyblog?a=ibP5gU0jX68:3yNOEED4RWk:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/abeletskyblog?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/abeletskyblog?a=ibP5gU0jX68:3yNOEED4RWk:63t7Ie-LG7Y"&gt;&lt;img src="http://feeds.feedburner.com/~ff/abeletskyblog?d=63t7Ie-LG7Y" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/abeletskyblog?a=ibP5gU0jX68:3yNOEED4RWk:-BTjWOF_DHI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/abeletskyblog?i=ibP5gU0jX68:3yNOEED4RWk:-BTjWOF_DHI" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/abeletskyblog/~4/ibP5gU0jX68" height="1" width="1"/&gt;</content><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/3980660135707078299/posts/default/8950891082615796390?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/3980660135707078299/posts/default/8950891082615796390?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/abeletskyblog/~3/ibP5gU0jX68/pre-announce-of-release-candidate.html" title="Pre-announce of Release &quot;Candidate&quot;" /><author><name>Alexander Beletsky</name><uri>https://profiles.google.com/104123427697898813533</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh5.googleusercontent.com/-WqHPxmC8QfM/AAAAAAAAAAI/AAAAAAAAHi4/tX9CTF-Dzy8/s512-c/photo.jpg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://lh6.googleusercontent.com/-LDlYwfKzvKQ/Tw_ji4BzopI/AAAAAAAAH3A/-SwXb_g_oYo/s72-c/image-1.png" height="72" width="72" /><feedburner:origLink>http://www.beletsky.net/2012/01/pre-announce-of-release-candidate.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DEEHRHY4fyp7ImA9WhRaFk4.&quot;"><id>tag:blogger.com,1999:blog-3980660135707078299.post-2693347729188072712</id><published>2012-01-10T21:30:00.000+02:00</published><updated>2012-02-19T09:30:35.837+02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-02-19T09:30:35.837+02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Tips" /><category scheme="http://www.blogger.com/atom/ns#" term="asp.net" /><title>Using ASP.NET MVC Validation Mechanism without ASP.NET MVC</title><content type="html">&lt;p&gt;I get used to &lt;code&gt;DataAnnotations&lt;/code&gt; for model validation very quickly. Indeed, it is great approach. You attribute you model with corresponding attributes, rest is done by framework. It is only &lt;code&gt;ModelState.IsValid&lt;/code&gt;, all you have to do before starting working with model.&lt;br /&gt;
&lt;/p&gt;&lt;p&gt;During implementation of some feature for &lt;a href="https://github.com/alexanderbeletsky/candidate"&gt;candidate&lt;/a&gt; I thought to myself, that I need need exactly same validation for my model class, but out of MVC framework. Namely, for some model class, like &lt;a href="https://github.com/alexanderbeletsky/candidate/blob/master/Candidate.Core/Configurations/Parts/Github.cs"&gt;Github.cs&lt;/a&gt; I just want to know, is it "configured" or not. And configured == valid in my context. Instead of writing custom code with checking all required properties to have some values I wished to do the same as ASP.NET MVC does, through DataAnnotations. It turned out to be possible and really easy.&lt;br /&gt;
&lt;/p&gt;&lt;h2&gt;Basic start&lt;/h2&gt;&lt;p&gt;Assume you have such model:&lt;br /&gt;
&lt;/p&gt;&lt;pre class="brush: csharp"&gt;public class SimpleModel
{
 [Required]
 public string SomeProperty { get; set; }
 
 [Range(0,50)]
 public int SomeAnotherProperty { get; set; }
}
    &lt;/pre&gt;&lt;p&gt;If your goal is just to get answer "yes or no", you can create such function:&lt;br /&gt;
&lt;/p&gt;&lt;pre class="brush: csharp"&gt;public bool ValidateSimpleModel(SimpleModel validate)
{
 return Validator.TryValidateObject(validate, new ValidationContext(validate, null, null), null);
}
    &lt;/pre&gt;&lt;p&gt;&lt;a href="http://msdn.microsoft.com/en-us/library/system.componentmodel.dataannotations.validator.aspx"&gt;Validator&lt;/a&gt; is a static class in DataAnnotations namespace. It takes target object, validation context and validation results collection. But due, to it just "tries" to perform validation, most of all parameters could be null.&lt;br /&gt;
&lt;/p&gt;&lt;h2&gt;Use validation results&lt;/h2&gt;&lt;p&gt;If you need more specific information, like which field is exactly invalid you need to have &lt;code&gt;ICollection&amp;lt;ValidationResult&amp;gt;&lt;/code&gt;&lt;br /&gt;
&lt;/p&gt;&lt;pre class="brush: csharp"&gt;public ICollection&amp;lt;ValidationResult&amp;gt; ValidateSimpleModel(SimpleModel validate)
{
 var validationResults = new List&amp;lt;ValidationResult&amp;gt;();
 Validator.TryValidateObject(validate, new ValidationContext(validate, null, null), validationResults);
 
 return validationResults;
}
    &lt;/pre&gt;&lt;p&gt;In case of invalid object it would return non-empy collection of &lt;a href="http://msdn.microsoft.com/en-us/library/system.componentmodel.dataannotations.validationresult.aspx"&gt;ValidationResult&lt;/a&gt;, that would contain all relevant information.&lt;br /&gt;
&lt;/p&gt;&lt;h2&gt;Wrapping up to extension method&lt;/h2&gt;&lt;p&gt;Finally, you can create simple extension extension method and apply DataAnnotations validation to any kind of object:&lt;br /&gt;
&lt;/p&gt;&lt;pre class="brush: csharp"&gt;public static class ValidatorExtensions
{
    public static bool TryValidateObject(this object validate)
    {
        return Validator.TryValidateObject(validate, new ValidationContext(validate, null, null), null);
    }
}
    &lt;/pre&gt;&lt;p&gt;So, the model could just have IsValid() method, like:&lt;br /&gt;
&lt;/p&gt;&lt;pre class="brush: csharp"&gt;public bool IsValid()
{
 return this.TryValidateObject();
}
    &lt;/pre&gt;&lt;p&gt;It works great for such simple task I need to accomplish.&lt;br /&gt;
&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3980660135707078299-2693347729188072712?l=www.beletsky.net' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/abeletskyblog?a=qalvpEdQrlU:PXF23xeR6Ss:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/abeletskyblog?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/abeletskyblog?a=qalvpEdQrlU:PXF23xeR6Ss:63t7Ie-LG7Y"&gt;&lt;img src="http://feeds.feedburner.com/~ff/abeletskyblog?d=63t7Ie-LG7Y" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/abeletskyblog?a=qalvpEdQrlU:PXF23xeR6Ss:-BTjWOF_DHI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/abeletskyblog?i=qalvpEdQrlU:PXF23xeR6Ss:-BTjWOF_DHI" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/abeletskyblog/~4/qalvpEdQrlU" height="1" width="1"/&gt;</content><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/3980660135707078299/posts/default/2693347729188072712?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/3980660135707078299/posts/default/2693347729188072712?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/abeletskyblog/~3/qalvpEdQrlU/using-aspnet-mvc-validation-mechanism.html" title="Using ASP.NET MVC Validation Mechanism without ASP.NET MVC" /><author><name>Alexander Beletsky</name><uri>https://profiles.google.com/104123427697898813533</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh5.googleusercontent.com/-WqHPxmC8QfM/AAAAAAAAAAI/AAAAAAAAHi4/tX9CTF-Dzy8/s512-c/photo.jpg" /></author><feedburner:origLink>http://www.beletsky.net/2012/01/using-aspnet-mvc-validation-mechanism.html</feedburner:origLink></entry><entry gd:etag="W/&quot;D0YCQ30_fSp7ImA9WhRWGEs.&quot;"><id>tag:blogger.com,1999:blog-3980660135707078299.post-6655774731210561979</id><published>2012-01-06T17:52:00.000+02:00</published><updated>2012-01-06T17:52:42.345+02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-01-06T17:52:42.345+02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Approvals" /><title>Approval Tests: Locking down an output</title><content type="html">&lt;p&gt;        We have &lt;a href="http://www.beletsky.net/2011/12/approval-tests-locking-down-legacy-code.html"&gt;seen&lt;/a&gt; how Approval Tests are useful for locking down some legacy code. You might say, that on practice we are having much more bigger problem, like some code that executes queries against the database. We need somehow to be able to work with that code, without worries of brake it down. Approvals could help here. &lt;br /&gt;
    &lt;/p&gt;    &lt;h2&gt;The case&lt;/h2&gt;    &lt;p&gt;        Again I just imagine some legacy code that works with DB, it might look something like that:&lt;br /&gt;
    &lt;/p&gt;    &lt;pre class="brush: csharp"&gt;public class ClassThatOutputsSomething
{
 private static Connection _connection;

 public void MethodThatProduceSomeResults(string parameterOne, int parameterTwo)
 {
  if (!IsConnectionOpened())
  {
   OpenConnection();
  }

  var connection = GetConnection();

  var value = HugeAndScarryLegacyCode.TheUgliesMethodYouMightEverSeen(parameterOne, parameterTwo, 'c');

  var query = string.Format(&amp;quot;INSERT INTO TableName (SomeColumn) VALUES ({0})&amp;quot;, value);
  connection.ExecuteQuery(query);
 }

    // ...
    &lt;/pre&gt;    &lt;p&gt;        The &lt;code&gt;MethodThatProduceSomeResults&lt;/code&gt; takes some arguments, call another method to get value and then store value to database. It will be problematic to tests what exactly is happening there. We might consider approach to check the difference in &lt;code&gt;TableName&lt;/code&gt; before code execution and after, but we will go smarter and easier way. &lt;br /&gt;
    &lt;/p&gt;    &lt;p&gt;        Let's prepare the test for that code.&lt;br /&gt;
    &lt;/p&gt;    &lt;h2&gt;Tests&lt;/h2&gt;    &lt;p&gt;        The great thing with Approvals is the tests are really elegant. Just 2 steps - DO and VERIFY.&lt;br /&gt;
    &lt;/p&gt;    &lt;pre class="brush: csharp"&gt;[Test]
public void should_be_able_to_test()
{
 // DO
 var some = new ClassThatOutputsSomething();
 some.MethodThatProduceSomeResults('some_input', 221);

 // VERIFY
 Approvals.Approve(...);
}
    &lt;/pre&gt;    &lt;p&gt;        But you can see, the problem here is that we don't have any return value of that method. Instead, it does something inside and keep that action in secret. We need some how to log all internal activities and than verify that log. &lt;code&gt;Approval.Utilities&lt;/code&gt; contains exactly what we need.&lt;br /&gt;
    &lt;/p&gt;    &lt;pre class="brush: csharp"&gt;[Test]
public void should_be_able_to_test()
{
 // DO
 var output = ApprovalUtilities.SimpleLogger.Logger.LogToStringBuilder();
 new ClassThatOutputsSomething().MethodThatProduceSomeResults('some_input', 221);

 // VERIFY
 Approvals.Approve(output);
}
    &lt;/pre&gt;    &lt;p&gt;        I have just added logger &lt;code&gt;ApprovalUtilities.SimpleLogger.Logger.LogToStringBuilder&lt;/code&gt; and do approve against it. But if I run this test I could see that output is just empty. Sure, we need to change &lt;code&gt;MethodThatProduceSomeResults&lt;/code&gt; a little.&lt;br /&gt;
    &lt;/p&gt;    &lt;pre class="brush: csharp"&gt;public class ClassThatOutputsSomething
{
 private static Connection _connection;

 public void MethodThatProduceSomeResults(string parameterOne, int parameterTwo)
 {
        // ...

        connection.ExecuteQuery(query);
        ApprovalUtilities.SimpleLogger.Logger.Event(query);
 }
    &lt;/pre&gt;    &lt;p&gt;        So, in the place where query is being executed, we placed the logger and put exact some query inside it. Now if I run the test I will got application output, that I will approve and use those approved results after. &lt;br /&gt;
    &lt;/p&gt;    &lt;p&gt;        I'm not limited with only one place I could put logger. On practice, would more that one places to grab the results, as well as more that one argument for &lt;code&gt;MethodThatProduceSomeResults&lt;/code&gt; method. By analysis of particular practical case, it is possible to place logger exactly where it's needed, plus prepare best matching inputs. Just for example: after code examination it might happen that &lt;code&gt;parameterOne&lt;/code&gt; is ProductId, but &lt;code&gt;parameterTwo&lt;/code&gt; is ProductPrice. In my test I could query the database to select all products and prices and call &lt;code&gt;MethodThatProduceSomeResults&lt;/code&gt; in loop, to get all potential output. That approved test will give me much confidence during refactoring.&lt;br /&gt;
    &lt;/p&gt;    &lt;h2&gt;Conclusion&lt;/h2&gt;    &lt;p&gt;        Locking down output is very powerful technique, you can use it for any kind of objects that are "hidden" inside legacy classes, like SQL or console outputs.  &lt;br /&gt;
    &lt;/p&gt;    &lt;p&gt;        On &lt;a href="http://herdingcode.com/?p=329"&gt;Herding Code&lt;/a&gt; episode &lt;a href="https://twitter.com/#!/LlewellynFalco"&gt;Llewellyn&lt;/a&gt; describes the case of some legacy project he worked on. There was a kind of report generator and it's code was just a big mess. He did copy of production database and put it in "Read-Only" mode. By running the report, he was able to find all places where code was accessing DB, since exception is thrown in that place. Putting in just the same log instructions as I did above, he managed to grab all SQL queries that run for that particular report. Everything were just in one file.&lt;br /&gt;
    &lt;/p&gt;    &lt;p&gt;        That's the good example of reaching 100% code coverage just with one test.&lt;br /&gt;
    &lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3980660135707078299-6655774731210561979?l=www.beletsky.net' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/abeletskyblog?a=rbRoXKdYycU:dO8vpAoGwMM:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/abeletskyblog?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/abeletskyblog?a=rbRoXKdYycU:dO8vpAoGwMM:63t7Ie-LG7Y"&gt;&lt;img src="http://feeds.feedburner.com/~ff/abeletskyblog?d=63t7Ie-LG7Y" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/abeletskyblog?a=rbRoXKdYycU:dO8vpAoGwMM:-BTjWOF_DHI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/abeletskyblog?i=rbRoXKdYycU:dO8vpAoGwMM:-BTjWOF_DHI" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/abeletskyblog/~4/rbRoXKdYycU" height="1" width="1"/&gt;</content><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/3980660135707078299/posts/default/6655774731210561979?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/3980660135707078299/posts/default/6655774731210561979?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/abeletskyblog/~3/rbRoXKdYycU/approval-tests-locking-down-output.html" title="Approval Tests: Locking down an output" /><author><name>Alexander Beletsky</name><uri>https://profiles.google.com/104123427697898813533</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh5.googleusercontent.com/-WqHPxmC8QfM/AAAAAAAAAAI/AAAAAAAAHi4/tX9CTF-Dzy8/s512-c/photo.jpg" /></author><feedburner:origLink>http://www.beletsky.net/2012/01/approval-tests-locking-down-output.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DUMCQ389eyp7ImA9WhRWEUU.&quot;"><id>tag:blogger.com,1999:blog-3980660135707078299.post-2811277880327031278</id><published>2011-12-29T21:37:00.000+02:00</published><updated>2011-12-29T21:37:42.163+02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-12-29T21:37:42.163+02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Retrospective" /><title>Retrospective 2011</title><content type="html">&lt;p&gt;Last year I failed to create retrospective blog post, so lesson learned and I started a little bit earlier now. Not the 1 day, but 3 days before NY :). Retrospective is a great practice and I hope it give me some value when I'll be reading it next year and laughing on my previous achievements.&lt;br /&gt;
&lt;/p&gt;&lt;p&gt;I'll try to cover 4 basic directions: Career, Development, Blog, Personal.&lt;br /&gt;
&lt;/p&gt;&lt;h2&gt;Career&lt;/h2&gt;&lt;p&gt;I continue to do my job for &lt;a href="http://e-conomic.com"&gt;e-conomic.com&lt;/a&gt;. As I said &lt;a href="http://www.beletsky.net/2011/03/my-first-year-in-company.html"&gt;here&lt;/a&gt; e-conomic is the most important thing that happened to me in 2010 and keeps it influence on 2011. I'm still a product developer there, but in general situation has been changing radically. First of all, we are now much more bigger team. Both Ukranian and Denmark parts of team are growing and new cool guys join us. Second, we finished up few projects at the beginning of the year and joined very cool adventure that I a little described &lt;a href="http://www.beletsky.net/2011/12/why-new-technologies-move-your-product.html"&gt;here&lt;/a&gt;. Sure, I have fun and boring, easy and tough, nice and bad days there. But overall impression is still very good. As soon as we'll keep same as we are doing, with same level of passion and team atmosphere - we are on right track.  &lt;br /&gt;
&lt;/p&gt;&lt;p&gt;Besides the e-conomic, there is something else that happened to me this year and had direct impact on career - &lt;a href="http://kievalt.net"&gt;Kiev ALT.NET&lt;/a&gt;. Unfortunately, I did not blog to much about that community just a some &lt;a href="http://www.beletsky.net/2011/12/kiev-altnet-community-thoughts.html"&gt;mention&lt;/a&gt; here. Community is very important to any developer and I'm really happy I found the one. I haven't noticed how I became a speaker, actually. With a few nervous tries on Kiev ALT.NET I've managed to give up to 8 (or so) public speeches this year. It might not be so much, but great achievement for me. The speaking opened new opportunities, especially in meeting new people. But first of all it is a great joy and motivation to learn new things.&lt;br /&gt;
&lt;/p&gt;&lt;p&gt;With a great atmosphere and enthusiastic people inside &lt;a href="http://kievalt.net"&gt;Kiev ALT.NET&lt;/a&gt; I've launched another project called &lt;a href="http://kyivbeerncode.org"&gt;Kiev Beer &amp;&amp; Code&lt;/a&gt;. The idea is taken from &lt;a href="http://seattle.beerandcode.org/"&gt;Seattle Beer &amp;&amp; Code&lt;/a&gt; community, but it is nothing more as developers gathering for social coding. The community is very young and to be honest I don't put to much efforts on it's promotion, but it a very beginning. I'm very happy with out current Beer &amp;&amp; Code team and will be much more happier if new guys are joining.  &lt;br /&gt;
&lt;/p&gt;&lt;p&gt;I became &lt;a href="http://java.dzone.com/users/alexanderb"&gt;MVB&lt;/a&gt; (Most Valuable Blogger) for DZone, that I'm really proud for. It is 2-way value, DZone is using my content.. To me it gives additional traffic. I hope we are still partners for long years.&lt;br /&gt;
&lt;/p&gt;&lt;p&gt;At the end of the year I tried myself in completely new area - trainings. Thanks to &lt;a href="http://xpinjection.com/"&gt;XP Injection&lt;/a&gt; training center in Kiev, I've been invited to 2 days training session "TDD in .NET". It &lt;a href="http://www.beletsky.net/2011/12/xp-days-ukraine-2011.html"&gt;appeared&lt;/a&gt; so much successful that chief trainer offered me a place in their trainers group. At December 22, I officially &lt;a href="http://xpinjection.com/2011/12/22/beletsky-joined-our-coaches-group/"&gt;joined&lt;/a&gt; XP Injection. I'm very excited about that and hope I can do my best there. So far, we've planned some further TDD .NET trainings, but definitely TDD won't be the only one topic I can work in.&lt;br /&gt;
&lt;/p&gt;&lt;h2&gt;Development&lt;/h2&gt;&lt;p&gt;I mean, everything that I work on my own: pet projects, self education etc. I don't remember who said that, but I very agree with this statement - "if you don't write code at home, you are not progressing". You have not time to learn at work. Work is the place to perform. You have to have sharp axe, if you came to chop the wood.&lt;br /&gt;
&lt;/p&gt;&lt;p&gt;My main sharp axe exercise is coding. I try to code as much as I can. For productive coding you have to have some projects. Doesn't matter what exactly, what's important is: you like the idea, you have corresponding technological stack. Technological stack have to correspond the area you want to improve in. My main area's are still: C#, HTML/CSS and JavaScript.&lt;br /&gt;
&lt;/p&gt;&lt;p&gt;I was reading &lt;a href="http://pragprog.com/book/tpp/the-pragmatic-programmer"&gt;Pragmatic Programmer&lt;/a&gt; this year, with a great advice: "Learn new programming language each year". I formulated Pragmatic Product Developer advice, just for my self: "Release new product each year". Even if you release something at work, release something on your own is completely different feeling. It takes too much effort, it's painful.. But shipment is like drug, you feel very happy as soon you ship.. You fill very bad as you don't ship for a while.&lt;br /&gt;
&lt;/p&gt;&lt;p&gt;While ago I write small article there I &lt;a href="http://www.beletsky.net/2011/09/what-im-going-to-do.html"&gt;mentioned&lt;/a&gt; what's my targets and what I working on. Let's quickly go through it:&lt;br /&gt;
&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;br /&gt;
&lt;strong&gt;trackyt.net&lt;/strong&gt; as I released that late 2010 I did provide a support up the the May of 2011. A lot of new features has been &lt;a href="https://github.com/alexanderbeletsky/trackyt.net"&gt;commited&lt;/a&gt; there, but still I slowed down the progress much. It has very low traffic, almost 0 active users. I was about to release version 2.0, absolutely different with all good things that I see in GTD. But I have to admit, I failed that. &lt;br /&gt;
&lt;/li&gt;
&lt;li&gt;&lt;br /&gt;
&lt;strong&gt;elmah.mvc.controller&lt;/strong&gt; &lt;a href="http://www.beletsky.net/2011/03/integrating-elmah-to-aspnet-mvc-in.html"&gt;started&lt;/a&gt; out as very simple &lt;a href="https://github.com/alexanderbeletsky/elmah.mvc.controller"&gt;helper&lt;/a&gt; for ASP.NET MVC applications that want to use ELMAH, but with a great surprise to me it appeared so popular, that finally wrapped up in a micro product. Now, it has ~2,000 downloads on &lt;a href="http://nuget.org/packages/Elmah.MVC"&gt;NuGet&lt;/a&gt;, I've received several pull requests and had a talk about it on Kiev ALT.NET. Even if is so small, I treat that as success. &lt;br /&gt;
&lt;/li&gt;
&lt;li&gt;&lt;br /&gt;
&lt;strong&gt;github.commits.widget&lt;/strong&gt; also a micro &lt;a href="https://github.com/alexanderbeletsky/github.commits.widget"&gt;product&lt;/a&gt; that gathered some attention. That was my attempt of working with github API in javascript and I spend maybe 3 hours to create that code, but I know several sites that using that widget. I had joy of creating that and happy that some people find it useful. &lt;br /&gt;
&lt;/li&gt;
&lt;li&gt;&lt;br /&gt;
&lt;strong&gt;githubbadges.com&lt;/strong&gt; a little &lt;a href="http://githubbadges.com/"&gt;application&lt;/a&gt; that I wrote to participate &lt;a href="http://10k.aneventapart.com/Entry/Details/512"&gt;10K competition&lt;/a&gt;. Total application zipped content should not exceed 10K. I've haven't won, I haven't got any mentions.. But again it was fun small project. I used some my knowledge of github API and tried to do very tiny JS and CSS &lt;a href="https://github.com/alexanderbeletsky/10k"&gt;code&lt;/a&gt;.&lt;br /&gt;
&lt;/li&gt;
&lt;li&gt;&lt;br /&gt;
&lt;strong&gt;candidate.net&lt;/strong&gt; is something I started this summer of &lt;a href="http://www.beletsky.net/2011/06/candidatenet-application-i-made-on.html"&gt;hackthone&lt;/a&gt;. Since then I completely rewrite it, start to use &lt;a href="https://github.com/alexanderbeletsky/bounce"&gt;bounce&lt;/a&gt; framework inside and had plans to release it October, but failed. I'm not throwing away this project and going to ship that soon. I have yet-another-huge-refactoring cycle now, but after that I hope that alpha version could be ready middle January.&lt;br /&gt;
&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;So, it looks like "I did something".. but really nothing impressive. I try to be a little more focused, not more than 2 projects in parallel + very clear criteria's of success for projects. But in general my criteria's are still simple: actually ship it, learn something new, enjoy the ride. &lt;br /&gt;
&lt;/p&gt;&lt;h2&gt;Blog&lt;/h2&gt;&lt;p&gt;Thanks to google analytics it is very simple to have analysis. Just take a look at those figures: &lt;br /&gt;
&lt;/p&gt;&lt;a href="https://lh4.googleusercontent.com/-vXQaNQ3spSM/Tvy__2LszrI/AAAAAAAAH2Y/D44-yv0Olpw/s1177/blog-stat-1.jpg"&gt;&lt;br /&gt;
&lt;img src="https://lh4.googleusercontent.com/-vXQaNQ3spSM/Tvy__2LszrI/AAAAAAAAH2Y/D44-yv0Olpw/s1177/blog-stat-1.jpg" alt="stat" style="width: 620px"/&gt;&lt;br /&gt;
&lt;/a&gt;&lt;br /&gt;
&lt;p&gt;So, I've got 25,341 Unique visitors and 36,560 visits in total. To understand what it means to me, let's take a look last year statistics for same period of time.&lt;br /&gt;
&lt;/p&gt;&lt;a href="https://lh4.googleusercontent.com/-51Hc2jcZ2rI/TvzAB6TkZJI/AAAAAAAAH2g/26wjbns9Fww/s1179/blog-stat-2.jpg"&gt;&lt;br /&gt;
&lt;img src="https://lh4.googleusercontent.com/-51Hc2jcZ2rI/TvzAB6TkZJI/AAAAAAAAH2g/26wjbns9Fww/s1179/blog-stat-2.jpg" alt="stat" style="width: 620px"/&gt;&lt;br /&gt;
&lt;/a&gt;&lt;br /&gt;
&lt;p&gt;In 2010 I got 3,979 Unique visitors. It basically means I improved traffic ~637%. This is actually huge number, I don't expect that next year of cause.. but hope that traffic will be improved more. &lt;br /&gt;
&lt;/p&gt;&lt;p&gt;OK, what was most popular content this year:&lt;br /&gt;
&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="http://www.beletsky.net/2011/03/integrating-elmah-to-aspnet-mvc-in.html"&gt;Integrating ELMAH to ASP.NET MVC in right way&lt;/a&gt; where I first time described my approach of putting ELMAH into ASP.NET MVC website&lt;/li&gt;
&lt;li&gt;&lt;br /&gt;
&lt;a href="http://www.beletsky.net/2011/01/implementation-of-rest-service-with.html"&gt;Implementation of REST service with ASP.NET MVC&lt;/a&gt; that I blogged at the very beginning of the year and described my vision on REST services in ASP.NET MVC. With a current experience I would probably change something where, hope to make next popular post.&lt;br /&gt;
&lt;/li&gt;
&lt;li&gt;&lt;br /&gt;
&lt;a href="http://www.beletsky.net/2011/10/inside-aspnet-mvc-idependencyresolver.html"&gt;Inside ASP.NET MVC: IDependencyResolver - Service locator in MVC&lt;/a&gt; one of mine articles of Inside ASP.NET series. It actually became on top of &lt;a href="http://asp.net"&gt;http://asp.net&lt;/a&gt; website, I was really happy about it.&lt;br /&gt;
&lt;/li&gt;
&lt;li&gt;&lt;br /&gt;
&lt;a href="http://www.beletsky.net/2011/06/how-to-start-using-git-in-svn-based.html"&gt;How to start using Git in SVN-based organization&lt;/a&gt; where I shared some experience of "easy-start" with Git even in SVN based company. It worked so nice to me and my teammates, that almost everyone is using git now.&lt;br /&gt;
&lt;/li&gt;
&lt;li&gt;&lt;br /&gt;
&lt;a href="http://www.beletsky.net/2011/03/aspnet-developers-disease.html"&gt;ASP.NET developers disease&lt;/a&gt; that I wrote under impressions of one of the job interview we did. My main point where was for the guys that stick to much to WebForms and server-side coding. It was a little provocative, but I hope it was useful.&lt;br /&gt;
&lt;/li&gt;
&lt;/ul&gt;&lt;h2&gt;Personal&lt;br /&gt;
&lt;/h2&gt;&lt;p&gt;First of all, I got married. I strongly believe it is for good and for long.&lt;br /&gt;
&lt;/p&gt;&lt;p&gt;I did several interesting trips, especially to &lt;a href="http://www.beletsky.net/2011/02/val-gardena-dolomites-trip-2011.html"&gt;Val Gardena&lt;/a&gt; with my friends at the beginning of the year and &lt;a href="http://www.beletsky.net/2011/11/sayonara-nippon.html"&gt;Japan&lt;/a&gt;. Unfortunately, I don't predict anything like that in 2012, so it will be kept for good memories.&lt;br /&gt;
&lt;/p&gt;&lt;p&gt;I have to admit I lowered my sport activities too much. I almost stopped every morning exercises, kyokushin karate, rollerblading. Doing those very occasionally. This is not good at all and I already feel bad influence of that. So, my next year is to make it more balanced.&lt;br /&gt;
&lt;/p&gt;&lt;p&gt;It was a great year to me. I wish Merry Christmas and Happy New Year to you, dear reader. I'm really looking forward to create new content you would like, new products you would find useful. Let's gather all good things happened this year and take them for next one.&lt;br /&gt;
&lt;/p&gt;&lt;p&gt;See you 2012!&lt;br /&gt;
&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3980660135707078299-2811277880327031278?l=www.beletsky.net' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/abeletskyblog?a=LHcEKPwYxeY:SHZPryY7Pyg:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/abeletskyblog?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/abeletskyblog?a=LHcEKPwYxeY:SHZPryY7Pyg:63t7Ie-LG7Y"&gt;&lt;img src="http://feeds.feedburner.com/~ff/abeletskyblog?d=63t7Ie-LG7Y" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/abeletskyblog?a=LHcEKPwYxeY:SHZPryY7Pyg:-BTjWOF_DHI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/abeletskyblog?i=LHcEKPwYxeY:SHZPryY7Pyg:-BTjWOF_DHI" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/abeletskyblog/~4/LHcEKPwYxeY" height="1" width="1"/&gt;</content><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/3980660135707078299/posts/default/2811277880327031278?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/3980660135707078299/posts/default/2811277880327031278?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/abeletskyblog/~3/LHcEKPwYxeY/retrospective-2011.html" title="Retrospective 2011" /><author><name>Alexander Beletsky</name><uri>https://profiles.google.com/104123427697898813533</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh5.googleusercontent.com/-WqHPxmC8QfM/AAAAAAAAAAI/AAAAAAAAHi4/tX9CTF-Dzy8/s512-c/photo.jpg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://lh4.googleusercontent.com/-vXQaNQ3spSM/Tvy__2LszrI/AAAAAAAAH2Y/D44-yv0Olpw/s72-c/blog-stat-1.jpg" height="72" width="72" /><feedburner:origLink>http://www.beletsky.net/2011/12/retrospective-2011.html</feedburner:origLink></entry><entry gd:etag="W/&quot;D0YDSXgyfSp7ImA9WhRWGEs.&quot;"><id>tag:blogger.com,1999:blog-3980660135707078299.post-8115368557832050059</id><published>2011-12-19T13:05:00.000+02:00</published><updated>2012-01-06T17:52:58.695+02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-01-06T17:52:58.695+02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Mind" /><category scheme="http://www.blogger.com/atom/ns#" term="Conference" /><title>XP Days Ukraine 2011</title><content type="html">&lt;p&gt;&lt;small&gt;Photos from conference are made by &lt;a href="https://plus.google.com/104783416826445069921/posts"&gt;Andrii Matukhno&lt;/a&gt;&lt;/small&gt;&lt;br /&gt;
&lt;/p&gt;&lt;p&gt;&lt;a href="http://xpdays.com.ua"&gt;XP Days&lt;/a&gt; is a 3 days event. First 2 days are dedicated for trainings and meet-ups and the last day was for speeches. This time I had 3 roles actually: trainer, speaker and visitor. And that was extremely cool.&lt;br /&gt;
&lt;/p&gt;&lt;h2&gt;.NET TDD class&lt;/h2&gt;&lt;p&gt;I've never done any trainer job before, so I was little worried of how it goes. With respect to XP practices we decided to do it in pair with &lt;a href="https://twitter.com/skalinets"&gt;Sergey Kalinets&lt;/a&gt;. &lt;br /&gt;
&lt;/p&gt;&lt;p&gt;Our group consisted of 12 students. After initial introduction I realized - wow, we've got a pretty strong guys here.. Most of group had some real TDD practice before and came to improve the skill and found out new techniques. We had a program for 2 days, which covers the theoretical intros to TDD and practical tips and tricks.&lt;br /&gt;
&lt;/p&gt;&lt;p&gt;We used &lt;a href="http://osherove.com/tdd-kata-1/"&gt;String Calculator&lt;/a&gt; kata which we used both days to warn up. This is very productive way of learning and improving and all guys in group absolutely loved that. I hope this kata became every morning exercise and would be shared among colleagues and be done together, which is great fun.&lt;br /&gt;
&lt;/p&gt;&lt;p&gt;We had great tandem, together with Sergey. We know each other from &lt;a href="http://kievalt.net/"&gt;Kiev ALT.NET&lt;/a&gt; community, but never worked closely. I was very surprised how similar initial experience of TDD we had, so there was absolutely no problem to collaborate. Sergey is very professional trainer, his confidence and experience ruled among these days, he managed to create the training in consistent way. Very naturally we divided technologies &amp; tools, since Sergey works mostly with Desktop and WCF and I work with Web. &lt;br /&gt;
&lt;/p&gt;&lt;p&gt;So, it went very fine as for me. Friday evening, when we've closed training I was very happy to receive feedback. I believe everyone liked what we did. If you guys are reading that, I would ask to put small comment to that post (yes, "+1" would be alright :)).&lt;br /&gt;
&lt;/p&gt;&lt;h2&gt;Conference&lt;/h2&gt;&lt;p&gt;There was a lot of interesting talks. Unfortunately I had to miss several quality-proved ones by &lt;a href="https://twitter.com/skalinets"&gt;Sergey Kalinets&lt;/a&gt; and &lt;a href="https://twitter.com/dimapasko"&gt;Dmitriy Pasko&lt;/a&gt;, I'm really sure that was great stuff. I liked several speeches the most: one by &lt;a href="https://twitter.com/ploeh"&gt;Mark Seeman&lt;/a&gt; about Convetions, that showed me how to write less code relying on conventions.. and lighting talk by &lt;a href="https://twitter.com/dmytromindra"&gt;Dmitry Mindra&lt;/a&gt; on software craftsmanship. It was so great and inspirational! I was touched with case regarding Dmitry's father and his attitude to craft. At the end of speech I was happy to get yellow bracelet in return to my promise to: &lt;br /&gt;
&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Love the craft&lt;/li&gt;
&lt;li&gt;Study and improve knowledge all the time&lt;/li&gt;
&lt;li&gt;Share the knowledge with people around you&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;I hope I will do that!&lt;br /&gt;
&lt;/p&gt;&lt;a href="https://lh4.googleusercontent.com/-maQ_RI-aSOg/Tu0k9YTFMiI/AAAAAAAAJP0/7rW_X2iyfqg/s620/IMG_9494.JPG"&gt;&lt;br /&gt;
&lt;img src="https://lh4.googleusercontent.com/-maQ_RI-aSOg/Tu0k9YTFMiI/AAAAAAAAJP0/7rW_X2iyfqg/s620/IMG_9494.JPG" alt="dmitry mindra" /&gt;&lt;br /&gt;
&lt;/a&gt;&lt;br /&gt;
&lt;p&gt;My speech was dedicated to &lt;a href="http://www.beletsky.net/search/label/Approvals"&gt;Approvals&lt;/a&gt;. Even I had some lack of time and did not manage to show final example I believe it worked great. The audience were very interactive and I felt the positive energy in the air.&lt;br /&gt;
&lt;/p&gt;&lt;p&gt;I had prepared introduction part and code examples that I did just on stage. In my opinion the best way to show something to developers is to write some code, but unfortunately it took a little more time that I expected. Moreover, I received many questions at the very first example, so I had to calm down people a little saying "Guys, please wait.. I haven't even started to show cool things" :)..  &lt;br /&gt;
&lt;/p&gt;&lt;a href="https://lh5.googleusercontent.com/-koMyH6IIFT4/Tu00bGOLp1I/AAAAAAAAJfs/u9HTu4G4Vdc/s620/IMG_5458.JPG"&gt;&lt;br /&gt;
&lt;img src="https://lh5.googleusercontent.com/-koMyH6IIFT4/Tu00bGOLp1I/AAAAAAAAJfs/u9HTu4G4Vdc/s620/IMG_5458.JPG" alt="alexander beletsky" /&gt;&lt;br /&gt;
&lt;/a&gt;&lt;br /&gt;
&lt;p&gt;One nice feature of this conference was that all participant two small card which they could fill with feedback and give to speaker back. I was amazed people very stepping by, saying thank you and giving those cards to me. It turns out that most of audience not familiar with Approvals, so general comment was "Man, I would never heard about that, thanks for sharing it". &lt;br /&gt;
&lt;/p&gt;&lt;a href="https://lh4.googleusercontent.com/-PW9Vn17dOFk/Tu8KVC0sm3I/AAAAAAAAH2E/GnEavhgaZ78/s620/IMG_8234.JPG"&gt;&lt;br /&gt;
&lt;img src="https://lh4.googleusercontent.com/-PW9Vn17dOFk/Tu8KVC0sm3I/AAAAAAAAH2E/GnEavhgaZ78/s620/IMG_8234.JPG" alt="good job cards" /&gt; &lt;br /&gt;
&lt;/a&gt;&lt;br /&gt;
&lt;p&gt;It was extremely pleasant to receive that feedback thought cards and twitter. I'm truly appreciate each good word I got from you guys. Totally I collected 22 feedback cards and treat it as very good result!&lt;br /&gt;
&lt;/p&gt;&lt;h2&gt;Conclusions&lt;/h2&gt;&lt;p&gt;First of all, big kudos for all people who make this event happen: &lt;a href="http://xpinjection.com/"&gt;XP Injection&lt;/a&gt;, &lt;a href="http://xpdays.com.ua/sponsors/"&gt;sponsors&lt;/a&gt;, &lt;a href="http://xpdays.com.ua/speakers/"&gt;speakers&lt;/a&gt; and visitors. Conference took place in business center &lt;a href="http://www.parus.biz/"&gt;Parus&lt;/a&gt;, which was a great idea. It is in a center of the Kyiv and has very suitable infrastructure.&lt;br /&gt;
&lt;/p&gt;&lt;p&gt;As always, it was great pleasure to meet with people from other cities and countries, getting new contacts. I hope that's not the last XP Days in Ukraine, not the last I'm participating in.&lt;br /&gt;
&lt;/p&gt;&lt;p&gt;The slides from my speech is shared on &lt;a href="http://speakerdeck.com/u/alexanderbeletsky/p/approval-testing"&gt;SpeakerDeck&lt;/a&gt;. Also, I'm happy to help you with Apporvals, so do not hesitate to contact my skype or twitter.&lt;br /&gt;
&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3980660135707078299-8115368557832050059?l=www.beletsky.net' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/abeletskyblog?a=c6YYaf59fjs:nZ8RHhDKoq4:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/abeletskyblog?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/abeletskyblog?a=c6YYaf59fjs:nZ8RHhDKoq4:63t7Ie-LG7Y"&gt;&lt;img src="http://feeds.feedburner.com/~ff/abeletskyblog?d=63t7Ie-LG7Y" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/abeletskyblog?a=c6YYaf59fjs:nZ8RHhDKoq4:-BTjWOF_DHI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/abeletskyblog?i=c6YYaf59fjs:nZ8RHhDKoq4:-BTjWOF_DHI" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/abeletskyblog/~4/c6YYaf59fjs" height="1" width="1"/&gt;</content><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/3980660135707078299/posts/default/8115368557832050059?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/3980660135707078299/posts/default/8115368557832050059?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/abeletskyblog/~3/c6YYaf59fjs/xp-days-ukraine-2011.html" title="XP Days Ukraine 2011" /><author><name>Alexander Beletsky</name><uri>https://profiles.google.com/104123427697898813533</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh5.googleusercontent.com/-WqHPxmC8QfM/AAAAAAAAAAI/AAAAAAAAHi4/tX9CTF-Dzy8/s512-c/photo.jpg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://lh4.googleusercontent.com/-maQ_RI-aSOg/Tu0k9YTFMiI/AAAAAAAAJP0/7rW_X2iyfqg/s72-c/IMG_9494.JPG" height="72" width="72" /><feedburner:origLink>http://www.beletsky.net/2011/12/xp-days-ukraine-2011.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CEQNQnYyfyp7ImA9WhRQGEU.&quot;"><id>tag:blogger.com,1999:blog-3980660135707078299.post-7600057367654983547</id><published>2011-12-14T19:06:00.000+02:00</published><updated>2011-12-14T19:06:33.897+02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-12-14T19:06:33.897+02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Approvals" /><category scheme="http://www.blogger.com/atom/ns#" term="Open source" /><category scheme="http://www.blogger.com/atom/ns#" term="TDD" /><title>Approval Tests: Locking Down Legacy Code</title><content type="html">&lt;p&gt;Suppose, you working on project with a lot of legacy code inside. I know it makes you sick, but as brave developer you want to improve things. You met that ugliest method in your life and only one thing you want to do - refactor it. But refactoring is dangerous procedure. For safe refactoring you need to have good test coverage. But wait, it is legacy code. You simply have no tests. What to do? Approvals have answer.&lt;br /&gt;
&lt;/p&gt;&lt;h2&gt;Legacy code is the code that...&lt;/h2&gt;&lt;p&gt;Works! Right, it is ugly, un-supportable, nothing you can easy change there. But the most wonderful feature of that code - it works for years. And first thing is to get advantage of that fact!&lt;br /&gt;
&lt;/p&gt;&lt;p&gt;Here is my "just for example" legacy method.&lt;br /&gt;
&lt;/p&gt;&lt;pre class="brush: csharp"&gt;namespace Playground.Legacy
{
    public class HugeAndScarryLegacyCode
    {
        public static string TheUgliesMethodYouMightEverSeen(string s, int i, char c)
        {
            if (s.Length &gt; 5)
            {
                s += "_some_suffix";
            }

            var r = new StringBuilder();
            foreach (var k in s)
            {
                if ((int)k % i == 0)
                {
                    r.Append(c);
                }
                else
                {
                    if (k == c)
                    {
                        if (r.Length &lt;= 2)
                        {
                            r.Append('a');
                        }
                        else
                        {
                            r.Append('b');
                        }
                    }
                    if (k == '^')
                    {
                        r.Append('c');
                    }
                    else
                    {
                        r.Append(k);
                    }
                }
            }

            return r.ToString();
        }
    }
}
&lt;/pre&gt;
&lt;p&gt;(it's it ugly enough?)
&lt;/p&gt;&lt;p&gt;It has a cycles, nested if-else case and all nice features of legacy code. We need to change it, but in the same time guarantee it would not be broken.
&lt;/p&gt;&lt;h2&gt;Trying first simple test&lt;/h2&gt;&lt;p&gt;Supposing also, I'm not much in details of how exactly this function works.. So, I'm creating the test like:
&lt;/p&gt;&lt;pre class="brush: csharp"&gt;[Test]
public void shoudl_work_some_how()
{
    Approvals.Approve(HugeAndScarryLegacyCode.TheUgliesMethodYouMightEverSeen("someinput", 10, 'c'));
}
&lt;/pre&gt;&lt;p&gt;I run it and got some result to approve:
&lt;/p&gt;&lt;a href="https://lh6.googleusercontent.com/-7-utFOmYWqw/TujWEUiQc-I/AAAAAAAAH1g/-1OCWEOAQYQ/s555/result-1.jpg"&gt;
&lt;img src="https://lh6.googleusercontent.com/-7-utFOmYWqw/TujWEUiQc-I/AAAAAAAAH1g/-1OCWEOAQYQ/s555/result-1.jpg" alt="approvals" /&gt;
&lt;/a&gt;
&lt;p&gt;I approve that, cause I know that function works. But something inside tells you - that is not enough. Try to run in under the coverage: 
&lt;/p&gt;&lt;a href="https://lh5.googleusercontent.com/-9AS23mH6UGI/TujWMRdftFI/AAAAAAAAH1o/VDbIJW4D3OQ/s621/result-2.jpg"&gt;
&lt;img src="https://lh5.googleusercontent.com/-9AS23mH6UGI/TujWMRdftFI/AAAAAAAAH1o/VDbIJW4D3OQ/s621/result-2.jpg" alt="approvals" /&gt;
&lt;/a&gt;
&lt;p&gt;That does not make me real confident with tests only one hit and coverage 76%. We have to create better tests cases.
&lt;/p&gt;&lt;h2&gt;Use combinations of arguments&lt;/h2&gt;&lt;p&gt;Approvals include some tools to deal this case. Let's change out test and write something like,
&lt;/p&gt;&lt;pre class="brush: csharp"&gt;[Test]
public void should_try_to_cover_it()
{
    var numbers = new[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
    var chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ".ToCharArray();
    var strings = new[] { "", "approvals", "xpdays", "^stangeword^" };

    ApprovalTests.Combinations.Approvals.ApproveAllCombinations(
        (s, i, c) =&gt; HugeAndScarryLegacyCode.TheUgliesMethodYouMightEverSeen(s, i, c),
        strings,
        numbers,
        chars);
}
&lt;/pre&gt;&lt;p&gt;With only few lines of code, I've got 1560 test cases and all of them are correct!
&lt;/p&gt;&lt;a href="https://lh3.googleusercontent.com/--P4qoqgHK-A/TujWW2-jkkI/AAAAAAAAH1w/nfOWsaKJH5Y/s575/result-3.jpg"&gt;
&lt;img src="https://lh3.googleusercontent.com/--P4qoqgHK-A/TujWW2-jkkI/AAAAAAAAH1w/nfOWsaKJH5Y/s575/result-3.jpg" alt="approvals" /&gt;
&lt;/a&gt;
&lt;p&gt;Besides, I got pretty good coverage. Ideal, I would say. Now, if even one small change would happen, some of 1560 tests will notice that. &lt;/p&gt;&lt;a href="https://lh3.googleusercontent.com/-P7b61iiuL7I/TujWflnUWUI/AAAAAAAAH14/ERoxa0k6dfI/s620/result-4.jpg"&gt;
&lt;img src="https://lh3.googleusercontent.com/-P7b61iiuL7I/TujWflnUWUI/AAAAAAAAH14/ERoxa0k6dfI/s620/result-4.jpg" alt="approvals" /&gt;
&lt;/a&gt;
&lt;h2&gt;Locking down&lt;/h2&gt;&lt;p&gt;The process of controlling the legacy code in that way is called "Locking down". After the code is locked down, you have high confidence (read low risk) of breaking changes you introduce. Please note how low effort it was to create all that 1560 tests and how much value gained in that.
&lt;/p&gt;&lt;p&gt;Notice, that test like &lt;code&gt;should_try_to_cover_it&lt;/code&gt; is not supposed to "live forever". You probably even don't need to check it in to source control. You just do your job, either refactoring or changing that functionality and use Approvals to notify you as fast as possible of something goes wrong.
&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3980660135707078299-7600057367654983547?l=www.beletsky.net' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/abeletskyblog?a=PFu9Pllb5X4:vRN-VwcnO7o:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/abeletskyblog?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/abeletskyblog?a=PFu9Pllb5X4:vRN-VwcnO7o:63t7Ie-LG7Y"&gt;&lt;img src="http://feeds.feedburner.com/~ff/abeletskyblog?d=63t7Ie-LG7Y" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/abeletskyblog?a=PFu9Pllb5X4:vRN-VwcnO7o:-BTjWOF_DHI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/abeletskyblog?i=PFu9Pllb5X4:vRN-VwcnO7o:-BTjWOF_DHI" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/abeletskyblog/~4/PFu9Pllb5X4" height="1" width="1"/&gt;</content><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/3980660135707078299/posts/default/7600057367654983547?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/3980660135707078299/posts/default/7600057367654983547?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/abeletskyblog/~3/PFu9Pllb5X4/approval-tests-locking-down-legacy-code.html" title="Approval Tests: Locking Down Legacy Code" /><author><name>Alexander Beletsky</name><uri>https://profiles.google.com/104123427697898813533</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh5.googleusercontent.com/-WqHPxmC8QfM/AAAAAAAAAAI/AAAAAAAAHi4/tX9CTF-Dzy8/s512-c/photo.jpg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://lh6.googleusercontent.com/-7-utFOmYWqw/TujWEUiQc-I/AAAAAAAAH1g/-1OCWEOAQYQ/s72-c/result-1.jpg" height="72" width="72" /><feedburner:origLink>http://www.beletsky.net/2011/12/approval-tests-locking-down-legacy-code.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DkYFRnkyfyp7ImA9WhRQF0s.&quot;"><id>tag:blogger.com,1999:blog-3980660135707078299.post-3759965096023101800</id><published>2011-12-13T10:15:00.000+02:00</published><updated>2011-12-13T10:15:17.797+02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-12-13T10:15:17.797+02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="MVC" /><category scheme="http://www.blogger.com/atom/ns#" term="Mind" /><category scheme="http://www.blogger.com/atom/ns#" term="asp.net" /><title>Why New Technologies Move Your Product Faster?</title><content type="html">&lt;p&gt;This summer my company &lt;a href="http://www.e-conomic.co.uk/"&gt;e-conomic&lt;/a&gt; started new project with a working title SBA (Small Business Accounting). The project is about the creation of the product for small business owner, like consultants,  web shops, freelancers etc. Since my company already had great expertise in that area the product vision and initial backlog of stories was already in place. Even more, we already had a product that does nearly the same but for a different target user - so, it was kind of natural to try to build SBA based on existing one. We started our journey having very ambitious plan in our mind meaning release in less than 6 month.&lt;br /&gt;
&lt;/p&gt;&lt;p&gt;But to our great disappointment the progress for next 2 month appeared very low. We underestimated one thing - the existing product is a great  but some of the underlying technologies were ill-suited for the new projects. Very simple things, like adding new custom form, UI changes, data access etc. were hard and unpleasant.&lt;br /&gt;
&lt;/p&gt;&lt;p&gt;The legacy code, de-motivation and low progress.. were about to bury the project. Fortunately, the company were brave enough to change something on a fly. We went a very risky way, to build new product not based on old technologies, but almost from scratch. And as for me, that was great decision! So, somewhere in October we re-started the project.&lt;br /&gt;
&lt;/p&gt;&lt;p&gt;What have we changed and how it went?&lt;br /&gt;
&lt;/p&gt;&lt;h2&gt;SVN =&gt; Git&lt;/h2&gt;&lt;p&gt;I have &lt;a href="http://www.beletsky.net/2011/06/how-to-start-using-git-in-svn-based.html"&gt;posted earlier&lt;/a&gt; some my experience of starting to use Git in SVN-based organization. That time it was 2-3 people that tried to adopt that process, now it is only 2-3 who are not using it. We are thinking about moving to pure Git environment, but our deployment procedure slightly depends on SVN. As soon as we fix it, we can get rid of SVN completely.&lt;br /&gt;
&lt;/p&gt;&lt;p&gt;You might argue, that changing source management tool is not exactly technological change and not affecting development velocity! But wait a minute.. How much time did you waste to resolve stupid tree conflicts? How much time you waste waiting for new branch, at the code freeze period? How many times your thrown away yours refactoring results, simply because you are not able to commit that now? &lt;br /&gt;
&lt;/p&gt;&lt;p&gt;All of that factors are contra-productive. It could be not even seen from first sight, but Git improves the velocity simply by getting rid of annoying things that are natural to centralized source control management systems.&lt;br /&gt;
&lt;/p&gt;&lt;a href="https://lh5.googleusercontent.com/-XG2gEof9UpY/TucIbWZAFWI/AAAAAAAAH1A/1CWmMN_-chQ/s620/git.jpg"&gt;&lt;br /&gt;
&lt;img src="https://lh5.googleusercontent.com/-XG2gEof9UpY/TucIbWZAFWI/AAAAAAAAH1A/1CWmMN_-chQ/s620/git.jpg" alt="git" /&gt;&lt;br /&gt;
&lt;/a&gt;&lt;br /&gt;
&lt;h2&gt;ASP.NET WebForms =&gt; ASP.NET MVC&lt;/h2&gt;&lt;p&gt;Supporting WebForm's code is a big mess. It's is difficult to test, difficult to understand and to change. We had a bunch of custom controls that worked fine, but adopting them to something different is hard.&lt;br /&gt;
&lt;/p&gt;&lt;p&gt;For the year I'm &lt;a href="http://www.beletsky.net/search/label/MVC"&gt;studding&lt;/a&gt; ASP.NET MVC and much inspired by it's clear and powerful design. So, I was really happy we finally &lt;a href="http://www.beletsky.net/2011/10/integrating-aspnet-mvc-into-legacy-web.html"&gt;moved&lt;/a&gt; that direction. &lt;br /&gt;
&lt;/p&gt;&lt;p&gt;We are using MVC in both modes: as for our web UI pages and for REST services. The same URL could produce both HTML or JSON response, depending on context. Having that, we are much flexible and not duplicate the code on pages and web services. MVC controllers are easy testable, Views are clean having only HTML with only few server side code snippets. Switch to ASP.NET MVC boosts us pretty much.&lt;br /&gt;
&lt;/p&gt;&lt;p&gt;I think the adaption of new technology was really fast, even if we had some issues at the beginning they have been solved. I have to say that to use ASP.NET MVC we have to update production environment, namely upgrade in Windows 2008 with II7 which requires additional investment. But I think it's only for good, cause having environment debt is the same as having technical debt in code.&lt;br /&gt;
&lt;/p&gt;&lt;a href="https://lh6.googleusercontent.com/-3FyOP31U69I/TucImLlSZvI/AAAAAAAAH1I/lWulB9EVFeo/s620/mvc.jpg"&gt;&lt;br /&gt;
&lt;img src="https://lh6.googleusercontent.com/-3FyOP31U69I/TucImLlSZvI/AAAAAAAAH1I/lWulB9EVFeo/s620/mvc.jpg" alt="asp.net mvc" /&gt;&lt;br /&gt;
&lt;/a&gt;&lt;br /&gt;
&lt;h2&gt;Pure jQuery =&gt; Backbone.js&lt;/h2&gt;&lt;p&gt;jQuery is the best javascript framework ever. It suites so nicely till the application is not getting to much big. As you getting out some imaginary "bounds" jQuery code get out of the control. Till that time we already had huge amount of .js files mixing out logic and UI stuff. &lt;br /&gt;
&lt;/p&gt;&lt;p&gt;We were choosing between Knockout.js and Backbone.js and finally stopped at Backbone. Backbone.js introduce order in client-side code. It has clear separation of concerns for Models, Views, Controllers.. so we can say Backbone.js is MVC framework on client.&lt;br /&gt;
&lt;/p&gt;&lt;p&gt;Having order is first step for productivity. The things are more predicable, read more fast to getting things done. Of cause, it takes a lot of effort to learn it. And no surprise some we still having some challenges caused by lack of expertise. But having &lt;a href="http://lostechies.com/derickbailey/"&gt;Derick Bailey&lt;/a&gt; as our consultant making it better. &lt;br /&gt;
&lt;/p&gt;&lt;p&gt;I would add that ASP.NET MVC and Backbone.js suits each other very nicely, since Backbone.js is REST oriented and ASP.NET MVC exposing REST in a right way.&lt;br /&gt;
&lt;/p&gt;&lt;a href="https://lh6.googleusercontent.com/-Ww_ElYoIAVo/TucIx1wP6tI/AAAAAAAAH1Q/jmKpUE2jjQY/s620/backbone.jpg"&gt;&lt;br /&gt;
&lt;img src="https://lh6.googleusercontent.com/-Ww_ElYoIAVo/TucIx1wP6tI/AAAAAAAAH1Q/jmKpUE2jjQY/s620/backbone.jpg" alt="backbone.js" /&gt;&lt;br /&gt;
&lt;/a&gt;&lt;br /&gt;
&lt;h2&gt;Super.Tricky.NHibernate.Wrapper =&gt; ADO.NET&lt;/h2&gt;&lt;p&gt;One of the pain-in-neck points of our application is data access. We have huge wrapper around the NHibernate framework. Words "Wrapper on NHibernate" could make someone sick, what if I say, "Wrapper on HHibernate, which is code generated"? &lt;br /&gt;
&lt;/p&gt;&lt;p&gt;So, someone might treat that are making step back. But I don't agree. Whatever things you can do in C# code, it is SQL only the language your Database can speak. Having a ORM's are kind of having translator during the conversation with foreign guy. It works great as soon you speak simply, it's getting worse than conversation going complicated, so translator hardly could translate everything you want to say. And of cause, it almost has no sense to have a translator, as soon if you can speak that language.&lt;br /&gt;
&lt;/p&gt;&lt;p&gt;We are not using pure ADO.NET, it would be complicated. We have a tiny wrapper on that that basically run queries and returns result sets. It might seem harder, but I would say it's very flexible. You can create what ever queries you need and map them what ever models you have. It works fine, it works fast. It is easy to test, since you no longer need NHibernate profiler to understand what's wrong in you application, code just close to you.&lt;br /&gt;
&lt;/p&gt;&lt;p&gt;After last &lt;a href="http://kievalt.net/"&gt;Kiev ALT.NET&lt;/a&gt; meeting I understood we are not alone here. A lot of people start to understand that NHibernate becoming to heavyweight. New movement of MicroORM's appeared, that combines power of SQL and functionality of mapping tables to objects. I want to believe that some MicroORM framework could be our next thing to adopt. &lt;br /&gt;
&lt;/p&gt;&lt;a href="https://lh5.googleusercontent.com/-8g_ydfqm6NU/TucI50rybVI/AAAAAAAAH1Y/PzhnR_Eudzo/s623/sql.jpg"&gt;&lt;br /&gt;
&lt;img src="https://lh5.googleusercontent.com/-8g_ydfqm6NU/TucI50rybVI/AAAAAAAAH1Y/PzhnR_Eudzo/s623/sql.jpg" alt="sql" /&gt;&lt;br /&gt;
&lt;/a&gt;&lt;br /&gt;
&lt;h2&gt;De-motivation =&gt; Obsession&lt;/h2&gt;&lt;p&gt;It is not technological factor.. it is not even something I easy describe. Developers are taking responsibility by changing the things or advocating for some particular technology. You are no longer have excuse of bad quality because of legacy reasons. Sure, legacy still plays some role but impact is not so high.&lt;br /&gt;
&lt;/p&gt;&lt;p&gt;Having a new technologies on board simply makes developers happier. Happy developer is obsessed developer, he is commited to success. He will work as much as he can to make good results. &lt;br /&gt;
&lt;/p&gt;&lt;p&gt;With a consistent challenge, every day is no longer "another day in office", but rather "yet another day on pirate ship". It starts to smell start-up shop, that tried to get on market as soon as possible, adapting last available tools. The project now is not something I just had to do, but kind of pet project, where you trying things out and feel great if those things works.&lt;br /&gt;
&lt;/p&gt;&lt;p&gt;That's why in particular I think it is great to start from scratch (or near to scratch) one a year or something. Pick up last thing, learn them, adopt and build something valuable - it is nothing to compare with maintenance of 5 year old code.&lt;br /&gt;
&lt;/p&gt;&lt;p&gt;New technologies moves you product faster!&lt;br /&gt;
&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3980660135707078299-3759965096023101800?l=www.beletsky.net' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/abeletskyblog?a=PU1rBtn9WQE:4bFvkupvfj8:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/abeletskyblog?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/abeletskyblog?a=PU1rBtn9WQE:4bFvkupvfj8:63t7Ie-LG7Y"&gt;&lt;img src="http://feeds.feedburner.com/~ff/abeletskyblog?d=63t7Ie-LG7Y" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/abeletskyblog?a=PU1rBtn9WQE:4bFvkupvfj8:-BTjWOF_DHI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/abeletskyblog?i=PU1rBtn9WQE:4bFvkupvfj8:-BTjWOF_DHI" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/abeletskyblog/~4/PU1rBtn9WQE" height="1" width="1"/&gt;</content><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/3980660135707078299/posts/default/3759965096023101800?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/3980660135707078299/posts/default/3759965096023101800?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/abeletskyblog/~3/PU1rBtn9WQE/why-new-technologies-move-your-product.html" title="Why New Technologies Move Your Product Faster?" /><author><name>Alexander Beletsky</name><uri>https://profiles.google.com/104123427697898813533</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh5.googleusercontent.com/-WqHPxmC8QfM/AAAAAAAAAAI/AAAAAAAAHi4/tX9CTF-Dzy8/s512-c/photo.jpg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://lh5.googleusercontent.com/-XG2gEof9UpY/TucIbWZAFWI/AAAAAAAAH1A/1CWmMN_-chQ/s72-c/git.jpg" height="72" width="72" /><feedburner:origLink>http://www.beletsky.net/2011/12/why-new-technologies-move-your-product.html</feedburner:origLink></entry><entry gd:etag="W/&quot;A0UMQns8fSp7ImA9WhRQFUQ.&quot;"><id>tag:blogger.com,1999:blog-3980660135707078299.post-4723391672261324371</id><published>2011-12-11T12:25:00.001+02:00</published><updated>2011-12-11T12:28:03.575+02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-12-11T12:28:03.575+02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="ELMAH.MVC" /><category scheme="http://www.blogger.com/atom/ns#" term="Tools" /><category scheme="http://www.blogger.com/atom/ns#" term="MVC" /><category scheme="http://www.blogger.com/atom/ns#" term="NuGet" /><category scheme="http://www.blogger.com/atom/ns#" term="asp.net" /><title>ELMAH MVC: Answering questions</title><content type="html">&lt;p&gt;I've received some questions recently regarding &lt;a href="https://nuget.org/packages/Elmah.MVC"&gt;ELMAH.MVC&lt;/a&gt; nuget package. Here is the summary blog post and I hope it is helpful.&lt;br /&gt;
&lt;/p&gt;&lt;h2&gt;How to change that to log it into a database?&lt;/h2&gt;&lt;p&gt;Indeed, the demo project on a &lt;a href="https://github.com/alexanderbeletsky/elmah.mvc.controller/blob/master/src/Web.config"&gt;github&lt;/a&gt; uses simple &lt;code&gt;Elmah.MemoryErrorLog&lt;/code&gt; just holding all errors in session. That works great for small application or just to try out things. In reallity you need some persistant storage, like files or database. And this is extreamly easy to do. Take a look at this section of web.config:&lt;br /&gt;
&lt;/p&gt;&lt;pre class="brush: xml"&gt;&amp;lt;elmah&amp;gt;
    &amp;lt;security allowRemoteAccess=&amp;quot;yes&amp;quot; /&amp;gt;
    &amp;lt;errorLog type=&amp;quot;Elmah.MemoryErrorLog, Elmah&amp;quot;/&amp;gt;
    &amp;lt;!--&amp;lt;errorLog type=&amp;quot;Elmah.SqlErrorLog, Elmah&amp;quot; connectionStringName=&amp;quot;elmah&amp;quot; /&amp;gt;--&amp;gt;
    &amp;lt;!--&amp;lt;errorLog type=&amp;quot;Elmah.XmlFileErrorLog, Elmah&amp;quot; logPath=&amp;quot;~/App_Data/Elmah.Errors&amp;quot; /&amp;gt;--&amp;gt;
&amp;lt;/elmah&amp;gt;
&lt;/pre&gt;&lt;p&gt;Just comment out &lt;code&gt;Elmah.MemoryErrorLog&lt;/code&gt; and de-comment &lt;code&gt;Elmah.SqlErrorLog&lt;/code&gt; (will store errors to SQL database) or &lt;code&gt;Elmah.XmlFileErrorLog&lt;/code&gt; (will store errors to XML files). XML logger, just requires a virtual path to folder there files will be stored. Sql logger, requires a connection string name for ELMAH database. The same web.config contains:&lt;br /&gt;
&lt;/p&gt;&lt;pre class="brush: xml"&gt;&amp;lt;connectionStrings&amp;gt;
    &amp;lt;add name=&amp;quot;elmah&amp;quot; connectionString=&amp;quot;Data Source=.\SQLEXPRESS;Initial Catalog=elmah;Integrated Security=True&amp;quot; providerName=&amp;quot;System.Data.SqlClient&amp;quot; /&amp;gt;
&amp;lt;/connectionStrings&amp;gt;
&lt;/pre&gt;&lt;p&gt;The database have to have ELMAH schema inside. It is very easy to prepare that schema, just run &lt;a href="https://github.com/alexanderbeletsky/elmah.mvc.controller/blob/master/db/database.sql"&gt;this&lt;/a&gt; SQL script against database you want to keep errors to.&lt;br /&gt;
&lt;/p&gt;&lt;h2&gt;Does ELMAH.MVC handle custom error pages?&lt;/h2&gt;&lt;p&gt;This is a misconception. ELMAH.MVC is not about custom pages, at all. This is good answer on &lt;a href="http://stackoverflow.com/a/1288819/386751"&gt;stackoverflow&lt;/a&gt; on that. For a code example, you can refer to something I did for before my projects just &lt;a href="https://github.com/alexanderbeletsky/trackyt.net/blob/master/src/Web/Controllers/ErrorController.cs"&gt;here&lt;/a&gt;&lt;br /&gt;
&lt;/p&gt;&lt;h2&gt;ELMAH.MVC gives me FxCop/StyleCop issues?&lt;/h2&gt;&lt;p&gt;I've received &lt;a href="https://github.com/alexanderbeletsky/elmah.mvc.controller/issues/4"&gt;that&lt;/a&gt; kind report on github issues. Initially I thought to do something about it but then I left that idea. The explanation is inside the ticket.&lt;br /&gt;
&lt;/p&gt;&lt;p&gt;Short answer is, ELMAH.MVC is nothing more that boilerplate code. As soon as you can see it work and it works OK for you, adopt it for your custom needs. That's it.&lt;br /&gt;
&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3980660135707078299-4723391672261324371?l=www.beletsky.net' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/abeletskyblog?a=zJhsrjFy1MU:SnM4bDj-EkI:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/abeletskyblog?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/abeletskyblog?a=zJhsrjFy1MU:SnM4bDj-EkI:63t7Ie-LG7Y"&gt;&lt;img src="http://feeds.feedburner.com/~ff/abeletskyblog?d=63t7Ie-LG7Y" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/abeletskyblog?a=zJhsrjFy1MU:SnM4bDj-EkI:-BTjWOF_DHI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/abeletskyblog?i=zJhsrjFy1MU:SnM4bDj-EkI:-BTjWOF_DHI" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/abeletskyblog/~4/zJhsrjFy1MU" height="1" width="1"/&gt;</content><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/3980660135707078299/posts/default/4723391672261324371?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/3980660135707078299/posts/default/4723391672261324371?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/abeletskyblog/~3/zJhsrjFy1MU/elmah-mvc-answering-questions.html" title="ELMAH MVC: Answering questions" /><author><name>Alexander Beletsky</name><uri>https://profiles.google.com/104123427697898813533</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh5.googleusercontent.com/-WqHPxmC8QfM/AAAAAAAAAAI/AAAAAAAAHi4/tX9CTF-Dzy8/s512-c/photo.jpg" /></author><feedburner:origLink>http://www.beletsky.net/2011/12/elmah-mvc-answering-questions.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CEQMQns4eyp7ImA9WhRQGEU.&quot;"><id>tag:blogger.com,1999:blog-3980660135707078299.post-2776792682609116511</id><published>2011-12-11T01:19:00.000+02:00</published><updated>2011-12-14T19:06:23.533+02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-12-14T19:06:23.533+02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Tools" /><category scheme="http://www.blogger.com/atom/ns#" term="Approvals" /><category scheme="http://www.blogger.com/atom/ns#" term="Open source" /><category scheme="http://www.blogger.com/atom/ns#" term="TDD" /><title>Approval Tests, Alternative View on Test Automation</title><content type="html">&lt;p&gt;&lt;a href="https://sourceforge.net/projects/approvaltests/"&gt;Approval Tests&lt;/a&gt; or simply Approvals in a framework created by &lt;a href="http://twitter.com/#!/LlewellynFalco"&gt;Llewellyn Falco&lt;/a&gt; and &lt;a href="http://dangilkerson.users.sourceforge.net/"&gt;Dan Gilkerson&lt;/a&gt;, providing support for .NET, Java, PHP and Ruby. It is not yet another unit testing framework like NUnit or MbUnit etc., instead those frameworks are used to run approval tests.&lt;br /&gt;
&lt;/p&gt;&lt;p&gt;Broadly speaking, software is nothing more as virtual box there we put some inputs and expect on outputs. The outputs could be produces by zillion ways. Those ways are differ by its implementation. Unit tests are too much focusing on implementation. Thats why unit tests might fail even if you have working code, or otherwise. Approvals are focusing on output.&lt;br /&gt;
&lt;/p&gt;&lt;h2&gt;How it works?&lt;/h2&gt;&lt;p&gt;Let's take a look on a very simple case. Say, I have a class &lt;code&gt;ShoppingCart&lt;/code&gt;. I can add some products inside the shopping cart, confirm my purchase. I expect that total price is calculated for me. &lt;br /&gt;
&lt;/p&gt;&lt;pre class="brush: csharp"&gt;[TestFixture]
[UseReporter(typeof(DiffReporter))]
public class ShoppingCartTests {

    [Test]
    public void should_calculate_the_total_price_for_shopping_cart() {
        // do
        var shoppingCart = new ShoppingCart();
        shoppingCart.Add(new Product { Id = "iPad", Price = 500 });
        shoppingCart.Add(new Product { Id = "Mouse", Price = 20 });
        shoppingCart.Confirm();

        // verify
        Approvals.Approve(shoppingCart);
    }
}
&lt;/pre&gt;&lt;p&gt;What happens if I run this test? If I'm running it first time it fails. No matter it works or doesn't. Framework simply don't know that yet. To understand how much correct that code is, it will actually ask you, to utilized human primary power - recognition.   &lt;br /&gt;
&lt;/p&gt;&lt;p&gt;In that case it will open the TortoiseDiff application and show actual and expected outputs.&lt;br /&gt;
&lt;/p&gt;&lt;a href="https://lh5.googleusercontent.com/-la_QjhoPxSc/TuPoxAXVteI/AAAAAAAAH0w/MdWZ0OAcalk/s779/Diff.jpg"&gt;&lt;br /&gt;
&lt;img src="https://lh5.googleusercontent.com/-la_QjhoPxSc/TuPoxAXVteI/AAAAAAAAH0w/MdWZ0OAcalk/s779/Diff.jpg" /&gt;&lt;br /&gt;
&lt;/a&gt;&lt;br /&gt;
&lt;p&gt;Here, I'm able just read that: "Ok, I have 2 products in my cart..one iPod and one Mouse, iPods costs 500 smth and mouse is 20 smth.. and the total price is 520 - looks good! I approve that result!".&lt;br /&gt;
&lt;/p&gt;&lt;p&gt;Technically the approving is just copying actual output file to expected. As soon as test passed, actual file output is deleted and approved file resides near test code file, so you just check it in source control.&lt;br /&gt;
&lt;/p&gt;&lt;p&gt;If then the shopping cart is modified and something goes wrong. There would be a failure. In case of unit tests, that would be multiple failure of different cases and it might be not so easy to understand what's exactly wrong. For approval test, it would be one failure. And the cool thing that I have a difference that shows there exactly the deviation is. &lt;br /&gt;
&lt;/p&gt;&lt;a href="https://lh3.googleusercontent.com/-CTO2HOQGoDs/TuPo7nJ1U8I/AAAAAAAAH04/ycao7SUf78s/s720/Diff2.jpg"&gt;&lt;br /&gt;
&lt;img src="https://lh3.googleusercontent.com/-CTO2HOQGoDs/TuPo7nJ1U8I/AAAAAAAAH04/ycao7SUf78s/s720/Diff2.jpg" /&gt;&lt;br /&gt;
&lt;/a&gt;&lt;br /&gt;
&lt;h2&gt;Where it works?&lt;/h2&gt;&lt;p&gt;It is not only the simple objects you can approve. What's the cool thing, you can approval against the different sources: objects, enumerables, files, HTML, XML etc. On a more high level: WpfForm, WinForm, ASP.NET Page. &lt;br /&gt;
&lt;/p&gt;&lt;p&gt;For instance, code for ASP.NET:&lt;br /&gt;
&lt;/p&gt;&lt;pre class="brush: csharp"&gt;[Test]
public void should_have_approved_layout() {
    ApprovalTests.Asp.Approvals.ApproveUrl("http://localhost:62642/customer/");
}
&lt;/pre&gt;&lt;p&gt;Or for WPF form&lt;br /&gt;
&lt;/p&gt;&lt;pre class="brush: csharp"&gt;[Test]
public void should_have_approved_layout() {
    ApprovalTests.Wpf.Approvals.Approve(new Form());
}
&lt;/pre&gt;&lt;p&gt;With WPF and Win forms is that it's able to serialize them into images, so the actual and expected results are actually images, so it is easy to track the differences (TortoiseDiff can do that).&lt;br /&gt;
&lt;/p&gt;&lt;h2&gt;When it works?&lt;/h2&gt;&lt;p&gt;It works best when you deal with 2 things: UI and legacy code.&lt;br /&gt;
&lt;/p&gt;&lt;p&gt;Testing of UI is always a difficult part. But what you typically need is: make sure that UI is not changed and if changed, where exactly is happening. Apporvals solves that nicely. It is only one line of code test, to test ASP.NET page for instance. &lt;br /&gt;
&lt;/p&gt;&lt;p&gt;Legacy is another story: you have no tests there at all, but you have to change code to implement new feature or refactor. The interesting thing about legacy code - It works! It works for years, no matter how it written (remember, virtual box). And this is a very great advantage of that code. With approvals, with only one test you can get all possible outputs (HTML, XLM, JSON, SQL or whatever output it could be) and approve, because you know - it works! After you have such test and approved result you are really much safe with a refactoring, since now you "locked down" all existing behavior.&lt;br /&gt;
&lt;/p&gt;&lt;p&gt;Approvals are not something you need to run all the time, like units or integration tests. It more like handy tool. You create approval tests, you do your job and at the end of the day it might happen - you no longer needed, so you can just throw it away.&lt;br /&gt;
&lt;/p&gt;&lt;h2&gt;Want to hear more?&lt;/h2&gt;&lt;p&gt;Just go and listen to &lt;a href="http://herdingcode.com/?p=329"&gt;this&lt;/a&gt; Herding Code podcast episode, or visit project &lt;a href="https://sourceforge.net/projects/approvaltests/"&gt;web site&lt;/a&gt; or join me at 17 December on &lt;a href="http://xpdays.com.ua/program/"&gt;XP Days Ukraine&lt;/a&gt; conference in Kiev, where I'm going to have a speech dedicated to Approvals.&lt;br /&gt;
&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3980660135707078299-2776792682609116511?l=www.beletsky.net' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/abeletskyblog?a=PUpr4t_gZDo:ypazL4AUmso:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/abeletskyblog?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/abeletskyblog?a=PUpr4t_gZDo:ypazL4AUmso:63t7Ie-LG7Y"&gt;&lt;img src="http://feeds.feedburner.com/~ff/abeletskyblog?d=63t7Ie-LG7Y" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/abeletskyblog?a=PUpr4t_gZDo:ypazL4AUmso:-BTjWOF_DHI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/abeletskyblog?i=PUpr4t_gZDo:ypazL4AUmso:-BTjWOF_DHI" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/abeletskyblog/~4/PUpr4t_gZDo" height="1" width="1"/&gt;</content><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/3980660135707078299/posts/default/2776792682609116511?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/3980660135707078299/posts/default/2776792682609116511?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/abeletskyblog/~3/PUpr4t_gZDo/approval-tests-alternative-view-on-test.html" title="Approval Tests, Alternative View on Test Automation" /><author><name>Alexander Beletsky</name><uri>https://profiles.google.com/104123427697898813533</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh5.googleusercontent.com/-WqHPxmC8QfM/AAAAAAAAAAI/AAAAAAAAHi4/tX9CTF-Dzy8/s512-c/photo.jpg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://lh5.googleusercontent.com/-la_QjhoPxSc/TuPoxAXVteI/AAAAAAAAH0w/MdWZ0OAcalk/s72-c/Diff.jpg" height="72" width="72" /><feedburner:origLink>http://www.beletsky.net/2011/12/approval-tests-alternative-view-on-test.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CEcMRn4yfip7ImA9WhRQEUw.&quot;"><id>tag:blogger.com,1999:blog-3980660135707078299.post-8559842918150312004</id><published>2011-12-05T21:05:00.001+02:00</published><updated>2011-12-05T21:08:07.096+02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-12-05T21:08:07.096+02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="InsideMVC" /><category scheme="http://www.blogger.com/atom/ns#" term="MVC" /><category scheme="http://www.blogger.com/atom/ns#" term="asp.net" /><title>Inside ASP.NET MVC: Instantiation of Controller</title><content type="html">&lt;p&gt;Controller are being created by &lt;code&gt;ControllerFactory&lt;/code&gt;, by default &lt;code&gt;IControllerFactory&lt;/code&gt; type is being resolved to &lt;code&gt;DefaultControllerFactory&lt;/code&gt;. Today's post is dedicated to some details of how actually &lt;code&gt;DefaultControllerFactory&lt;/code&gt; works and creates instance of required controller. Let's go from the beginning!&lt;br /&gt;
&lt;/p&gt;&lt;h2&gt;Request for controller instance&lt;/h2&gt;&lt;p&gt;Initially, we are at &lt;a href="http://www.beletsky.net/2011/06/inside-aspnet-mvc-all-begins-here.html"&gt;MvcHandler&lt;/a&gt;'s &lt;code&gt;ProcessRequestInit&lt;/code&gt; method, where we extract controllers name from RouteData and request controller factory to create corresponding controller.&lt;br /&gt;
&lt;/p&gt;&lt;pre class="brush: csharp"&gt;private void ProcessRequestInit(HttpContextBase httpContext, out IController controller, out IControllerFactory factory) {
 // If request validation has already been enabled, make it lazy. This allows attributes like [HttpPost] (which looks
 // at Request.Form) to work correctly without triggering full validation.
 bool? isRequestValidationEnabled = ValidationUtility.IsValidationEnabled(HttpContext.Current);
 if (isRequestValidationEnabled == true) {
  ValidationUtility.EnableDynamicValidation(HttpContext.Current);
 }

 AddVersionHeader(httpContext);
 RemoveOptionalRoutingParameters();

 // Get the controller type
 string controllerName = RequestContext.RouteData.GetRequiredString(&amp;quot;controller&amp;quot;);

 // Instantiate the controller and call Execute
 factory = ControllerBuilder.GetControllerFactory();
 controller = factory.CreateController(RequestContext, controllerName);
 if (controller == null) {
  throw new InvalidOperationException(
   String.Format(
    CultureInfo.CurrentCulture,
    MvcResources.ControllerBuilder_FactoryReturnedNull,
    factory.GetType(),
    controllerName));
 }
}
&lt;/pre&gt;&lt;h2&gt;DefaultControllerBuilder internals&lt;br /&gt;
&lt;/h2&gt;&lt;p&gt;&lt;code&gt;CreateController&lt;/code&gt; is rather elegant method, basically it does some arguments check's, resolve the controller type by it's name and then call to &lt;code&gt;GetControllerIntance&lt;/code&gt; to instantiate that type.&lt;br /&gt;
&lt;/p&gt;&lt;pre class="brush: csharp"&gt;public virtual IController CreateController(RequestContext requestContext, string controllerName) {
 if (requestContext == null) {
  throw new ArgumentNullException(&amp;quot;requestContext&amp;quot;);
 }
 if (String.IsNullOrEmpty(controllerName)) {
  throw new ArgumentException(MvcResources.Common_NullOrEmpty, &amp;quot;controllerName&amp;quot;);
 }
 Type controllerType = GetControllerType(requestContext, controllerName);
 IController controller = GetControllerInstance(requestContext, controllerType);
 return controller;
}
&lt;/pre&gt;&lt;h2&gt;Getting the controller type&lt;/h2&gt;&lt;p&gt;&lt;code&gt;GetControllerType&lt;/code&gt; is delegating it's call to internal &lt;code&gt;GetControllerTypeWithinNamespaces&lt;/code&gt;. It receives Route, Controller's name and Namespaces.  &lt;br /&gt;
&lt;/p&gt;&lt;pre class="brush: csharp"&gt;private Type GetControllerTypeWithinNamespaces(RouteBase route, string controllerName, HashSet&amp;lt;string&amp;gt; namespaces) {
 // Once the master list of controllers has been created we can quickly index into it
 ControllerTypeCache.EnsureInitialized(BuildManager);

 ICollection&amp;lt;Type&amp;gt; matchingTypes = ControllerTypeCache.GetControllerTypes(controllerName, namespaces);
 switch (matchingTypes.Count) {
  case 0:
   // no matching types
   return null;

  case 1:
   // single matching type
   return matchingTypes.First();

  default:
   // multiple matching types
   throw CreateAmbiguousControllerException(route, controllerName, matchingTypes);
 }
}
&lt;/pre&gt;&lt;p&gt;The namespaces parameter are quite important. If you remember, you can explicitly mention the namespace during the route definition, with overloaded MapRoute method:&lt;br /&gt;
&lt;/p&gt;&lt;pre class="brush: csharp"&gt;public static Route MapRoute(this RouteCollection routes, string name, string url, string[] namespaces) {
 return MapRoute(routes, name, url, null /* defaults */, null /* constraints */, namespaces);
}
&lt;/pre&gt;&lt;p&gt;Namespaces parameter then being stored to Route.DataTokens["Namespaces"]. Namespaces parameter matters, then you have controllers with same names. This is in particular makes sense then you have different areas.&lt;br /&gt;
&lt;/p&gt;&lt;h2&gt;Caching Controller Types&lt;/h2&gt;&lt;p&gt;The interesting thing is that framework not re-reads types for each request, that would be just to expesive, but instead it uses a cache which is initialized at the very first request and used at the life time of application. The call &lt;code&gt;ControllerTypeCache.EnsureInitialized(BuildManager);&lt;/code&gt; makes sure that cache is in actual state. How does MVC caching the types?&lt;br /&gt;
&lt;/p&gt;&lt;p&gt;Very simple and straight forward solution - in .XML file.&lt;br /&gt;
&lt;/p&gt;&lt;pre class="brush:csharp"&gt;public static List&amp;lt;Type&amp;gt; GetFilteredTypesFromAssemblies(string cacheName, Predicate&amp;lt;Type&amp;gt; predicate, IBuildManager buildManager) {
 TypeCacheSerializer serializer = new TypeCacheSerializer();

 // first, try reading from the cache on disk
 List&amp;lt;Type&amp;gt; matchingTypes = ReadTypesFromCache(cacheName, predicate, buildManager, serializer);
 if (matchingTypes != null) {
  return matchingTypes;
 }

 // if reading from the cache failed, enumerate over every assembly looking for a matching type
 matchingTypes = FilterTypesInAssemblies(buildManager, predicate).ToList();

 // finally, save the cache back to disk
 SaveTypesToCache(cacheName, matchingTypes, buildManager, serializer);

 return matchingTypes;
}
&lt;/pre&gt;&lt;p&gt;It try's read cache from file, if there are not matching types there it would try to read assemblies and then store it to cache. You might be interested where this file is actually located, so take a look:&lt;br /&gt;
&lt;/p&gt;&lt;a href="https://lh4.googleusercontent.com/-UkykIJvxzV8/Tt0WMwVDXsI/AAAAAAAAH0o/hgnCXDEYvmY/s848/code_1.jpg"&gt;&lt;br /&gt;
&lt;img src="https://lh4.googleusercontent.com/-UkykIJvxzV8/Tt0WMwVDXsI/AAAAAAAAH0o/hgnCXDEYvmY/s848/code_1.jpg" alt="cache file name" /&gt;&lt;br /&gt;
&lt;/a&gt;&lt;br /&gt;
&lt;p&gt;And for the most curious guys, here is the content:&lt;br /&gt;
&lt;/p&gt;&lt;pre class="brush: xml"&gt;&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;utf-8&amp;quot;?&amp;gt;
&amp;lt;!--This file is automatically generated. Please do not modify the contents of this file.--&amp;gt;
&amp;lt;typeCache lastModified=&amp;quot;14.10.2011 19:33:03&amp;quot; mvcVersionId=&amp;quot;aa5414f4-4d8e-4f2a-a98b-7334bf15d104&amp;quot;&amp;gt;
  &amp;lt;assembly name=&amp;quot;MvcForDebug2, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null&amp;quot;&amp;gt;
    &amp;lt;module versionId=&amp;quot;1ad99820-dc17-4be0-9f56-6dd2bdcd7950&amp;quot;&amp;gt;
      &amp;lt;type&amp;gt;MvcForDebug2.Controllers.HomeController&amp;lt;/type&amp;gt;
    &amp;lt;/module&amp;gt;
  &amp;lt;/assembly&amp;gt;
&amp;lt;/typeCache&amp;gt;
&lt;/pre&gt;&lt;p&gt;&lt;code&gt;FilterTypesInAssemblies&lt;/code&gt; method tries to get all controllers it can. What it does, it goes throught all referenced assemblies and using special predicate class matching the types. &lt;br /&gt;
&lt;/p&gt;&lt;pre class="brush:csharp"&gt;private static IEnumerable&amp;lt;Type&amp;gt; FilterTypesInAssemblies(IBuildManager buildManager, Predicate&amp;lt;Type&amp;gt; predicate) {
 // Go through all assemblies referenced by the application and search for types matching a predicate
 IEnumerable&amp;lt;Type&amp;gt; typesSoFar = Type.EmptyTypes;

 ICollection assemblies = buildManager.GetReferencedAssemblies();
 foreach (Assembly assembly in assemblies) {
  Type[] typesInAsm;
  try {
   typesInAsm = assembly.GetTypes();
  }
  catch (ReflectionTypeLoadException ex) {
   typesInAsm = ex.Types;
  }
  typesSoFar = typesSoFar.Concat(typesInAsm);
 }
 return typesSoFar.Where(type =&amp;gt; TypeIsPublicClass(type) &amp;amp;&amp;amp; predicate(type));
}
&lt;/pre&gt;&lt;p&gt;So, the last interesting thing here is the predicate that actually used:&lt;br /&gt;
&lt;/p&gt;&lt;pre class="brush:csharp"&gt;internal static bool IsControllerType(Type t) {
 return
  t != null &amp;amp;&amp;amp;
  t.IsPublic &amp;amp;&amp;amp;
  t.Name.EndsWith(&amp;quot;Controller&amp;quot;, StringComparison.OrdinalIgnoreCase) &amp;amp;&amp;amp;
  !t.IsAbstract &amp;amp;&amp;amp;
  typeof(IController).IsAssignableFrom(t);
}
&lt;/pre&gt;&lt;p&gt;You can see, it tries to match any public, ends with "Controller" not abstract and implementing &lt;code&gt;IController&lt;/code&gt; interface. That's why important do not forget to call all your controller with "Controller" suffix (yes, I did that mistake several times in the beginning of my MVC journey).&lt;br /&gt;
&lt;/p&gt;&lt;p&gt;Note, that if you have 2 controllers with same names in different namespaces, but did not provide namespace constraint you will have several &lt;code&gt;matchingTypes&lt;/code&gt;, so the &lt;code&gt;CreateAmbiguousControllerException&lt;/code&gt; will be thrown. I believe each of us seen that kind of exception at least once.&lt;br /&gt;
&lt;/p&gt;&lt;h2&gt;Instantiating the Type&lt;/h2&gt;&lt;p&gt;As we go a little back and check the code of &lt;code&gt;CreateController&lt;/code&gt;: now, we've got the type (or null if type has not been resolved). Next thing is to instantiate it. Nothing really fancy here:&lt;br /&gt;
&lt;/p&gt;&lt;pre class="brush:csharp"&gt;protected internal virtual IController GetControllerInstance(RequestContext requestContext, Type controllerType) {
 if (controllerType == null) {
  throw new HttpException(404,
   String.Format(
    CultureInfo.CurrentCulture,
    MvcResources.DefaultControllerFactory_NoControllerFound,
    requestContext.HttpContext.Request.Path));
 }
 if (!typeof(IController).IsAssignableFrom(controllerType)) {
  throw new ArgumentException(
   String.Format(
    CultureInfo.CurrentCulture,
    MvcResources.DefaultControllerFactory_TypeDoesNotSubclassControllerBase,
    controllerType),
   &amp;quot;controllerType&amp;quot;);
 }
 return ControllerActivator.Create(requestContext, controllerType);
}
&lt;/pre&gt;&lt;p&gt;If everything is all right with controller type it ask ControllerActivator to create the instance. In default case, ControllerActivator is &lt;code&gt;DefaultControllerActivator&lt;/code&gt;:&lt;br /&gt;
&lt;/p&gt;&lt;pre class="brush:csharp"&gt;public IController Create(RequestContext requestContext, Type controllerType) {
 try {
  return (IController)(_resolverThunk().GetService(controllerType) ?? Activator.CreateInstance(controllerType));
 }
 catch (Exception ex) {
  throw new InvalidOperationException(
   String.Format(
    CultureInfo.CurrentCulture,
    MvcResources.DefaultControllerFactory_ErrorCreatingController,
    controllerType),
   ex);
 }
}
&lt;/pre&gt;&lt;p&gt;As for the rest of MVC entities it would use &lt;code&gt;IDependencyResolver&lt;/code&gt; to resolve that type. &lt;code&gt;IDependecyResolved&lt;/code&gt; is detailed &lt;a href="http://www.beletsky.net/2011/10/inside-aspnet-mvc-idependencyresolver.html"&gt;here&lt;/a&gt;, but as you remember by default at the very end it calls &lt;code&gt;Activator.CreateInstance(type)&lt;/code&gt; method.&lt;br /&gt;
&lt;/p&gt;&lt;h2&gt;Conclusions&lt;/h2&gt;&lt;p&gt;New controller is instantiated on each HTTP request. The instantiation is in-directed, means first we retrieve Type, after creating Instance. The type is being searched dynamically by getting out reflection information from assemblies. To optimize the performance of ASP.NET MVC application, the internal cache of types is used. The cache is stored in file in "Temporary ASP.NET Files\root\cdd53039\36a27802\UserCache\MVC-ControllerTypeCache.xml" folder. Namespaces of controllers are matters, in case of two or more controllers has the same name but different namespaces the exception would be thrown. In case of controller type could not be resolved, the HTTP 404 response is generated. Otherwise, the controller instance would be created by &lt;code&gt;IControllerActivator&lt;/code&gt; instance.&lt;br /&gt;
&lt;/p&gt;&lt;p&gt;Previous post: &lt;a href="http://www.beletsky.net/2011/10/inside-aspnet-mvc-idependencyresolver.html"&gt;Inside ASP.NET MVC: IDependencyResolver - Service locator in MVC&lt;/a&gt;&lt;br /&gt;
&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3980660135707078299-8559842918150312004?l=www.beletsky.net' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/abeletskyblog?a=oVuPKsyMYZ0:Lkz6lr6jTC0:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/abeletskyblog?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/abeletskyblog?a=oVuPKsyMYZ0:Lkz6lr6jTC0:63t7Ie-LG7Y"&gt;&lt;img src="http://feeds.feedburner.com/~ff/abeletskyblog?d=63t7Ie-LG7Y" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/abeletskyblog?a=oVuPKsyMYZ0:Lkz6lr6jTC0:-BTjWOF_DHI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/abeletskyblog?i=oVuPKsyMYZ0:Lkz6lr6jTC0:-BTjWOF_DHI" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/abeletskyblog/~4/oVuPKsyMYZ0" height="1" width="1"/&gt;</content><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/3980660135707078299/posts/default/8559842918150312004?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/3980660135707078299/posts/default/8559842918150312004?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/abeletskyblog/~3/oVuPKsyMYZ0/inside-aspnet-mvc-instantiation-of.html" title="Inside ASP.NET MVC: Instantiation of Controller" /><author><name>Alexander Beletsky</name><uri>https://profiles.google.com/104123427697898813533</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh5.googleusercontent.com/-WqHPxmC8QfM/AAAAAAAAAAI/AAAAAAAAHi4/tX9CTF-Dzy8/s512-c/photo.jpg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://lh4.googleusercontent.com/-UkykIJvxzV8/Tt0WMwVDXsI/AAAAAAAAH0o/hgnCXDEYvmY/s72-c/code_1.jpg" height="72" width="72" /><feedburner:origLink>http://www.beletsky.net/2011/12/inside-aspnet-mvc-instantiation-of.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DUQBR34_fSp7ImA9WhRQE0s.&quot;"><id>tag:blogger.com,1999:blog-3980660135707078299.post-1983617754911678201</id><published>2011-12-03T11:52:00.001+02:00</published><updated>2011-12-08T20:02:36.045+02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-12-08T20:02:36.045+02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Mind" /><category scheme="http://www.blogger.com/atom/ns#" term="KievAltNet" /><title>Kiev ALT.NET Community Thoughts</title><content type="html">&lt;p&gt;I've just reviewed blog posts I created thought that year and realized that I miss very important piece of information here. Something that literally changed my developers life. And I'm talking about &lt;a href="http://kievalt.net/"&gt;Kiev ALT.NET&lt;/a&gt; community.&lt;br /&gt;
&lt;/p&gt;&lt;p&gt;From my first join at the beginning of the year I amazed with very cool and friendly atmosphere there. I tried to visit every meeting and each of them brought some value for me. And the most valuable asset I got there is people I met. Those guys simply rock.&lt;br /&gt;
&lt;/p&gt;&lt;a href="https://lh4.googleusercontent.com/-3_a5l569SpU/TtnvsnVAekI/AAAAAAAAH0g/gQeYOduVHZM/s512/kiev.jpg"&gt;&lt;br /&gt;
&lt;img src="https://lh4.googleusercontent.com/-3_a5l569SpU/TtnvsnVAekI/AAAAAAAAH0g/gQeYOduVHZM/s512/kiev.jpg" alt="kiev alt.net" /&gt;&lt;br /&gt;
&lt;/a&gt;&lt;br /&gt;
&lt;p&gt;&lt;a href="http://twitter.com/chaliy"&gt;Mike Chaliy&lt;/a&gt;, the leader of community does exceptional job. I could imagine how hard could it be to do all organization work and he does that very well. &lt;br /&gt;
&lt;/p&gt;&lt;p&gt;What's important, Mike involved me to do my own speech. I remember that first time when I was sharing my experience with &lt;a href="http://www.beletsky.net/2011/05/continuous-production-make-it-work.html"&gt;Continues Deployment&lt;/a&gt; based on Chuck Norris tools and Jenkins. That was a good start and I did several more speeches after. I would say it happened only because of Kiev ALT.NET.&lt;br /&gt;
&lt;/p&gt;&lt;p&gt;Getting of knowledge for me is not only books, podcasts and just coding practice. But also, discussions, questions and speeches. I this is definitely productive way of learning. &lt;br /&gt;
&lt;/p&gt;&lt;p&gt;So, I'm very thankful to Kiev ALT.NET for that positive feel of progress, pleasure of communication with smart guys and fun time of after parties.I wish a long life for community and try to help it as much as I can.&lt;br /&gt;
&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3980660135707078299-1983617754911678201?l=www.beletsky.net' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/abeletskyblog?a=mO49wKdg_yo:-8dpgXSYH78:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/abeletskyblog?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/abeletskyblog?a=mO49wKdg_yo:-8dpgXSYH78:63t7Ie-LG7Y"&gt;&lt;img src="http://feeds.feedburner.com/~ff/abeletskyblog?d=63t7Ie-LG7Y" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/abeletskyblog?a=mO49wKdg_yo:-8dpgXSYH78:-BTjWOF_DHI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/abeletskyblog?i=mO49wKdg_yo:-8dpgXSYH78:-BTjWOF_DHI" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/abeletskyblog/~4/mO49wKdg_yo" height="1" width="1"/&gt;</content><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/3980660135707078299/posts/default/1983617754911678201?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/3980660135707078299/posts/default/1983617754911678201?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/abeletskyblog/~3/mO49wKdg_yo/kiev-altnet-community-thoughts.html" title="Kiev ALT.NET Community Thoughts" /><author><name>Alexander Beletsky</name><uri>https://profiles.google.com/104123427697898813533</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh5.googleusercontent.com/-WqHPxmC8QfM/AAAAAAAAAAI/AAAAAAAAHi4/tX9CTF-Dzy8/s512-c/photo.jpg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://lh4.googleusercontent.com/-3_a5l569SpU/TtnvsnVAekI/AAAAAAAAH0g/gQeYOduVHZM/s72-c/kiev.jpg" height="72" width="72" /><feedburner:origLink>http://www.beletsky.net/2011/12/kiev-altnet-community-thoughts.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DUYCQHw_eSp7ImA9WhRQE0s.&quot;"><id>tag:blogger.com,1999:blog-3980660135707078299.post-684346956117198281</id><published>2011-11-16T18:10:00.001+02:00</published><updated>2011-12-08T19:59:21.241+02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-12-08T19:59:21.241+02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="TDD" /><title>Develop With Tests</title><content type="html">&lt;p&gt;I've been recently thinking about my TDD and I came to interesting conclusion.  I'm not TDD practitioner any more!&lt;br /&gt;
&lt;/p&gt;&lt;p&gt;TDD is quite strict  practice, it suppose you following certain rules. The main rule is test first. You create test, you create code after. For years I've been using that practice as dogma. I've seen a lot of value with such approach and that worked for me really much. &lt;br /&gt;
&lt;/p&gt;&lt;p&gt;Do you use that rules now? Not always.. Do you use something different than TDD? Yes, I do &lt;strong&gt;develop with tests&lt;/strong&gt;.&lt;br /&gt;
&lt;/p&gt;&lt;p&gt;See, TDD main power is not in tests itself. The power of TDD is Test Driven Design. This is design that makes code more readable and maintainable. Tests of cause helps regression and general quality, but it is not always the truth. As long as you practice TDD much you feel how designed for tests code should look like. You do not need to create test to prove that code is testable. Following very simple rules you simply guarantee that tests are possible here. &lt;br /&gt;
&lt;/p&gt;&lt;p&gt;Now, I simply optimize the process a bit. I could skip first step and go ahead for code. That does not mean I'm skipping test. No, I'll create there I feel it necessary.. And I feel that mostly to all code I create. But this is no longer TDD, I call that develop with tests. DWT as you want ;)&lt;br /&gt;
&lt;/p&gt;&lt;a href="https://lh3.googleusercontent.com/-wRTF3X1cJm0/TsPgJH6ryEI/AAAAAAAAH0M/H51scOr_Gf8/s620/dwt.jpg"&gt;&lt;br /&gt;
&lt;img src="https://lh3.googleusercontent.com/-wRTF3X1cJm0/TsPgJH6ryEI/AAAAAAAAH0M/H51scOr_Gf8/s620/dwt.jpg" alt="develop with tests" /&gt;&lt;br /&gt;
&lt;/a&gt;&lt;br /&gt;
&lt;p&gt;I think a some developers might say, "Oh, I'm using DWT as well". Others will say, "I will use DWT since TDD is boring and requires too much time". Please do not do that. I strongly believe that is TDD that could make you stronger as developers and your code robust and good looking. So follow the rules before you absolutely sure, you ready to break them.&lt;br /&gt;
&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3980660135707078299-684346956117198281?l=www.beletsky.net' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/abeletskyblog?a=tK0z173rwj8:lmvLryKubBY:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/abeletskyblog?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/abeletskyblog?a=tK0z173rwj8:lmvLryKubBY:63t7Ie-LG7Y"&gt;&lt;img src="http://feeds.feedburner.com/~ff/abeletskyblog?d=63t7Ie-LG7Y" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/abeletskyblog?a=tK0z173rwj8:lmvLryKubBY:-BTjWOF_DHI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/abeletskyblog?i=tK0z173rwj8:lmvLryKubBY:-BTjWOF_DHI" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/abeletskyblog/~4/tK0z173rwj8" height="1" width="1"/&gt;</content><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/3980660135707078299/posts/default/684346956117198281?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/3980660135707078299/posts/default/684346956117198281?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/abeletskyblog/~3/tK0z173rwj8/develop-with-tests.html" title="Develop With Tests" /><author><name>Alexander Beletsky</name><uri>https://profiles.google.com/104123427697898813533</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh5.googleusercontent.com/-WqHPxmC8QfM/AAAAAAAAAAI/AAAAAAAAHi4/tX9CTF-Dzy8/s512-c/photo.jpg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://lh3.googleusercontent.com/-wRTF3X1cJm0/TsPgJH6ryEI/AAAAAAAAH0M/H51scOr_Gf8/s72-c/dwt.jpg" height="72" width="72" /><feedburner:origLink>http://www.beletsky.net/2011/11/develop-with-tests.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DUYDQnY7cSp7ImA9WhRQE0s.&quot;"><id>tag:blogger.com,1999:blog-3980660135707078299.post-6361158427351900418</id><published>2011-11-14T10:10:00.001+02:00</published><updated>2011-12-08T19:59:33.809+02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-12-08T19:59:33.809+02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Mind" /><title>It's Writing Time</title><content type="html">&lt;p&gt;There are great series of stories called &lt;a href="http://en.wikipedia.org/wiki/Azazel_(Asimov)"&gt;"Azazel"&lt;/a&gt; by &lt;a href="http://en.wikipedia.org/wiki/Isaac_Asimov"&gt;Isaac Asimov&lt;/a&gt;. They are about 2 cm demon named Azazel and George, guy who is able to talk to him. Azazel knows actually nothing about demons or angels, hell or haven.. But he understands the nature of things able to change them. The stories are short and fun and smart, so I would recommend it to read.&lt;br /&gt;
&lt;/p&gt;&lt;p&gt;In particular, there is one great story called "Writing time". It's about the man whose name is Mordehai and he is writer. He has a great issue. He always need to wait for something, like wait for doctors, waiters, cab drivers, wait in a shop lines etc. Mordehai treated that time as completely wasted, because he could not spent it for job.&lt;br /&gt;
&lt;/p&gt;&lt;p&gt;He shared that problem with George. George asked Azazel if it's possible to help to poor Mordehai. As always Azazel was angry about peoples misery, but agreed to help. He could introduce change that make it possible to Mordehai never need to wait for somebody. That change required a little cost, literally the sun will stop shining in 2 million years earlier, but who cares.&lt;br /&gt;
&lt;/p&gt;&lt;p&gt;George met Mordehai again in several month. For his great disappointment, writer created simply nothing in that time! Not even a small story. Instead of being hyper productive he became non productive at all.&lt;br /&gt;
&lt;/p&gt;&lt;p&gt;How could it be, that person who spend all his time for work are not able to do the work? As Mordehai understood as he sat behind his type writer - he had no ideas. Simply, he don't know what to write about. &lt;br /&gt;
&lt;/p&gt;&lt;p&gt;As it turned out all that time he waited actually spent for thinking. It was absolutely not a waste for him, otherwise it was the most productive time.. But he did not realized that before. Unfortunately, Mordehai's career totally ruined. &lt;br /&gt;
&lt;/p&gt;&lt;p&gt;You know what? I think that I'm wasting the time instead of doing "cool things". I work as hard as I can, but the results aren't impressive. I neither could find good idea nor have good rest recently - I'm exactly like Mordehai who blames waiting line for his problems.&lt;br /&gt;
&lt;/p&gt;&lt;p&gt;I'll try not to repeat this issue. Having a rest, spending time with family or sport activities are equally important as job (perhaps even more important). And even if you are "doing nothing", something is still going on your head. If inputs are right, outputs will be right as well.. Sooner or later.&lt;br /&gt;
&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3980660135707078299-6361158427351900418?l=www.beletsky.net' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/abeletskyblog?a=ndrBIV9v4-8:wlppYSit0u8:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/abeletskyblog?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/abeletskyblog?a=ndrBIV9v4-8:wlppYSit0u8:63t7Ie-LG7Y"&gt;&lt;img src="http://feeds.feedburner.com/~ff/abeletskyblog?d=63t7Ie-LG7Y" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/abeletskyblog?a=ndrBIV9v4-8:wlppYSit0u8:-BTjWOF_DHI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/abeletskyblog?i=ndrBIV9v4-8:wlppYSit0u8:-BTjWOF_DHI" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/abeletskyblog/~4/ndrBIV9v4-8" height="1" width="1"/&gt;</content><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/3980660135707078299/posts/default/6361158427351900418?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/3980660135707078299/posts/default/6361158427351900418?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/abeletskyblog/~3/ndrBIV9v4-8/its-writing-time.html" title="It's Writing Time" /><author><name>Alexander Beletsky</name><uri>https://profiles.google.com/104123427697898813533</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh5.googleusercontent.com/-WqHPxmC8QfM/AAAAAAAAAAI/AAAAAAAAHi4/tX9CTF-Dzy8/s512-c/photo.jpg" /></author><feedburner:origLink>http://www.beletsky.net/2011/11/its-writing-time.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DEIHRXg_cCp7ImA9WhRSEU8.&quot;"><id>tag:blogger.com,1999:blog-3980660135707078299.post-4253576904542004728</id><published>2011-11-12T21:34:00.001+02:00</published><updated>2011-11-12T21:35:34.648+02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-11-12T21:35:34.648+02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Life" /><title>Sayonara Nippon</title><content type="html">&lt;p&gt;I've just got back from the most wonderful country I ever been to - Japan. &lt;br /&gt;
&lt;/p&gt;&lt;a href="https://lh5.googleusercontent.com/-JQHNK-xBJqE/Tr7JuF_SRNI/AAAAAAAAHzk/UsxHzEvgek8/s620/Gates.jpg?gl=UA"&gt;&lt;br /&gt;
&lt;img src="https://lh5.googleusercontent.com/-JQHNK-xBJqE/Tr7JuF_SRNI/AAAAAAAAHzk/UsxHzEvgek8/s620/Gates.jpg?gl=UA" alt="japan gates" /&gt;&lt;br /&gt;
&lt;/a&gt;&lt;br /&gt;
&lt;p&gt;Japan is really different from everything I got used to. Differences are everywhere, from traffic direction to people behavior. But in general Japan is well developed, high cultural country with interesting history.&lt;br /&gt;
&lt;/p&gt;&lt;p&gt;Tokyo is huge, but the same is &lt;a href="http://www.tokyometro.jp/en/"&gt;Tokyo Metropolitan&lt;/a&gt; which is really complex, but makes travel from one part of city to another very fast. First day we have a lot of problems to understand metropolitan labyrinths, but with a little practice it does not look so scary anymore. Btw, I've never seen very over crowded stations and trains, even if you travel in rush hour. Comparing to Kyiv metro, Tokyo one is very expensive, where you pay as much as you go.  &lt;br /&gt;
&lt;/p&gt;&lt;a href="https://lh4.googleusercontent.com/-MSLfarHSstA/Tr7Jv5PqImI/AAAAAAAAHzs/nSskJV4W5Ac/s620/metro.JPG?gl=UA"&gt;&lt;br /&gt;
&lt;img src="https://lh4.googleusercontent.com/-MSLfarHSstA/Tr7Jv5PqImI/AAAAAAAAHzs/nSskJV4W5Ac/s620/metro.JPG?gl=UA" alt="tokyo metropolitan" /&gt;&lt;br /&gt;
&lt;/a&gt;&lt;br /&gt;
&lt;p&gt;People there are very kind, ready to help you. But the problem is communication. Very few Japanese can speak English. Usual dialog is something like. "Do you speak English?", "A little.." and then nothing, even if you try to use as elementary words as possible. So, language barrier is very high. But as soon as they understood your problem, be sure you gonna get help. Once we've lost in metropolitan and one lady went out from station with ask, contacted metropolitan officer and explained our further actions. Such scenario happened several times.&lt;br /&gt;
&lt;/p&gt;&lt;a href="https://lh6.googleusercontent.com/-Yzz0uvSJ0Rc/Tr7JtvG9fkI/AAAAAAAAHzc/Vh8w20Qfjbc/s620/food.JPG?gl=UA"&gt;&lt;br /&gt;
&lt;img src="https://lh6.googleusercontent.com/-Yzz0uvSJ0Rc/Tr7JtvG9fkI/AAAAAAAAHzc/Vh8w20Qfjbc/s620/food.JPG?gl=UA" alt="noodles" /&gt;&lt;br /&gt;
&lt;/a&gt;&lt;br /&gt;
&lt;p&gt;Food is very delicious and relatively not expensive. Chinese and Japanese dishes are usually available together in restaurants. But if you want to go with sushi, you have to find specialized one. There are absolutely not a problem to eat in Tokyo. In each corner you could find small restaurants and cafeterias where you will be able to find what you like. Food is available mostly everywhere, including metro stations.     &lt;br /&gt;
&lt;/p&gt;&lt;a href="https://lh6.googleusercontent.com/-oPJTvUilLkA/Tr7JxUvajTI/AAAAAAAAHz0/ipwdXzxSFcE/s620/tree.JPG?gl=UA"&gt;&lt;br /&gt;
&lt;img src="https://lh6.googleusercontent.com/-oPJTvUilLkA/Tr7JxUvajTI/AAAAAAAAHz0/ipwdXzxSFcE/s620/tree.JPG?gl=UA" alt="tokyo park" /&gt;&lt;br /&gt;
&lt;/a&gt;&lt;br /&gt;
&lt;p&gt;Tokyo is concrete and wires jungle, but there are several great parks inside. They are beauty and calm. It is easy to find a bench to sit and observe spectacular views. It is great to relax body and mind there.&lt;br /&gt;
&lt;/p&gt;&lt;p&gt;I would not say I've seen a lot, but I really enjoyed with everything I saw. &lt;br /&gt;
&lt;/p&gt;&lt;p&gt;Sayonara Nippon! Hope to visit you again in a while.. Best luck to you!&lt;br /&gt;
&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3980660135707078299-4253576904542004728?l=www.beletsky.net' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/abeletskyblog?a=ev7URPdGV2w:rc2ZxknDfQc:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/abeletskyblog?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/abeletskyblog?a=ev7URPdGV2w:rc2ZxknDfQc:63t7Ie-LG7Y"&gt;&lt;img src="http://feeds.feedburner.com/~ff/abeletskyblog?d=63t7Ie-LG7Y" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/abeletskyblog?a=ev7URPdGV2w:rc2ZxknDfQc:-BTjWOF_DHI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/abeletskyblog?i=ev7URPdGV2w:rc2ZxknDfQc:-BTjWOF_DHI" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/abeletskyblog/~4/ev7URPdGV2w" height="1" width="1"/&gt;</content><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/3980660135707078299/posts/default/4253576904542004728?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/3980660135707078299/posts/default/4253576904542004728?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/abeletskyblog/~3/ev7URPdGV2w/sayonara-nippon.html" title="Sayonara Nippon" /><author><name>Alexander Beletsky</name><uri>https://profiles.google.com/104123427697898813533</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh5.googleusercontent.com/-WqHPxmC8QfM/AAAAAAAAAAI/AAAAAAAAHi4/tX9CTF-Dzy8/s512-c/photo.jpg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://lh5.googleusercontent.com/-JQHNK-xBJqE/Tr7JuF_SRNI/AAAAAAAAHzk/UsxHzEvgek8/s72-c/Gates.jpg?gl=UA" height="72" width="72" /><feedburner:origLink>http://www.beletsky.net/2011/11/sayonara-nippon.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DUYNRXozfSp7ImA9WhRQE0s.&quot;"><id>tag:blogger.com,1999:blog-3980660135707078299.post-7394902221507301301</id><published>2011-10-31T16:42:00.000+02:00</published><updated>2011-12-08T19:59:54.485+02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-12-08T19:59:54.485+02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="MVC" /><category scheme="http://www.blogger.com/atom/ns#" term="asp.net" /><title>Using Ninject.MVC For Better ASP.NET MVC Integration</title><content type="html">&lt;p&gt;After the ASP.NET MVC infrastructure is &lt;a href="http://www.beletsky.net/2011/10/integrating-aspnet-mvc-into-legacy-web.html"&gt;ready&lt;/a&gt;, next logical step it to setup IoC container for application. Ninject setup is easy task, usually you solve that by implementation of your own &lt;a href="http://www.beletsky.net/2011/07/inside-aspnet-mvc-controllerbuilder.html"&gt;ControllerFactory&lt;/a&gt; and put it to &lt;a href="http://www.beletsky.net/2011/07/inside-aspnet-mvc-controllerbuilder.html"&gt;ControllerBuilder&lt;/a&gt;. As soon it is good enough approach it does not solve some important MVC implications, like injection of prosperities into filters. To make our lives a little easier Ninject team released &lt;a href="https://github.com/ninject/ninject.web.mvc"&gt;Ninject.Web.MVC&lt;/a&gt; extension library that solves a lot of similar problems.&lt;br /&gt;
&lt;/p&gt;&lt;h2&gt;Getting binaries&lt;/h2&gt;&lt;p&gt;Just follow the github to &lt;a href="https://github.com/ninject/ninject.web.mvc/downloads"&gt;download&lt;/a&gt; latest version of Ninject.Web.MVC and place it to web site &lt;code&gt;/Bin&lt;/code&gt; directory. No changes to &lt;code&gt;web.config&lt;/code&gt; or something.&lt;br /&gt;
&lt;/p&gt;&lt;h2&gt;Tweaking global.asax&lt;/h2&gt;&lt;p&gt;Now, let's change &lt;code&gt;global.asax&lt;/code&gt; according to Ninject.Web.MVC guidelines. I'll just show how my current &lt;code&gt;global.aspx&lt;/code&gt; looks like:&lt;br /&gt;
&lt;/p&gt;&lt;pre class="brush: xml"&gt;&amp;lt;%@ Application Language='C#' Inherits=&amp;quot;Ninject.Web.Mvc.NinjectHttpApplication&amp;quot; %&amp;gt;
&amp;lt;%@ Import Namespace=&amp;quot;Ninject&amp;quot; %&amp;gt;

&amp;lt;script RunAt=&amp;quot;server&amp;quot;&amp;gt;
 public void Application_Start()
 {

 }

 protected override void OnApplicationStarted()
 {
  AreaRegistration.RegisterAllAreas();
 }
 
 protected override IKernel CreateKernel()
 {
  var kernel = new StandardKernel();
  Sba.Web.Infrastructure.RegisterServices.For(kernel);
  
  return kernel;
 }

 public void Application_End()
 {
 }

 public void Application_Error(object sender, EventArgs args)
 {
 }
&amp;lt;/script&amp;gt;
&lt;/pre&gt;&lt;p&gt;So, we basically inherit from &lt;code&gt;NinjectHttpApplication&lt;/code&gt; class and override &lt;code&gt;CreateKernel()&lt;/code&gt; method. You can see that inside the method I do call to &lt;code&gt;RegisterServices&lt;/code&gt; - it is nothing more as static class, with &lt;code&gt;For&lt;/code&gt; method that actually do the registration. Here is example:&lt;br /&gt;
&lt;/p&gt;&lt;pre class="brush: csharp"&gt;using Ninject;
using Ninject.Web.Mvc;
using Sba.Common.Repositories;
using Sba.Sales.Models;
using Sba.Sales.Repositories;
using Sba.Sales.Repositories.ViewHandlerRepositories;

namespace Sba.Web.Infrastructure
{
 public class RegisterServices
 {
  public static void For(IKernel kernel)
  {
   kernel.Bind&amp;lt;ISessionLoader&amp;gt;().To&amp;lt;LazySessionLoader&amp;gt;();
   kernel.Bind&amp;lt;ILazyLoadChecker&amp;gt;().To&amp;lt;NHibernateLazyLoadChecker&amp;gt;();
   kernel.Bind&amp;lt;IDraftInvoicesRepository&amp;gt;().To&amp;lt;DraftInvoicesRepository&amp;gt;();
   kernel.Bind&amp;lt;IDraftInvoiceLinesRepository&amp;gt;().To&amp;lt;DraftInvoiceLinesRepository&amp;gt;();
   kernel.Bind&amp;lt;IPaymentTermsRepository&amp;gt;().To&amp;lt;PaymentTermsRepository&amp;gt;();
   kernel.Bind&amp;lt;IUnitsRepository&amp;gt;().To&amp;lt;UnitsRepository&amp;gt;();
   kernel.Bind&amp;lt;ICustomersRepository&amp;gt;().To&amp;lt;CustomersRepository&amp;gt;();
  }
 }
}
&lt;/pre&gt;&lt;h2&gt;Injection the properties into filters&lt;/h2&gt;&lt;p&gt;The main advantage of &lt;code&gt;NinjectHttpApplication&lt;/code&gt; class usage, that now it handles the injection in different MVC entities by itself. For instance if you need inject to filter:&lt;br /&gt;
&lt;/p&gt;&lt;pre class="brush: csharp"&gt;using System.Web.Mvc;
using Ninject;
using Economic2.Core;
using Sba.Common.Repositories;

namespace Sba.Common.Infrastructure.Filters
{
 public class SbaAuthorizeAttribute : AuthorizeAttribute
 {
  [Inject]
  public ISessionLoader SessionLoader { get; set; }

  public override void OnAuthorization(AuthorizationContext filterContext)
  {
            // some authorization logic here..
  }
 }
}
&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3980660135707078299-7394902221507301301?l=www.beletsky.net' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/abeletskyblog?a=Y-1ZPnhrwtc:hs1fCHHI18E:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/abeletskyblog?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/abeletskyblog?a=Y-1ZPnhrwtc:hs1fCHHI18E:63t7Ie-LG7Y"&gt;&lt;img src="http://feeds.feedburner.com/~ff/abeletskyblog?d=63t7Ie-LG7Y" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/abeletskyblog?a=Y-1ZPnhrwtc:hs1fCHHI18E:-BTjWOF_DHI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/abeletskyblog?i=Y-1ZPnhrwtc:hs1fCHHI18E:-BTjWOF_DHI" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/abeletskyblog/~4/Y-1ZPnhrwtc" height="1" width="1"/&gt;</content><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/3980660135707078299/posts/default/7394902221507301301?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/3980660135707078299/posts/default/7394902221507301301?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/abeletskyblog/~3/Y-1ZPnhrwtc/using-ninjectmvc-for-better-aspnet-mvc.html" title="Using Ninject.MVC For Better ASP.NET MVC Integration" /><author><name>Alexander Beletsky</name><uri>https://profiles.google.com/104123427697898813533</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh5.googleusercontent.com/-WqHPxmC8QfM/AAAAAAAAAAI/AAAAAAAAHi4/tX9CTF-Dzy8/s512-c/photo.jpg" /></author><feedburner:origLink>http://www.beletsky.net/2011/10/using-ninjectmvc-for-better-aspnet-mvc.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DUUFRHc7eyp7ImA9WhRQE0s.&quot;"><id>tag:blogger.com,1999:blog-3980660135707078299.post-9013691678718608510</id><published>2011-10-30T09:05:00.000+02:00</published><updated>2011-12-08T20:00:15.903+02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-12-08T20:00:15.903+02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="MVC" /><category scheme="http://www.blogger.com/atom/ns#" term="Tips" /><category scheme="http://www.blogger.com/atom/ns#" term="asp.net" /><title>Integrating ASP.NET MVC Into Legacy Web Site</title><content type="html">&lt;p&gt;For some quite long time I naively thought that it is not possible (or at least very difficult) to make ASP.NET MVC stuff work on a Web Site project. But, my latest &lt;a href="http://www.beletsky.net/search/label/InsideMVC"&gt;hacking of MVC&lt;/a&gt; opened another perspectives. There are no any difficulties with ASP.NET MVC on Web Sites. I'll share an experience of integration ASP.NET MVC in my work project legacy Web Site.&lt;br /&gt;
&lt;/p&gt;&lt;h2&gt;Pre-conditions&lt;/h2&gt;&lt;p&gt;In my case I integrated ASP.NET MVC2, since we are still running on .NET 3.5. If you are running .NET 4.0 the best is to go with ASP.NET MVC3 already. The difference of setup would not be huge, just in proper versions of assemblies.&lt;br /&gt;
&lt;/p&gt;&lt;p&gt;I assume you already have ASP.NET MVC2 framework on your machine (if you have VS2010 - you definitely have one), if no just go that &lt;a href="http://www.microsoft.com/download/en/details.aspx?displaylang=en&amp;id=22079"&gt;link&lt;/a&gt; and install it.&lt;br /&gt;
&lt;/p&gt;&lt;h2&gt;Web config changes&lt;/h2&gt;&lt;p&gt;MVC assembly have to be added to &lt;code&gt;web.config&lt;/code&gt;. Since the MVC infrastructure heavily depends on Routing mode, it have to be put to &lt;code&gt;web.config&lt;/code&gt; as well.&lt;br /&gt;
&lt;/p&gt;&lt;p&gt;Register MVC assemblies:&lt;br /&gt;
&lt;/p&gt;&lt;pre class="brush: xml"&gt;&amp;lt;compilation defaultLanguage=&amp;quot;c#&amp;quot; debug=&amp;quot;true&amp;quot;&amp;gt;
 &amp;lt;assemblies&amp;gt;
  &amp;lt;add assembly=&amp;quot;System.Core, Version=3.5.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089&amp;quot;/&amp;gt;
  &amp;lt;add assembly=&amp;quot;System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35&amp;quot;/&amp;gt;
  &amp;lt;add assembly=&amp;quot;System.Data.DataSetExtensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089&amp;quot;/&amp;gt;
  &amp;lt;add assembly=&amp;quot;System.Xml.Linq, Version=3.5.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089&amp;quot;/&amp;gt;
  &amp;lt;add assembly=&amp;quot;System.Design, Version=2.0.0.0, Culture=neutral, PublicKeyToken=B03F5F7F11D50A3A&amp;quot;/&amp;gt;

  &amp;lt;!-- Your application specific assemblies--&amp;gt;
        ...

  &amp;lt;!-- ASP.NET MVC --&amp;gt;
  &amp;lt;add assembly=&amp;quot;System.Web.Abstractions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35&amp;quot;/&amp;gt;
  &amp;lt;add assembly=&amp;quot;System.Web.Routing, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35&amp;quot;/&amp;gt;
  &amp;lt;add assembly=&amp;quot;System.Web.Mvc, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35&amp;quot;/&amp;gt;
 &amp;lt;/assemblies&amp;gt;
&amp;lt;/compilation&amp;gt;
&lt;/pre&gt;&lt;p&gt;Namespaces:&lt;br /&gt;
&lt;/p&gt;&lt;pre class="brush: xml"&gt;&amp;lt;pages enableViewStateMac=&amp;quot;false&amp;quot; enableViewState=&amp;quot;false&amp;quot; validateRequest=&amp;quot;true&amp;quot; viewStateEncryptionMode=&amp;quot;Never&amp;quot;&amp;gt;
  &amp;lt;controls&amp;gt;
    &amp;lt;add tagPrefix=&amp;quot;asp&amp;quot; namespace=&amp;quot;System.Web.UI&amp;quot; assembly=&amp;quot;System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35&amp;quot;/&amp;gt;
    &amp;lt;add tagPrefix=&amp;quot;asp&amp;quot; namespace=&amp;quot;System.Web.UI.WebControls&amp;quot; assembly=&amp;quot;System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35&amp;quot;/&amp;gt;
  &amp;lt;/controls&amp;gt;
  
  &amp;lt;-- ASP.NET MVC --&amp;gt;
  &amp;lt;namespaces&amp;gt;
    &amp;lt;add namespace=&amp;quot;System.Web.Mvc&amp;quot;/&amp;gt;
    &amp;lt;add namespace=&amp;quot;System.Web.Mvc.Ajax&amp;quot;/&amp;gt;
    &amp;lt;add namespace=&amp;quot;System.Web.Mvc.Html&amp;quot;/&amp;gt;
    &amp;lt;add namespace=&amp;quot;System.Web.Routing&amp;quot;/&amp;gt;
    &amp;lt;add namespace=&amp;quot;System.Linq&amp;quot;/&amp;gt;
    &amp;lt;add namespace=&amp;quot;System.Collections.Generic&amp;quot;/&amp;gt;
    &amp;lt;add namespace=&amp;quot;Microsoft.Web.Mvc&amp;quot;/&amp;gt;
  &amp;lt;/namespaces&amp;gt;
&amp;lt;/pages&amp;gt;
&lt;/pre&gt;&lt;p&gt;Register URLRouting module and handler.&lt;br /&gt;
&lt;/p&gt;&lt;pre class="brush: xml"&gt;&amp;lt;system.webServer&amp;gt;
  &amp;lt;validation validateIntegratedModeConfiguration=&amp;quot;false&amp;quot;/&amp;gt;
  &amp;lt;modules&amp;gt;
 ...
 
 &amp;lt;!-- ASP.NET MVC --&amp;gt;
    &amp;lt;add name=&amp;quot;UrlRoutingModule&amp;quot; type=&amp;quot;System.Web.Routing.UrlRoutingModule, System.Web.Routing, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35&amp;quot; /&amp;gt;
  &amp;lt;/modules&amp;gt;
  &amp;lt;handlers&amp;gt;
    ...
 
 &amp;lt;!-- ASP.NET MVC --&amp;gt;
    &amp;lt;add name=&amp;quot;UrlRoutingHandler&amp;quot; preCondition=&amp;quot;integratedMode&amp;quot; verb=&amp;quot;*&amp;quot; path=&amp;quot;UrlRouting.axd&amp;quot; type=&amp;quot;System.Web.HttpForbiddenHandler, System.Web, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a&amp;quot; /&amp;gt;
  &amp;lt;/handlers&amp;gt;
&amp;lt;/system.webServer&amp;gt;
&lt;/pre&gt;&lt;h2&gt;Global.asax changes&lt;/h2&gt;&lt;p&gt;You would be probably have &lt;code&gt;global.asax&lt;/code&gt; without code-behind class. It's not a problem, all you need is slightly change the &lt;code&gt;Application_Start()&lt;/code&gt; method. Basically you can go and register routes there, as you do in any ASP.NET MVC application. But I didn't do that. Instead, I used the advantages of &lt;a href="http://msdn.microsoft.com/en-us/library/ee671793.aspx"&gt;Areas&lt;/a&gt; feature of MVC2, since it makes better logical grouping. So, my &lt;code&gt;global.asax&lt;/code&gt; are:&lt;br /&gt;
&lt;/p&gt;&lt;pre class="brush: csharp"&gt;public void Application_Start()
{
 AreaRegistration.RegisterAllAreas();
}
&lt;/pre&gt;&lt;h2&gt;Models, Views, Controllers&lt;/h2&gt;&lt;p&gt;In typical ASP.NET MVC application you have 3 folders, for - Models, Views, Controllers. Models/Controllers are C# code, views are .aspx pages. With a Web Site you typically place code into &lt;code&gt;App_Code&lt;/code&gt; folder. But you should not do that. Instead, it it better to create a separate class library project that would hold your models and controllers. Views would be placed under corresponding Area folder.&lt;br /&gt;
&lt;/p&gt;&lt;h2&gt;New project for Models/Controllers&lt;/h2&gt;&lt;p&gt;Just create a new class library project with such folder structure:&lt;br /&gt;
&lt;/p&gt;&lt;a href="https://lh4.googleusercontent.com/-ny77OywB_Pk/Tqz2RrcVfCI/AAAAAAAAHnM/P2Awn0D79zc/s391/img-1.png"&gt;&lt;br /&gt;
&lt;img src="https://lh4.googleusercontent.com/-ny77OywB_Pk/Tqz2RrcVfCI/AAAAAAAAHnM/P2Awn0D79zc/s391/img-1.png" alt="asp.net mvc class library" /&gt;&lt;br /&gt;
&lt;/a&gt;&lt;br /&gt;
&lt;p&gt;The most important - it should contain Area Registration class inside. This is the one that suppose to register all router for your application:&lt;br /&gt;
&lt;/p&gt;&lt;pre class="brush: csharp"&gt;using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web.Mvc;

namespace Sba.Web.Areas.Sales
{
 public class SalesAreaRegistration : AreaRegistration 
 {
  public override string AreaName
  {
   get 
   {
    return "Sales";
   }
  }

  public override void RegisterArea(AreaRegistrationContext context)
  {
            // All routes are here..

   context.MapRoute(
    "Sba_Sales",
    "sba/sales/{controller}/{action}/{id}",
    new { controller = "Home", action = "Index", id = UrlParameter.Optional }
   );
  }
 }
}
&lt;/pre&gt;&lt;p&gt;That's it. Now you implement Controller/Models in usual way and able to add unit tests project for new assembly.&lt;br /&gt;
&lt;/p&gt;&lt;p&gt;Make sure that assembly will be placed into to Web Site &lt;code&gt;/Bin&lt;/code&gt; folder. I simply added &lt;code&gt;../Site/Bin&lt;/code&gt; as project output directory. At the site initialization and &lt;code&gt;Application_Start()&lt;/code&gt; call of Global.asax, all &lt;code&gt;AreaRegistration&lt;/code&gt; instances would be created and routes being registered.&lt;br /&gt;
&lt;/p&gt;&lt;h2&gt;Views&lt;/h2&gt;&lt;p&gt;Views have to be placed in the Web Site folder itself. MVC has several rules for views placements, so you have to follow them. Views for controllers that are part of Area's have to be places into &lt;code&gt;Site/Areas/AreaName/Views&lt;/code&gt;, the common stuff line master pages are in &lt;code&gt;Site/Views/Shared&lt;/code&gt;. It is very important that each View folder must contain the &lt;code&gt;web.config&lt;/code&gt; inside. You can either pick it up from default MVC2 application of just grab from &lt;a href="https://gist.github.com/1325577"&gt;gist&lt;/a&gt;.&lt;br /&gt;
&lt;/p&gt;&lt;a href="https://lh3.googleusercontent.com/-1oPOjbGMkIA/Tqz2Rs4oS6I/AAAAAAAAHnE/_jP0yI97UZg/s313/img-3.png"&gt;&lt;br /&gt;
&lt;img src="https://lh3.googleusercontent.com/-1oPOjbGMkIA/Tqz2Rs4oS6I/AAAAAAAAHnE/_jP0yI97UZg/s313/img-3.png" alt="views folder structure" /&gt;&lt;br /&gt;
&lt;/a&gt;&lt;br /&gt;
&lt;h2&gt;IIS configuration&lt;/h2&gt;&lt;p&gt;Our application previously worked in "Classic" mode. Even thought, it is possible to run MVC on "Classic" I would not really recommend it to do and if production environment allows, just switch you application pool to "Integrated mode".   &lt;br /&gt;
&lt;/p&gt;&lt;a href="https://lh6.googleusercontent.com/-cgYuQPO2v3o/Tqz2Rho34dI/AAAAAAAAHnI/jP_SfDVxFcY/s349/img-2.png"&gt;&lt;br /&gt;
&lt;img src="https://lh6.googleusercontent.com/-cgYuQPO2v3o/Tqz2Rho34dI/AAAAAAAAHnI/jP_SfDVxFcY/s349/img-2.png" alt="iis application pool config" /&gt;&lt;br /&gt;
&lt;/a&gt;&lt;br /&gt;
&lt;p&gt;After you did it, you can go and run you application. If you setup basic Home controller and view, you should be able to access it by given route. If you receiving 403 HTTP error check:&lt;br /&gt;
&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Are you really on integrated mode?&lt;/li&gt;
&lt;li&gt;Are there any physical folders that the same as you routing, e.g /sba/sales route and /site/sba/sales folder? In such case you either should correct the routing or change site folder structure.&lt;/li&gt;
&lt;/ul&gt;&lt;h2&gt;Session is Null issue&lt;/h2&gt;&lt;p&gt;Moving along and starting implementation of some real controllers, we've got very strange &lt;code&gt;NullReferenceException&lt;/code&gt; problem. After bit debugging it turned out that &lt;code&gt;HttpContext.Current.Session&lt;/code&gt; is null in controller actions. That's the common problem for legacy web sites. It is very well described in this &lt;a href="http://stackoverflow.com/questions/218057/httpcontext-current-session-is-null-when-routing-requests"&gt;stackoverflow&lt;/a&gt; answer. So, you just need to add one more section into &lt;code&gt;web.config&lt;/code&gt; file.&lt;br /&gt;
&lt;/p&gt;&lt;pre class="brush: xml"&gt;&amp;lt;configuration&amp;gt;
  ...
  &amp;lt;system.webServer&amp;gt;
    ...
    &amp;lt;modules&amp;gt;
      &amp;lt;remove name=&amp;quot;Session&amp;quot; /&amp;gt;
      &amp;lt;add name=&amp;quot;Session&amp;quot; type=&amp;quot;System.Web.SessionState.SessionStateModule&amp;quot;/&amp;gt;
      ...
    &amp;lt;/modules&amp;gt;
  &amp;lt;/system.webServer&amp;gt;
&amp;lt;/configuration&amp;gt;
&lt;/pre&gt;&lt;p&gt;After all of those configuration changes your Web Site is fully adopted to ASP.NET MVC framework usage. So, just go ahead and feel the awesomeness of MVC!&lt;br /&gt;
&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3980660135707078299-9013691678718608510?l=www.beletsky.net' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/abeletskyblog?a=PEDNfV8ZLZ0:Li7qjQc-NjY:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/abeletskyblog?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/abeletskyblog?a=PEDNfV8ZLZ0:Li7qjQc-NjY:63t7Ie-LG7Y"&gt;&lt;img src="http://feeds.feedburner.com/~ff/abeletskyblog?d=63t7Ie-LG7Y" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/abeletskyblog?a=PEDNfV8ZLZ0:Li7qjQc-NjY:-BTjWOF_DHI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/abeletskyblog?i=PEDNfV8ZLZ0:Li7qjQc-NjY:-BTjWOF_DHI" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/abeletskyblog/~4/PEDNfV8ZLZ0" height="1" width="1"/&gt;</content><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/3980660135707078299/posts/default/9013691678718608510?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/3980660135707078299/posts/default/9013691678718608510?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/abeletskyblog/~3/PEDNfV8ZLZ0/integrating-aspnet-mvc-into-legacy-web.html" title="Integrating ASP.NET MVC Into Legacy Web Site" /><author><name>Alexander Beletsky</name><uri>https://profiles.google.com/104123427697898813533</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh5.googleusercontent.com/-WqHPxmC8QfM/AAAAAAAAAAI/AAAAAAAAHi4/tX9CTF-Dzy8/s512-c/photo.jpg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://lh4.googleusercontent.com/-ny77OywB_Pk/Tqz2RrcVfCI/AAAAAAAAHnM/P2Awn0D79zc/s72-c/img-1.png" height="72" width="72" /><feedburner:origLink>http://www.beletsky.net/2011/10/integrating-aspnet-mvc-into-legacy-web.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DUUGR3czfyp7ImA9WhRQE0s.&quot;"><id>tag:blogger.com,1999:blog-3980660135707078299.post-825697481495573690</id><published>2011-10-25T09:47:00.000+03:00</published><updated>2011-12-08T20:00:26.987+02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-12-08T20:00:26.987+02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="DDD" /><category scheme="http://www.blogger.com/atom/ns#" term="BeerNCode" /><category scheme="http://www.blogger.com/atom/ns#" term="Conference" /><title>Greg Young and Rinat Abdulin Visited Kyiv</title><content type="html">&lt;p&gt;It finally happened, &lt;a href="http://codebetter.com/gregyoung/"&gt;Greg Young&lt;/a&gt; and &lt;a href="http://abdullin.com/"&gt;Rinat Abdulin&lt;/a&gt; have been guesting Kyiv for almost the week. &lt;br /&gt;
&lt;/p&gt;&lt;p&gt;Initially we've gathered on &lt;a href="http://kyivbeerncode.org/"&gt;Beer &amp;&amp; Code&lt;/a&gt; meeting. The format a little changed that time, but I would say that was really interesting meeting. Greg introduced one of the project he currently working on &lt;a href="http://continuoustests.com/"&gt;http://continuoustests.com/&lt;/a&gt; that now referenced as "Mighty Moose". "Mighty Moose" appear to be really powerful tool that tracks both code and tests changes, and in case of changes taking place it automatically re-runs all related test cases. So, we've grabbed the latest version on MM and played with it a bit. MM is officially in betta now and gonna to be release soon, so did a small contribution by submitting some bugs found on a fly. I also really much enjoyed the quick demonstration of &lt;a href="https://github.com/gregoryyoung/Simple.Testing"&gt;Simple.Testing&lt;/a&gt; framework. It worth to have a separate blog post on that, but in short - it is BDD style framework that literally produce plain English specifications as it's output. It's indeed very simple - just several hundreds LOC's, but very impressive.&lt;br /&gt;
&lt;/p&gt;&lt;p&gt;But of cause, the main event was &lt;a href="http://www.facebook.com/event.php?eid=268332313185736"&gt;Free Event Centric Weekend&lt;/a&gt;. It is very hard to describe what was there just in this short post. You might check out some tweets on &lt;a href="http://twitter.com/#!/search/eventcentric"&gt;#eventcentric&lt;/a&gt; channel. Greg and Rinat were sharing their huge experience on CQRS/DDD and I would say that was extremely interesting. I'm not using either CQRS or DDD on my daily work, so a lot of new concept's I've heard are still really unknown to me, but I'm happy I looked behind the curtain. Greg is &lt;a href="http://martinfowler.com/bliki/ShuHaRi.html"&gt;Ri&lt;/a&gt; level developer - he is simply breaking the concepts. Seriously, I was blown away with some of the statements and my brain is still "damaged" with everything I heard there.&lt;br /&gt;
&lt;/p&gt;&lt;a href="https://lh4.googleusercontent.com/-_2de-YNoo-0/TqZWzXugX3I/AAAAAAAAHm0/_zNc09RHImQ/s720/eventcentic.jpg"&gt;&lt;br /&gt;
&lt;img src="https://lh4.googleusercontent.com/-_2de-YNoo-0/TqZWzXugX3I/AAAAAAAAHm0/_zNc09RHImQ/s720/eventcentic.jpg" alt="Eventcentric meeting in Kyiv" style="width: 620px" /&gt;&lt;br /&gt;
&lt;/a&gt;&lt;br /&gt;
&lt;p&gt;Besides of that we had several cool evenings, drinking beers. I would say that was great week and I'm really happy to meet you guys. I would also say big thanks to &lt;a href="http://kievalt.net/"&gt;KievAltNet&lt;/a&gt;, &lt;a href="http://www.luxoft.com/"&gt;Luxoft&lt;/a&gt; with support they provided to make this happen. I know this in not your last visit to Kiev, so see you soon! &lt;br /&gt;
&lt;/p&gt;&lt;p&gt;ps. As more you know as more unknown you are able to see...&lt;br /&gt;
&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3980660135707078299-825697481495573690?l=www.beletsky.net' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/abeletskyblog?a=YxZe8e6oNoM:LNT98_yxpRk:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/abeletskyblog?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/abeletskyblog?a=YxZe8e6oNoM:LNT98_yxpRk:63t7Ie-LG7Y"&gt;&lt;img src="http://feeds.feedburner.com/~ff/abeletskyblog?d=63t7Ie-LG7Y" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/abeletskyblog?a=YxZe8e6oNoM:LNT98_yxpRk:-BTjWOF_DHI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/abeletskyblog?i=YxZe8e6oNoM:LNT98_yxpRk:-BTjWOF_DHI" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/abeletskyblog/~4/YxZe8e6oNoM" height="1" width="1"/&gt;</content><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/3980660135707078299/posts/default/825697481495573690?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/3980660135707078299/posts/default/825697481495573690?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/abeletskyblog/~3/YxZe8e6oNoM/greg-young-and-rinat-abdulin-visited.html" title="Greg Young and Rinat Abdulin Visited Kyiv" /><author><name>Alexander Beletsky</name><uri>https://profiles.google.com/104123427697898813533</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh5.googleusercontent.com/-WqHPxmC8QfM/AAAAAAAAAAI/AAAAAAAAHi4/tX9CTF-Dzy8/s512-c/photo.jpg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://lh4.googleusercontent.com/-_2de-YNoo-0/TqZWzXugX3I/AAAAAAAAHm0/_zNc09RHImQ/s72-c/eventcentic.jpg" height="72" width="72" /><feedburner:origLink>http://www.beletsky.net/2011/10/greg-young-and-rinat-abdulin-visited.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DUUHSHczeSp7ImA9WhRQE0s.&quot;"><id>tag:blogger.com,1999:blog-3980660135707078299.post-1565641697008792124</id><published>2011-10-16T16:55:00.000+03:00</published><updated>2011-12-08T20:00:39.981+02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-12-08T20:00:39.981+02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Conference" /><title>NETWork Conference in Kharkiv</title><content type="html">&lt;p&gt;In short, it was one of the most exciting and interesting conferences I ever been (and participated) so far. My big respect goes to organizers: &lt;a href="http://sigmaukraine.com/"&gt;Sigma Ukraine&lt;/a&gt;, &lt;a href="http://www.akvelon.com.ua/"&gt;Akvelon&lt;/a&gt; and &lt;a href="http://ciklum.net/"&gt;Ciklum&lt;/a&gt; as main sponsor. &lt;br /&gt;
&lt;/p&gt;&lt;p&gt;In a little long, I've been invited to participate this conference by &lt;a href="http://www.facebook.com/anastasiakladova"&gt;Anastasia Kladova&lt;/a&gt;, the PR manager of &lt;a href="http://sigmaukraine.com/"&gt;Sigma Ukraine&lt;/a&gt; during my visit of &lt;a href="http://www.beletsky.net/2011/08/it-jam-2011-in-odessa_23.html"&gt;IT Jam 2011&lt;/a&gt; this summer. It sounded so cool to me, since so famous guys as &lt;a href="http://network-ua.com/speaker/ayende-rahien-aka-oren-eini/"&gt;Ayende&lt;/a&gt;, &lt;a href="http://network-ua.com/speaker/greg-young/"&gt;Greg Young&lt;/a&gt; and &lt;a href="http://network-ua.com/speaker/rinat-abdullin/"&gt;Rinat Abdulin&lt;/a&gt; would be the speakers there as well. I had not other choice, just to agree.&lt;br /&gt;
&lt;/p&gt;&lt;p&gt;Well, my trip to Kharkiv started not very good. Due to my personal awkwardness I simply missed the train. Now I have fun of that fact, by then I was standing on station and seeing my train passing away - it was not so fun to me. Anyway, with great advice of &lt;a href=""&gt;@chaliy&lt;/a&gt; by phone I switched to another train. The one one problem was - it comes to Kharkiv pretty late, at 10.00 o'clock.&lt;br /&gt;
&lt;/p&gt;&lt;p&gt;Unfortunately I missed first keynote by &lt;a href="http://network-ua.com/speaker/sander-hoogendorn/"&gt;Sander&lt;/a&gt; and first session of speeches. But I was ready for the rest of the day. I would not describe long my feelings to meet colleagues from other cities, which we communicate thought twitter. But it is exactly the conferences like that, where we have real opportunity to talk to each other. As for me, such communication is a bigger asset of any conference including NETWork.&lt;br /&gt;
&lt;/p&gt;&lt;a href="https://lh6.googleusercontent.com/-kH4mZBDxBug/Tp2QkwVhZ1I/AAAAAAAAHmo/DRX7IEoA1pI/s720/DSC_2356.JPG"&gt;&lt;br /&gt;
&lt;img src="https://lh6.googleusercontent.com/-kH4mZBDxBug/Tp2QkwVhZ1I/AAAAAAAAHmo/DRX7IEoA1pI/s720/DSC_2356.JPG" /&gt;&lt;br /&gt;
&lt;/a&gt;&lt;br /&gt;
&lt;p&gt;Let me share some feedback I got about the speeches I visited:&lt;br /&gt;
&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;br /&gt;
&lt;strong&gt;CQRS AND EVENT SOURCING&lt;/strong&gt; by &lt;a href="http://network-ua.com/speaker/greg-young/"&gt;Greg Young&lt;/a&gt; - I really much enjoyed the that speech. Doesn't matter I've seen it before on video :) - still I was amazed about his speakers skill and energy he exposed towards the audience. His mimic, body language and personal behavior - made the speech really attractive. I would not say I heard something really new to me, but at least I improved some knowledge I already had.&lt;br /&gt;
&lt;/li&gt;
&lt;li&gt;&lt;br /&gt;
&lt;strong&gt;APPLIED CODE GENERATION IN .NET&lt;/strong&gt; by &lt;a href="http://network-ua.com/speaker/dmitro-mindra/"&gt;Dmitry Mindra&lt;/a&gt; - great talk about Code Generation in .NET application. Even, if I dislike code generation much, Dmitry managed to find good Pros. and Cons. of code generation. So, at the end of the speech I even was not possible to start holy war on that topic, since really strong facts he had.&lt;br /&gt;
&lt;/li&gt;
&lt;li&gt;&lt;br /&gt;
&lt;strong&gt;INSIDE ASP.NET MVC FRAMEWORK&lt;/strong&gt; be me - yeah, that's my speech so I'm not really happy as usual. Again, I didn't fit everything I wanted to say. Something that I did seems was not really clear and far away from comprehensive. It would be last attempt I do that 'Inside MVC' talk - it is simply too big, so probably next time I just select one small topic and focus on that. Anyway, I all the time enjoy the speaking and I really like that feeling of stress before and relax after :).  &lt;br /&gt;
&lt;/li&gt;
&lt;li&gt;&lt;br /&gt;
&lt;strong&gt;NOSQL – A CHANGE OF PERSPECTIVE FOR THE DEVELOPER OF TODAY&lt;/strong&gt; by &lt;a href="http://network-ua.com/speaker/ayende-rahien-aka-oren-eini/"&gt;Ayende&lt;/a&gt; - I have a split decision on that. The beginning of the speech was simply boring, I don't understand the reason of spending 0.5h do describe the difference of price of 1 Mb HDD in 80's and 00's. Moreover, due to Ayende's accent sometimes I just missed the idea. The end of the speech were more exiting but still I was disappointed. Ayende is great developer, everybody knows that - but it was not even one small example of code working with RavenDB. Probably he left it for some practical session, but still I think it is kind of drawback of his presentation.&lt;br /&gt;
&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;And after all speeches we had a kind of Round Table. All speaker got on stage and answering the questions of audience. It was a little funny to me how it went. First, the language - some questions were in English but answered in Russian, some was Russian but answered English :). I actually used English in respect towards our foreign guests, but anyway. The answers were long, not exact and mainly loosing the point of original question. I think the moderation (with a timing and topics) is really important here. &lt;br /&gt;
&lt;/p&gt;&lt;p&gt;What I remembered the most is the question to Ayende - "How you became so productive?", and the answer was something that great developer should answer "I'm not so productive, I just code a lot and do some blog posts". Yeah, "Code a lot" - so simple rule to became from good to great. I'll remember that.&lt;br /&gt;
&lt;/p&gt;&lt;p&gt;Finally we had a great dinner at the one of Kharkiv's restaurant's. And I went to train station (0.5 hours ahead). There I met my guys from &lt;a href="http://kievalt.net/"&gt;Kiev ALT.NET&lt;/a&gt; who had a great mood and bag full of beer. So, we've had nice Beer &amp;&amp; Talk session till 3.00 AM on our way back home. &lt;br /&gt;
&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3980660135707078299-1565641697008792124?l=www.beletsky.net' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/abeletskyblog?a=k9PpcQQHXFU:l2k9PX8Wo6M:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/abeletskyblog?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/abeletskyblog?a=k9PpcQQHXFU:l2k9PX8Wo6M:63t7Ie-LG7Y"&gt;&lt;img src="http://feeds.feedburner.com/~ff/abeletskyblog?d=63t7Ie-LG7Y" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/abeletskyblog?a=k9PpcQQHXFU:l2k9PX8Wo6M:-BTjWOF_DHI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/abeletskyblog?i=k9PpcQQHXFU:l2k9PX8Wo6M:-BTjWOF_DHI" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/abeletskyblog/~4/k9PpcQQHXFU" height="1" width="1"/&gt;</content><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/3980660135707078299/posts/default/1565641697008792124?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/3980660135707078299/posts/default/1565641697008792124?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/abeletskyblog/~3/k9PpcQQHXFU/network-conference-in-kharkiv.html" title="NETWork Conference in Kharkiv" /><author><name>Alexander Beletsky</name><uri>https://profiles.google.com/104123427697898813533</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh5.googleusercontent.com/-WqHPxmC8QfM/AAAAAAAAAAI/AAAAAAAAHi4/tX9CTF-Dzy8/s512-c/photo.jpg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://lh6.googleusercontent.com/-kH4mZBDxBug/Tp2QkwVhZ1I/AAAAAAAAHmo/DRX7IEoA1pI/s72-c/DSC_2356.JPG" height="72" width="72" /><feedburner:origLink>http://www.beletsky.net/2011/10/network-conference-in-kharkiv.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CE8ARn0-fyp7ImA9WhRQEUw.&quot;"><id>tag:blogger.com,1999:blog-3980660135707078299.post-7189493725800582516</id><published>2011-10-13T21:55:00.000+03:00</published><updated>2011-12-05T21:20:47.357+02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-12-05T21:20:47.357+02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="InsideMVC" /><category scheme="http://www.blogger.com/atom/ns#" term="MVC" /><category scheme="http://www.blogger.com/atom/ns#" term="asp.net" /><title>Inside ASP.NET MVC: IDependencyResolver - Service locator in MVC</title><content type="html">&lt;p&gt;All types inside ASP.NET MVC3 framework are being resolved by &lt;code&gt;IDependencyResolver&lt;/code&gt;. The design goal of this interface is to provide flexibility and decrease coupling between components. &lt;br /&gt;
&lt;/p&gt;&lt;pre class="brush:csharp"&gt;namespace System.Web.Mvc {
    using System.Collections.Generic;

    public interface IDependencyResolver {
        object GetService(Type serviceType);
        IEnumerable&amp;lt;object&amp;gt; GetServices(Type serviceType);
    }
}
&lt;/pre&gt;&lt;p&gt;If take a look into the code you will definitely smell the &lt;a href="http://msdn.microsoft.com/en-us/library/ff648968.aspx"&gt;Service Locator&lt;/a&gt; pattern. Indeed, &lt;code&gt;IDependencyResolver&lt;/code&gt; is pure service locator.&lt;br /&gt;
&lt;/p&gt;&lt;h2&gt;DependencyResolver as IDependencyResolver holder&lt;/h2&gt;&lt;p&gt;&lt;code&gt;IDependencyResolver&lt;/code&gt; instance is being accessed through the &lt;code&gt;DependencyResolver&lt;/code&gt; class. &lt;br /&gt;
&lt;/p&gt;&lt;pre class="brush:csharp"&gt;public class DependencyResolver {
 // Static accessors

 private static DependencyResolver _instance = new DependencyResolver();

 public static IDependencyResolver Current {
  get {
   return _instance.InnerCurrent;
  }
 }
&lt;/pre&gt;&lt;p&gt;It is a singleton class, current instance is being accessed through &lt;code&gt;Current&lt;/code&gt; property. The default implementation is &lt;code&gt;DefaultDependencyResolver&lt;/code&gt;. &lt;br /&gt;
&lt;/p&gt;&lt;pre class="brush:csharp"&gt;// Instance implementation (for testing purposes)

private IDependencyResolver _current = new DefaultDependencyResolver();

&lt;/pre&gt;&lt;p&gt;Even if the comment says (for testing purposes) that class is used in real code. Let's take a look on that.&lt;br /&gt;
&lt;/p&gt;&lt;pre class="brush:csharp"&gt;private class DefaultDependencyResolver : IDependencyResolver {
 [SuppressMessage(&amp;quot;Microsoft.Design&amp;quot;, &amp;quot;CA1031:DoNotCatchGeneralExceptionTypes&amp;quot;, Justification = &amp;quot;This method might throw exceptions whose type we cannot strongly link against; namely, ActivationException from common service locator&amp;quot;)]
 public object GetService(Type serviceType) {
  try {
   return Activator.CreateInstance(serviceType);
  }
  catch {
   return null;
  }
 }

 public IEnumerable&amp;lt;object&amp;gt; GetServices(Type serviceType) {
  return Enumerable.Empty&amp;lt;object&amp;gt;();
 }
}
&lt;/pre&gt;&lt;p&gt;As you might see, it is extremely simple. It just tries to resolve the type by &lt;code&gt;Activator&lt;/code&gt; class. If the type could be resolved it just returns it's instance, otherwise just return null. The &lt;code&gt;GetServices&lt;/code&gt; method just returns empty enumerable. &lt;br /&gt;
&lt;/p&gt;&lt;h2&gt;Substituting default DependencyResolver&lt;/h2&gt;&lt;p&gt;As I said above, the main design goal of &lt;code&gt;DependencyResolver&lt;/code&gt; is to provide flexibility. By flexibility I mean just easy way to substitute any type with own implementation. Say you want to change the &lt;code&gt;ControllerFactory&lt;/code&gt; or &lt;code&gt;ModelBinder&lt;/code&gt; or what ever you like. Everything is possible just by overriding &lt;code&gt;IDependencyResolver&lt;/code&gt;.&lt;br /&gt;
&lt;/p&gt;&lt;p&gt;I've seen one common misconception about MVC3, that it is contains IoC container inside it. It is not true, but it expose the interface which really much suites interfaces of famous IoC containers. To do not have a strict rules and force developers to use one type of IoC, ASP.NET MVC developers created a facility by which you can integrate yours IoC of choice. Let's have a look how to do that. &lt;br /&gt;
&lt;/p&gt;&lt;p&gt;&lt;code&gt;DependencyResolver&lt;/code&gt; contains the number of setters to substitute the instance.&lt;br /&gt;
&lt;/p&gt;&lt;pre class="brush:csharp"&gt;public static void SetResolver(IDependencyResolver resolver) {
 _instance.InnerSetResolver(resolver);
}

public static void SetResolver(object commonServiceLocator) {
 _instance.InnerSetResolver(commonServiceLocator);
}

[SuppressMessage(&amp;quot;Microsoft.Design&amp;quot;, &amp;quot;CA1006:DoNotNestGenericTypesInMemberSignatures&amp;quot;, Justification = &amp;quot;This is an appropriate nesting of generic types.&amp;quot;)]
public static void SetResolver(Func&amp;lt;Type, object&amp;gt; getService, Func&amp;lt;Type, IEnumerable&amp;lt;object&amp;gt;&amp;gt; getServices) {
 _instance.InnerSetResolver(getService, getServices);
}
&lt;/pre&gt;&lt;p&gt;As example of implementation here my very dummy dependency resolver.&lt;br /&gt;
&lt;/p&gt;&lt;pre class="brush:csharp"&gt;namespace MvcForDebug2.Infrastructure {
    public class DummyDependencyResolver : IDependencyResolver {
        public object GetService(Type serviceType) {
            if (serviceType.Equals(typeof(IControllerFactory))) {
                return new DummyControllerFactory();
            }

            return null;
        }

        public IEnumerable&amp;lt;object&amp;gt; GetServices(Type serviceType) {
            return null;
        }
    }
}
&lt;/pre&gt;&lt;p&gt;Finally, in global.asx.cs you need to set it up.&lt;br /&gt;
&lt;/p&gt;&lt;pre class="brush:csharp"&gt;protected void Application_Start()
{
 AreaRegistration.RegisterAllAreas();

 RegisterGlobalFilters(GlobalFilters.Filters);
 RegisterRoutes(RouteTable.Routes);

 DependencyResolver.SetResolver(new DummyDependencyResolver());
 //ControllerBuilder.Current.SetControllerFactory(new DummyControllerFactory());
}
&lt;/pre&gt;&lt;h2&gt;Conclusions&lt;/h2&gt;&lt;p&gt;&lt;code&gt;IDependencyResolver&lt;/code&gt; is a powerful feature of ASP.NET MVC3. It is used to create all internal MVC types, so by overriding it you can override default behavior of many framework aspects. Typically you should not have any complex code in &lt;code&gt;GetService&lt;/code&gt; and &lt;code&gt;GetServices&lt;/code&gt; methods, but instead just delegation of call to IoC container.&lt;br /&gt;
&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3980660135707078299-7189493725800582516?l=www.beletsky.net' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/abeletskyblog?a=Fmk9rX0WfLw:HtYO6kpNTtI:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/abeletskyblog?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/abeletskyblog?a=Fmk9rX0WfLw:HtYO6kpNTtI:63t7Ie-LG7Y"&gt;&lt;img src="http://feeds.feedburner.com/~ff/abeletskyblog?d=63t7Ie-LG7Y" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/abeletskyblog?a=Fmk9rX0WfLw:HtYO6kpNTtI:-BTjWOF_DHI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/abeletskyblog?i=Fmk9rX0WfLw:HtYO6kpNTtI:-BTjWOF_DHI" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/abeletskyblog/~4/Fmk9rX0WfLw" height="1" width="1"/&gt;</content><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/3980660135707078299/posts/default/7189493725800582516?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/3980660135707078299/posts/default/7189493725800582516?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/abeletskyblog/~3/Fmk9rX0WfLw/inside-aspnet-mvc-idependencyresolver.html" title="Inside ASP.NET MVC: IDependencyResolver - Service locator in MVC" /><author><name>Alexander Beletsky</name><uri>https://profiles.google.com/104123427697898813533</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh5.googleusercontent.com/-WqHPxmC8QfM/AAAAAAAAAAI/AAAAAAAAHi4/tX9CTF-Dzy8/s512-c/photo.jpg" /></author><feedburner:origLink>http://www.beletsky.net/2011/10/inside-aspnet-mvc-idependencyresolver.html</feedburner:origLink></entry></feed>

