<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://codebetter.com/utility/FeedStylesheets/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/"><channel><title>Karl Seguin</title><link>http://codebetter.com/blogs/karlseguin/default.aspx</link><description>.NET From Ottawa, Ontario - http://twitter.com/karlseguin/</description><dc:language>en</dc:language><generator>CommunityServer 2008.5 SP1 (Build: 31106.3070)</generator><item><title>NHibernate : Handling the Special Cases</title><link>http://codebetter.com/blogs/karlseguin/archive/2009/06/18/nhibnerate-handling-the-special-cases.aspx</link><pubDate>Thu, 18 Jun 2009 14:03:00 GMT</pubDate><guid isPermaLink="false">d21fbbc9-c112-4f32-ad14-95939a2c53d4:248687</guid><dc:creator>karl</dc:creator><slash:comments>8</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://codebetter.com/blogs/karlseguin/rsscomments.aspx?PostID=248687</wfw:commentRss><comments>http://codebetter.com/blogs/karlseguin/archive/2009/06/18/nhibnerate-handling-the-special-cases.aspx#comments</comments><description>&lt;p&gt;In my last &lt;a href="http://codebetter.com/blogs/karlseguin/archive/2009/06/10/nhibernate-some-naked-thoughts.aspx"&gt;NHibernate post&lt;/a&gt; I mentioned that NHibernate is great because it does the heavy lifting for the common tasks that make up 95% of my data access layer, while letting me tweak the remaining 5% as needed.&lt;/p&gt;
&lt;p&gt;Let&amp;#39;s look at some of the ways you can tweak, or even circumvent NHibernate for those queries that require some extra attention. Do note that there are a lot of different solutions &amp;ndash; we&amp;#39;re only looking at a few. &lt;/p&gt;
&lt;p&gt;The most obvious method is to use named queries and custom SQL statements in your mapping. This provides you a lot of flexibility without diverging from NHibernate&amp;#39;s realm. The &lt;a href="http://www.nhforge.org/doc/nh/en/index.html"&gt;NHibernate reference&lt;/a&gt; has good documentation on this approach, so we won&amp;#39;t cover it (check out section &lt;a href="http://www.nhforge.org/doc/nh/en/index.html#querysql-namedqueries"&gt;14.2 &amp;quot;Named Queries&amp;quot;&lt;/a&gt;, &lt;a href="http://www.nhforge.org/doc/nh/en/index.html#querysql-cud"&gt;14.3 &amp;quot;Custom SQL for create, update and delete&amp;quot;&lt;/a&gt; and &lt;a href="http://www.nhforge.org/doc/nh/en/index.html#querysql-creating"&gt;14.4 &amp;quot;Custom SQL for loading&amp;quot;&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;The next option is to use an ISqlQuery via the ISession.CreateSqlQuery. Unlike an IQuery which works against your domain using HQL, an ISqlQuery is closely tied to your database and SQL. However, you still get access to NHibernate parameter substitutions, paging capabilities and O/R mapping (if you want). Again, the NHibernate reference has a very detailed section, check out &lt;a href="http://www.nhforge.org/doc/nh/en/index.html#querysql-creating"&gt;14.1 &amp;quot;Using an ISQLQuery&amp;quot;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;You can optimize your Deletes by supplying the ISession.Delete command some HQL rather than the instance you want to delete. For example, if you want to delete all comments belonging to a blog post, you can do:&lt;/p&gt;
&lt;pre name="code" class="c-sharp"&gt;session.Delete(&amp;quot;from Comment where PostId = :id&amp;quot;, postId, NHibernateUtil.Int32);&lt;/pre&gt;
&lt;p&gt;More recently the NHibernate team made it possible to execute any statement (insert/delete/update) from an IQuery. You can find out more from &lt;a href="http://ayende.com/Blog/archive/2009/05/28/nhibernate-ndash-executable-dml.aspx"&gt;this post&lt;/a&gt; by Ayende.&lt;/p&gt;
&lt;p&gt;When necessary (typically bulk imports or other bulk operations), you can circumvent NHibernate&amp;#39;s first-level cache by using an IStatelessSession rather than an ISession. Rather than calling OpenSession on your ISessionFactory, simply call OpenStatlessSession. Keep in mind that the IStatelessSession doesn&amp;#39;t have the exact same API as an ISession.&lt;/p&gt;
&lt;p&gt;When things get really crazy, you can always get an ADO.NET connection from the ISession&amp;#39;s Connection property. With a raw database connection, the world is your oyster. You can always write your code in such a way that you have direct access to our connection string to create your own connection, thus completely and fully circumventing NHibernate.&lt;/p&gt;
&lt;p&gt;Finally, any of these methods can be combined with some simple designs in order to ensure that everything is neat and tidy:&lt;/p&gt;
&lt;pre name="code" class="c-sharp"&gt;public abstract class Repository : IRepository
{
    public void Delete&amp;lt;T&amp;gt;(T entity)
    {
        WithinTransaction(s =&amp;gt; s.Delete(target));
    }

    protected void WithinTransaction(Action action)
    {
        WithinTransaction(Session, action);
    }        
    protected static void WithinTransaction(ISession session, Action action)
    {
        var transaction = session.BeginTransaction();
        try
        {
            action();
            transaction.Commit();
        }
        catch (Exception)
        {
            transaction.Rollback();
            throw;
        }
        finally
        {
            transaction.Dispose();
        }
    }
}


public class PostRepository : Repositor, IPostRepository
{
    public void Delete(int postId)
    {
        WithinTransaction(s =&amp;gt; 
            {
                session.Delete(&amp;quot;from Comment where PostId = :id&amp;quot;, postId, NHibernateUtil.Int32);
                session.Delete(&amp;quot;from Post where Id = :id&amp;quot;, postId, NHibernateUtil.Int32);
            });
    }
}&lt;/pre&gt;
&lt;p&gt;Once you understand NHibernate&amp;#39;s flexibility and understand your code&amp;#39;s hot spots, it generally takes a pretty trivial amount of tweaking to speed things up. While the changes you make, in the name of performance, to your models (both domain and data) may be disgusting rest assured that HHibernate will not stand in your way. Be warned though that many of the above solutions may have side effects with respect to NHibernate&amp;#39;s 1st and 2nd level caches. However, if you were to custom write everything, including caching, you&amp;#39;d likely have similar synch issues.
&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://codebetter.com/aggbug.aspx?PostID=248687" width="1" height="1"&gt;</description></item><item><title>NHibernate : Some Naked Thoughts</title><link>http://codebetter.com/blogs/karlseguin/archive/2009/06/10/nhibernate-some-naked-thoughts.aspx</link><pubDate>Thu, 11 Jun 2009 01:07:00 GMT</pubDate><guid isPermaLink="false">d21fbbc9-c112-4f32-ad14-95939a2c53d4:248388</guid><dc:creator>karl</dc:creator><slash:comments>29</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://codebetter.com/blogs/karlseguin/rsscomments.aspx?PostID=248388</wfw:commentRss><comments>http://codebetter.com/blogs/karlseguin/archive/2009/06/10/nhibernate-some-naked-thoughts.aspx#comments</comments><description>&lt;h4&gt;Please, Just Remember One Thing&lt;/h4&gt;
&lt;p&gt;Just for a few seconds forget everything you know about NHibernate.&lt;/p&gt;
&lt;p&gt;Good.&lt;/p&gt;
&lt;p&gt;Now, before I snap my fingers and everything comes flooding back, the only thing you need to know about NHibernate is that whenever you need to, you can easily circumvent it and do whatever is needed to get the job done (like use an IDbConnection and IDbCommand to execute a stored procedure).&lt;/p&gt;
&lt;p&gt;**snap**&lt;/p&gt;
&lt;p&gt;I often hear people saying it, and often say it myself, but people just don&amp;#39;t seem to get it. You use NHibernate to save yourself from having to write a ton of code for 95% of your data access, and then, after profiling, optimize the critical 5% with whatever other approach you prefer. Its stupidly easy. You can access an IDbConnection directly from an NHibernate&amp;#39;s ISession, or subclass your NHibernateDataAccess class with an SqlServerDataAccess class and override those critical sections.&lt;/p&gt;
&lt;p&gt;Instead of taking the above sane approach, I see people laboring through huge amounts of mundane code in order to keep control over that unique 5% (maybe a special report, or performance sensitive path).  I see people concerned about performance, without understanding that for most of what an application does, the performance difference between method A, B and C are indistinguishable, whereas the maintenance and developer costs vary hugely.&lt;/p&gt;
&lt;p&gt;Essentially I see people who are worried about not being able to tweak when necessary and people who simply don&amp;#39;t want to change.&lt;/p&gt;
&lt;p&gt;To the first group I say that your fears are understood, but not to worry. You can always drop down to the assembly of data access (SQL, Sprocs, ...).&lt;/p&gt;
&lt;h4&gt;Four Areas of Improvement&lt;/h4&gt;
&lt;p&gt;NHibernate makes my life easier and my code better, but it isn&amp;#39;t without problems. A lot of these have to do with the fact that it&amp;#39;s trying to solve a complex problem, of which numerous variations exist.  As such, NHibernate&amp;#39;s biggest problem is that it&amp;#39;s hard to learn and harder still to master. There are some specific pain points I&amp;#39;d like to see addressed.&lt;/p&gt;
&lt;p&gt;First, mapping needs to be simplified. It&amp;#39;s extremely intimidating to a newcomer and requires that you understand most of the fundamentals.  This is already being addressed with FluentNhibernate and hopefully the project will continue to mature.&lt;/p&gt;
&lt;p&gt;Secondly, collections and references can be particularly puzzling. From the names used (bags, maps and sets are all foreign to most .NET developers), to advanced features like caching, lazy loading and cascading. I&amp;#39;m not sure if this is something that can actually be improved, or if this battle needs to be fought via documentation.  &lt;/p&gt;
&lt;p&gt;Thirdly, neither HQL nor Criterias feel like the most natural querying languages. Hopefully development on Linq to NHibernate will continue to be a priority.&lt;/p&gt;
&lt;p&gt;Finally, NHibernate is an abstraction that will leak. This shouldn&amp;#39;t be unexpected, but it would be nice to try and address some of the worst offenders. The leaks that continuously trip me up are related to management of ISessions. Lazy loading and session management is a black art &amp;ndash; doubtlessly easy for masters, and frustrating for everyone else.&lt;/p&gt;
&lt;h4&gt;NHibernate and Microsoft&lt;/h4&gt;
&lt;p&gt;Microsoft has long been criticized for its attitude towards open source frameworks. The common approach appears to be to compete with established open source frameworks using inferior solutions. MSTest, MSBuild, Sandcastle, ASP.NET Ajax, ASP.NET MVC, Entity Framework, Unity, Logging Application Block, Velocity, Team Foundation SSC are all examples that come to mind. &lt;/p&gt;
&lt;p&gt;It&amp;#39;d be nice if Microsoft took a different approach with NHibernate, by not only acknowledging its presence and using it in samples and demos, but also actively contributing to it. Remember, during NHibernate&amp;#39;s lifetime, Microsoft has invented three distinct data access strategies (DataSets, Linq to SQL and the Entity Framework). So much effort, so much relearning by developers, to end up with a poor replica of NHibernate years later.&lt;/p&gt;
&lt;p&gt;A couple years ago, Google contributed Hibernate Shards to the Hibernate project (and I&amp;#39;d bet that they&amp;#39;ve been involved in Hibernate in other ways since then). Surely Microsoft can help fund the project in a manner that works with the NHibernate team (money or resources).  &lt;/p&gt;
&lt;h4&gt;NHibernate and You&lt;/h4&gt;
&lt;p&gt;I do think it&amp;#39;s important for any developer to learn new things. Equally important is to learn them from different people. Its important that you learn Ruby or Python, not because you should use them, but because seeing MVC over ActiveRecord completely changes your perspective on how applications can be built. The more approaches that you know, the more likely you are to pick the right one for the job. If you only know one approach then you&amp;#39;ll always use that one &amp;ndash; and you better hope like hell that the person selling you that approach knows what he or she is talking about.&lt;/p&gt;
&lt;p&gt;As for NHibernate specifically, most developers should learn about O/R mappers. You should know the advantages and disadvantages and therefore know when a situations calls for it or not.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://codebetter.com/aggbug.aspx?PostID=248388" width="1" height="1"&gt;</description></item><item><title>Revisiting CodeBetter.Canvas </title><link>http://codebetter.com/blogs/karlseguin/archive/2009/05/25/revisiting-codebetter-canvas.aspx</link><pubDate>Mon, 25 May 2009 13:02:00 GMT</pubDate><guid isPermaLink="false">d21fbbc9-c112-4f32-ad14-95939a2c53d4:236926</guid><dc:creator>karl</dc:creator><slash:comments>12</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://codebetter.com/blogs/karlseguin/rsscomments.aspx?PostID=236926</wfw:commentRss><comments>http://codebetter.com/blogs/karlseguin/archive/2009/05/25/revisiting-codebetter-canvas.aspx#comments</comments><description>&lt;p&gt;A month ago &lt;a href="http://codebetter.com/blogs/karlseguin/archive/2009/04/28/presenting-codebetter-canvas.aspx"&gt;I released CodeBetter.Canvas&lt;/a&gt;, a simple application with equally simple goals:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Provide developers with a starting point for new ASP.NET MVC projects&lt;/li&gt;
&lt;li&gt;Provide developers with a learning tool for oft-talked about tools/patterns&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Instead of building a full-fledge application (like another blog engine, or shopping site), I wanted to build something as close to a blank canvas as possible - not only because it made the task more managable for me, but also because I thought it would be a better way to learn, and a more practical application for developers to use as a launching pad for their own real projects. While being an MVC application, the focus is more general: namely proper use of dependency injection, leveraging NHibernate/FluentNhibernate/Linq2Nhibernate, unit testing and mocking, and jQuery.&lt;/p&gt;
&lt;p&gt;Yesterday I released an updated version of CodeBetter.Canvas to Google Code. You can check it out at &lt;a href="http://code.google.com/p/codebettercanvas/"&gt;http://code.google.com/p/codebettercanvas/&lt;/a&gt;. There are a number of new things in this release, including a revamped repository model, the introduction of a model binding framework (these end up doing a lot of heavy lifting), an improved validation framework, and ideas on how to do paged lists.&lt;/p&gt;
&lt;p&gt;Enjoy.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://codebetter.com/aggbug.aspx?PostID=236926" width="1" height="1"&gt;</description></item><item><title>2 years ago I gave up on Silverlight</title><link>http://codebetter.com/blogs/karlseguin/archive/2009/05/23/2-years-ago-i-gave-up-on-silverlight.aspx</link><pubDate>Sat, 23 May 2009 15:51:00 GMT</pubDate><guid isPermaLink="false">d21fbbc9-c112-4f32-ad14-95939a2c53d4:235087</guid><dc:creator>karl</dc:creator><slash:comments>19</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://codebetter.com/blogs/karlseguin/rsscomments.aspx?PostID=235087</wfw:commentRss><comments>http://codebetter.com/blogs/karlseguin/archive/2009/05/23/2-years-ago-i-gave-up-on-silverlight.aspx#comments</comments><description>&lt;p&gt;Almost two years ago, to the day, I completely gave up on Silverlight. How do I remember the day so clearly? Because every now and I again, I get an email notification that someone has replied to my following forum post: &lt;a href="http://silverlight.net/forums/p/1334/216456.aspx"&gt;http://silverlight.net/forums/p/1334/216456.aspx&lt;/a&gt;. In it, I asked why the Shape classes are sealed. At the time I figured it might have just been a early-release kinda thing. However, since the issue continues to be raised I&amp;#39;ll assume the problem still hasn&amp;#39;t been fixed.&lt;/p&gt;
&lt;p&gt;This whole thing reminds me of another common .NET problem - internal framework classes. This was a hot topic with the release of .NET 3.5 and the ExpressionVisitor code, so much so that a David Kean from Microsoft &lt;a href="http://davesbox.com/archive/2008/12/09/quot-i-can-t-believe-microsoft-didn-t-make-enter-api-name-here-public-quot.aspx"&gt;jumped in&lt;/a&gt; to explain the situation. For the most part though, all it did was highlight how inefficient and unwilling to change Microsoft was. Why are classes internal? Because the process to make them public involves 20 some people and a multi-layered review system. There&amp;#39;s no &amp;quot;how do you guys handle these problems?&amp;quot; or &amp;quot;where can we improve&amp;quot; - merely a statement of fact of how things are (and therefore must be).&lt;/p&gt;
&lt;p&gt;Back to the sealed silverlight classes. This to is a pretty old topic - remember Java is virtual by default, C# is not. What annoys me though, is the approach Microsoft has taken. I asked &lt;i&gt;Why are the classes sealed&lt;/i&gt;, and the official response was &lt;i&gt;Why do you want them unsealed?&lt;/i&gt; If .NET is built on the basis that developers need to justify how they use the framework, we&amp;#39;re in deep shit. The default behavior of a framework developer should be to open components, and only close them off when necessary. Otherwise it limits what your customers can do with your product, places assumptions on how your framework will be used, and makes it clear that you think you know better than we do. Lets not forget that coming up with a use-case for inheriting Line isn&amp;#39;t particularly difficult - maybe I want to create my own DottedLine class?&lt;/p&gt;
&lt;p&gt;The specific wording used by Nick Kramer (Silverlight&amp;#39;s Program Manager) was: &lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;quot;We want to err on the side of less API surface area -- if you&amp;#39;re
missing something important someone will tell you, but if you include a
feature that doesn&amp;#39;t get used you&amp;#39;ll never hear about it, and will pay
the download cost for it forever. We weren&amp;#39;t able to think of a
compelling reason for arbitrary subclassing, but maybe we weren&amp;#39;t
creative enough -- what scenarios do you have in mind?&amp;quot;&lt;/p&gt;
&lt;p&gt;It isn&amp;#39;t Nick Kramer &amp;amp; Team&amp;#39;s job to think of reasons for subclassing (its our job to do that). Nick Kramer and Team should only be concerned with reasons not to have an unsealed class. Nick did provide some of that reasoning, but I&amp;#39;m unconvinced. Essentially coming down to performance and wrapping unmanaged objects - issues simple enough to cover via documentation.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://codebetter.com/aggbug.aspx?PostID=235087" width="1" height="1"&gt;</description></item><item><title>Making the untestable testable with Anonymous Methods and Dependency Injection</title><link>http://codebetter.com/blogs/karlseguin/archive/2009/05/08/making-the-untestable-testable-with-anonymous-methods-and-dependency-injection.aspx</link><pubDate>Fri, 08 May 2009 14:42:00 GMT</pubDate><guid isPermaLink="false">d21fbbc9-c112-4f32-ad14-95939a2c53d4:218672</guid><dc:creator>karl</dc:creator><slash:comments>23</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://codebetter.com/blogs/karlseguin/rsscomments.aspx?PostID=218672</wfw:commentRss><comments>http://codebetter.com/blogs/karlseguin/archive/2009/05/08/making-the-untestable-testable-with-anonymous-methods-and-dependency-injection.aspx#comments</comments><description>&lt;p&gt;Making the untestable testable with Anonymous Methods and Dependency Injection
&lt;/p&gt;
&lt;p&gt;It can be  frustrating to want to write unit tests, only to hit some code which is rather untestable. Take for example, the following code:&lt;/p&gt;
&lt;pre name="code" class="c-sharp"&gt;public class MailSender
{
   public void SendActivationMail(User user, string activationCode)
   {
            string body = GetCopyOfActivationBody(); //implementation doesn&amp;#39;t matter
            body = body.Replace(&amp;quot;#NAME#&amp;quot;, user.Name).Replace(&amp;quot;#CODE#&amp;quot;, activationKey).Replace(&amp;quot;#EMAIL#&amp;quot;, user.Email);
            var message = new MailMessage(&amp;quot;support@piccolo.cool&amp;quot;, user.Email, &amp;quot;Account Activation&amp;quot;, content) {IsBodyHtml = true};
            new SmtpClient().Send(message);
   }
}&lt;/pre&gt;
&lt;p&gt;Obviously, I can&amp;#39;t test this method as-is without making sure that a mail server is setup. And even if it was, how would I verify that the properties of my MailMessage object were properly set?&lt;/p&gt;
&lt;p&gt;In the past, I probably would have solved this by using a virtual method and mocking it:&lt;/p&gt;
&lt;pre name="code" class="c-sharp"&gt;public void SendActivationMail(User user, string activationCode)
{
        string body = GetCopyOfActivationBody(); //implementation doesn&amp;#39;t matter
        body = body.Replace(&amp;quot;#NAME#&amp;quot;, user.Name).Replace(&amp;quot;#CODE#&amp;quot;, activationKey).Replace(&amp;quot;#EMAIL#&amp;quot;, user.Email);
        var message = new MailMessage(&amp;quot;support@piccolo.cool&amp;quot;, user.Email, &amp;quot;Account Activation&amp;quot;, content) {IsBodyHtml = true};
        SendMessage(message);
}
public virtual void SendMessage(MailMessage message)
{
   new SmtpClient().Send(message);
}&lt;/pre&gt;
&lt;p&gt;Now we can create a mock of our MailSender class and mock our SendMessage method. I still think this is an acceptable solution, but I now prefer to inject an anonymous method as a dependency. The benefit is that my unit tests are more straightforward, and I&amp;#39;m not having to expose a method like SendMessage.&lt;/p&gt;
&lt;p&gt;Before you move on, you should be familiar with anonymous methods, I&amp;#39;ve blogged about them &lt;a href="http://codebetter.com/blogs/karlseguin/archive/2008/07/03/get-your-func-on.aspx"&gt;in the past&lt;/a&gt; and/or you can check out &lt;a href="http://dimecasts.net/Casts/CastDetails/105"&gt;this dimecast&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;First we&amp;#39;ll change our MailSender class to accept a simple anonymous method into its constructor:&lt;/p&gt;
&lt;pre name="code" class="c-sharp"&gt;public class MailSender
{
   private readonly Action&amp;lt;MailMessage&amp;gt; _sendMessage;
   public MailSender(Action&amp;lt;MailMessage&amp;gt; sendMessage)
   {
      _sendMessage = sendMessage;
   }
}&lt;/pre&gt;
&lt;p&gt;Next we&amp;#39;ll change our SendActivationMail to use the sendMessage action:&lt;/p&gt;
&lt;pre name="code" class="c-sharp"&gt;public void SendActivationMail(User user, string activationCode)
{
   string body = GetCopyOfActivationBody(); //implementation doesn&amp;#39;t matter
   body = body.Replace(&amp;quot;#NAME#&amp;quot;, user.Name).Replace(&amp;quot;#CODE#&amp;quot;, activationKey).Replace(&amp;quot;#EMAIL#&amp;quot;, user.Email);
   var message = new MailMessage(&amp;quot;support@piccolo.cool&amp;quot;, user.Email, &amp;quot;Account Activation&amp;quot;, content) {IsBodyHtml = true};
   _sendMessage(message);
}&lt;/pre&gt;
&lt;p&gt;Before we write our test, let&amp;#39;s configure this dependency for our normal, production use. Here I&amp;#39;m using Ninject (some version of the 2.0 branch, so the syntax might be slightly different for you):&lt;/p&gt;
&lt;pre name="code" class="c-sharp"&gt;Bind&amp;lt;Action&amp;lt;MailMessage&amp;gt;&amp;gt;().ToConstant(message =&amp;gt; new SmtpClient().Send(message));&lt;/pre&gt;
&lt;p&gt;That&amp;#39;s all there is to it. Now, whenever we get an instance of our MailSender class through Ninject, it&amp;#39;ll automatically inject the default behaviour and happily send emails away (for those curious where/how to configure the host/port/username/password, I prefer to do that in the web.config/app.config via the &amp;lt;system.net&amp;gt; section.) As for our tests, they look something like:&lt;/p&gt;
&lt;pre name="code" class="c-sharp"&gt;[Fact]
public void SendsActivationEmailToUser()
{
    var user = new User {Email = &amp;quot;nail@namekian.cool&amp;quot;};
    var action = new Action&amp;lt;MailMessage&amp;gt;(m =&amp;gt; Assert.Equal(user.Email, m.To.ToString()));
    new MailSender(action).SendActivationMail(user, null);
}
&lt;/pre&gt;
&lt;p&gt;There you have it. By injecting our own test-specific anonymous method into our MailSender class we&amp;#39;ve turned otherwise untestable code into code which is easy to test.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://codebetter.com/aggbug.aspx?PostID=218672" width="1" height="1"&gt;</description></item><item><title>Part of your job should be to learn</title><link>http://codebetter.com/blogs/karlseguin/archive/2009/05/07/part-of-your-job-should-be-to-learn.aspx</link><pubDate>Thu, 07 May 2009 12:11:00 GMT</pubDate><guid isPermaLink="false">d21fbbc9-c112-4f32-ad14-95939a2c53d4:217574</guid><dc:creator>karl</dc:creator><slash:comments>12</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://codebetter.com/blogs/karlseguin/rsscomments.aspx?PostID=217574</wfw:commentRss><comments>http://codebetter.com/blogs/karlseguin/archive/2009/05/07/part-of-your-job-should-be-to-learn.aspx#comments</comments><description>&lt;p&gt;Jan recently asked:&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;quot;Something I don&amp;#39;t see being addressed that often - When you say you
read a lot, is that on your own time, or do you actually spend time at
work reading? I think spending time at work reading &amp;amp; learning is
justifiable, although not always easy.&amp;quot;&lt;/p&gt;
&lt;p&gt;My answer is an absolute and irrevocable &lt;b&gt;ABSOLUTELY&lt;/b&gt;. You should spend as much time as possible learning while at work, and you should use your work itself as a learning platform. Even in an organization that&amp;#39;s constantly under intense client deadlines, you should be able to fit in reading a couple blog posts at the start of your day and during lunch time. It helps if you have a specific list of high-value blogs (as opposed to having to wade through sites like weblogs.asp.net for example). Jeremy Miller recently mentioned that he likes &lt;a href="http://www.infoq.com/"&gt;http://www.infoq.com/&lt;/a&gt;, so I&amp;#39;m going to start keeping an eye on it. There&amp;#39;s also my own aggregate at &lt;a href="http://www.foundationsof.com/"&gt;http://www.foundationsof.com/&lt;/a&gt; which is good if you like codebetter-like content.&lt;/p&gt;
&lt;p&gt;Also, I find that there are always some throw-away projects on the go which are ideally suited for experimentation (like that one data import that needs to get done). At the very least, these projects can help you get over some of the technical hurdles of learning a new tool.&lt;/p&gt;
&lt;p&gt;You can even find the time to create and maintain your own OSS project at work. For example, I had to write a JSON parser for the compact framework (at the time, none existed). I talked to my manager and, since our company isn&amp;#39;t in the market of selling software (or making software for that matter), got approval to release it on &lt;a href="http://www.codeplex.com/JsonCF"&gt;CodePlex&lt;/a&gt;. In a previous job, I had to write a AMF serializer/deserializer, and since it was based on a GPLd Java Port I also got approval to release it.&lt;/p&gt;
&lt;p&gt;Learning at work is something you should talk to your manager about - whether that be for formal training, or simply reading blogs and contributing to OSS projects. Furthermore, the process can be formalized as a team activity, through Lunch and Learns or code reviews. Are you considering using a DI framework, unit testing, or NHibernate at work? Why not download &lt;a href="http://codebetter.com/blogs/karlseguin/archive/2009/04/28/presenting-codebetter-canvas.aspx"&gt;CodeBetter.Canvas&lt;/a&gt; and get your colleagues together for an hour to review specific parts of the code?&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://codebetter.com/aggbug.aspx?PostID=217574" width="1" height="1"&gt;</description></item><item><title>2009 - A Year of Learning (so far)</title><link>http://codebetter.com/blogs/karlseguin/archive/2009/05/04/2009-a-year-of-learning-so-far.aspx</link><pubDate>Mon, 04 May 2009 14:57:00 GMT</pubDate><guid isPermaLink="false">d21fbbc9-c112-4f32-ad14-95939a2c53d4:213906</guid><dc:creator>karl</dc:creator><slash:comments>26</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://codebetter.com/blogs/karlseguin/rsscomments.aspx?PostID=213906</wfw:commentRss><comments>http://codebetter.com/blogs/karlseguin/archive/2009/05/04/2009-a-year-of-learning-so-far.aspx#comments</comments><description>&lt;p&gt;I spend a lot of time learning. I read a lot, work on small projects that let me experiment, and blog (which is probably the best way to learn). I don&amp;#39;t see how you can be effective or successful in the long run without a serious commitment to learning. &lt;a href="http://blog.objectmentor.com/"&gt;Uncle Bob&lt;/a&gt; says it well:&lt;/p&gt;
&lt;p&gt;&amp;quot;I think that maintaining your technical chops is a full time job. For that reason I have avoided becoming a business wonk. I hire people to do that for me so I can keep my technical skills as sharp as possible and remain relevant to my profession. I don&amp;rsquo;t believe I can offer technical advice unless I am living that technical advice.&amp;quot;&lt;/p&gt;
&lt;p&gt;What I find most interesting is that I&amp;#39;m becoming a better learner. I&amp;#39;ve always been very eager to improve, but not always effective at it. I&amp;#39;m much better now at filtering through the high noise to signal ratio. A lot of the big sites/blogs I followed years ago are now completely off my radar - too much marketing, too much self promotion, too little focus on craftsmanship and quality. I&amp;#39;ve also found twitter to be an indispensable tool for picking up on new trends and to see what others are working on/with.&lt;/p&gt;
&lt;p&gt;Off the top of my head, here are some of the things I&amp;#39;ve learnt recently (mix of design and tools):&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;I&amp;#39;ve refined my knowledge of DI and am slowly becoming a Ninject ninja,&lt;/li&gt;
&lt;li&gt;I finally feel like I&amp;#39;m writing effective unit tests (that was a long road), and I&amp;#39;m hooked on XUnit,&lt;/li&gt;
&lt;li&gt;I understand the difference between mocks and stubs, dynamics and stricts, and mock less code but do so more effectively,&lt;/li&gt;
&lt;li&gt;I&amp;#39;m starting my 3rd project with NHibernate and (finally) feel comfortable enough to blog/present on it,&lt;/li&gt;
&lt;li&gt;I&amp;#39;ve using FluentNhibernate for a new project, and leveraging NHProf (as of last Friday =] ),&lt;/li&gt;
&lt;li&gt;I&amp;#39;m starting my 2nd full ASP.NET MVC project, it&amp;#39;s amazing how much cleaner things are now, thanks to past failures (by me and others) and better tooling,&lt;/li&gt;
&lt;li&gt;I continue to build small projects in PHP,&lt;/li&gt;
&lt;li&gt;I&amp;#39;m slowly learning Python,&lt;/li&gt;
&lt;li&gt;I&amp;#39;m using a Mac and making sure I don&amp;#39;t forget how to configure apache, use vi and write little bash crons&lt;/li&gt;
&lt;li&gt;I have Android on my radar&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;What interesting tools/design/framework are you learning?&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://codebetter.com/aggbug.aspx?PostID=213906" width="1" height="1"&gt;</description></item><item><title>Presenting CodeBetter.Canvas</title><link>http://codebetter.com/blogs/karlseguin/archive/2009/04/28/presenting-codebetter-canvas.aspx</link><pubDate>Wed, 29 Apr 2009 02:25:00 GMT</pubDate><guid isPermaLink="false">d21fbbc9-c112-4f32-ad14-95939a2c53d4:207410</guid><dc:creator>karl</dc:creator><slash:comments>17</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://codebetter.com/blogs/karlseguin/rsscomments.aspx?PostID=207410</wfw:commentRss><comments>http://codebetter.com/blogs/karlseguin/archive/2009/04/28/presenting-codebetter-canvas.aspx#comments</comments><description>&lt;p&gt;&lt;b&gt;UPDATE: A new version is available, read more at &lt;a href="http://codebetter.com/blogs/karlseguin/archive/2009/05/25/revisiting-codebetter-canvas.aspx"&gt;http://codebetter.com/blogs/karlseguin/archive/2009/05/25/revisiting-codebetter-canvas.aspx&lt;/a&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;I recently wrote a code-heavy 3-part series on validation. Half-way through, I realized that a sample application would
probably help bring together all the incoherent code snippets I was throwing around.&lt;/p&gt;
&lt;p&gt;Historically, I&amp;#39;ve been pretty harsh on shitty code-samples (you can go back to when I first started blogging and probably 
find some pretty harsh criticism of Adobe and MSDN). As a consequence, I&amp;#39;ve always tried to write above-average code samples, 
Of course, more recently I&amp;#39;ve taken a number of high profile projects to task, namely Oxite and Kobe. As soon as I started putting
this sample together, I saw an opportunity to go beyond demo-ing a custom validation library and provide some of the guidance
I felt other projects were lacking.&lt;/p&gt;
&lt;p&gt;Functionality-wise, all you can do is register a user. The downside of the simplification is that it doesn&amp;#39;t address 
many (most?) of the real challenges you&amp;#39;re likely to face. Even I think the entire thing seems rather ivory tower. On the upside
you can use this project as a canvas for your own project, or as a launch-pad to learn about all types of exciting technologies.
Specifically, despite the extreme lightweightedness, this project makes use of Dependency Injection (via Ninject), OR Mapping
(via FluentNHibernate), Unit Testing (via XUnit), mocking (via RhinoMocks) and a couple more trendy topics.&lt;/p&gt;
&lt;p&gt;This isn&amp;#39;t a perfect example, but I&amp;#39;m pretty happy with it. I think developers who have a genuine interest in learning 
and enthusiasm for programming will gain a lot from this. I&amp;#39;m sorry for the total lack of documentation, but this is really a
help-yourself kinda thing. &lt;/p&gt;
&lt;p&gt;I should point out that the way I handle the database path (I use sqlite) is horrible. I did it that way so that the application
will [hopefully] work out of the box (all you need in ASP.NET MVC installed). The hack in question is located in the Configuration class.
Also, this isn&amp;#39;t an opinionated MVC implementation. This isn&amp;#39;t really about MVC at all.&lt;/p&gt;
&lt;p&gt;If you want help or have a suggestion/comment post a comment here. I&amp;#39;d love to help any way I can, or even better, learn
to from my mistakes so that I don&amp;#39;t do them again.&lt;/p&gt;
&lt;p&gt;Finally, I apologize to the people who just wanted to peak at the validation framework. My demo turned into something more.
If I did a good job, you should be able to easily find all of the pieces.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://codebetter.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/karlseguin/CodeBetter.Canvas.zip"&gt;You can download it here&lt;/a&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://codebetter.com/aggbug.aspx?PostID=207410" width="1" height="1"&gt;</description></item><item><title>Validation - Part 3 - Server-Side</title><link>http://codebetter.com/blogs/karlseguin/archive/2009/04/28/validation-part-3-server-side.aspx</link><pubDate>Wed, 29 Apr 2009 00:08:00 GMT</pubDate><guid isPermaLink="false">d21fbbc9-c112-4f32-ad14-95939a2c53d4:207305</guid><dc:creator>karl</dc:creator><slash:comments>10</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://codebetter.com/blogs/karlseguin/rsscomments.aspx?PostID=207305</wfw:commentRss><comments>http://codebetter.com/blogs/karlseguin/archive/2009/04/28/validation-part-3-server-side.aspx#comments</comments><description>&lt;p&gt;Validation - Part 3 - Server-Side
&lt;/p&gt;
&lt;p&gt;&lt;b&gt;&amp;lt;Update&amp;gt;&lt;/b&gt;&lt;br /&gt;
You can download the sample application from &lt;a href="http://codebetter.com/blogs/karlseguin/archive/2009/04/28/presenting-codebetter-canvas.aspx"&gt;here&lt;/a&gt;. Sorry, it turned into more than just a demo of the validation stuff.&lt;br /&gt;&lt;b&gt;&amp;lt;/Update&amp;gt;&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;So far we&amp;#39;ve built-up a small foundation for a custom validation framework in &lt;a href="http://codebetter.com/blogs/karlseguin/archive/2009/04/26/validation-part-1-getting-started.aspx"&gt;part 1&lt;/a&gt;, and then tied that to a jQuery plugin for our client-side validation in &lt;a href="http://codebetter.com/blogs/karlseguin/archive/2009/04/27/validation-part-2-client-side.aspx"&gt;part 2&lt;/a&gt;. In this part we&amp;#39;ll look at doing server-side validation. Of the three parts, this is the simplest.
&lt;/p&gt;
&lt;h3&gt;Validator&lt;/h3&gt;
&lt;p&gt;Most of the heavy lifting takes place in our &lt;code&gt;Validator&lt;/code&gt; class. Before looking at it, we&amp;#39;ll make use of a simple &lt;code&gt;ValidationError&lt;/code&gt; object to hold any errors:&lt;/p&gt;
&lt;pre name="code" class="c-sharp"&gt;public class ValidationError
{
    public string Field { get; private set; }
    public string Message { get; private set; }

    public ValidationError(string field)
    {
        Field = field;
    }

    public ValidationError(string field, string message)
    {
        Field = field;
        Message = message;
    }
}&lt;/pre&gt;
&lt;p&gt;And here&amp;#39;s the powerful Validator:&lt;/p&gt;
&lt;pre name="code" class="c-sharp"&gt;public interface IValidator
{
    bool Validate(object o, out ValidationError[] errors);
}

public class Validator : IValidator
{
    private readonly IRepository _repository;
    public Validator(IRepository repository)
    {
        _repository = repository;
    }
    
    public bool Validate(object o, out ValidationError[] e)
    {
        var errors = new List&amp;lt;ValidationError&amp;gt;(10);
        var propertyErrors = ValidateProperties(o);
        if (propertyErrors != null)
        {
            errors.AddRange(propertyErrors);
        }
        var customErrors = ValidateCustom(o);
        if (customErrors != null)
        {
            errors.AddRange(customErrors);
        }           
        e = errors.ToArray();
        return e.Length == 0;            
    }        

    private static ICollection&amp;lt;ValidationError&amp;gt; ValidateProperties(object o)
    {                        
        //todo
    }
    private ICollection&amp;lt;ValidationError&amp;gt; ValidateCustom(object o)
    {
        //todo
    }
}&lt;/pre&gt;
&lt;p&gt;All the &lt;code&gt;Validate&lt;/code&gt; method does is take an object and merge any attribute-based errors with any custom-based errors.  Here&amp;#39;s the implementation for &lt;code&gt;ValidateProperties&lt;/code&gt;:&lt;/p&gt;
&lt;pre name="code" class="c-sharp"&gt;private static ICollection&amp;lt;ValidationError&amp;gt; ValidateProperties(object o)
{                        
    if (!ValidatorConfiguration.Rules.ContainsKey(o.GetType()))
    {
        return null;
    }
    var errors = new List&amp;lt;ValidationError&amp;gt;(10);
    foreach (var property in ValidatorConfiguration.Rules[o.GetType()].Properties)
    {
        var value = property.Property.GetValue(o, null);
        foreach (var validator in property.Validators)
        {
            if (validator.IsValid(o, value)) { continue; }
            errors.Add(new ValidationError(property.Property.Name));
            break;
        }
    }
    return errors;
}&lt;/pre&gt;
&lt;p&gt;We loop through each validation attribute of each property of our object (assuming any validation rules are configured for it). Notice that we don&amp;#39;t add a message to our &lt;code&gt;ValidationError&lt;/code&gt; - that&amp;#39;s because those are already rendered on the client in the form of the &amp;quot;tip&amp;quot; - we&amp;#39;ll get back to that in a bit.&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;ValidateCustom&lt;/code&gt; is even simpler:&lt;/p&gt;
&lt;pre name="code" class="c-sharp"&gt;private ICollection&amp;lt;ValidationError&amp;gt; ValidateCustom(object o)
{
    if (!(o is IValidate))
    {
        return null;
    }
    return ((IValidate) o).Validate(_repository);            
}&lt;/pre&gt;
&lt;p&gt;Here&amp;#39;s an example of what a custom &lt;code&gt;Validate&lt;/code&gt; method might look like:&lt;/p&gt;
&lt;pre name="code" class="c-sharp"&gt;//our user clas
public virtual ValidationError[] Validate(IRepository repository)
{
    if (repository.Exists&amp;lt;User&amp;gt;(u =&amp;gt; u.Email == Email))
    {
        return new[] {new ValidationError(&amp;quot;Email&amp;quot;, &amp;quot;This email is already registered&amp;quot;)};
    }
    return null;
}&lt;/pre&gt;
&lt;p&gt;Notice that I pass around an &lt;code&gt;IRepository&lt;/code&gt;. That&amp;#39;s just to show how you might pass infrastructure elements that your validators will need.&lt;/p&gt;
&lt;h3&gt;Back to the Client&lt;/h3&gt;
&lt;p&gt;You can now use the &lt;code&gt;Validator&lt;/code&gt; from your WebForms or Controllers. The downloadable example shows a more proper (opinionated) MVC example, but without going into the necessary infrastructure, you might do something as simple as:&lt;/p&gt;
&lt;pre name="code" class="c-sharp"&gt;public class UserController : Controller
{
    private readonly IValidator _validator;

    public UserController(IValidator validator)
    {
        _validator = validator;            
    }

     //Everything about this action is ugly, check out the example for a better approach
    public ViewResult Register([Bind(Exclude=&amp;quot;id&amp;quot;)]User user)
    {
           ValidationError[] errors;
            if (!_validator.Validate(user, out errors))
            {
                ViewData[&amp;quot;ValidationErrors&amp;quot;] = ToJson(errors);
                return View(user);
            }
            //todo Save the user;
            return View(&amp;quot;RegistrationSuccessful&amp;quot;);
    }

    private string ToJSon(ValidationError[] errors)
    {         
            var sb = new StringBuilder(&amp;quot;init:{&amp;quot;);
            Array.ForEach(errors, e =&amp;gt; sb.AppendFormat(&amp;quot;{0}:&amp;#39;{1}&amp;#39;,&amp;quot;, e.Field, e.Message.Replace(&amp;quot;&amp;#39;&amp;quot;, &amp;quot;\\&amp;#39;&amp;quot;));
            _validationErrors = sb.RemoveLast().Append(&amp;quot;}&amp;quot;).ToString();
            return _validationErrors;
    }
}&lt;/pre&gt;
&lt;p&gt;We&amp;#39;ve serialized our array of errors to JSON and stored them in our &lt;code&gt;ViewData&lt;/code&gt;. We&amp;#39;ll modify our jQuery plugin to handle the errros. First though, we change our jQuery call:&lt;/p&gt;
&lt;pre name="code" class="c-sharp"&gt;$(&amp;#39;#register&amp;#39;).validate({&amp;lt;%=Html.RulesFor&amp;lt;User&amp;gt;() %&amp;gt;, &amp;lt;%=ViewData[&amp;quot;ValidationErrors&amp;quot;]%&amp;gt;});    
&lt;/pre&gt;
&lt;p&gt;The last change is to the &lt;code&gt;initialize&lt;/code&gt; method, while we are hooking up each field&amp;#39;s &lt;code&gt;blur&lt;/code&gt; event, we&amp;#39;ll also see if an init error exists within the options:&lt;/p&gt;
&lt;pre name="code" class="c-sharp"&gt;$fields.each(function(i, field)
{
    var $field = $(field);
    $field.blur(function()
    {
        v.validateField(this);
    });                          
    if (options.init[field.name] != null)                        
    {                            
        v.markAsInvalid($field, options.init[field.name] != &amp;#39;&amp;#39; ? options.init[field.name] : rules[field.name].tip);
    }                      
});&lt;/pre&gt;
&lt;h3&gt;Conclusion&lt;/h3&gt;
&lt;p&gt;Folks, that&amp;#39;s how easy it is to do custom validation. Granted its quite a bit of code, but there&amp;#39;s nothing overly complex (except for maybe the reflection or jQuery plugin if you aren&amp;#39;t familiar with either). Do stay tuned as tomorrow I&amp;#39;ll make a sample application available for download which should help make all of this more useful.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://codebetter.com/aggbug.aspx?PostID=207305" width="1" height="1"&gt;</description></item><item><title>The 7 Phases of Unit Testing</title><link>http://codebetter.com/blogs/karlseguin/archive/2009/04/27/the-7-phases-of-unit-testing.aspx</link><pubDate>Tue, 28 Apr 2009 01:02:00 GMT</pubDate><guid isPermaLink="false">d21fbbc9-c112-4f32-ad14-95939a2c53d4:206105</guid><dc:creator>karl</dc:creator><slash:comments>30</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://codebetter.com/blogs/karlseguin/rsscomments.aspx?PostID=206105</wfw:commentRss><comments>http://codebetter.com/blogs/karlseguin/archive/2009/04/27/the-7-phases-of-unit-testing.aspx#comments</comments><description>&lt;p&gt;1 - Refuse to unit test because &amp;quot;you don&amp;#39;t have enough time&amp;quot;&lt;br /&gt;2 - Start unit testing and immediately start blogging about unit testing and TDD and how great they are and how everyone should do it&lt;br /&gt;3 - Unit test everything - make private methods internal and abuse the InternalsVisibleTo attribute. Test getters and setters or else you won&amp;#39;t get 100% code coverage&lt;br /&gt;4 - Get fed with how brittle your unit tests are and start writing integration tests without realizing it.&lt;br /&gt;5 - Discover a mocking framework and make heavy use of strict semantics&lt;br /&gt;6 - Mock absolutely everything that can possibly be mocked&lt;br /&gt;7 - Start writing effective unit tests&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://codebetter.com/aggbug.aspx?PostID=206105" width="1" height="1"&gt;</description></item><item><title>Validation - Part 2 - Client-Side</title><link>http://codebetter.com/blogs/karlseguin/archive/2009/04/27/validation-part-2-client-side.aspx</link><pubDate>Tue, 28 Apr 2009 00:27:00 GMT</pubDate><guid isPermaLink="false">d21fbbc9-c112-4f32-ad14-95939a2c53d4:206069</guid><dc:creator>karl</dc:creator><slash:comments>7</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://codebetter.com/blogs/karlseguin/rsscomments.aspx?PostID=206069</wfw:commentRss><comments>http://codebetter.com/blogs/karlseguin/archive/2009/04/27/validation-part-2-client-side.aspx#comments</comments><description>&lt;p&gt;Validation - Part 2 - Client-Side
&lt;/p&gt;
&lt;p&gt;In &lt;a href="http://codebetter.com/blogs/karlseguin/archive/2009/04/26/validation-part-1-getting-started.aspx"&gt;Part 1&lt;/a&gt; we looked at our basic framework for validation - a set of attributes, an interface, and some configuration objects. Now we&amp;#39;ll see how these can be used in conjunction with jQuery to provide client-side validation.&lt;/p&gt;
&lt;p&gt;As we already saw, every validation attribute has &lt;code&gt;a ToJson&lt;/code&gt; method which serializes attributes into a dictionary. Our goal is end up with something like:&lt;/p&gt;
&lt;pre name="code" class="c-sharp"&gt;$(&amp;#39;#saveUserForm&amp;#39;).validate(
   {
      rules:
      {
         Email:{required:true,pattern:&amp;#39;.+@.+\\..+&amp;#39;},
         Password:{required:true,min:4,max:30}
      }      
   }
);&lt;/pre&gt;
&lt;h3&gt;HtmlValidation&lt;/h3&gt;
&lt;p&gt;Before we look at the actual jQuery validate function, lets see how we can take our &lt;code&gt;ValidatorConfiguration&lt;/code&gt; to generate this type of JSON object. Like we did with the core &lt;code&gt;ValidationConfiguration&lt;/code&gt;, we&amp;#39;ll cache our JSON strings per object type so that they aren&amp;#39;t generated over and over again. Here&amp;#39;s the core body of our class:&lt;/p&gt;
&lt;p&gt;public static class HtmlValidation
{
	private static readonly IDictionary&amp;lt;Type, string&amp;gt; _rules = new Dictionary&amp;lt;Type, string&amp;gt;();  
	
	public static void Initialize(IDictionary&amp;lt;Type, EntityValidationInfo&amp;gt; rules)
	{            
    	foreach (var rule in rules)
      	{
        	_rules.Add(rule.Key, BuildJson(rule.Value));
	    }
	}
	private static string BuildJson(EntityValidationInfo entity)
	{
        //todo
	}
}&lt;/p&gt;
&lt;p&gt;We initialize this our &lt;code&gt;HtmlValidation&lt;/code&gt; class in our &lt;code&gt;Application_Start&lt;/code&gt;:&lt;/p&gt;
&lt;pre name="code" class="c-sharp"&gt;ValidatorConfiguration.Initialize(&amp;quot;MyAssembly&amp;quot;, &amp;quot;MyAssembly.Web&amp;quot;);  //from part 1
HtmlValidation.Initialize(ValidatorConfiguration.Rules);&lt;/pre&gt;
&lt;p&gt;Next we implement the BuildJson method:&lt;/p&gt;
&lt;pre name="code" class="c-sharp"&gt;private static string BuildJson(EntityValidationInfo entity)
{
    var sb = new StringBuilder(&amp;quot;rules:{&amp;quot;);
    foreach (var property in entity.Properties)
    {                
        sb.Append(property.Property.Name);
        sb.Append(&amp;quot;:{&amp;quot;);
        foreach (BaseValidatorAttribute attribute in property.Validators)
        {
            foreach (var kvp in attribute.ToJson())
            {
                sb.AppendFormat(&amp;quot;{0}:{1},&amp;quot;, kvp.Key, kvp.Value);
            }
        }
        var tip = property.Property.GetCustomAttributes(typeof(TipAttribute), true);
        if (tip != null)
        {
            sb.AppendFormat(&amp;quot;tip:&amp;#39;{0}&amp;#39;&amp;quot;, (((TipAttribute)tip[0]).Tip).Replace(&amp;quot;&amp;#39;&amp;quot;, &amp;quot;\\&amp;#39;&amp;quot;));
        }
        sb.RemoveLastIf(&amp;#39;,&amp;#39;);
        sb.Append(&amp;quot;},&amp;quot;);
    }
    return sb.RemoveLast().Append(&amp;quot;}&amp;quot;).ToString();
}&lt;/pre&gt;
&lt;p&gt;Nothing too fancy here. We ToJson each attribute of each property and join them into a JSON string. Those &lt;code&gt;RemoveLast&lt;/code&gt; and &lt;code&gt;RemoveLastIf&lt;/code&gt; methods on &lt;code&gt;StringBuilder&lt;/code&gt; are little extension methods I use to stay sane:&lt;/p&gt;
&lt;pre name="code" class="c-sharp"&gt;public static class StringBuilderExtensions
{
    public static StringBuilder RemoveLast(this StringBuilder sb)
    {
        return sb.RemoveLast(1);
    }
    public static StringBuilder RemoveLastIf(this StringBuilder sb, char c)
    {
        if (sb.Length &amp;gt; 0 &amp;amp;&amp;amp; sb[sb.Length - 1] == c)
        {
            sb.RemoveLast();
        }
        return sb;            
    }
    public static StringBuilder RemoveLast(this StringBuilder sb, int count)
    {
        if (sb.Length &amp;gt; count)
        {
            sb.Remove(sb.Length - count, count);
        }
        return sb;
    }        
}&lt;/pre&gt;
&lt;p&gt;With that done, we just need a method that makes our cached &lt;code&gt;_rules&lt;/code&gt; accessible. I wrote this an an &lt;code&gt;HtmlHelper&lt;/code&gt; extension for MVC, but there isn&amp;#39;t anything MVC-specific about it. You should be able to easily get this working in WebForms as well:&lt;/p&gt;
&lt;pre name="code" class="c-sharp"&gt;public static string RulesFor&amp;lt;T&amp;gt;(this HtmlHelper html)
{            
    return _rules[typeof (T)];            
} &lt;/pre&gt;
&lt;p&gt;Now we can use that from within our aspx page/view:&lt;/p&gt;
&lt;pre name="code" class="c-sharp"&gt;$(&amp;#39;#register&amp;#39;).validate({&amp;lt;%=Html.RulesFor&amp;lt;User&amp;gt;() %&amp;gt;});   &lt;/pre&gt;
&lt;h3&gt;$.validate&lt;/h3&gt;
&lt;p&gt;Our final task in this part is to build our validate function using jQuery. I&amp;#39;ve written a 2-part primer (&lt;a href="http://dotnetslackers.com/articles/ajax/JQuery-Primer-Part-1.aspx"&gt;part 1&lt;/a&gt;, &lt;a href="http://dotnetslackers.com/articles/ajax/JQuery-Primer-Part-2.aspx"&gt;part 2&lt;/a&gt;) in the past, so I&amp;#39;ll assume that you are familiar with jQuery. Needless to say that I&amp;#39;m a big fan of it and rather enjoy writing JavaScript plugins (funny how much I hated JavaScript not too long ago). We&amp;#39;ll look at the validate plugin in chunks, and I&amp;#39;ll provide the complete code at the end. First, a skeleton:&lt;/p&gt;
&lt;pre name="code" class="c-sharp"&gt;(function($)
{
    $.fn.validate = function(options, command)
    {
        var defaults = { };
        options = $.extend(defaults, options);
        var rules = options.rules;        
        
        return this.each(function()
        {   
            //make sure this isn&amp;#39;t called twice
            if (this.validator) { return false; }
            var $form = $(this);    
            var $fields = $(&amp;#39;input,select,textarea&amp;#39;, $form);

            var v =
            {
                initialize: function()
                {              
                },
                validateField: function(field)
                {                                                              
                },            
                markAsInvalid: function($field, tip)
                {                                                     
                },
                markAsValid: function($field)
                {
                }  
            }                     
            this.validator = v;
            v.initialize();         

        });
    };
})(jQuery);&lt;/pre&gt;
&lt;p&gt;The &lt;code&gt;initialize&lt;/code&gt; method hooks up to the form&amp;#39;s submit event and validates each field, it also gives focus to the first invalid field:&lt;/p&gt;
&lt;pre name="code" class="c-sharp"&gt;initialize: function()
{              
    $form.submit(function()
    {
        var isValid = true;
        $fields.each(function(i, field)
        {                            
            if (!v.validateField(field) &amp;amp;&amp;amp; isValid) 
            { 
                isValid = false;
                $(field).focus();
            }
        });                                                
        return isValid;
    });                    
},&lt;/pre&gt;
&lt;p&gt;By returning false when there&amp;#39;s an error, we prevent the form from submitting. The actual validation takes place inside the &lt;code&gt;validateField&lt;/code&gt; method. Since we only have a few simple validators, everything happens within that method:&lt;/p&gt;
&lt;pre name="code" class="c-sharp"&gt;validateField: function(field)
{                                           
    var rule = rules[field.name];                    
    if (!rule) { return true; }                    
    var $field = $(field);
    var value = $field.val();
    var isValid = true;
    if (rule.required &amp;amp;&amp;amp; value.length == 0) { isValid = false ; }
    else if (rule.min &amp;amp;&amp;amp; rule.min &amp;gt; value.length) { isValid = false; }
    else if (rule.max &amp;amp;&amp;amp; rule.max &amp;lt; value.length) { isValid = false; }
    else if (rule.pattern &amp;amp;&amp;amp; !rule.pattern.test(value)) { isValid = false; }
    if (!isValid)
    {                        
        v.markAsInvalid($field, rule.tip);                        
    }
    else
    {
        v.markAsValid($field);                        
    }
    return isValid;                    
}, &lt;/pre&gt;
&lt;p&gt;The last two methods, &lt;code&gt;markAsValid&lt;/code&gt; and &lt;code&gt;markAsInvalid&lt;/code&gt; display or remove an actual error&lt;/p&gt;
&lt;pre name="code" class="c-sharp"&gt;markAsInvalid: function($field, tip)
{                                    
    if (tip)
    {
        var $tip = $field.siblings(&amp;#39;.tip&amp;#39;);
        if ($tip.length == 0)
        {                        
            $tip = $(&amp;#39;&amp;lt;label&amp;gt;&amp;#39;).attr(&amp;#39;for&amp;#39;, $field.attr(&amp;#39;name&amp;#39;)).addClass(&amp;#39;tip&amp;#39;).insertAfter($field);                        
        }
        $tip.html(tip).fadeIn();
    }
    $field.addClass(&amp;#39;error&amp;#39;);
},
markAsValid: function($field)
{
    $field.siblings(&amp;#39;.tip&amp;#39;).fadeOut();
    $field.removeClass(&amp;#39;error&amp;#39;);
}  &lt;/pre&gt;
&lt;p&gt;
if &lt;code&gt;markAsValid&lt;/code&gt; is given a tip, it&amp;#39;ll add and fadeIn a label next to the field. It&amp;#39;ll also add a class named error to the field. &lt;code&gt;markAsValid&lt;/code&gt; does the opposite - fading out the tip and removing the class.&lt;/p&gt;
&lt;h3&gt;Improvement&lt;/h3&gt;
&lt;p&gt;We&amp;#39;ll add a slight improvement to our &lt;code&gt;initialize&lt;/code&gt; method - not only will we hook into the form&amp;#39;s submit event, but also each field&amp;#39;s blur event, so that users get a more responsive feel. Luckily, all the infrastructure is already in place, so all we do is add the following code to initialize:&lt;/p&gt;
&lt;pre name="code" class="c-sharp"&gt;$fields.each(function(i, field)
{
    var $field = $(field);
    $field.blur(function()
    {
        v.validateField(this);
    });                                            
});&lt;/pre&gt;
&lt;h3&gt;Code&lt;/h3&gt;
&lt;p&gt;Believe it or not, all that code make up only two classes. Since it was all broken up, here they are.&lt;/p&gt;
&lt;p&gt;First, the &lt;code&gt;HtmlValidation&lt;/code&gt; class (minus the &lt;code&gt;StringBuilder&lt;/code&gt; extentions):&lt;/p&gt;
&lt;pre name="code" class="c-sharp"&gt;public static class HtmlValidationExtensions
{
    private static readonly IDictionary&amp;lt;Type, string&amp;gt; _rules = new Dictionary&amp;lt;Type, string&amp;gt;();    
    public static string RulesFor&amp;lt;T&amp;gt;(this HtmlHelper html)
    {            
        return _rules[typeof (T)];            
    }
    public static void Initialize(IDictionary&amp;lt;Type, EntityValidationInfo&amp;gt; rules)
    {            
        foreach (var rule in rules)
        {
            _rules.Add(rule.Key, BuildJson(rule.Value));
        }
    }
    private static string BuildJson(EntityValidationInfo entity)
    {
        var sb = new StringBuilder(&amp;quot;rules:{&amp;quot;);
        foreach (var property in entity.Properties)
        {                
            sb.Append(property.Property.Name);
            sb.Append(&amp;quot;:{&amp;quot;);
            foreach (BaseValidatorAttribute attribute in property.Validators)
            {
                foreach (var kvp in attribute.ToJson())
                {
                    sb.AppendFormat(&amp;quot;{0}:{1},&amp;quot;, kvp.Key, kvp.Value);
                }
            }
            var tip = property.Property.GetCustomAttributes(typeof(TipAttribute), true);
            if (tip != null)
            {
                sb.AppendFormat(&amp;quot;tip:&amp;#39;{0}&amp;#39;&amp;quot;, (((TipAttribute)tip[0]).Tip).Replace(&amp;quot;&amp;#39;&amp;quot;, &amp;quot;\\&amp;#39;&amp;quot;));
            }
            sb.RemoveLastIf(&amp;#39;,&amp;#39;);
            sb.Append(&amp;quot;},&amp;quot;);
        }
        return sb.RemoveLast().Append(&amp;quot;}&amp;quot;).ToString();
    }
}&lt;/pre&gt;
&lt;p&gt;Next, the &lt;code&gt;$.validate&lt;/code&gt; plugin:&lt;/p&gt;
&lt;pre name="code" class="c-sharp"&gt;(function($)
{
    $.fn.validate = function(options, command)
    {
        var defaults = { };
        options = $.extend(defaults, options);
        var rules = options.rules;        
        
        return this.each(function()
        {
            if (this.validator) { return false; }
            var $form = $(this);    
            var $fields = $(&amp;#39;input,select,textarea&amp;#39;, $form);

            var v =
            {
                initialize: function()
                {
                    $fields.each(function(i, field)
                    {
                        var $field = $(field);
                        $field.blur(function()
                        {
                            v.validateField(this);
                        });                                      
                    });
                    $form.submit(function()
                    {
                        var isValid = true;
                        $fields.each(function(i, field)
                        {                            
                            if (!v.validateField(field) &amp;amp;&amp;amp; isValid) 
                            { 
                                isValid = false;
                                $(field).focus();
                            }
                        });                                                
                        return isValid;
                    });                    
                },
                validateField: function(field)
                {                                           
                    var rule = rules[field.name];                    
                    if (!rule) { return true; }                    
                    var $field = $(field);
                    var value = $field.val();
                    var isValid = true;
                    if (rule.required &amp;amp;&amp;amp; value.length == 0) { isValid = false ; }
                    else if (rule.min &amp;amp;&amp;amp; rule.min &amp;gt; value.length) { isValid = false; }
                    else if (rule.max &amp;amp;&amp;amp; rule.max &amp;lt; value.length) { isValid = false; }
                    else if (rule.pattern &amp;amp;&amp;amp; !rule.pattern.test(value)) { isValid = false; }
                    if (!isValid)
                    {                        
                        v.markAsInvalid($field, rule.tip);                        
                    }
                    else
                    {
                        v.markAsValid($field);                        
                    }
                    return isValid;
                    
                },            
                markAsInvalid: function($field, tip)
                {                                    
                    if (tip)
                    {
                        var $tip = $field.siblings(&amp;#39;.tip&amp;#39;);
                        if ($tip.length == 0)
                        {                        
                            $tip = $(&amp;#39;&amp;lt;label&amp;gt;&amp;#39;).attr(&amp;#39;for&amp;#39;, $field.attr(&amp;#39;name&amp;#39;)).addClass(&amp;#39;tip&amp;#39;).insertAfter($field);                        
                        }
                        $tip.html(tip).fadeIn();
                    }
                    $field.addClass(&amp;#39;error&amp;#39;);
                },
                markAsValid: function($field)
                {
                    $field.siblings(&amp;#39;.tip&amp;#39;).fadeOut();
                    $field.removeClass(&amp;#39;error&amp;#39;);
                }  
            }                     
            this.validator = v;
            v.initialize();         
        });
    };
})(jQuery);&lt;/pre&gt;
&lt;h3&gt;Conclusion&lt;/h3&gt;
&lt;p&gt;That&amp;#39;s a lot of code, but hopefully it&amp;#39;ll help you get started. In part 3 we&amp;#39;ll look at server-side validation, and how to tie that back into the client.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://codebetter.com/aggbug.aspx?PostID=206069" width="1" height="1"&gt;</description></item><item><title>Validation - Part 1 - Getting Started</title><link>http://codebetter.com/blogs/karlseguin/archive/2009/04/26/validation-part-1-getting-started.aspx</link><pubDate>Sun, 26 Apr 2009 19:17:00 GMT</pubDate><guid isPermaLink="false">d21fbbc9-c112-4f32-ad14-95939a2c53d4:204139</guid><dc:creator>karl</dc:creator><slash:comments>12</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://codebetter.com/blogs/karlseguin/rsscomments.aspx?PostID=204139</wfw:commentRss><comments>http://codebetter.com/blogs/karlseguin/archive/2009/04/26/validation-part-1-getting-started.aspx#comments</comments><description>&lt;p&gt;There are a lot of good and free frameworks to help you deal with validating user-submitted data. You can use attribute-based frameworks, such as Castle Validators or .NET 3.5 Data Annotations to decorate your objects with simple rules, and then leverage frameworks such as xVal or the MVC Validation Toolkit to enforce those attribute both on the client and server side.  (For those who dislike using attributes in this manner, you could also use something like FluentValidation).&lt;/p&gt;
&lt;p&gt;Despite these frameworks, there may be situations where you need to roll your own, which is what we&amp;#39;re going to look at in this series. We won&amp;#39;t be doing anything fancy, but we will look at an end-to-end custom solution.&lt;/p&gt;
&lt;h3&gt;Attributes&lt;/h3&gt;
&lt;p&gt;The first thing we need to do is decide how we&amp;#39;ll define our rules. We&amp;#39;ll pick a mix of attributes for simple validation cases, and an interface for more advanced/custom validation.  Our goal is to end up with something like:&lt;/p&gt;
&lt;pre name="code" class="c-sharp"&gt;public interface IValidate
{
    ValidationError[] Validate(IRepository repository);
}

public class User : IValidate
{        
	private string _email;
	private string _password;

	[Required, StringLength(50), Pattern(&amp;quot;.+@.+\\..+&amp;quot;), Tip(&amp;quot;Please enter a valid email, a confirmation email will be sent.&amp;quot;)]
	public string Email
	{
	    get { return _email; }
	    set { _email = value; }
	}
	[Required, StringLength(4, 30), Tip(&amp;quot;Please enter your password. 4-30 characters&amp;quot;)]
	public string Password
	{
	    get { return _password; }
	    set { _password = value; }
	}

	public virtual ValidationError[] Validate(IRepository repository)
	{
	    if (repository.Exists&amp;lt;User&amp;gt;(u =&amp;gt; u.Email == Email))
	    {
	        return new[] {new ValidationError(&amp;quot;Email&amp;quot;, &amp;quot;This email is already registered&amp;quot;)};
	    }
	    return null;
	}
}&lt;/pre&gt;
&lt;p&gt;
We could always externalize the &amp;quot;Tips&amp;quot; for localization (or cleanliness) purposes, but this keeps everything rather simple. (If you&amp;#39;re put off by the attributes, check out&lt;a href="http://www.codeplex.com/FluentValidation"&gt;FluentValidation&lt;/a&gt; for an idea on how else you migth define your rules).
&lt;/p&gt;
&lt;p&gt;The foundation for our attributes is a simple base class:&lt;/p&gt;
&lt;pre name="code" class="c-sharp"&gt;[AttributeUsage(AttributeTargets.Property, AllowMultiple = false, Inherited = true)]
public abstract class BaseValidatorAttribute : Attribute
{
   public abstract IDictionary&amp;lt;string, string&amp;gt; ToJson();
   public abstract bool IsValid(object value);
}
&lt;/pre&gt;
&lt;p&gt;And here&amp;#39;s the simplest implementation:&lt;/p&gt;
&lt;pre name="code" class="c-sharp"&gt;public class RequiredAttribute : BaseValidatorAttribute
{
    public override IDictionary&amp;lt;string, string&amp;gt; ToJson()
    {
        return new Dictionary&amp;lt;string, string&amp;gt; {{&amp;quot;required&amp;quot;, &amp;quot;true&amp;quot;}};
    }  

    public override bool IsValid(object value)
    {
        if (value == null)
        {
            return false;
        }
        return !(value is string) || ((string)value).Length != 0;
    }
}&lt;/pre&gt;
&lt;p&gt;The &lt;code&gt;IsValid&lt;/code&gt; method is used to validate the object server-side. The &lt;code&gt;ToJson&lt;/code&gt; method is used to generate a javascript object for client-side use.&lt;/p&gt;
&lt;p&gt;Let&amp;#39;s take a look at the &lt;code&gt;StringLengthAttribute&lt;/code&gt; - which is slightly more complicated:&lt;/p&gt;
&lt;pre name="code" class="c-sharp"&gt;public class StringLengthAttribute : BaseValidatorAttribute
{
   private readonly int _minimumLength;
   private readonly int _maximumLength;

   public int MinimumLength
   {
      get { return _minimumLength; }
   }
   public int MaximumLength
   {
      get { return _maximumLength; }
   }

   public StringLengthAttribute(int maximumLength) : this(0, maximumLength){}
   public StringLengthAttribute(int minimumLength, int maximumLength)
   {
      _minimumLength = minimumLength;
      _maximumLength = maximumLength;
   }

   public override IDictionary&amp;lt;string, string&amp;gt; ToJson()
   {            
      return new Dictionary&amp;lt;string, string&amp;gt;
         {
            { &amp;quot;min&amp;quot;, _minimumLength.ToString() },
            { &amp;quot;max&amp;quot;, _maximumLength.ToString() },
         };
   }

   public override bool IsValid(object value)
   {            
      if (!(value is string))
      {
         return false;
      }            
      var length = ((string)value).Length;
      return length &amp;gt;= _minimumLength &amp;amp;&amp;amp; length &amp;lt;= _maximumLength;
   }
}&lt;/pre&gt;
&lt;p&gt;There really is no limit to what you&amp;#39;re able to do with these attributes. You can build groups of validation rules (each group might have its own tip), compare validators, or even validators that hit the DB, such as a &lt;code&gt;UniqueAttribute&lt;/code&gt; (although we&amp;#39;ve opted to implement that via the &lt;code&gt;IValidate&lt;/code&gt; interface). &lt;/p&gt;
&lt;h3&gt;ValidatorConfiguration&lt;/h3&gt;
&lt;p&gt;There are two problems we&amp;#39;ll run into by using attributes - they are somewhat cumbersome to program against, and they can impact performance. Since validation is static, we can parse and cache more useful structures which we can then use when doing our actual client-side and server-side validation. We&amp;#39;ll use two classes to represent our attributes:&lt;/p&gt;
&lt;pre name="code" class="c-sharp"&gt;public class EntityValidationInfo
{
   public IEnumerable&amp;lt;PropertyValidationInfo&amp;gt; Properties { get; private set; }
   public EntityValidationInfo(IEnumerable&amp;lt;PropertyValidationInfo&amp;gt; properties)
   {        
      Properties = properties;
   }
}
public class PropertyValidationInfo
{
   public IEnumerable&amp;lt;BaseValidatorAttribute&amp;gt; Validators { get; private set; }
   public PropertyInfo Property { get; private set;}
   public PropertyValidationInfo(PropertyInfo property, IEnumerable&amp;lt;BaseValidatorAttribute&amp;gt; validators)
   {
      Property = property;
      Validators = validators;
   }
}&lt;/pre&gt;
&lt;p&gt;The purpose behind these is that given an object type, we can lookup its &lt;code&gt;EntityValidationInfo&lt;/code&gt; which contains a collection of properties and validators. Next we&amp;#39;ll create a &lt;code&gt;ValidatorConfiguration&lt;/code&gt; class with a couple static members:&lt;/p&gt;
&lt;pre name="code" class="c-sharp"&gt;public class ValidatorConfiguration
{
    private static IDictionary&amp;lt;Type, EntityValidationInfo&amp;gt; _rules;
    public static IDictionary&amp;lt;Type, EntityValidationInfo&amp;gt; Rules
    {
        get { return _rules; }
    }
    public static void Initialize(params string[] assemblyNames)
    {     
          //todo
    }
}&lt;/pre&gt;
&lt;p&gt;Our goal is to initialize &lt;code&gt;ValidatorConfiguration&lt;/code&gt; once, on startup, and then access its &lt;code&gt;Rules&lt;/code&gt; property as needed. The &lt;code&gt;Initialize&lt;/code&gt; method takes in assembly names to scan for classes using validation attributes (you might have these spread out across multiple assemblies). In an ASP.NET application, we&amp;#39;d use the Application_Start event and use something like:&lt;/p&gt;
&lt;pre name="code" class="c-sharp"&gt;ValidatorConfiguration.Initialize(&amp;quot;MyAssembly&amp;quot;, &amp;quot;MyAssembly.Web&amp;quot;);&lt;/pre&gt;
&lt;p&gt;Finally, the implementation of Initialize looks like:&lt;/p&gt;
&lt;pre name="code" class="c-sharp"&gt;public static void Initialize(params string[] assemblyNames)
{
   _rules = new Dictionary&amp;lt;Type, EntityValidationInfo&amp;gt;(10);
   foreach (var assemblyName in assemblyNames)
   {
       foreach (var kvp in LoadFromAssembly(Assembly.Load(assemblyName)))
       {
           _rules.Add(kvp.Key, kvp.Value);
       }                
   }
}
private static IDictionary&amp;lt;Type, EntityValidationInfo&amp;gt; LoadFromAssembly(Assembly assembly)
{
   var rules = new Dictionary&amp;lt;Type, EntityValidationInfo&amp;gt;(10);
   foreach (var type in assembly.GetExportedTypes())
   {
       var info = GetEntityValidationInfo(type);
       if (info != null) { rules.Add(type, info); }
   }
   return rules;
}
private static EntityValidationInfo GetEntityValidationInfo(Type type)
{
   var properties = new List&amp;lt;PropertyValidationInfo&amp;gt;();
   foreach (var property in type.GetProperties())
   {
       var attributes = (BaseValidatorAttribute[])property.GetCustomAttributes(typeof(BaseValidatorAttribute), true);
       if (attributes.Length == 0) { continue; }
       properties.Add(new PropertyValidationInfo(property, attributes));
   }
   return properties.Count == 0 ? null : new EntityValidationInfo(properties);
}&lt;/pre&gt;
&lt;p&gt;There isn&amp;#39;t much magic going on here. We loop through each property, of each public type of each assembly, looking for validation attributes. If we don&amp;#39;t find any, we simply move on to the next. If we do find them, we create new instances of our &lt;code&gt;EntityValidationInfo&lt;/code&gt; and &lt;code&gt;PropertyValidationInfo&lt;/code&gt; and associate that to a Type within the static &lt;code&gt;_rules&lt;/code&gt; field.&lt;/p&gt;
&lt;h3&gt;Conclusion&lt;/h3&gt;
&lt;p&gt;We&amp;#39;ve managed to lay the foundation for actually being able to validate stuff. In Part 2 we&amp;#39;ll look at client-side validation, and in Part 3 we&amp;#39;ll cover server-side validation. Stay tuned.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://codebetter.com/aggbug.aspx?PostID=204139" width="1" height="1"&gt;</description></item><item><title>www.asp.net costs millions to run?</title><link>http://codebetter.com/blogs/karlseguin/archive/2009/04/25/www-asp-net-costs-millions-to-run.aspx</link><pubDate>Sat, 25 Apr 2009 15:02:00 GMT</pubDate><guid isPermaLink="false">d21fbbc9-c112-4f32-ad14-95939a2c53d4:202698</guid><dc:creator>karl</dc:creator><slash:comments>34</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://codebetter.com/blogs/karlseguin/rsscomments.aspx?PostID=202698</wfw:commentRss><comments>http://codebetter.com/blogs/karlseguin/archive/2009/04/25/www-asp-net-costs-millions-to-run.aspx#comments</comments><description>&lt;p&gt;For those who missed it, &lt;a href="http://www.misfitgeek.com/"&gt;Joe Stagner&lt;/a&gt; commented that www.asp.net costs millions of dollars to run. Since Joe was a little vague about exactly what that meant, I&amp;#39;m going to assume that he&amp;#39;s talking about straight-up yearly hosting costs (because it was in the context of hosting, and if that was a monthly cost it would be 12-times more incredible than the already incredible yearly cost). I find this either highly doubtful, or really worrisome.
&lt;/p&gt;
&lt;p&gt;So let&amp;#39;s look at what $83 000 a month of hosting gets you. Now, there are tens of thousands of possible hosting companies. My top picks would be Softlayer, Peer1, DataPipe or LiquiqWeb - all of which have the right blend of price and reliability (Softlayer and DataPipe are always on Netcraft&amp;#39;s list of most reliable hosting providers). We&amp;#39;re talking real quality hosting here. For about $350/month, I can get (more or less) the following server from any of these places:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Quad Core Xeon 5335 Clovertown @ 2.00GHz &lt;/li&gt;
&lt;li&gt;2GB of ram&lt;/li&gt;
&lt;li&gt;2x250GB SATA RAID 1&lt;/li&gt;
&lt;li&gt;2TB bandwidth&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;You&amp;#39;d likely want different servers for different roles - such as more RAM and SCSI drives on your database servers, but for simplicity sake, lets keep everything homogenized.&lt;/p&gt;
&lt;p&gt;That $83 000 buys you roughly 240 such servers - fully managed. Am I the only one who thinks that&amp;#39;s a lot? Consider too that this is retail price, surely Microsoft, with such a large order, could get drastically lower prices (and the fact that they heavily promote their existing hosting company).  Now, it&amp;#39;s possible that Joe was talking about more than just www.asp.net, and possibly all of the &amp;quot;Microsoft Community&amp;quot; sites (channel 9, IIS 7.0, silverlight.net...). That might make things slightly more reasonable. However, I remain both skeptical, and very curious about the details of this server farm. How many memcached servers are in play? Is database sharding used? Are lightweight HTTPd servers or CDN networks used for static content?&lt;/p&gt;
&lt;p&gt;What worries me is that if it costs Microsoft millions of dollars to run its own community sites, with its bulk-purchasing power and &lt;b&gt;free Microsoft licences&lt;/b&gt; what chance to the rest of us have? It suddenly becomes obvious why IIS has a lower market penetration amongst popular sites (19%) than its average market penetration (29%). Its also obvious why that market penetration has gone down over the past couple years.&lt;/p&gt;
&lt;p&gt;Finally, I&amp;#39;m curious if they do any carbon offsetting. I doubt this setup is even close to achieving google&amp;#39;s amazing PUE of 1.13.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://codebetter.com/aggbug.aspx?PostID=202698" width="1" height="1"&gt;</description></item><item><title>Is ASP.NET MVC a half-baked solution?</title><link>http://codebetter.com/blogs/karlseguin/archive/2009/04/24/is-asp-net-mvc-a-half-baked-solution.aspx</link><pubDate>Fri, 24 Apr 2009 17:45:00 GMT</pubDate><guid isPermaLink="false">d21fbbc9-c112-4f32-ad14-95939a2c53d4:202085</guid><dc:creator>karl</dc:creator><slash:comments>30</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://codebetter.com/blogs/karlseguin/rsscomments.aspx?PostID=202085</wfw:commentRss><comments>http://codebetter.com/blogs/karlseguin/archive/2009/04/24/is-asp-net-mvc-a-half-baked-solution.aspx#comments</comments><description>&lt;p&gt;Earlier this morning, I commented on twitter that I was starting my 2nd full-fledged ASP.NET MVC project, and was finding myself writing a massive amount of infrastructure code. Ironically, having to write so much infrastructure code was a major complaint I had against both &lt;a href="http://codebetter.com/blogs/karlseguin/archive/2008/12/15/oxite-oh-dear-lord-why.aspx"&gt;Oxite&lt;/a&gt; and &lt;a href="http://codebetter.com/blogs/karlseguin/archive/2009/04/16/kobe-oh-dead-lord-why.aspx"&gt;Kobe&lt;/a&gt;. A number of other twitter-folk replied with similar thoughts.  There isn&amp;#39;t a day that passes that I don&amp;#39;t think to myself using ASP.NET MVC is a mistake.&lt;/p&gt;
&lt;p&gt;Let&amp;#39;s be clear, ASP.NET MVC is an improvement over WebForms - and those developers refusing to leverage ASP.NET MVC (or something else) for new projects are simply lazy. WebForms is full of leaky abstraction, really tight coupling, and ridiculous concepts - such as viewstates and postbacks. &lt;/p&gt;
&lt;p&gt;Being able to write complex systems more cleanly is a good start, but given where web development stands in general, and other platforms specifically, ASP.NET MVC lags far behind (Perl being the only one I can think of which is worse).&lt;/p&gt;
&lt;p&gt;There&amp;#39;s little question that a big part of the problem is that this is really a VC stack - there is no thought, no support, and no tools for the Model. When you compare the thousands of lines you&amp;#39;ll end up writing for your repository/dal/linq/nhiberate to other MVC stacks (which commonly only require that your models to inherit from 1 class), you&amp;#39;re already at a serious productivity disadvantage. But the true impact is actually much worse - you lose any cohesiveness of purpose through the controller and views. There is no way to generate HTML labels from model properties, or client side validation. In frameworks such as Akelos, RoR or Django everything flows outwards from the model which allows those frameworks to provide cohesive and integrated tools, not just HtmlHelpers, ActionResults and Routing (which is &lt;b&gt;all&lt;/b&gt; you get from ASP.NET MVC).&lt;/p&gt;
&lt;p&gt;You end up having to do a whole lot of plumbing on both sides of your system.
Alternatively, you can leverage some OSS tools, like MvcContrib, FluentNHibernate, xVal, Castle.*, jQuery. While all of those tools are really great, they too lack any cohesiveness.  For example, trying to modify the jquery.validate hook from xVal which relied on modified Castle.Validators (to make them work on FluentHTML) was simply too much work for me. I considered using FluentValidation, but the only reference to xVal integration was a blog post.&lt;/p&gt;
&lt;p&gt;I&amp;#39;m a huge fan of these tools, but ASP.NET MVC + 7 different OSS projects simply can&amp;#39;t come close to competing with the elegance, ease of use, and completeness of a well-managed and controlled project like Web2Py (for one of the many examples).&lt;/p&gt;
&lt;p&gt;There is some good news, and that&amp;#39;s that a lot of this &amp;quot;infrastructure&amp;quot; is reusable, which makes projects like &lt;a href="http://code.google.com/p/sharp-architecture/"&gt;S#arp Architecture&lt;/a&gt; possible. However, I&amp;#39;m still sceptical that these projects can truly succeed against better integrated frameworks.&lt;/p&gt;
&lt;p&gt;There will be those that defend ASP.NET MVC by saying that it&amp;#39;s still very young. Microsoft only has itself to blame for being so slow and hard-headed for so long. Others will be thankful that ASP.NET MVC is less opinionated, and thus more flexible, than most other MVC stacks. I agree with this, but only because they ought to have an System.Mvc.Core assembly which contains the open-and-flexible frameworks (yet still provide much more than they currently do), as well as a System.Mvc assembly which is much more opinionated and thus provides even greater functionality.&lt;/p&gt;
&lt;p&gt;When you look at the popular web frameworks for web 2.0 style sites, ASP.NET MVC and WebForms are backed by the biggest and richest company (by several  orders of magnitude) yet remains the least popular.  ASP.NET MVC offers less features, requires more knoweldge, and has lower productivity, despite Microsoft having a cafeteria staff that&amp;#39;s probably 10x the size of PHP, Rails and Django&amp;#39;s entire development teams combined. (Even more ironic, www.asp.net is the only major web-framework website to have ads on it...none of the open source websites do...how screwed up is that?)
&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://codebetter.com/aggbug.aspx?PostID=202085" width="1" height="1"&gt;</description></item><item><title>Tidbit - svn:externals</title><link>http://codebetter.com/blogs/karlseguin/archive/2009/04/20/tidbit-svn-externals.aspx</link><pubDate>Mon, 20 Apr 2009 13:24:00 GMT</pubDate><guid isPermaLink="false">d21fbbc9-c112-4f32-ad14-95939a2c53d4:199337</guid><dc:creator>karl</dc:creator><slash:comments>5</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://codebetter.com/blogs/karlseguin/rsscomments.aspx?PostID=199337</wfw:commentRss><comments>http://codebetter.com/blogs/karlseguin/archive/2009/04/20/tidbit-svn-externals.aspx#comments</comments><description>&lt;p&gt;Not too long ago, I had a need to tie a number of svn repositories together. What I wanted was to create a 1 repository with a number of sharable assets (images, language files, 3rd party libraries, shared code) and have other repositories somehow link to it.&lt;/p&gt;
&lt;p&gt;The way I had handled this in the past was simple: checkout each svn repository and cross reference them. As an example, my directory structure would look something like:&lt;/p&gt;
&lt;pre&gt;AssetRepository/references/xunit.dll
Project1Respository/Project1.sln
Project1Respository/Project1.Tests/Project1.Tests.csproj&lt;/pre&gt;
&lt;p&gt;I would then add a reference to the xunit.dll from Project1.Tests, which would use the following relative path: ../../AssetRepository/references/xunt.dll.&lt;/p&gt;
&lt;p&gt;This solution works great, except it imposes a structure that each team-member must adhere to. In this case, all repositories must be at the same level within the same folder.&lt;/p&gt;
&lt;p&gt;Luckily, Subversion has a better solution, the svn:externals property. svn:externals essentially creates a shortcut/link from a folder in one repository to some other repository (or to another place within the same repository). Once 1 person sets it up, it just works for everyone else &amp;ndash; they&amp;#39;ll never know that AssetRepository even exists. &lt;/p&gt;
&lt;p&gt;How do you do it? If you are using TurtoiseSVN, right click on the Project1Repository and pick &amp;ldquo;Properties&amp;rdquo; from the TurtoiseSVN context-menu. Add a new entry with the name of &amp;quot;svn:externals&amp;quot; and a value to the local path + SPACE + external repository. In our case, value would look like:&lt;/p&gt;
&lt;pre&gt;References svn://AssetRepository/references&lt;/pre&gt;
&lt;p&gt;That&amp;#39;s all there is to it. You checkout the Project1Repository, you&amp;#39;ll end up with an extra folder:&lt;/p&gt;
&lt;pre&gt;Project1Respository/Project1.sln
Project1Respository/Project1.Tests/Project1.Tests.csproj
Project1Respository/References/xunit.dll&lt;/pre&gt;
&lt;p&gt;You might think that you need to create an empty &amp;#39;References&amp;#39; folder at the root of your Project1Repository &amp;ndash; don&amp;#39;t. The local path specified in your svn:externals definition should not physically exists within that repository.&lt;/p&gt;
&lt;p&gt;That&amp;#39;s all there is to it. Other developers can now checkout/commit without ever knowing how things are set. If they change a file within the References/ folder, it&amp;#39;ll commit to the proper repository, namely AssetRepository.&lt;/p&gt;
&lt;p&gt;You can learn more from the &lt;a href="http://svnbook.red-bean.com/nightly/en/svn.advanced.externals.html"&gt;red-book&lt;/a&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://codebetter.com/aggbug.aspx?PostID=199337" width="1" height="1"&gt;</description></item></channel></rss>