<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-8281741202770949929</id><updated>2012-02-01T23:06:42.595+03:00</updated><category term='C#'/><category term='C++'/><category term='jqGrid'/><category term='HP'/><category term='jQuery'/><category term='git'/><category term='Chrome'/><category term='Spark'/><category term='concepts'/><category term='Razor'/><category term='DRY'/><category term='SSRS'/><category term='VS2010'/><category term='NHibernate'/><category term='Hardware'/><category term='DDD'/><category term='ubuntu'/><category term='ASP.NET MVC'/><category term='Silverlight'/><category term='humor'/><category term='FireFox'/><title type='text'>Programmer's Den</title><subtitle type='html'></subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://sprokhorenko.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8281741202770949929/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://sprokhorenko.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Sergey Prokhorenko</name><uri>http://www.blogger.com/profile/06389461574659526392</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://4.bp.blogspot.com/_St_fXOeTKCk/Sp0sRG9IkRI/AAAAAAAAAAM/Fccwc6J00SE/S220/1344263.jpeg'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>96</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-8281741202770949929.post-1715168113213973907</id><published>2012-02-01T22:59:00.001+03:00</published><updated>2012-02-01T23:06:42.607+03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='C++'/><title type='text'>Specialize C++ constructor template parameter by base type</title><content type='html'>&lt;div dir="ltr" style="text-align: left;" trbidi="on"&gt;If we want to restrict C++ templated member function type, we can use return type:&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;class&lt;/b&gt; A&lt;br /&gt;
{&lt;br /&gt;
&amp;nbsp;&amp;nbsp; &lt;b&gt;template&lt;/b&gt; &amp;lt;&lt;b&gt;typename&lt;/b&gt; T&amp;gt;&lt;br /&gt;
&amp;nbsp;&amp;nbsp; &lt;b&gt;typename&lt;/b&gt; std::enable_if&amp;lt;std::is_base_of&amp;lt;base, T&amp;gt;::value&amp;gt;::type function(T arg) {}&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
function will be considered only if T is derived from base. But what in case of A::A() constructor? There's no return value.&lt;br /&gt;
&lt;br /&gt;
In this case we can use a dummy parameter with default value:&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;class&lt;/b&gt; A&lt;br /&gt;
{&lt;br /&gt;
&amp;nbsp;&amp;nbsp; &lt;b&gt;template&lt;/b&gt; &amp;lt;&lt;b&gt;typename&lt;/b&gt; T&amp;gt;&lt;br /&gt;
&amp;nbsp;&amp;nbsp; A(T arg, &lt;b&gt;typename&lt;/b&gt; std::enable_if&amp;lt;std::is_base_of&amp;lt;base, T&amp;gt;::value&amp;gt;::type *dummy = 0) {}&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
This constructor will be used only for types derived from base, and we can still invoke it with single parameter. Even more, this constructor will still be used in implicit type conversions:&lt;br /&gt;
&lt;br /&gt;
A variable = derived_from_base();&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8281741202770949929-1715168113213973907?l=sprokhorenko.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sprokhorenko.blogspot.com/feeds/1715168113213973907/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://sprokhorenko.blogspot.com/2012/02/specialize-c-constructor-template.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8281741202770949929/posts/default/1715168113213973907'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8281741202770949929/posts/default/1715168113213973907'/><link rel='alternate' type='text/html' href='http://sprokhorenko.blogspot.com/2012/02/specialize-c-constructor-template.html' title='Specialize C++ constructor template parameter by base type'/><author><name>Sergey Prokhorenko</name><uri>http://www.blogger.com/profile/06389461574659526392</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://4.bp.blogspot.com/_St_fXOeTKCk/Sp0sRG9IkRI/AAAAAAAAAAM/Fccwc6J00SE/S220/1344263.jpeg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8281741202770949929.post-6410671004208124059</id><published>2011-09-23T11:43:00.000+03:00</published><updated>2011-09-23T11:43:49.391+03:00</updated><title type='text'>Char is not string</title><content type='html'>&lt;div dir="ltr" style="text-align: left;" trbidi="on"&gt;Did you know that&lt;br /&gt;
&lt;b&gt;(list.Count() + ' ').ToString()&lt;/b&gt;&lt;br /&gt;
produces "33"&lt;br /&gt;
and&lt;br /&gt;
&lt;b&gt;list.Count() + " "&lt;/b&gt;&lt;br /&gt;
produces "1 "?&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8281741202770949929-6410671004208124059?l=sprokhorenko.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sprokhorenko.blogspot.com/feeds/6410671004208124059/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://sprokhorenko.blogspot.com/2011/09/char-is-not-string.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8281741202770949929/posts/default/6410671004208124059'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8281741202770949929/posts/default/6410671004208124059'/><link rel='alternate' type='text/html' href='http://sprokhorenko.blogspot.com/2011/09/char-is-not-string.html' title='Char is not string'/><author><name>Sergey Prokhorenko</name><uri>http://www.blogger.com/profile/06389461574659526392</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://4.bp.blogspot.com/_St_fXOeTKCk/Sp0sRG9IkRI/AAAAAAAAAAM/Fccwc6J00SE/S220/1344263.jpeg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8281741202770949929.post-127608700249258087</id><published>2011-03-28T11:54:00.001+03:00</published><updated>2011-03-28T11:55:56.241+03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ASP.NET MVC'/><title type='text'>Bind to entity Id</title><content type='html'>&lt;div dir="ltr" style="text-align: left;" trbidi="on"&gt;Since I started to use ASP.NET MVC, I enjoy model binders. They take a huge amount of irrelevant infrastructure code out sight, out of code, and out of mind, making it easier to create and maintain.&lt;br /&gt;
&lt;br /&gt;
Now, one of the most helpful custom binders that I use if the one that binds entity by id.&lt;br /&gt;
&lt;br /&gt;
The basic idea is that if we have&lt;br /&gt;
&lt;span class="Apple-style-span" style="color: blue;"&gt;&amp;nbsp; public ActionResult Action(Entity entity) {}&lt;/span&gt;&lt;br /&gt;
or in view model&lt;br /&gt;
&lt;span class="Apple-style-span" style="color: blue;"&gt;&amp;nbsp; public Entity EntityProperty { get; set; }&lt;/span&gt;&lt;br /&gt;
we don't have to write any code - entity will be bound to data by the binder, and we get either object and no errors, or null and failed ModelState.&lt;br /&gt;
&lt;br /&gt;
&lt;div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;&lt;span class="Apple-style-span" style="color: blue;"&gt;&amp;nbsp; public ActionResult Action(Entity entity)&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="color: blue;"&gt;&amp;nbsp; {&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="color: blue;"&gt;&amp;nbsp; &amp;nbsp; if (!ModelState.IsValid) { return ... }&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="color: blue;"&gt;&amp;nbsp; }&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div&gt;Here we have model state errors for &lt;b&gt;all&lt;/b&gt; failed entities (invalid IDs from page, not found in DB, etc), without any single line of code (except our one-for-all binder).&lt;/div&gt;&lt;div&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div&gt;In the views, I have something like&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="color: blue;"&gt;&amp;nbsp; ${Html.HiddenFor(x =&amp;gt; x.EntityProperty)}&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div&gt;I can't use .EditorFor(x =&amp;gt; x.EntityProperty.Id) because I will get wrong name in POST, so how do I get id in the input value? There're two approaches:&lt;/div&gt;&lt;div&gt;1. Tweak view template or html helpers, so that, when entity (derived from BaseEntity, for example) is passed to HiddenFor, it uses .Id instead of .ToString()&lt;/div&gt;&lt;div&gt;2. Override Entity.ToString() to return .Id.ToString()&lt;/div&gt;&lt;div&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div&gt;Now, even if we do Html.EditorFor(Model) - for entire model - we get proper IDs for entities, and we get them back on POST - without any additional code at all.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div&gt;Sometimes, we want to bind by another property, not Id. E.g. in REST/urls we want product name as parameters, not ids - because it looks better in URLs. Hard? Not at all, we just apply a different binder:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div&gt;&lt;div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;&lt;span class="Apple-style-span" style="color: blue;"&gt;&amp;nbsp; public ActionResult Action([ModelBinder(typeof(EntityNameBinder))] Entity entity) {}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div&gt;where our EntityNameBinder is:&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="color: blue;"&gt;&amp;nbsp; &amp;nbsp;public class EntityNameBinder : EntityBinder&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="color: blue;"&gt;&amp;nbsp; &amp;nbsp;{&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="color: blue;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; public EntityNameBinder() : base("Name") { }&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="color: blue;"&gt;&amp;nbsp; &amp;nbsp;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;- that is, we just pass property name to bind to. Internally binder uses repository to find entities (simplified):&lt;/div&gt;&lt;pre class="c-sharp" name="code"&gt;&amp;nbsp; var rep = ServiceLocator.Current.GetInstance(typeof(IBaseRepository&amp;lt;&amp;gt;).MakeGenericType(entityType));

&amp;nbsp; var boundValue = rep.GetType().GetMethod("FindOne").Invoke(rep, new object[]{ new Dictionary&amp;lt;string, object&amp;gt;{{propertyName, valueFromView}} });&lt;/pre&gt;&lt;div&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div&gt;This method works even for lists, we just tweak our custom binder a bit to detect IList&amp;lt;Entity&amp;gt;/Entity. And so we can use this in view models:&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="color: blue;"&gt;&amp;nbsp; public IList&amp;lt;Entity&amp;gt; EntityListProperty { get; set; }&lt;/span&gt;&lt;/div&gt;&lt;div&gt;once again without any single line of additional code.&lt;br /&gt;
&lt;br /&gt;
Another usefull aspect of this approach, is that controllers code is very clean - model in, model view out - and thus very easy to test.&lt;br /&gt;
&lt;br /&gt;
And, last but not least, one should never bind to entities directly - because it is not safe (remote user can bind to non-desired public properties, etc). With this custom binder, this is completely eliminated - there's no way to fill entity properties with values from the page, period. The workflow is always to create view model (whose properties get values from the page) and then use it populate entity (using AutoMapper, for example).&lt;/div&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8281741202770949929-127608700249258087?l=sprokhorenko.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sprokhorenko.blogspot.com/feeds/127608700249258087/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://sprokhorenko.blogspot.com/2011/03/bind-to-entity-id.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8281741202770949929/posts/default/127608700249258087'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8281741202770949929/posts/default/127608700249258087'/><link rel='alternate' type='text/html' href='http://sprokhorenko.blogspot.com/2011/03/bind-to-entity-id.html' title='Bind to entity Id'/><author><name>Sergey Prokhorenko</name><uri>http://www.blogger.com/profile/06389461574659526392</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://4.bp.blogspot.com/_St_fXOeTKCk/Sp0sRG9IkRI/AAAAAAAAAAM/Fccwc6J00SE/S220/1344263.jpeg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8281741202770949929.post-8041416054035298697</id><published>2011-02-16T15:44:00.000+02:00</published><updated>2011-02-16T15:44:41.590+02:00</updated><title type='text'>Matryoshka</title><content type='html'>&lt;div dir="ltr" style="text-align: left;" trbidi="on"&gt;Opening remote ftp in VirtualBox guest though virtualbox shared folder that points to /home/user/.gvfs is how we all work today.&lt;br /&gt;
&lt;br /&gt;
I mean, virtualization über alles.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8281741202770949929-8041416054035298697?l=sprokhorenko.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sprokhorenko.blogspot.com/feeds/8041416054035298697/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://sprokhorenko.blogspot.com/2011/02/matryoshka.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8281741202770949929/posts/default/8041416054035298697'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8281741202770949929/posts/default/8041416054035298697'/><link rel='alternate' type='text/html' href='http://sprokhorenko.blogspot.com/2011/02/matryoshka.html' title='Matryoshka'/><author><name>Sergey Prokhorenko</name><uri>http://www.blogger.com/profile/06389461574659526392</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://4.bp.blogspot.com/_St_fXOeTKCk/Sp0sRG9IkRI/AAAAAAAAAAM/Fccwc6J00SE/S220/1344263.jpeg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8281741202770949929.post-3529205324111409637</id><published>2011-02-04T10:55:00.000+02:00</published><updated>2011-02-04T10:55:09.811+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='git'/><title type='text'>Moving to git</title><content type='html'>&lt;div dir="ltr" style="text-align: left;" trbidi="on"&gt;Yes, everybody did this already. And if you did not, hurry up! There's limited number of git repositories in the world, don't be late!&lt;br /&gt;
&lt;br /&gt;
Git is a fantastic tool, and the only problem is that it looks too complex at first. But it is not, really, at least if you don't do fancy branching and merging within your 10 people scrum team. If you work alone (or in pair) it's much simpler and you can still benefit from it.&lt;br /&gt;
&lt;br /&gt;
Here's why:&amp;nbsp;&lt;a href="http://whygitisbetterthanx.com/"&gt;whygitisbetterthanx.com/&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
Well, I just don't want to repeat what has been said so many times. But for me, it allows for much easier branching and merging.&amp;nbsp;Often customers need a small fix to existing production version while I'm working on next sprint. git seems to have a lot of tools to make it easy - stash, easy branching, etc.&lt;br /&gt;
&lt;br /&gt;
And it's fast.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8281741202770949929-3529205324111409637?l=sprokhorenko.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sprokhorenko.blogspot.com/feeds/3529205324111409637/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://sprokhorenko.blogspot.com/2011/02/moving-to-git.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8281741202770949929/posts/default/3529205324111409637'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8281741202770949929/posts/default/3529205324111409637'/><link rel='alternate' type='text/html' href='http://sprokhorenko.blogspot.com/2011/02/moving-to-git.html' title='Moving to git'/><author><name>Sergey Prokhorenko</name><uri>http://www.blogger.com/profile/06389461574659526392</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://4.bp.blogspot.com/_St_fXOeTKCk/Sp0sRG9IkRI/AAAAAAAAAAM/Fccwc6J00SE/S220/1344263.jpeg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8281741202770949929.post-1481502634566260631</id><published>2011-01-13T11:47:00.000+02:00</published><updated>2011-01-13T11:47:41.957+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ASP.NET MVC'/><title type='text'>What matters</title><content type='html'>And frankly, ASP.NET MVC v1 is enough to go. No need for fancy stuff.&lt;br /&gt;
&lt;br /&gt;
Because, what really matters is domain logic and code. ASP.NET MVC is just a thin framework, almost infrastructure. If it is &amp;gt;50% of your project, then your're doing it wrong. Move all the infrastructure out of the way (attributes, IoC, etc).&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8281741202770949929-1481502634566260631?l=sprokhorenko.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sprokhorenko.blogspot.com/feeds/1481502634566260631/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://sprokhorenko.blogspot.com/2011/01/what-matters.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8281741202770949929/posts/default/1481502634566260631'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8281741202770949929/posts/default/1481502634566260631'/><link rel='alternate' type='text/html' href='http://sprokhorenko.blogspot.com/2011/01/what-matters.html' title='What matters'/><author><name>Sergey Prokhorenko</name><uri>http://www.blogger.com/profile/06389461574659526392</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://4.bp.blogspot.com/_St_fXOeTKCk/Sp0sRG9IkRI/AAAAAAAAAAM/Fccwc6J00SE/S220/1344263.jpeg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8281741202770949929.post-4975456667883837247</id><published>2010-12-15T15:13:00.001+02:00</published><updated>2010-12-15T15:13:18.667+02:00</updated><title type='text'>Verison</title><content type='html'>For many times I type to fast and get "verison" instead of "version" in my sources.&lt;br /&gt;
&lt;br /&gt;
I wonder if that's how they got the name.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8281741202770949929-4975456667883837247?l=sprokhorenko.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sprokhorenko.blogspot.com/feeds/4975456667883837247/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://sprokhorenko.blogspot.com/2010/12/verison.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8281741202770949929/posts/default/4975456667883837247'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8281741202770949929/posts/default/4975456667883837247'/><link rel='alternate' type='text/html' href='http://sprokhorenko.blogspot.com/2010/12/verison.html' title='Verison'/><author><name>Sergey Prokhorenko</name><uri>http://www.blogger.com/profile/06389461574659526392</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://4.bp.blogspot.com/_St_fXOeTKCk/Sp0sRG9IkRI/AAAAAAAAAAM/Fccwc6J00SE/S220/1344263.jpeg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8281741202770949929.post-3955734132698513662</id><published>2010-12-15T14:59:00.000+02:00</published><updated>2010-12-15T14:59:06.693+02:00</updated><title type='text'>Vimperator</title><content type='html'>Finally got installed and used to Vimperator for Firefox. It's fantastic! Now I see why similarities (like Vrome for Chrome) are called "pale shade" by some people.&lt;br /&gt;
&lt;br /&gt;
Also, Vimperator doesn't mean that I have to seat with both hands on keyboard like a hardcore hacker. It's so convinient (with autocompletion etc) that I can rule the browser with only left hand. Without Vimperator I can also rule my browser with only one hand (the one that holds the mouse) - but even that feel harder and more awkward compared to what Vimperator gives me.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8281741202770949929-3955734132698513662?l=sprokhorenko.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sprokhorenko.blogspot.com/feeds/3955734132698513662/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://sprokhorenko.blogspot.com/2010/12/vimperator.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8281741202770949929/posts/default/3955734132698513662'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8281741202770949929/posts/default/3955734132698513662'/><link rel='alternate' type='text/html' href='http://sprokhorenko.blogspot.com/2010/12/vimperator.html' title='Vimperator'/><author><name>Sergey Prokhorenko</name><uri>http://www.blogger.com/profile/06389461574659526392</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://4.bp.blogspot.com/_St_fXOeTKCk/Sp0sRG9IkRI/AAAAAAAAAAM/Fccwc6J00SE/S220/1344263.jpeg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8281741202770949929.post-7731589311025275020</id><published>2010-12-08T16:05:00.000+02:00</published><updated>2010-12-08T16:05:04.510+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='C#'/><title type='text'>We can do without it</title><content type='html'>Do you remember those days when &lt;a href="http://en.wikipedia.org/wiki/Hungarian_notation"&gt;Hungarian notation&lt;/a&gt; was widely used? That was long ago. With its move to C# Microsoft invented a completely new set of rules - CamelCase, no prefixes, and so on. Hungarian notation died.&lt;br /&gt;
&lt;br /&gt;
My colleague argued that Hungarian notation was good because one could tell much about a variable type with sources opened even in Notepad. In C#, there was now much less information. The only place where variable type was available was at the declaration.&lt;br /&gt;
&lt;br /&gt;
In forth C# version, Microsoft added the &lt;a href="http://msdn.microsoft.com/en-us/library/bb383973.aspx"&gt;var&lt;/a&gt; keyword. Done (at least I think so) to allow for anonymous types, LINQ, and related stuff, it is now also widely used in plain old source code because of the simplicity it gives. However, with this keyword, we stripped &lt;b&gt;all&lt;/b&gt; type information from our variables. In the line&lt;br /&gt;
&lt;br /&gt;
var block = item.GetChild();&lt;br /&gt;
&lt;br /&gt;
we see zero details on what is block. The only source of information now is intellisense.&lt;br /&gt;
&lt;br /&gt;
And I don't see anyone complaining that they can't see variable type in their Notepad.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8281741202770949929-7731589311025275020?l=sprokhorenko.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sprokhorenko.blogspot.com/feeds/7731589311025275020/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://sprokhorenko.blogspot.com/2010/12/we-can-do-without-it.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8281741202770949929/posts/default/7731589311025275020'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8281741202770949929/posts/default/7731589311025275020'/><link rel='alternate' type='text/html' href='http://sprokhorenko.blogspot.com/2010/12/we-can-do-without-it.html' title='We can do without it'/><author><name>Sergey Prokhorenko</name><uri>http://www.blogger.com/profile/06389461574659526392</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://4.bp.blogspot.com/_St_fXOeTKCk/Sp0sRG9IkRI/AAAAAAAAAAM/Fccwc6J00SE/S220/1344263.jpeg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8281741202770949929.post-4173597608654751632</id><published>2010-11-12T16:26:00.000+02:00</published><updated>2010-11-12T16:26:41.601+02:00</updated><title type='text'>The importance of end-user testing</title><content type='html'>Recently I implemented a feature for a project. After that, I got 500 random data pieces from the database and tested. No errors. Then I deployed new version.&lt;br /&gt;
&lt;br /&gt;
The next day I got error report from the user who couldn't use the new feature at all. Two different pieces of data, two different errors in my code. That's already hilarious. But there's more. I fixed both issues, and deployed another version.&lt;br /&gt;
&lt;br /&gt;
The next day, I got error report from the user who couldn't use the new feature at all. One more arbitrary piece of data. One more error in my code. Well, &lt;i&gt;that&lt;/i&gt; was the last one, but...&lt;br /&gt;
&lt;br /&gt;
Picture this to yourself - you see a program and you got 3 attempts. Bang! Bang! Bang! You shot randomly into 3 different places and right to the bugs there.&lt;br /&gt;
&lt;br /&gt;
Programmers just can't do that. They know too well where to aim.&lt;br /&gt;
&lt;br /&gt;
So, what does it tell us?&lt;br /&gt;
&lt;br /&gt;
1. Programmers can't test. They can't do QA. You have to have testers and/or end user to verify what programmers did.&lt;br /&gt;
2. Don't trust machine tests. You can throw hundreds of input data pieces to your test, be it unit tests or integration tests, it doesn't matter. You can't predict or replicate what users do. They &lt;b&gt;will&lt;/b&gt; do something you didn't think about.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8281741202770949929-4173597608654751632?l=sprokhorenko.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sprokhorenko.blogspot.com/feeds/4173597608654751632/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://sprokhorenko.blogspot.com/2010/11/importance-of-end-user-testing.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8281741202770949929/posts/default/4173597608654751632'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8281741202770949929/posts/default/4173597608654751632'/><link rel='alternate' type='text/html' href='http://sprokhorenko.blogspot.com/2010/11/importance-of-end-user-testing.html' title='The importance of end-user testing'/><author><name>Sergey Prokhorenko</name><uri>http://www.blogger.com/profile/06389461574659526392</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://4.bp.blogspot.com/_St_fXOeTKCk/Sp0sRG9IkRI/AAAAAAAAAAM/Fccwc6J00SE/S220/1344263.jpeg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8281741202770949929.post-3060776715907501073</id><published>2010-11-09T17:15:00.000+02:00</published><updated>2010-11-09T17:15:21.152+02:00</updated><title type='text'>Look under the dress</title><content type='html'>That is just an example of bad code, though widely used by many:&lt;br /&gt;
&lt;br /&gt;
if (this.GetType().Name == "ParentTypeName")&lt;br /&gt;
&amp;nbsp;&amp;nbsp; // do funny workarounds&lt;br /&gt;
&lt;br /&gt;
Basically same thing as doing static variables, gotos, controlling workflow via exceptions, etc.&lt;br /&gt;
&lt;br /&gt;
What's really funny here is that many people argue that it's OK, because this code &lt;b&gt;works&lt;/b&gt;. And to change it is as easy as adding overridable method and change implementation there. Oh well.&lt;br /&gt;
&lt;br /&gt;
I could never explain such things to those people, which (I believe) is my fault. I suppose the only way would be to collect &lt;b&gt;practical&lt;/b&gt; examples of related gotchas - because, just as I said, those people believe that it is OK if it works, i.e. they're won't buy abstract reasoning.&lt;br /&gt;
&lt;br /&gt;
&lt;i&gt;Your code is not maintenable&lt;/i&gt; - "bullshit" they say.&lt;br /&gt;
&lt;i&gt;We lost 1 day fixing &lt;b&gt;these&lt;/b&gt; bugs because of such code, and customers were already upset and lost some data, and now we don't even know how to add &lt;b&gt;a feature&lt;/b&gt; without breaking existing implementation because compiler doesn't tell us anymore that property name changed&lt;/i&gt; - well, this &lt;b&gt;may&lt;/b&gt; work.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8281741202770949929-3060776715907501073?l=sprokhorenko.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sprokhorenko.blogspot.com/feeds/3060776715907501073/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://sprokhorenko.blogspot.com/2010/11/look-under-dress.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8281741202770949929/posts/default/3060776715907501073'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8281741202770949929/posts/default/3060776715907501073'/><link rel='alternate' type='text/html' href='http://sprokhorenko.blogspot.com/2010/11/look-under-dress.html' title='Look under the dress'/><author><name>Sergey Prokhorenko</name><uri>http://www.blogger.com/profile/06389461574659526392</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://4.bp.blogspot.com/_St_fXOeTKCk/Sp0sRG9IkRI/AAAAAAAAAAM/Fccwc6J00SE/S220/1344263.jpeg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8281741202770949929.post-3229901353783688997</id><published>2010-10-12T12:18:00.000+03:00</published><updated>2010-10-12T12:18:23.879+03:00</updated><title type='text'>Ubuntu 10.10: improved once again</title><content type='html'>I don't know how they did it - I believe it's not Canonical but freetype developers, maybe because of &lt;a href="http://apple.slashdot.org/story/10/07/19/1524250/FreeType-Project-Cheers-TrueType-Patent-Expiration"&gt;bytecode patents expiration&lt;/a&gt; - but still, the Ubuntu fonts that I'm so fond of are even better now! It's mostly white/light-on-black where they were slightly colored previously, now they're crisp and contrast everywhere.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8281741202770949929-3229901353783688997?l=sprokhorenko.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sprokhorenko.blogspot.com/feeds/3229901353783688997/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://sprokhorenko.blogspot.com/2010/10/ubuntu-1010-improved-once-again.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8281741202770949929/posts/default/3229901353783688997'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8281741202770949929/posts/default/3229901353783688997'/><link rel='alternate' type='text/html' href='http://sprokhorenko.blogspot.com/2010/10/ubuntu-1010-improved-once-again.html' title='Ubuntu 10.10: improved once again'/><author><name>Sergey Prokhorenko</name><uri>http://www.blogger.com/profile/06389461574659526392</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://4.bp.blogspot.com/_St_fXOeTKCk/Sp0sRG9IkRI/AAAAAAAAAAM/Fccwc6J00SE/S220/1344263.jpeg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8281741202770949929.post-3916612331173548008</id><published>2010-09-20T11:58:00.000+03:00</published><updated>2010-09-20T11:58:54.688+03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='C#'/><title type='text'>It's still dangerous</title><content type='html'>I've spent 2 days trying to understand why my new code does not work. I've added caching, and depending on request, it started to return completely different results for same IDs.&lt;br /&gt;
&lt;br /&gt;
So I invested a lot of time into caching problems, ASP.NET threading issues, and so on.&lt;br /&gt;
&lt;br /&gt;
And then, finally, I've spot the wrong code. It was...&lt;br /&gt;
&lt;br /&gt;
list.Where(x =&gt; x.IsFlagSet = isFlagSet)&lt;br /&gt;
&lt;br /&gt;
Damn! I thought that they had protected us from hitting this wall in C#... but no, it's still unsafe when a boolean variable is assigned. Not even a warning from the compiler. You can easily do an assignment inside your if/where, and God help you to find the bug.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8281741202770949929-3916612331173548008?l=sprokhorenko.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sprokhorenko.blogspot.com/feeds/3916612331173548008/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://sprokhorenko.blogspot.com/2010/09/its-still-dangerous.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8281741202770949929/posts/default/3916612331173548008'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8281741202770949929/posts/default/3916612331173548008'/><link rel='alternate' type='text/html' href='http://sprokhorenko.blogspot.com/2010/09/its-still-dangerous.html' title='It&apos;s still dangerous'/><author><name>Sergey Prokhorenko</name><uri>http://www.blogger.com/profile/06389461574659526392</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://4.bp.blogspot.com/_St_fXOeTKCk/Sp0sRG9IkRI/AAAAAAAAAAM/Fccwc6J00SE/S220/1344263.jpeg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8281741202770949929.post-9014287743551787507</id><published>2010-09-17T22:13:00.000+03:00</published><updated>2010-09-17T22:13:07.927+03:00</updated><title type='text'>Just use the tools</title><content type='html'>I often see questions on StackOverflow about some javascript code that doesn't work, where people (that ask the question) didn't even try to debug this code. Like they never knew that javascript debuggers existed. I just don't get it.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8281741202770949929-9014287743551787507?l=sprokhorenko.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sprokhorenko.blogspot.com/feeds/9014287743551787507/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://sprokhorenko.blogspot.com/2010/09/just-use-tools.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8281741202770949929/posts/default/9014287743551787507'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8281741202770949929/posts/default/9014287743551787507'/><link rel='alternate' type='text/html' href='http://sprokhorenko.blogspot.com/2010/09/just-use-tools.html' title='Just use the tools'/><author><name>Sergey Prokhorenko</name><uri>http://www.blogger.com/profile/06389461574659526392</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://4.bp.blogspot.com/_St_fXOeTKCk/Sp0sRG9IkRI/AAAAAAAAAAM/Fccwc6J00SE/S220/1344263.jpeg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8281741202770949929.post-2132346099951004429</id><published>2010-09-13T17:31:00.000+03:00</published><updated>2010-09-13T17:31:46.544+03:00</updated><title type='text'>Fiddler and connection refused</title><content type='html'>My IE crashed during Silverlight application debug session, so that I had to forcibly close VirtualBox Windows session, and restart it.&lt;br /&gt;
&lt;br /&gt;
No internet. Not even localhost. "Connection refused" for any URL.&lt;br /&gt;
&lt;br /&gt;
This could be because of a proxy, but I didn't have any. It took me 5 minutes to remember that I had Fiddler turned on and to do a wild guess that maybe Fiddler tweaks IE to use (some kind of) a proxy during session.&lt;br /&gt;
&lt;br /&gt;
I just ran Fiddler again, and &lt;span class="f"&gt;&lt;cite&gt;voilà&lt;/cite&gt;&lt;/span&gt; - everything back to normal.&lt;br /&gt;
&lt;br /&gt;
Just a funny fact of everyday's life.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8281741202770949929-2132346099951004429?l=sprokhorenko.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sprokhorenko.blogspot.com/feeds/2132346099951004429/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://sprokhorenko.blogspot.com/2010/09/fiddler-and-connection-refused.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8281741202770949929/posts/default/2132346099951004429'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8281741202770949929/posts/default/2132346099951004429'/><link rel='alternate' type='text/html' href='http://sprokhorenko.blogspot.com/2010/09/fiddler-and-connection-refused.html' title='Fiddler and connection refused'/><author><name>Sergey Prokhorenko</name><uri>http://www.blogger.com/profile/06389461574659526392</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://4.bp.blogspot.com/_St_fXOeTKCk/Sp0sRG9IkRI/AAAAAAAAAAM/Fccwc6J00SE/S220/1344263.jpeg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8281741202770949929.post-3786984613585475362</id><published>2010-09-08T22:22:00.002+03:00</published><updated>2010-09-08T22:22:48.237+03:00</updated><title type='text'>Hush!</title><content type='html'>Yes it's possible, and I'm absolutely happy now. 45nm technology processor to ensure not much heat is generated (and not much air flow is needed), PWM fan working at lowest speed, Corsair power supply for very low noise, and notebook 2.5" hard drive - now my old active speakers produce more noise than the computer.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8281741202770949929-3786984613585475362?l=sprokhorenko.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sprokhorenko.blogspot.com/feeds/3786984613585475362/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://sprokhorenko.blogspot.com/2010/09/hush.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8281741202770949929/posts/default/3786984613585475362'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8281741202770949929/posts/default/3786984613585475362'/><link rel='alternate' type='text/html' href='http://sprokhorenko.blogspot.com/2010/09/hush.html' title='Hush!'/><author><name>Sergey Prokhorenko</name><uri>http://www.blogger.com/profile/06389461574659526392</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://4.bp.blogspot.com/_St_fXOeTKCk/Sp0sRG9IkRI/AAAAAAAAAAM/Fccwc6J00SE/S220/1344263.jpeg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8281741202770949929.post-4478129844580123061</id><published>2010-08-24T12:35:00.000+03:00</published><updated>2010-08-24T12:35:47.028+03:00</updated><title type='text'>Programming = workarounds</title><content type='html'>Since working on MS Access databases I learned that programming is really nothing more than finding workarounds against bugs and incompatibilities. Anyone can "vision" the program; but it takes experience to implement. This is why theoretical programming skills given to us in college matter nothing in real life. It's hard to apply them without bumping into couple of things that you would never thought about.&lt;br /&gt;
&lt;br /&gt;
Here's an example.&lt;br /&gt;
&lt;br /&gt;
In Spark View Engine one can use H() to HTML encode stuff. Very convenient. Now, suddenly when I render my view to PDF I get null references instead of customer properties (because I see ${H(customer.Name)} instead of customer name). The same view has just been rendered perfectly as web page.&lt;br /&gt;
&lt;br /&gt;
Now, is it easy to guess that H() is actually a method of the HtmlHelper, and that .Html property of the Page object is null in this case, while none of these facts are mentioned in the ${H(customer.Name)} code, nor it's mentioned anywhere in the books that .Html can ever be null?&lt;br /&gt;
&lt;br /&gt;
Pretty easy, once you have experience, and you're used to apply logic like "customer properties were not null on web page, we pass same view model to PDF generation view, view is the same, just context is different, so, the problem is not in customer object, so this must be H(), may be it is not static but member of HtmlHelper, and it is null, despite the crazyness of this fact".&lt;br /&gt;
&lt;br /&gt;
The above sentence is a huge part of the real everyday programming.&lt;br /&gt;
&lt;br /&gt;
Did I say huge? No, just a little part. Because then you have to find out how to solve this. Use System.Web.HttpUtility.HtmlEncode instead of H()? Or, if you know how, write Spark macro on that page to override H() behaviour - and you have to know Spark macros, and that they are compiled into functions, and all the stuff about scopes, that local function created by macro will be used instead of a more global H(), etc.&lt;br /&gt;
&lt;br /&gt;
And please think how maintainable this will be. And if you can have similar issues in other places. And this little piece of knowledge (.Html can be null) is now in your head. And this is what builds up the experience - the experience that will help you (or a collegue) 3 years later in a completely different situation in Java and weird framework where they have page object that can't be null.&lt;br /&gt;
&lt;br /&gt;
But know you know it can.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8281741202770949929-4478129844580123061?l=sprokhorenko.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sprokhorenko.blogspot.com/feeds/4478129844580123061/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://sprokhorenko.blogspot.com/2010/08/programming-workarounds.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8281741202770949929/posts/default/4478129844580123061'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8281741202770949929/posts/default/4478129844580123061'/><link rel='alternate' type='text/html' href='http://sprokhorenko.blogspot.com/2010/08/programming-workarounds.html' title='Programming = workarounds'/><author><name>Sergey Prokhorenko</name><uri>http://www.blogger.com/profile/06389461574659526392</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://4.bp.blogspot.com/_St_fXOeTKCk/Sp0sRG9IkRI/AAAAAAAAAAM/Fccwc6J00SE/S220/1344263.jpeg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8281741202770949929.post-998755836453278972</id><published>2010-07-27T14:01:00.000+03:00</published><updated>2010-07-27T14:01:52.770+03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ASP.NET MVC'/><title type='text'>Do views need Intellisense?</title><content type='html'>I've just seen a comment about new ASP.NET MVC v3 release that includes Razor view engine yet without Intellisense support:&lt;br /&gt;
&lt;blockquote&gt;It's good to see Razor but I can't live now without Intellisense&lt;/blockquote&gt;Yet I make my Spark views without any Intellisense at all and I'm happy about it. Why? It's written on the Spark's web site: because it allows HTML to dominate.&lt;br /&gt;
&lt;br /&gt;
No extra HTML helpers, no fancy C# inside views. I don't use MvcContrib grid, I write my HTML helpers using Spark macros, I write forms and links using HTML tags. In fact, I write HTML vews and only add properties where appropriate.&lt;br /&gt;
&lt;br /&gt;
Yes, I need to know few C# calls and property names, but I never had problems with it, don't make your views to deal with too much C# code and you'll be good.&lt;br /&gt;
&lt;br /&gt;
In fact, I think, if you can't write your views without Intellisense, then you're using too much C# code in your views and you're actually writing &lt;b&gt;bad&lt;/b&gt; views. Stop it. Use Spark (or StringTemplate) and you won't need Intellisense no more.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8281741202770949929-998755836453278972?l=sprokhorenko.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sprokhorenko.blogspot.com/feeds/998755836453278972/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://sprokhorenko.blogspot.com/2010/07/do-views-need-intellisense.html#comment-form' title='10 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8281741202770949929/posts/default/998755836453278972'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8281741202770949929/posts/default/998755836453278972'/><link rel='alternate' type='text/html' href='http://sprokhorenko.blogspot.com/2010/07/do-views-need-intellisense.html' title='Do views need Intellisense?'/><author><name>Sergey Prokhorenko</name><uri>http://www.blogger.com/profile/06389461574659526392</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://4.bp.blogspot.com/_St_fXOeTKCk/Sp0sRG9IkRI/AAAAAAAAAAM/Fccwc6J00SE/S220/1344263.jpeg'/></author><thr:total>10</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8281741202770949929.post-6740324466044076454</id><published>2010-07-16T23:59:00.000+03:00</published><updated>2010-07-16T23:59:23.753+03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='DDD'/><title type='text'>DDD terminology</title><content type='html'>&lt;div class="post-text"&gt;Another re-post from StackOverflow from the question about about DDD terms.&lt;br /&gt;
&lt;br /&gt;
This is my understanding and I did &lt;strong&gt;NOT&lt;/strong&gt; read any DDD book, even the holy bible of it.&lt;br /&gt;
&lt;ul&gt;&lt;li&gt;Services - stateless classes that usually operate on different layer objects, thus helping to decouple them; also to avoid code duplication&lt;/li&gt;
&lt;li&gt;Factories - classes that knows how to create objects, thus decouple invoking code from knowing implementation details, making it easier to switch implementations; many factories also help to auto-resolve object dependencies (IoC containers); factories are infrastructure&lt;/li&gt;
&lt;li&gt;Repository - interfaces (and corresponding implementations) that narrows data access to the bare minimum that clients should know about&lt;/li&gt;
&lt;li&gt;Aggregates - classes that unifies access to several related entities via single interfaces (e.g. order and line items)&lt;/li&gt;
&lt;li&gt;Domain Objects (Entities) - classes that operate purely on domain/business logic, and do not care about persistence, presentation, or other concerns&lt;/li&gt;
&lt;li&gt;Infrastructure - classes/layers that glue different objects or layers together; contains the actual implementation details that are not important to real application/user at all (e.g. how data is written to database, how HTTP form is mapped to view models)&lt;/li&gt;
&lt;/ul&gt;Repository provides access to a very specific, usually single, kind of domain object. They emulate collection of objects, to some extent. Services usually operate on very different types of objects, usually accessed via static methods (do not have state), and can perform any operation (e.g. send email, prepare report), while repositories concentrate on CRUD methods.&lt;br /&gt;
&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8281741202770949929-6740324466044076454?l=sprokhorenko.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sprokhorenko.blogspot.com/feeds/6740324466044076454/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://sprokhorenko.blogspot.com/2010/07/ddd-terminology.html#comment-form' title='5 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8281741202770949929/posts/default/6740324466044076454'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8281741202770949929/posts/default/6740324466044076454'/><link rel='alternate' type='text/html' href='http://sprokhorenko.blogspot.com/2010/07/ddd-terminology.html' title='DDD terminology'/><author><name>Sergey Prokhorenko</name><uri>http://www.blogger.com/profile/06389461574659526392</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://4.bp.blogspot.com/_St_fXOeTKCk/Sp0sRG9IkRI/AAAAAAAAAAM/Fccwc6J00SE/S220/1344263.jpeg'/></author><thr:total>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8281741202770949929.post-3109466497049440550</id><published>2010-07-04T17:53:00.000+03:00</published><updated>2010-07-04T17:53:00.442+03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Razor'/><category scheme='http://www.blogger.com/atom/ns#' term='ASP.NET MVC'/><category scheme='http://www.blogger.com/atom/ns#' term='Spark'/><title type='text'>Razor view engine</title><content type='html'>Today I &lt;a href="http://stackoverflow.com/questions/3174786/asp-net-mvc-razor-view-engine/3174910#3174910"&gt;learned&lt;/a&gt; about new default ASP.NET MVC view engine called Razor. Yes from what I read they're going to make it a default choice for views instead of WebForms. Nice! I'm still not convinced to move away from Spark, however; you can see why from the link above. Here're few goodies that Spark has:&lt;br /&gt;
&lt;ul&gt;&lt;li&gt;write html extensions using same markup language, not C# (macros) - I  see that Razor also supports this, I hope it supports method/parameters  override;&lt;/li&gt;
&lt;li&gt;custom tags (write _Tag.spark to use &amp;lt;Tag /&amp;gt;);&lt;/li&gt;
&lt;li&gt;autogenerated variables like varIsFirst, varIndex, etc;&lt;/li&gt;
&lt;li&gt;special expression forms (?{} for conditional attributes, $!{} to  skip errors, etc);&lt;/li&gt;
&lt;li&gt;nice master/partial layouts support, including ability to specify in  partial that part of markup should be render only once in master (e.g.  script includes);&lt;/li&gt;
&lt;li&gt;you can still have WebForms markup - great for compatibility and  incremental upgrade;&lt;/li&gt;
&lt;li&gt;support to use both "" and '' quotes inside each other (extremely  useful).&lt;/li&gt;
&lt;/ul&gt;But Razor is a view engine from &lt;b&gt;Microsoft&lt;/b&gt;; enough to say. We can expect its usage to raise in a year or so. Which is good, because once people start using Razor, and if it's not good, it will be easier for them to switch to Spark rather than back to WebForms. And the world will become a bit better ;-)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8281741202770949929-3109466497049440550?l=sprokhorenko.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sprokhorenko.blogspot.com/feeds/3109466497049440550/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://sprokhorenko.blogspot.com/2010/07/razor-view-engine.html#comment-form' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8281741202770949929/posts/default/3109466497049440550'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8281741202770949929/posts/default/3109466497049440550'/><link rel='alternate' type='text/html' href='http://sprokhorenko.blogspot.com/2010/07/razor-view-engine.html' title='Razor view engine'/><author><name>Sergey Prokhorenko</name><uri>http://www.blogger.com/profile/06389461574659526392</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://4.bp.blogspot.com/_St_fXOeTKCk/Sp0sRG9IkRI/AAAAAAAAAAM/Fccwc6J00SE/S220/1344263.jpeg'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8281741202770949929.post-8184920017480028145</id><published>2010-06-17T15:39:00.001+03:00</published><updated>2010-07-04T00:09:48.062+03:00</updated><title type='text'>Readability counts</title><content type='html'>&lt;code&gt;This is the suggestion (marked accepted) that I read on StackOverflow: &lt;br /&gt;
&lt;/code&gt;&lt;br /&gt;
&lt;blockquote&gt;&lt;code&gt; list&amp;lt;Account&amp;gt;::iterator it = std::find_if(accountList.begin(), accountList.end(), bind(isEqual, idYouSearch, _1)); &lt;/code&gt;&lt;br /&gt;
&lt;code&gt;&lt;/code&gt;&lt;/blockquote&gt;&lt;code&gt; &lt;br /&gt;
A perfectly reasonable one, if we're going to use modern C++. But it sucks. I would much more prefer&lt;br /&gt;
&lt;/code&gt;&lt;br /&gt;
&lt;blockquote&gt;&lt;code&gt; var it = accountList.Contains(idYouSearch);&lt;/code&gt;&lt;br /&gt;
&lt;code&gt;&lt;/code&gt;&lt;/blockquote&gt;&lt;code&gt; or&lt;/code&gt;&lt;br /&gt;
&lt;blockquote&gt;&lt;code&gt; var it = accountList.IndexOf(x =&amp;gt; x.Id = idYouSearch);&lt;/code&gt;&lt;br /&gt;
&lt;code&gt;&lt;/code&gt;&lt;/blockquote&gt;&lt;code&gt; &lt;br /&gt;
I can't see nor can accept any reasons that may make my source code to look like Perl excersises in high math. I prefer it to look like requirements documentation.&lt;/code&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8281741202770949929-8184920017480028145?l=sprokhorenko.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sprokhorenko.blogspot.com/feeds/8184920017480028145/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://sprokhorenko.blogspot.com/2010/06/readability-counts.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8281741202770949929/posts/default/8184920017480028145'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8281741202770949929/posts/default/8184920017480028145'/><link rel='alternate' type='text/html' href='http://sprokhorenko.blogspot.com/2010/06/readability-counts.html' title='Readability counts'/><author><name>Sergey Prokhorenko</name><uri>http://www.blogger.com/profile/06389461574659526392</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://4.bp.blogspot.com/_St_fXOeTKCk/Sp0sRG9IkRI/AAAAAAAAAAM/Fccwc6J00SE/S220/1344263.jpeg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8281741202770949929.post-8613915499711068896</id><published>2010-06-10T15:08:00.000+03:00</published><updated>2010-06-10T15:08:44.983+03:00</updated><title type='text'>Brush your namespaces!</title><content type='html'>One good indicator for a good programmer would be the level of tidiness that he/she prefers. An apparent example is unnecessary using statements (or includes in C++). A good programmer will never keep any unnecessary code, be it commented obsolete statements, unused includes, method parameters, or local variables. This should be as natural as brushing teeth every day.&lt;br /&gt;
&lt;br /&gt;
But, frankly, a good programmer can't just pass by any bad code, be it variable without a meaningful name, a code block that can be made shorter, and so on.&lt;br /&gt;
&lt;br /&gt;
I suppose this is because programmers are used to keep the image of the code in their heads, and it's natural to want to remove any mismatch.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8281741202770949929-8613915499711068896?l=sprokhorenko.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sprokhorenko.blogspot.com/feeds/8613915499711068896/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://sprokhorenko.blogspot.com/2010/06/brush-your-namespaces.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8281741202770949929/posts/default/8613915499711068896'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8281741202770949929/posts/default/8613915499711068896'/><link rel='alternate' type='text/html' href='http://sprokhorenko.blogspot.com/2010/06/brush-your-namespaces.html' title='Brush your namespaces!'/><author><name>Sergey Prokhorenko</name><uri>http://www.blogger.com/profile/06389461574659526392</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://4.bp.blogspot.com/_St_fXOeTKCk/Sp0sRG9IkRI/AAAAAAAAAAM/Fccwc6J00SE/S220/1344263.jpeg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8281741202770949929.post-4073189151428487956</id><published>2010-04-30T16:08:00.000+03:00</published><updated>2010-04-30T16:08:05.768+03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ubuntu'/><title type='text'>US layout rules the world</title><content type='html'>A quote from Ubuntu launchpad &lt;a href="https://bugs.launchpad.net/ubuntu/+source/kdebase-workspace/+bug/550704"&gt;bug&lt;/a&gt;:&lt;br /&gt;
&lt;blockquote&gt;I only find the keyboard indicator useful if I need to switch between  different keyboard layouts, which the majority of users won't have to  do, regardless of whether their installation is in English or in another  language&lt;/blockquote&gt;Yes, right, majority of users don't switch between keyboard layouts, because the majority uses en-US. But what about us minority people, are we going to write "apt-get remove ubuntu" in what language and keyboard layout that we currently have turned on? Russian? Hebrew? French? "азе-пуе куьщму гигтег" is not a valid command I suppose.&lt;br /&gt;
&lt;br /&gt;
I wonder why &lt;a class="sprite person" href="https://launchpad.net/%7Edpm"&gt;David  Planella&lt;/a&gt; don't vote to remove keyboard layouts at all, because for majority of users they make no sense. At least David don't find that useful.&lt;br /&gt;
&lt;br /&gt;
But I'm sure they find new (K)ubuntu logos very useful. Much more useful than helping people to use "non US-only" layout setup.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8281741202770949929-4073189151428487956?l=sprokhorenko.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sprokhorenko.blogspot.com/feeds/4073189151428487956/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://sprokhorenko.blogspot.com/2010/04/us-layout-rules-world.html#comment-form' title='8 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8281741202770949929/posts/default/4073189151428487956'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8281741202770949929/posts/default/4073189151428487956'/><link rel='alternate' type='text/html' href='http://sprokhorenko.blogspot.com/2010/04/us-layout-rules-world.html' title='US layout rules the world'/><author><name>Sergey Prokhorenko</name><uri>http://www.blogger.com/profile/06389461574659526392</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://4.bp.blogspot.com/_St_fXOeTKCk/Sp0sRG9IkRI/AAAAAAAAAAM/Fccwc6J00SE/S220/1344263.jpeg'/></author><thr:total>8</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8281741202770949929.post-620608525919835974</id><published>2010-04-17T16:03:00.000+03:00</published><updated>2010-04-17T16:03:35.708+03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ubuntu'/><title type='text'>Unstable Ubuntu nature</title><content type='html'>A quote from https://help.ubuntu.com/community/BinaryDriverHowto/Nvidia/Nouveau:&lt;br /&gt;
&lt;br /&gt;
&lt;blockquote&gt;&lt;div class="line867"&gt;&lt;em&gt;Note: Ubuntu 10:04 will use Nouveau out of the  box.&lt;/em&gt; &lt;span class="anchor" id="line-11"&gt;&lt;/span&gt;&lt;span class="anchor" id="line-12"&gt;&lt;/span&gt;&lt;/div&gt;&lt;strong&gt; &lt;img alt="{X}" height="16" src="https://help.ubuntu.com/htdocs/ubuntunew/img/icon-error.png" title="{X}" width="16" /&gt; WARNING: THE DRIVER IS MOSTLY  UNSTABLE. PROCEED AT YOUR OWN RISK.&lt;/strong&gt;&lt;/blockquote&gt;Yes, it looks like they are going to use MOSTLY UNSTABLE driver by default. Hopefully the information at that page is obsolete.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8281741202770949929-620608525919835974?l=sprokhorenko.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sprokhorenko.blogspot.com/feeds/620608525919835974/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://sprokhorenko.blogspot.com/2010/04/unstable-ubuntu-nature.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8281741202770949929/posts/default/620608525919835974'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8281741202770949929/posts/default/620608525919835974'/><link rel='alternate' type='text/html' href='http://sprokhorenko.blogspot.com/2010/04/unstable-ubuntu-nature.html' title='Unstable Ubuntu nature'/><author><name>Sergey Prokhorenko</name><uri>http://www.blogger.com/profile/06389461574659526392</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://4.bp.blogspot.com/_St_fXOeTKCk/Sp0sRG9IkRI/AAAAAAAAAAM/Fccwc6J00SE/S220/1344263.jpeg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8281741202770949929.post-491065135095246604</id><published>2010-04-15T15:51:00.000+03:00</published><updated>2010-04-15T15:51:55.820+03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Silverlight'/><title type='text'>Silverlight usability</title><content type='html'>Silverlight is the future of web? C'mon, it's not even a usable solution. Can I select &lt;b&gt;any &lt;/b&gt;text on &lt;b&gt;any&lt;/b&gt; control, just like I can do in Web? Forget it.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8281741202770949929-491065135095246604?l=sprokhorenko.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sprokhorenko.blogspot.com/feeds/491065135095246604/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://sprokhorenko.blogspot.com/2010/04/silverlight-usability.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8281741202770949929/posts/default/491065135095246604'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8281741202770949929/posts/default/491065135095246604'/><link rel='alternate' type='text/html' href='http://sprokhorenko.blogspot.com/2010/04/silverlight-usability.html' title='Silverlight usability'/><author><name>Sergey Prokhorenko</name><uri>http://www.blogger.com/profile/06389461574659526392</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://4.bp.blogspot.com/_St_fXOeTKCk/Sp0sRG9IkRI/AAAAAAAAAAM/Fccwc6J00SE/S220/1344263.jpeg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8281741202770949929.post-7817737955838735220</id><published>2010-04-08T23:32:00.000+03:00</published><updated>2010-04-08T23:32:55.515+03:00</updated><title type='text'>Passion to answer</title><content type='html'>An interesting issue about StackOverflow. I used to answer a lot of ASP.NET MVC/etc questions there... while I was developing similar application and learning the stuff myself. Now I don't answer much.&lt;br /&gt;
&lt;br /&gt;
The problem is, I only answer interesting questions. And the more I master, the fewer interesting questions I see. Suddenly all of them are trivial and not worth answering.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8281741202770949929-7817737955838735220?l=sprokhorenko.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sprokhorenko.blogspot.com/feeds/7817737955838735220/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://sprokhorenko.blogspot.com/2010/04/passion-to-answer.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8281741202770949929/posts/default/7817737955838735220'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8281741202770949929/posts/default/7817737955838735220'/><link rel='alternate' type='text/html' href='http://sprokhorenko.blogspot.com/2010/04/passion-to-answer.html' title='Passion to answer'/><author><name>Sergey Prokhorenko</name><uri>http://www.blogger.com/profile/06389461574659526392</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://4.bp.blogspot.com/_St_fXOeTKCk/Sp0sRG9IkRI/AAAAAAAAAAM/Fccwc6J00SE/S220/1344263.jpeg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8281741202770949929.post-2982106458311855090</id><published>2010-04-06T11:11:00.000+03:00</published><updated>2010-04-06T11:11:09.515+03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='C#'/><category scheme='http://www.blogger.com/atom/ns#' term='Silverlight'/><title type='text'>Event handlers are evil</title><content type='html'>I hate event-based programming. Silverlight is highly based on it, and I hate it.&lt;br /&gt;
&lt;br /&gt;
People seem to dislike Inversion of Control because they think it will be harder to understand the code. Wrong. It's very easy to see what classes do implement the interface (especially with ReSharper). What makes it harder to understand the code is 10 events with event handlers all over in different places/assemblies/projects. And you can't easily see "who's subscribed". Instead of control calling the passed IClient interface, you see control calling its own OnClientHandle and you're doomed.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8281741202770949929-2982106458311855090?l=sprokhorenko.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sprokhorenko.blogspot.com/feeds/2982106458311855090/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://sprokhorenko.blogspot.com/2010/04/event-handlers-are-evil.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8281741202770949929/posts/default/2982106458311855090'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8281741202770949929/posts/default/2982106458311855090'/><link rel='alternate' type='text/html' href='http://sprokhorenko.blogspot.com/2010/04/event-handlers-are-evil.html' title='Event handlers are evil'/><author><name>Sergey Prokhorenko</name><uri>http://www.blogger.com/profile/06389461574659526392</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://4.bp.blogspot.com/_St_fXOeTKCk/Sp0sRG9IkRI/AAAAAAAAAAM/Fccwc6J00SE/S220/1344263.jpeg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8281741202770949929.post-6092274331090970492</id><published>2010-04-05T10:54:00.000+03:00</published><updated>2010-04-05T10:54:49.326+03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ubuntu'/><title type='text'>Compiz shadows</title><content type='html'>There's bad side of Ubuntu (and Linux), and there's good side. The bad side is that there're always many little issues that doesn't stop you but annoys. The good side is that there's (almost always) a way to fix them.&lt;br /&gt;
&lt;br /&gt;
One example is a bug with Compiz that makes shadows to be shown over panels and other desktop workplaces. And the fix is as easy as setting "!state=maxvert" for shadows setup in Compiz.&lt;br /&gt;
&lt;br /&gt;
There're several bugs for this in both Ubuntu launchpad and Compiz bug tracker. This makes people argue that Ubuntu is very buggy. No, it's not. I'm not an expert in Compiz at all but even I could fix this without any help in 5 minutes. So all these bugs are because people are new to Ubuntu, and because they can (and do) report their little problems directly to developers. Not because there're lots of &lt;b&gt;bugs&lt;/b&gt; in Ubuntu.&lt;br /&gt;
&lt;br /&gt;
Now, developers &lt;i&gt;could&lt;/i&gt; close these bugs as "rejected" or something, and/or provide solutions (like the one above). Well, maybe allowing everyone to report their little problems directly to developers is not a very good idea - important bugs can sink in the sea of minor reports. That's a problem. And maybe Ubuntu team will solve it, I don't know. But I wouldn't blame anyone, given that it's still Linux and you're free to solve problems yourself.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8281741202770949929-6092274331090970492?l=sprokhorenko.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sprokhorenko.blogspot.com/feeds/6092274331090970492/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://sprokhorenko.blogspot.com/2010/04/compiz-shadows.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8281741202770949929/posts/default/6092274331090970492'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8281741202770949929/posts/default/6092274331090970492'/><link rel='alternate' type='text/html' href='http://sprokhorenko.blogspot.com/2010/04/compiz-shadows.html' title='Compiz shadows'/><author><name>Sergey Prokhorenko</name><uri>http://www.blogger.com/profile/06389461574659526392</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://4.bp.blogspot.com/_St_fXOeTKCk/Sp0sRG9IkRI/AAAAAAAAAAM/Fccwc6J00SE/S220/1344263.jpeg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8281741202770949929.post-2493701909659817313</id><published>2010-03-25T14:10:00.000+02:00</published><updated>2010-03-25T14:10:56.989+02:00</updated><title type='text'>Context ads</title><content type='html'>I've just asked a question on StackOverflow about ASP.NET MVC issue, and got "nice" ads on the right asking if ASP.NET MVC drives me crazy. No it doesn't... but it shows how context ads that Google used so successfully seem to dominate the market nowadays.&lt;br /&gt;
&lt;br /&gt;
I wonder when Google will use StackOverflow data to range searches for me.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8281741202770949929-2493701909659817313?l=sprokhorenko.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sprokhorenko.blogspot.com/feeds/2493701909659817313/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://sprokhorenko.blogspot.com/2010/03/context-ads.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8281741202770949929/posts/default/2493701909659817313'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8281741202770949929/posts/default/2493701909659817313'/><link rel='alternate' type='text/html' href='http://sprokhorenko.blogspot.com/2010/03/context-ads.html' title='Context ads'/><author><name>Sergey Prokhorenko</name><uri>http://www.blogger.com/profile/06389461574659526392</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://4.bp.blogspot.com/_St_fXOeTKCk/Sp0sRG9IkRI/AAAAAAAAAAM/Fccwc6J00SE/S220/1344263.jpeg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8281741202770949929.post-970213314165661433</id><published>2010-03-25T11:23:00.000+02:00</published><updated>2010-03-25T11:23:32.136+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ubuntu'/><title type='text'>Time to change</title><content type='html'>No posts for some time, that was mostly because I was playing with Ubuntu as working system (not a home one). It's fantastic! The most amazing thing is that it runs much faster, and&amp;nbsp;&lt;b&gt;EVEN&lt;/b&gt;&amp;nbsp;when I run Windows 2003 in VirtualBox at the same time it is not slower at all! Windows7 can barely run itself on my 2GB and with virtual machine it just... crawl.&lt;br /&gt;
&lt;br /&gt;
So I'm going to setup virtual box to run ASP.NET and keep other work in Ubuntu.&lt;br /&gt;
&lt;br /&gt;
And by the way Ubuntu fonts still make me crazy about them. They rock!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8281741202770949929-970213314165661433?l=sprokhorenko.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sprokhorenko.blogspot.com/feeds/970213314165661433/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://sprokhorenko.blogspot.com/2010/03/time-to-change.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8281741202770949929/posts/default/970213314165661433'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8281741202770949929/posts/default/970213314165661433'/><link rel='alternate' type='text/html' href='http://sprokhorenko.blogspot.com/2010/03/time-to-change.html' title='Time to change'/><author><name>Sergey Prokhorenko</name><uri>http://www.blogger.com/profile/06389461574659526392</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://4.bp.blogspot.com/_St_fXOeTKCk/Sp0sRG9IkRI/AAAAAAAAAAM/Fccwc6J00SE/S220/1344263.jpeg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8281741202770949929.post-6490327194787604840</id><published>2010-03-14T18:55:00.000+02:00</published><updated>2010-03-14T18:55:58.717+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ubuntu'/><title type='text'>Ubuntu</title><content type='html'>I use Ubuntu everyday on my home computer. It is so good that I began to regret my Windows life at work; in fact, I feel sad working on Windows and constatly look for ways to move to Ubuntu for development. My collegues develop Flex and thus can work in Ubuntu without problems. I use more MS-oriented technologies like ASP.NET MVC and Silverlight. There're Mono and Moonlight; however I can't fully use them as a replacement, for various reasons - Moonlight 3 is not ready yet, or ASP.NET MVC needs Excel JET driver, and so on. I consider using Windows inside virtual box, though; I think I'll get enough of Windows soon. Ubuntu is just too good, both in look and feel, and I can't resist.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8281741202770949929-6490327194787604840?l=sprokhorenko.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sprokhorenko.blogspot.com/feeds/6490327194787604840/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://sprokhorenko.blogspot.com/2010/03/ubuntu.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8281741202770949929/posts/default/6490327194787604840'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8281741202770949929/posts/default/6490327194787604840'/><link rel='alternate' type='text/html' href='http://sprokhorenko.blogspot.com/2010/03/ubuntu.html' title='Ubuntu'/><author><name>Sergey Prokhorenko</name><uri>http://www.blogger.com/profile/06389461574659526392</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://4.bp.blogspot.com/_St_fXOeTKCk/Sp0sRG9IkRI/AAAAAAAAAAM/Fccwc6J00SE/S220/1344263.jpeg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8281741202770949929.post-4624410273081629253</id><published>2010-02-24T14:12:00.000+02:00</published><updated>2010-02-24T14:12:27.240+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='NHibernate'/><title type='text'>To master NHibernate is...</title><content type='html'>I really like NHibernate, but its error messages drive me crazy. I've just spent an hour figuring out why changing auto-mapped (by Fluent NHibernate) property to .Map().Access.LowerCaseUnderscore() causes&lt;br /&gt;
&lt;div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;&lt;span class="Apple-style-span" style="-webkit-border-horizontal-spacing: 5px; -webkit-border-vertical-spacing: 5px; font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 15px; line-height: 20px;"&gt;&lt;i&gt;Could not determine type for: Orders.Core.Discount&lt;/i&gt;&lt;/span&gt;&lt;/div&gt;Only to find that I'm dumb and Discount is an entity and I have to use References() instead of Map(). Now, I found this out by comparing HBM maps for the working and invalid configurations - thanks to myself doing HBMs tests and export. But this is not something one can figure out easily from NHibernate messages.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8281741202770949929-4624410273081629253?l=sprokhorenko.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sprokhorenko.blogspot.com/feeds/4624410273081629253/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://sprokhorenko.blogspot.com/2010/02/to-master-nhibernate-is.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8281741202770949929/posts/default/4624410273081629253'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8281741202770949929/posts/default/4624410273081629253'/><link rel='alternate' type='text/html' href='http://sprokhorenko.blogspot.com/2010/02/to-master-nhibernate-is.html' title='To master NHibernate is...'/><author><name>Sergey Prokhorenko</name><uri>http://www.blogger.com/profile/06389461574659526392</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://4.bp.blogspot.com/_St_fXOeTKCk/Sp0sRG9IkRI/AAAAAAAAAAM/Fccwc6J00SE/S220/1344263.jpeg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8281741202770949929.post-417136007915864513</id><published>2010-02-24T13:09:00.000+02:00</published><updated>2010-02-24T13:09:06.510+02:00</updated><title type='text'>Upgrades week</title><content type='html'>Wow, seems like this is the Upgrades Week of the Year! And more is coming - S#arp with MVC v2 support, MVC v2 itself, and maybe VS2010 release. So many toys!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8281741202770949929-417136007915864513?l=sprokhorenko.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sprokhorenko.blogspot.com/feeds/417136007915864513/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://sprokhorenko.blogspot.com/2010/02/upgrades-week.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8281741202770949929/posts/default/417136007915864513'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8281741202770949929/posts/default/417136007915864513'/><link rel='alternate' type='text/html' href='http://sprokhorenko.blogspot.com/2010/02/upgrades-week.html' title='Upgrades week'/><author><name>Sergey Prokhorenko</name><uri>http://www.blogger.com/profile/06389461574659526392</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://4.bp.blogspot.com/_St_fXOeTKCk/Sp0sRG9IkRI/AAAAAAAAAAM/Fccwc6J00SE/S220/1344263.jpeg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8281741202770949929.post-8827475986305844515</id><published>2010-02-24T13:07:00.000+02:00</published><updated>2010-02-24T13:07:20.444+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='VS2010'/><title type='text'>Build VS2010RC projects using NAnt without VS installed</title><content type='html'>&lt;a href="http://www.blogger.com/"&gt;&lt;/a&gt;&lt;span id="goog_1267009032001"&gt;&lt;/span&gt;&lt;span id="goog_1267009032002"&gt;&lt;/span&gt;Yes, more problems with VS2010RC, this time because I have CI server (Hudson) set up to build my project and it uses NAnt Contrib tasks to build solution using MSBuild. And it doesn't work.&lt;br /&gt;
&lt;br /&gt;
First problem was that MSBuild from .NET 3.5 did not understand VS2010 solutions. OK I installed .NET 4.0 on the build server.&lt;br /&gt;
&lt;br /&gt;
Now, NAnt.Contrib still used 3.5 to build. Maybe I could pass newer MSBuild path to it or tweak nant config, but I decided to invoke MSBuild via NAnt's exec - simple but works.&lt;br /&gt;
&lt;br /&gt;
Now MSBuild 4.0 ran but complained that I do not have .targets under&amp;nbsp;"c:\Program Files\MSBuild\Microsoft\VisualStudio\v10.0\..." folder. OK I just simply copied this folder from the dev machine to the server - this trick worked for me for VS2008 builds, too.&lt;br /&gt;
&lt;br /&gt;
Now MSBuild 4.0 complained that SDK v7.0A is not installed and it cannot find tools (sgen.exe). First I thought I'd copy v7.0A folder completely and tweak registry to point to the tools (SdkInstallRoot I guess)... but then I had found &lt;a href="http://social.msdn.microsoft.com/Forums/en/tfsprerelease/thread/db71a41f-11b2-4a7f-b97d-1539c04fe79b"&gt;this post&lt;/a&gt; and thus just passed /toolsversion:3.5 to MSBuild.&lt;br /&gt;
&lt;br /&gt;
And it's happy now! It can build my VS2010 solution without VS2010 or new SDK installed on the build server. Nice. But it takes time ;-)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8281741202770949929-8827475986305844515?l=sprokhorenko.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sprokhorenko.blogspot.com/feeds/8827475986305844515/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://sprokhorenko.blogspot.com/2010/02/build-vs2010rc-projects-using-nant.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8281741202770949929/posts/default/8827475986305844515'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8281741202770949929/posts/default/8827475986305844515'/><link rel='alternate' type='text/html' href='http://sprokhorenko.blogspot.com/2010/02/build-vs2010rc-projects-using-nant.html' title='Build VS2010RC projects using NAnt without VS installed'/><author><name>Sergey Prokhorenko</name><uri>http://www.blogger.com/profile/06389461574659526392</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://4.bp.blogspot.com/_St_fXOeTKCk/Sp0sRG9IkRI/AAAAAAAAAAM/Fccwc6J00SE/S220/1344263.jpeg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8281741202770949929.post-9216940946999365316</id><published>2010-02-24T11:06:00.000+02:00</published><updated>2010-02-24T11:06:50.092+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='VS2010'/><category scheme='http://www.blogger.com/atom/ns#' term='ASP.NET MVC'/><title type='text'>Upgrade S#arp Architecture / ASP.NET MVC project to VS2010RC</title><content type='html'>VS2010RC failed to upgrade my S#arp Architecture project, specifically, the web application that uses ASP.NET MVC v1. After some googling I've found &lt;a href="http://weblogs.asp.net/leftslipper/archive/2009/01/20/opening-an-asp-net-mvc-project-without-having-asp-net-mvc-installed-the-project-type-is-not-supported-by-this-installation.aspx"&gt;this useful link&lt;/a&gt;, which solved the problem... only to another one to appear. VS2010RC complained the project is configured to run on IIS and for this it needs admin privileges; so what? I can change it later. But it failed to upgrade the project. So, I had to edit .csproj manually once again and set UseIIS to false. Now everything's fine.&lt;br /&gt;
&lt;br /&gt;
Now, I like the VS2010 look, it goes well with my dark theme, but I had to use AvalonClearTypeTuner (or &lt;a href="http://windowsclient.net/wpf/white-papers/wpftextclarity.aspx"&gt;registry settings&lt;/a&gt;) to lower ClearType level a bit - my fonts were colored too much (on the dark background). But at least I &lt;b&gt;could&lt;/b&gt;&amp;nbsp;do this.&lt;br /&gt;
&lt;br /&gt;
There're other issues, too - for example, context menu in Solution Explorer is trimmed (with scrolling arrow) when drops down and there's too little space on the bottom - while it could extend to the top (I had similar UI issue recently with jQuery menus in my project). But that's only RC after all.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8281741202770949929-9216940946999365316?l=sprokhorenko.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sprokhorenko.blogspot.com/feeds/9216940946999365316/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://sprokhorenko.blogspot.com/2010/02/upgrade-sarp-architecture-aspnet-mvc.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8281741202770949929/posts/default/9216940946999365316'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8281741202770949929/posts/default/9216940946999365316'/><link rel='alternate' type='text/html' href='http://sprokhorenko.blogspot.com/2010/02/upgrade-sarp-architecture-aspnet-mvc.html' title='Upgrade S#arp Architecture / ASP.NET MVC project to VS2010RC'/><author><name>Sergey Prokhorenko</name><uri>http://www.blogger.com/profile/06389461574659526392</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://4.bp.blogspot.com/_St_fXOeTKCk/Sp0sRG9IkRI/AAAAAAAAAAM/Fccwc6J00SE/S220/1344263.jpeg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8281741202770949929.post-4713301041201345827</id><published>2010-02-23T12:45:00.000+02:00</published><updated>2010-02-23T12:45:53.229+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='jQuery'/><title type='text'>RTFM?</title><content type='html'>I've updated to jQuery 1.4.2 / jQuery UI 1.8rc2. There were couple of minor issues, like, for example, JSON response coming as JSON object and not text. The biggest issue was with a third-party plugin &lt;a href="http://github.com/btburnett3/jquery.ui.spinner"&gt;ui.spinner&lt;/a&gt; which uses widget factory that got major &lt;a href="http://docs.jquery.com/UI/Upgrade_Guide_18#Widget_Factory"&gt;refactoring&lt;/a&gt;&amp;nbsp;in new UI release. I struggled for an hour to understand what changes are needed, but then I gave up, read the &lt;a href="http://github.com/scottgonzalez/jquery-ui-1.8-widget-factory"&gt;upgrade manual&lt;/a&gt;, and made it work in 5 minutes.&lt;br /&gt;
&lt;br /&gt;
Funny that manuals did not really helped. Examples did.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8281741202770949929-4713301041201345827?l=sprokhorenko.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sprokhorenko.blogspot.com/feeds/4713301041201345827/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://sprokhorenko.blogspot.com/2010/02/rtfm.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8281741202770949929/posts/default/4713301041201345827'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8281741202770949929/posts/default/4713301041201345827'/><link rel='alternate' type='text/html' href='http://sprokhorenko.blogspot.com/2010/02/rtfm.html' title='RTFM?'/><author><name>Sergey Prokhorenko</name><uri>http://www.blogger.com/profile/06389461574659526392</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://4.bp.blogspot.com/_St_fXOeTKCk/Sp0sRG9IkRI/AAAAAAAAAAM/Fccwc6J00SE/S220/1344263.jpeg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8281741202770949929.post-750044441531598893</id><published>2010-02-16T16:09:00.000+02:00</published><updated>2010-02-16T16:09:29.073+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Chrome'/><category scheme='http://www.blogger.com/atom/ns#' term='Silverlight'/><title type='text'>Model alerts replacement for Chrome</title><content type='html'>Even though it's more than 10 years since I've seen articles and books telling that modal dialogs are &lt;b&gt;BAD&lt;/b&gt;, we still have lots of them. One example is browsers' alert box, which looks &lt;b&gt;very&lt;/b&gt; ugly in the stateless modeless nature of the web.&lt;br /&gt;
&lt;br /&gt;
Fortunately there's a solution for Chrome: &lt;a href="https://chrome.google.com/extensions/detail/ehnbelnegmgdnjaghgomaakjcmpcakhk"&gt;Nice Alert&lt;/a&gt;. Here's how nice it is: I've just opened a Silverlight 3 application that asked me for login. I did 3 unsuccessfull logins and each time I got a nice beautiful popup windows with error message in the top right corner. Only after I did successfull logon and the error popups didn't disappear I understood that it's not the cool Silverlight thing - it's Nice Alert replacing ugly "alert()" for me (it didn't disappear because it's Siverlight and there're no page refreshes).&lt;br /&gt;
&lt;br /&gt;
Which means, it fits nicely even with the modern slick Silverlight applications. Not to say, it's unobtrusive and fun.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8281741202770949929-750044441531598893?l=sprokhorenko.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sprokhorenko.blogspot.com/feeds/750044441531598893/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://sprokhorenko.blogspot.com/2010/02/model-alerts-replacement-for-chrome.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8281741202770949929/posts/default/750044441531598893'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8281741202770949929/posts/default/750044441531598893'/><link rel='alternate' type='text/html' href='http://sprokhorenko.blogspot.com/2010/02/model-alerts-replacement-for-chrome.html' title='Model alerts replacement for Chrome'/><author><name>Sergey Prokhorenko</name><uri>http://www.blogger.com/profile/06389461574659526392</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://4.bp.blogspot.com/_St_fXOeTKCk/Sp0sRG9IkRI/AAAAAAAAAAM/Fccwc6J00SE/S220/1344263.jpeg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8281741202770949929.post-638680631830375597</id><published>2010-02-15T23:22:00.002+02:00</published><updated>2010-02-15T23:23:30.695+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='SSRS'/><category scheme='http://www.blogger.com/atom/ns#' term='Spark'/><title type='text'>Another usage for Spark</title><content type='html'>&lt;a href="http://www.sparkviewengine.com/"&gt;Spark&lt;/a&gt; turned out to be a pretty useful thing. I've just found another usage for it - generate RDL (Reporting Services reports) files. User selects fields, groups, and all I need to do is to add couple of each="var col in columns" attributes to the TableCell elements in the RDL template definition (well, maybe also couple of =Fields!${col.Name}.Value lines). Very easy and cool. Ad-hoc reports generation with very little effort.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8281741202770949929-638680631830375597?l=sprokhorenko.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sprokhorenko.blogspot.com/feeds/638680631830375597/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://sprokhorenko.blogspot.com/2010/02/another-usage-for-spark.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8281741202770949929/posts/default/638680631830375597'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8281741202770949929/posts/default/638680631830375597'/><link rel='alternate' type='text/html' href='http://sprokhorenko.blogspot.com/2010/02/another-usage-for-spark.html' title='Another usage for Spark'/><author><name>Sergey Prokhorenko</name><uri>http://www.blogger.com/profile/06389461574659526392</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://4.bp.blogspot.com/_St_fXOeTKCk/Sp0sRG9IkRI/AAAAAAAAAAM/Fccwc6J00SE/S220/1344263.jpeg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8281741202770949929.post-2724249587306799424</id><published>2010-02-12T21:31:00.000+02:00</published><updated>2010-02-12T21:31:51.596+02:00</updated><title type='text'>Design rule</title><content type='html'>I have a simple test to check if web page's design is good or bad - and that's page zoom. Good page, when zoomed either text-only or full-page, doesn't break layout and keep it's main column big and readable. Bad pages expand outside screen, shrink their main column to 100 pixels (well, if you zoom big enough) while expanding siderbars fullscreen, have elements overlapped and all these sort of things.&lt;br /&gt;
&lt;br /&gt;
Unfortunately, &lt;b&gt;lots&lt;/b&gt;&amp;nbsp;of web pages are not designed to be read with zoom not equal to 100%.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8281741202770949929-2724249587306799424?l=sprokhorenko.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sprokhorenko.blogspot.com/feeds/2724249587306799424/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://sprokhorenko.blogspot.com/2010/02/design-rule.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8281741202770949929/posts/default/2724249587306799424'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8281741202770949929/posts/default/2724249587306799424'/><link rel='alternate' type='text/html' href='http://sprokhorenko.blogspot.com/2010/02/design-rule.html' title='Design rule'/><author><name>Sergey Prokhorenko</name><uri>http://www.blogger.com/profile/06389461574659526392</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://4.bp.blogspot.com/_St_fXOeTKCk/Sp0sRG9IkRI/AAAAAAAAAAM/Fccwc6J00SE/S220/1344263.jpeg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8281741202770949929.post-2553828605119305810</id><published>2010-02-10T17:13:00.000+02:00</published><updated>2010-02-10T17:13:09.398+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Chrome'/><title type='text'>Deal with over-designed pages</title><content type='html'>I now use Chrome. Being a (relatively) poor old guy I always set fonts big, colors contrast (BonW), and give few kind words to designers that make cool web pages that are hard to read. Thanks to Chrome extensions, I can ignore those bastards. But, as always, there's no perfection in the world. There's no single perfect extension for Chrome that suites ALL my reading needs. Thus I have now &lt;b&gt;FOUR&lt;/b&gt; extensions installed to deal with cool-designed web pages:&lt;br /&gt;
&lt;br /&gt;
1. Readability Redux. A great one and good for long reading. But it changes page design competely.&lt;br /&gt;
2. Webpage Decorator. Very flexible customization of colors and fonts, but a bit too many clicks sometimes. Keeps configuration across sessions but doesn't change ALL text on sites - seems to tweak body only (which is sometimes what I want).&lt;br /&gt;
3. TidyRead. Not sure if I'll keep this one, seems to be flexible but I find it hard and not intuitive to use.&lt;br /&gt;
4. Change Colors. One click to change to pre-defined colors. Doesn't keep configuration across sessions, which is sometimes what I want (single click and no worries about undo is the strength of this extension).&lt;br /&gt;
&lt;br /&gt;
If I had two keep only two I'd keep Readability Redux and Webpage Decorator. For single one I'd go with the latter because it keeps page closer to original design. But thanks God I can have all of them.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8281741202770949929-2553828605119305810?l=sprokhorenko.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sprokhorenko.blogspot.com/feeds/2553828605119305810/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://sprokhorenko.blogspot.com/2010/02/deal-with-over-designed-pages.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8281741202770949929/posts/default/2553828605119305810'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8281741202770949929/posts/default/2553828605119305810'/><link rel='alternate' type='text/html' href='http://sprokhorenko.blogspot.com/2010/02/deal-with-over-designed-pages.html' title='Deal with over-designed pages'/><author><name>Sergey Prokhorenko</name><uri>http://www.blogger.com/profile/06389461574659526392</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://4.bp.blogspot.com/_St_fXOeTKCk/Sp0sRG9IkRI/AAAAAAAAAAM/Fccwc6J00SE/S220/1344263.jpeg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8281741202770949929.post-2153005774090772136</id><published>2010-02-05T15:48:00.000+02:00</published><updated>2010-02-05T15:48:17.362+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='SSRS'/><title type='text'>Old tricks in the new bottle</title><content type='html'>I still use Reporting Services even though I was going not to do so. Why? Well, because it's easy to go the wrong path.&lt;br /&gt;
&lt;br /&gt;
But anyway. I'm developing a fairly complex report. It's single Tablix but it has 6 row groups and lots of unrelated information (~40 columns in the query from 22 tables). I managed to use single Tablix to present unrelated Orders, Resellers, Customers, Order Items, and inner Products. Now, the funny thing is that to achieve this, I had to use the same old trick that previously used to work in Crystal Reports.&lt;br /&gt;
&lt;br /&gt;
I created dummy groups.&lt;br /&gt;
&lt;br /&gt;
I don't know the reasons behind this - maybe I'm not smart enough - but when I add new row to the top outer row group, Report Builder just extends the group's cell (makes it bigger), it doesn't add new cells. To solve this I create a fake child group for "" (it can be any constant value). Then, I can add that group's rows/cells.&lt;br /&gt;
&lt;br /&gt;
In this sense, once you master one reporting engine, you master them all.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8281741202770949929-2153005774090772136?l=sprokhorenko.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sprokhorenko.blogspot.com/feeds/2153005774090772136/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://sprokhorenko.blogspot.com/2010/02/old-tricks-in-new-bottle.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8281741202770949929/posts/default/2153005774090772136'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8281741202770949929/posts/default/2153005774090772136'/><link rel='alternate' type='text/html' href='http://sprokhorenko.blogspot.com/2010/02/old-tricks-in-new-bottle.html' title='Old tricks in the new bottle'/><author><name>Sergey Prokhorenko</name><uri>http://www.blogger.com/profile/06389461574659526392</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://4.bp.blogspot.com/_St_fXOeTKCk/Sp0sRG9IkRI/AAAAAAAAAAM/Fccwc6J00SE/S220/1344263.jpeg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8281741202770949929.post-9025380016775815036</id><published>2010-02-01T17:28:00.001+02:00</published><updated>2010-02-01T17:28:55.387+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Chrome'/><category scheme='http://www.blogger.com/atom/ns#' term='FireFox'/><title type='text'>It is a war</title><content type='html'>&lt;span class="Apple-style-span" style="font-family: Arial; font-size: medium;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;&lt;br /&gt;
&lt;/span&gt;&lt;/span&gt;I was FireFox user for a long time. Recently I tried Chrome but it lacked so many features that I switched back to FireFox in no time, especially given that FF 3.6 boosted performance a lot.&lt;br /&gt;
&lt;br /&gt;
But Chrome 5.x is so much better now - it can remember sites zoom level, it does remember sessions and closed tabs, it has extensions for almost everything I need - AdBlock, Undo Close Tabs, Google Bookmarks... Actually some of them are even better than FireFox ones, for example Google Bookmarks.&lt;br /&gt;
&lt;br /&gt;
I can't say now that Chrome is the winner. Like in any war, there're no winners. Except that, in real wars, both sides lose a lot because of destruction; while in this browsers war both sides develop a lot, and we users win.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8281741202770949929-9025380016775815036?l=sprokhorenko.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sprokhorenko.blogspot.com/feeds/9025380016775815036/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://sprokhorenko.blogspot.com/2010/02/it-is-war.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8281741202770949929/posts/default/9025380016775815036'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8281741202770949929/posts/default/9025380016775815036'/><link rel='alternate' type='text/html' href='http://sprokhorenko.blogspot.com/2010/02/it-is-war.html' title='It is a war'/><author><name>Sergey Prokhorenko</name><uri>http://www.blogger.com/profile/06389461574659526392</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://4.bp.blogspot.com/_St_fXOeTKCk/Sp0sRG9IkRI/AAAAAAAAAAM/Fccwc6J00SE/S220/1344263.jpeg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8281741202770949929.post-5266190169566043195</id><published>2010-01-28T15:29:00.000+02:00</published><updated>2010-01-28T15:29:19.846+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='NHibernate'/><title type='text'>Nice NHibernate features</title><content type='html'>According to Ayende's blog, NHibernate finally got two very useful features:&lt;br /&gt;
&lt;br /&gt;
1. &lt;a href="http://ayende.com/Blog/archive/2010/01/27/nhibernate-new-feature-lazy-properties.aspx"&gt;Lazy properties&lt;/a&gt; - not only classes can be lazy now (more lazyness in the world, yeah!).&lt;br /&gt;
2. &lt;a href="http://ayende.com/Blog/archive/2010/01/28/nhibernate-new-feature-no-proxy-associations.aspx"&gt;Better proxies and type matching&lt;/a&gt;&lt;br /&gt;
- "no-proxy" entities will still be lazy-loaded, yet "entity is EntityType" will work. This one I personally like.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8281741202770949929-5266190169566043195?l=sprokhorenko.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sprokhorenko.blogspot.com/feeds/5266190169566043195/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://sprokhorenko.blogspot.com/2010/01/nice-nhibernate-features.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8281741202770949929/posts/default/5266190169566043195'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8281741202770949929/posts/default/5266190169566043195'/><link rel='alternate' type='text/html' href='http://sprokhorenko.blogspot.com/2010/01/nice-nhibernate-features.html' title='Nice NHibernate features'/><author><name>Sergey Prokhorenko</name><uri>http://www.blogger.com/profile/06389461574659526392</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://4.bp.blogspot.com/_St_fXOeTKCk/Sp0sRG9IkRI/AAAAAAAAAAM/Fccwc6J00SE/S220/1344263.jpeg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8281741202770949929.post-5979422172863105202</id><published>2010-01-27T23:19:00.000+02:00</published><updated>2010-01-27T23:19:22.015+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Hardware'/><category scheme='http://www.blogger.com/atom/ns#' term='HP'/><title type='text'>HP lies</title><content type='html'>My HP dv6408nr notebook started to die. The first one to die is wifi adapter. This is (turned out) a well-known problem which is described &lt;a href="http://www.hplies.com/"&gt;here&lt;/a&gt; (basically nVidia card overheat that destroys motherboard components). It's a manufacturing problem/mistake that affects many HP notebooks (lots of dv series) and thousands of users and that they fail to admit.&lt;br /&gt;
&lt;br /&gt;
The funny thing is that when I bought it, I worked offshore for HP, and I knew guys who worked for them for some time. They told me I'd be sorry that I bought HP notebook. They said it was going to have problems. I didn't believe them. Now I see they were right. Actually, many thousands of people see that.&lt;br /&gt;
&lt;br /&gt;
It's 2.5 years since I bought it so I'm not &lt;b&gt;that&lt;/b&gt; disappointed. But still. No more HP.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8281741202770949929-5979422172863105202?l=sprokhorenko.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sprokhorenko.blogspot.com/feeds/5979422172863105202/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://sprokhorenko.blogspot.com/2010/01/hp-lies.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8281741202770949929/posts/default/5979422172863105202'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8281741202770949929/posts/default/5979422172863105202'/><link rel='alternate' type='text/html' href='http://sprokhorenko.blogspot.com/2010/01/hp-lies.html' title='HP lies'/><author><name>Sergey Prokhorenko</name><uri>http://www.blogger.com/profile/06389461574659526392</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://4.bp.blogspot.com/_St_fXOeTKCk/Sp0sRG9IkRI/AAAAAAAAAAM/Fccwc6J00SE/S220/1344263.jpeg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8281741202770949929.post-5540399977555858564</id><published>2010-01-27T12:08:00.003+02:00</published><updated>2010-01-27T12:36:20.544+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='SSRS'/><title type='text'>Microsoft is still Microsoft</title><content type='html'>Recently they try to play fair and do some OSS-like projects. But old habits die hard. Take a look at this &lt;a href="http://beaucrawford.net/post/Enable-HTML-in-ReportViewer-LocalReport.aspx"&gt;link&lt;/a&gt;. Here's a summary: SSRS LocalReport won't allow to export HTML, however it does support this - the only change is to use reflection to set &lt;i&gt;m_isExposedExternally&lt;/i&gt; on internal &lt;i&gt;Html40RenderingExtension&lt;/i&gt;. And suddenly it works.&lt;br /&gt;
&lt;br /&gt;
Now, does this sound like good old MS? This is &lt;b&gt;exactly&lt;/b&gt; what we used to do with undocumented DLL methods, only now that's inside assemblies.&lt;br /&gt;
&lt;br /&gt;
Now, it doesn't work in SSRS2008 since they have dropped HTML. They have some &lt;a href="http://blogs.msdn.com/robertbruckner/archive/2009/01/05/executionlog2-view.aspx"&gt;RPL&lt;/a&gt; which is "an internal, binary format"... good old Microsoft, good old "internal, binary" formats they use. Well, actually they have the &lt;a href="http://msdn.microsoft.com/en-us/library/ee301773.aspx"&gt;specification&lt;/a&gt;, go implement it. And it doesn't look like HTML.&lt;br /&gt;
&lt;br /&gt;
With report viewer in VS2008 not supporting local SSRS2008 reports, with HTML support dropped for local reports (if we can call it &lt;i&gt;support&lt;/i&gt;), with subreports not supported in local mode, I now wonder if they care about local reports at all. Do they write it in SSRS advertisements: "&lt;b&gt;Want to generate reports locally? Goodbye, loser!&lt;/b&gt;"? I doubt so - but they have to.&lt;br /&gt;
&lt;br /&gt;
Now it's my turn. I'm going to say goodbye to SSRS.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8281741202770949929-5540399977555858564?l=sprokhorenko.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sprokhorenko.blogspot.com/feeds/5540399977555858564/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://sprokhorenko.blogspot.com/2010/01/microsoft-is-still-microsoft.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8281741202770949929/posts/default/5540399977555858564'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8281741202770949929/posts/default/5540399977555858564'/><link rel='alternate' type='text/html' href='http://sprokhorenko.blogspot.com/2010/01/microsoft-is-still-microsoft.html' title='Microsoft is still Microsoft'/><author><name>Sergey Prokhorenko</name><uri>http://www.blogger.com/profile/06389461574659526392</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://4.bp.blogspot.com/_St_fXOeTKCk/Sp0sRG9IkRI/AAAAAAAAAAM/Fccwc6J00SE/S220/1344263.jpeg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8281741202770949929.post-2491997417519943855</id><published>2010-01-25T13:49:00.000+02:00</published><updated>2010-01-25T13:49:07.570+02:00</updated><title type='text'>Reporting Engines suck</title><content type='html'>In my development life I've only tried these reporting engines: MS Access, MS Reporting Services, and Crystal Reports. And I have to say, they all suck. MS Access suck very little but it's not suitable for business apps. But both SSRS with CR suck a lot. If you want your hair become gray and your life become full of frustration - go use them. Spending many hours just to overcome their nasty bugs - for example, this little textbox not wanting to keep its width, or queries suddenly doing cross-join - will make you wonder if it's easier - and less time consuming - to write your own little engine. But then you remember about export to Excel (which doesn't always work as expected) and to Word (which doesn't always work as expected, either) and reportviewer control (which doesn't support local reports - WTF?) and subreports (which are not supported in local reports - WTF? or do not support deep nesting - WTF?) and you think - "There's nothing perfect in this world. I'm going to workaround these issues. I'm going to get used to pain."&lt;br /&gt;
&lt;br /&gt;
And then they wonder why there's so much weird sex in the Internet. &lt;b&gt;You &lt;/b&gt;created that, bastards!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8281741202770949929-2491997417519943855?l=sprokhorenko.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sprokhorenko.blogspot.com/feeds/2491997417519943855/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://sprokhorenko.blogspot.com/2010/01/reporting-engines-suck.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8281741202770949929/posts/default/2491997417519943855'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8281741202770949929/posts/default/2491997417519943855'/><link rel='alternate' type='text/html' href='http://sprokhorenko.blogspot.com/2010/01/reporting-engines-suck.html' title='Reporting Engines suck'/><author><name>Sergey Prokhorenko</name><uri>http://www.blogger.com/profile/06389461574659526392</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://4.bp.blogspot.com/_St_fXOeTKCk/Sp0sRG9IkRI/AAAAAAAAAAM/Fccwc6J00SE/S220/1344263.jpeg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8281741202770949929.post-3235614279851352977</id><published>2010-01-24T23:51:00.000+02:00</published><updated>2010-01-24T23:51:20.518+02:00</updated><title type='text'>Google can kill</title><content type='html'>"Google &lt;strike&gt;Chrome&lt;/strike&gt; is able to remotely kill any extension that is found to be doing  bad things" (c) &lt;a href="http://www.techcrunch.com/2009/12/10/chrome-firefox/"&gt;http://www.techcrunch.com/2009/12/10/chrome-firefox/&lt;/a&gt;.&lt;br /&gt;
&lt;br /&gt;
Once again, Google is watching you&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8281741202770949929-3235614279851352977?l=sprokhorenko.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sprokhorenko.blogspot.com/feeds/3235614279851352977/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://sprokhorenko.blogspot.com/2010/01/google-can-kill.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8281741202770949929/posts/default/3235614279851352977'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8281741202770949929/posts/default/3235614279851352977'/><link rel='alternate' type='text/html' href='http://sprokhorenko.blogspot.com/2010/01/google-can-kill.html' title='Google can kill'/><author><name>Sergey Prokhorenko</name><uri>http://www.blogger.com/profile/06389461574659526392</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://4.bp.blogspot.com/_St_fXOeTKCk/Sp0sRG9IkRI/AAAAAAAAAAM/Fccwc6J00SE/S220/1344263.jpeg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8281741202770949929.post-7585674652757003733</id><published>2010-01-21T12:31:00.000+02:00</published><updated>2010-01-21T12:31:24.287+02:00</updated><title type='text'>Personal bug tracker</title><content type='html'>I searched for a good to-do keeping program, particularly to make quick project notes (like "make this", "need to add this", etc). I tried several apps but QuickNotes for FireFox is the winner. Now, it's not about this particular addon; it's about the idea that it brings to life: basically, the sequence to add a note (configurable of course) is "Alt-F" - enter text - "ESC". And it's lightspeed fast. Yes it works from FireFox only but for now this is not a problem to me.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8281741202770949929-7585674652757003733?l=sprokhorenko.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sprokhorenko.blogspot.com/feeds/7585674652757003733/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://sprokhorenko.blogspot.com/2010/01/personal-bug-tracker.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8281741202770949929/posts/default/7585674652757003733'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8281741202770949929/posts/default/7585674652757003733'/><link rel='alternate' type='text/html' href='http://sprokhorenko.blogspot.com/2010/01/personal-bug-tracker.html' title='Personal bug tracker'/><author><name>Sergey Prokhorenko</name><uri>http://www.blogger.com/profile/06389461574659526392</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://4.bp.blogspot.com/_St_fXOeTKCk/Sp0sRG9IkRI/AAAAAAAAAAM/Fccwc6J00SE/S220/1344263.jpeg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8281741202770949929.post-8912697052436872970</id><published>2010-01-19T21:34:00.002+02:00</published><updated>2010-01-19T21:40:52.158+02:00</updated><title type='text'>Why do I like to read programming blogs</title><content type='html'>So, why people read other blogs? Why do I do?&lt;br /&gt;
&lt;br /&gt;
One of the funny but still functional reasons is that I do it to make sure that I follow the best and approved practices. I understood it while reading &lt;a href="http://www.danielroot.info/2009/05/four-aspnet-mvc-rules-of-thumb.html"&gt;this post&lt;/a&gt;. The fact that I do already use the rules from there made me a) feel good b) smile to myself c) confirm that I do good things as a developer.&lt;br /&gt;
&lt;br /&gt;
Sure sometimes I read blogs for other reasons. For example, for pure fun. Or to learn something. But often I do it just to confirm that I do like others do. Or, that others do like me. That's more animal than conscious I guess.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8281741202770949929-8912697052436872970?l=sprokhorenko.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sprokhorenko.blogspot.com/feeds/8912697052436872970/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://sprokhorenko.blogspot.com/2010/01/w.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8281741202770949929/posts/default/8912697052436872970'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8281741202770949929/posts/default/8912697052436872970'/><link rel='alternate' type='text/html' href='http://sprokhorenko.blogspot.com/2010/01/w.html' title='Why do I like to read programming blogs'/><author><name>Sergey Prokhorenko</name><uri>http://www.blogger.com/profile/06389461574659526392</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://4.bp.blogspot.com/_St_fXOeTKCk/Sp0sRG9IkRI/AAAAAAAAAAM/Fccwc6J00SE/S220/1344263.jpeg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8281741202770949929.post-94890867859992329</id><published>2010-01-19T17:57:00.000+02:00</published><updated>2010-01-19T17:57:48.656+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='concepts'/><title type='text'>Why DDD helps</title><content type='html'>Why domain driven design helps? Because it lays out a solid foundation.&lt;br /&gt;
&lt;br /&gt;
When one joins a half-the-way project, it usually has a defined set of tasks and to do list. It is clear what to do. But when a project starts I sometimes just don't know where to start.&lt;br /&gt;
&lt;br /&gt;
That's one of the reasons that frameworks exist - they help to get started.&amp;nbsp;&lt;a href="http://www.sharparchitecture.ne/"&gt;S#arp Architecture&lt;/a&gt;&amp;nbsp;did just that for me, and MFC does that, and Turbo Vision did (do you remember those?). Note that experienced professionals can do without frameworks - either because there're templates from the past or because they can replicate framework-aided code from their memory.&lt;br /&gt;
&lt;br /&gt;
But framework is not enough. If we start coding right away on all layers - like, placing buttons, doing writes, and so on - we'll start quick but will soon slow down. If we, however, carefully think about the design, the project, customer needs, and all the stuff, and code just that - without the infrastructure - it will take some time, but it will pay off for a long term. Infrastructure matters, new UIs (and old UIs fixes), database changes - everything will be easy.&lt;br /&gt;
&lt;br /&gt;
Note that this doesn't mean big up-front design, where we think about every single detail. No, it's just that we think about and start with our core domain concepts. We let them drive the application, not vice versa.&lt;br /&gt;
&lt;br /&gt;
In my current project I experience just that - a warm feeling that project structure is clear, and any change can find its well defined place. Of course the design may degrade with time - that's why God gave us refactoring - but this is another story. For me, a month of DDD investigation and domain layer design - and I started with pure POCO classes - resulted in months of convenient coding, be it UI, validation, or service layer. And it is fun to work with.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8281741202770949929-94890867859992329?l=sprokhorenko.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sprokhorenko.blogspot.com/feeds/94890867859992329/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://sprokhorenko.blogspot.com/2010/01/why-ddd-helps.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8281741202770949929/posts/default/94890867859992329'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8281741202770949929/posts/default/94890867859992329'/><link rel='alternate' type='text/html' href='http://sprokhorenko.blogspot.com/2010/01/why-ddd-helps.html' title='Why DDD helps'/><author><name>Sergey Prokhorenko</name><uri>http://www.blogger.com/profile/06389461574659526392</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://4.bp.blogspot.com/_St_fXOeTKCk/Sp0sRG9IkRI/AAAAAAAAAAM/Fccwc6J00SE/S220/1344263.jpeg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8281741202770949929.post-8761980328657217653</id><published>2010-01-19T12:45:00.000+02:00</published><updated>2010-01-19T12:45:48.536+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='jqGrid'/><category scheme='http://www.blogger.com/atom/ns#' term='ASP.NET MVC'/><title type='text'>jqGrid + ASP.NET MVC: internals</title><content type='html'>A few words on jqGrid and ASP.NET MVC solution internals. I'll just describe the classes that are used there. The most useful thing is that these classes can be used standalone (the solution itself is nothing more than separate classes glued together).&lt;br /&gt;
&lt;br /&gt;
So.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;IJqGridSelectSource&lt;/b&gt;&amp;nbsp;- this interface can be used in UIHint attribute as select parameter value ("value", typeof(MyJqGridSelectSource)) - allowing a more dynamic select sources.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;JqFormatterAttribute&lt;/b&gt;&amp;nbsp;- attribute that allows to specify jqGrid formatters.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;JqGridData&lt;/b&gt; - actually taken from some post on the internet, simply represents a response that jqGrid expects from us in AJAX request (json response).&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;JqRequestViewModel&lt;/b&gt; - represents a request that jqGrid send to us to get the data.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;JqJsonSerializer&lt;/b&gt; - custom json serializer; mainly because I don't want entities to be serialized (i.e. it only serializes collections and simple types, and depth can be configured).&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;JqGridExtensions&lt;/b&gt; - two helpers here: one to take action's incoming &lt;br /&gt;
request and sue it to convert a list to an ActionResult (with all paging information, etc); another is the important &lt;b&gt;JqGridModel&lt;/b&gt; method that processes ViewModel definition and generates colModel array.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;JqGridControllerBase&lt;/b&gt; - a base for controllers that work with first-level entities. Requires IBaseRepository with CRUD methods and a special GetAll() method that accepts PagedRequest. SelectList method provides a pre-defined action that is useful to populate select lists in the edit forms.&lt;br /&gt;
&lt;b&gt;JqSubGridControllerBase&lt;/b&gt; - a base for controller that work with second-level entities (those contained in collections inside first-level entities, for examples Addresses).&lt;br /&gt;
Both controller types handle CRUD actions.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;PagedRequest&lt;/b&gt; - it is a page request abstract (in the core layer in the real project). It is either filled by the IBaseRepository implementation, or by its own GetLocal() method that works with in-memory lists.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;PageResult&lt;/b&gt; - returned by GetAll() and GetLocal() methods. Contains few page hints in addition to page data - like, for example, StartIndex that can be used to find the page for a particular entitty.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;NameOverride&lt;/b&gt; &amp;amp; &lt;b&gt;PagedRequestExtensions&lt;/b&gt; - a helper class and convenient extensions are used to help to convert ViewModel property names to database-level property names (for example, "OrganizationName" to "Organization.Name").&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;RepositoryExtensions&lt;/b&gt; - helper methods to get view/UI-specific data from repository (for example, entities represented by select list ids).&lt;br /&gt;
&lt;br /&gt;
And many small classes like attributes to be used with view models (Email, ExDisplay) and controllers (Transaction) and IEnumerable/string extensions (TypeHelpers.cs).&lt;br /&gt;
&lt;br /&gt;
The two most useful ones here are &lt;i&gt;JqGridModel&lt;/i&gt; method that handles a lot of view model attributes, and &lt;i&gt;Jq(Sub)GridControllerBase&lt;/i&gt; controllers that arrange all of the above into the complete CRUD solution.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8281741202770949929-8761980328657217653?l=sprokhorenko.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sprokhorenko.blogspot.com/feeds/8761980328657217653/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://sprokhorenko.blogspot.com/2010/01/jqgrid-aspnet-mvc-internals.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8281741202770949929/posts/default/8761980328657217653'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8281741202770949929/posts/default/8761980328657217653'/><link rel='alternate' type='text/html' href='http://sprokhorenko.blogspot.com/2010/01/jqgrid-aspnet-mvc-internals.html' title='jqGrid + ASP.NET MVC: internals'/><author><name>Sergey Prokhorenko</name><uri>http://www.blogger.com/profile/06389461574659526392</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://4.bp.blogspot.com/_St_fXOeTKCk/Sp0sRG9IkRI/AAAAAAAAAAM/Fccwc6J00SE/S220/1344263.jpeg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8281741202770949929.post-6885750849474068680</id><published>2010-01-14T16:35:00.005+02:00</published><updated>2010-01-15T13:40:19.031+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='jqGrid'/><category scheme='http://www.blogger.com/atom/ns#' term='ASP.NET MVC'/><title type='text'>jqGrid + MVC: new version sources</title><content type='html'>Finally as &lt;a href="http://sprokhorenko.blogspot.com/2009/12/dedicated-to-my-wife.html"&gt;promised&lt;/a&gt; I've put the separate pieces of the jqGrid + ASP.NET MVC solution... together in a solution - so that this time it does compile. Can't say it's usable right away because I didn't provide any runnable examples yet - but everything is there.&lt;br /&gt;
&lt;br /&gt;
So here're the &lt;a href="http://queen3.at.tut.by/JqGridMvc.zip"&gt;sources&lt;/a&gt;, and what's inside?&lt;br /&gt;
&lt;br /&gt;
1. All the related files, including extension methods, attributes, and JS functions.&lt;br /&gt;
2. Required libraries (SharpArch, NHibernate, AutoMapper, MS ones - a minimal set).&lt;br /&gt;
3. A sample domain model, view model, controller, and view in UsersController.cs / Index.spark files - just a non-functional demo (because it relies on other controllers and parts of the real app). But it should give the idea on how easy it is to create a sophisticated grid with only few lines of code.&lt;br /&gt;
&lt;br /&gt;
A lot of new stuff is implemented - for example, &lt;b&gt;UIHint(""&lt;/b&gt; now accepts empty hint, allowing to override attributes of the automatic checkbox/select controls. But what is important is that many bugs are fixed, interfaces are even more simplified, and ServiceLocator is no longer used - repositories are passed via IoC.&lt;br /&gt;
&lt;br /&gt;
Technically, with the above sources, to add CRUD page for the existing domain class, all one has to do is:&lt;br /&gt;
- create ViewModel and add attributes to control display/edit jqGrid behaviour&lt;br /&gt;
- create controller and override InternalGet/Construct/Save methods (all one-liners).&lt;br /&gt;
&lt;br /&gt;
That's it. I hope to create a simple working demo for this soon.&lt;br /&gt;
&lt;br /&gt;
P.S. For those who like pictures, here's &lt;a href="http://queen3.at.tut.by/ProductEdit.PNG"&gt;an example of an edit form&lt;/a&gt; of the grid that was built in less than 10 minutes - and it covers maybe 20% of the functionality (no grid display with custom formatters, no validation handling, no checkboxes or datepicker, etc).&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8281741202770949929-6885750849474068680?l=sprokhorenko.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sprokhorenko.blogspot.com/feeds/6885750849474068680/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://sprokhorenko.blogspot.com/2010/01/jqgrid-mvc-new-version-sources.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8281741202770949929/posts/default/6885750849474068680'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8281741202770949929/posts/default/6885750849474068680'/><link rel='alternate' type='text/html' href='http://sprokhorenko.blogspot.com/2010/01/jqgrid-mvc-new-version-sources.html' title='jqGrid + MVC: new version sources'/><author><name>Sergey Prokhorenko</name><uri>http://www.blogger.com/profile/06389461574659526392</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://4.bp.blogspot.com/_St_fXOeTKCk/Sp0sRG9IkRI/AAAAAAAAAAM/Fccwc6J00SE/S220/1344263.jpeg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8281741202770949929.post-2916242705427766661</id><published>2010-01-12T00:22:00.002+02:00</published><updated>2010-01-12T00:22:58.655+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='jqGrid'/><category scheme='http://www.blogger.com/atom/ns#' term='ASP.NET MVC'/><title type='text'>ASP.NET MVC + jqGrid</title><content type='html'>I've just got back from vacation and I think I need to post the updated ASP.NET MVC + jqGrid integration (it has a lot of fixes), as well as to explain some internals. Not sure if anyone needs it, but that's not the point ;-)&lt;br /&gt;
&lt;br /&gt;
I hope to do this in near future.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8281741202770949929-2916242705427766661?l=sprokhorenko.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sprokhorenko.blogspot.com/feeds/2916242705427766661/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://sprokhorenko.blogspot.com/2010/01/aspnet-mvc-jqgrid.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8281741202770949929/posts/default/2916242705427766661'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8281741202770949929/posts/default/2916242705427766661'/><link rel='alternate' type='text/html' href='http://sprokhorenko.blogspot.com/2010/01/aspnet-mvc-jqgrid.html' title='ASP.NET MVC + jqGrid'/><author><name>Sergey Prokhorenko</name><uri>http://www.blogger.com/profile/06389461574659526392</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://4.bp.blogspot.com/_St_fXOeTKCk/Sp0sRG9IkRI/AAAAAAAAAAM/Fccwc6J00SE/S220/1344263.jpeg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8281741202770949929.post-1920798414636469239</id><published>2010-01-12T00:19:00.000+02:00</published><updated>2010-01-12T00:19:15.631+02:00</updated><title type='text'>Visual class designer</title><content type='html'>I often see class diagrams in blog posts. They look great. But I refuse to understand how can someone write programs using graphical tools. I mean, create classes. As a programmer I spent most of my time in the text editor. If I work with C#, write code in C#, and use classes written in C#, why would I design my classes not in C#? Why should I switch paradigms back and forth?&lt;br /&gt;
&lt;br /&gt;
That's what I thought reading recent Ayende's posts on NH-vs-EF. I use Fluent NHibernate and I'm completely, absolutely happy with it. I just love it, more than NH itself. Mostly because of it's automapping feature.&lt;br /&gt;
&lt;br /&gt;
But I'm a kind of a person that never understood the need for UML or (say) visual HTML editors. Well, I do understand that some people may need visual tools. I do. I just can't accept it; it's like calling someone who uses FrontPage to be a web programmer. It's so much more natural (as well as faster and more convenient) to speak in native language, be it HTML, C#, or whatever.&lt;br /&gt;
&lt;br /&gt;
Hm, I guess I got it. Those people just can't speak the language well. Or, they can't think in that language. The class design doesn't show up in their minds.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8281741202770949929-1920798414636469239?l=sprokhorenko.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sprokhorenko.blogspot.com/feeds/1920798414636469239/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://sprokhorenko.blogspot.com/2010/01/visual-class-designer.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8281741202770949929/posts/default/1920798414636469239'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8281741202770949929/posts/default/1920798414636469239'/><link rel='alternate' type='text/html' href='http://sprokhorenko.blogspot.com/2010/01/visual-class-designer.html' title='Visual class designer'/><author><name>Sergey Prokhorenko</name><uri>http://www.blogger.com/profile/06389461574659526392</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://4.bp.blogspot.com/_St_fXOeTKCk/Sp0sRG9IkRI/AAAAAAAAAAM/Fccwc6J00SE/S220/1344263.jpeg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8281741202770949929.post-5198102236685783381</id><published>2009-12-24T12:12:00.000+02:00</published><updated>2009-12-24T12:12:01.573+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='concepts'/><title type='text'>The light side of web services</title><content type='html'>In my current project I have to use a legacy web service that tracks some pieces of information. The source code of this web services is far from perfect; but the external interface, even if not 100% satisfactory, is still usable and I am able to integrate it into the new system with only reasonable anti-corruption layer (or mapping layer) involved.&lt;br /&gt;
&lt;br /&gt;
This is I guess one of the good things about web services - they just &lt;b&gt;enforce&lt;/b&gt; SoC. No matter how bad programmers are, no matter how tight deadlines are or how pointy the hair of the boss is - you just cannot make things &lt;b&gt;completely&lt;/b&gt; wrong. And this leaves a hope for those who have to maintain the system.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8281741202770949929-5198102236685783381?l=sprokhorenko.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sprokhorenko.blogspot.com/feeds/5198102236685783381/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://sprokhorenko.blogspot.com/2009/12/light-side-of-web-services.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8281741202770949929/posts/default/5198102236685783381'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8281741202770949929/posts/default/5198102236685783381'/><link rel='alternate' type='text/html' href='http://sprokhorenko.blogspot.com/2009/12/light-side-of-web-services.html' title='The light side of web services'/><author><name>Sergey Prokhorenko</name><uri>http://www.blogger.com/profile/06389461574659526392</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://4.bp.blogspot.com/_St_fXOeTKCk/Sp0sRG9IkRI/AAAAAAAAAAM/Fccwc6J00SE/S220/1344263.jpeg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8281741202770949929.post-2368545033222926166</id><published>2009-12-19T20:12:00.007+02:00</published><updated>2009-12-20T00:24:54.565+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='jqGrid'/><category scheme='http://www.blogger.com/atom/ns#' term='ASP.NET MVC'/><category scheme='http://www.blogger.com/atom/ns#' term='jQuery'/><title type='text'>jqGrid + ASP.NET MVC: quick and powerful</title><content type='html'>&lt;div style="text-align: right;"&gt;&lt;span style="font-size: x-small;"&gt;Dedicated to my wife.&amp;nbsp;&lt;/span&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div style="text-align: right;"&gt;&lt;span style="font-size: x-small;"&gt;Thanks for the patience.&lt;/span&gt;&lt;br /&gt;
&lt;/div&gt;&lt;br /&gt;
In this post I'll explain (or at least will try to, in this and next posts) how to combine jqGrid and ASP.NET MVC to provide a powerful&amp;nbsp;and easy to use solution to quickly create very complex CRUD pages. This is a real code;&amp;nbsp;it was developed as part of a real project - a data-driven admin interface. Note that it is not jqGrid neither ASP.NET MVC guide; it's just a proof of concept that may help to simplify CRUD development.&lt;br /&gt;
&lt;br /&gt;
It includes:&lt;br /&gt;
- NHibernate base repository that provides methods for generic paging, sorting, filtering, and selected item lookup;&lt;br /&gt;
- Two kinds of ASP.NET MVC base controllers - one for entities, another for entity collections -&amp;nbsp;that can handle basic CRUD methods with minimal required overrides;&lt;br /&gt;
- Set of jqGrid C# classes to handle jqGrid communication and to generate jqGrid colModel from C# models,&amp;nbsp;using DataAnnotation and couple of custom attributes;&lt;br /&gt;
- Helper jQuery function that handles most of the common jqGrid setup.&lt;br /&gt;
&lt;br /&gt;
It took me about 3-4 days to implement all of this. It's not a framework; it's just couple of helper classes&amp;nbsp;glued together. I won't even provide a working sample project.&lt;br /&gt;
However, it really allows to create rich CRUD interfaces in several minutes. To give an impression&amp;nbsp;of what it does, let's quickly create a page to manage this model:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="c-sharp" name="code"&gt;&amp;nbsp;&amp;nbsp; public class Employee : User // user has Email property
&amp;nbsp;&amp;nbsp; {
&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp;public Employee(Partner organization)
&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp;{
&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; Roles = new List&amp;lt;Role&amp;gt;();
&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; Organization = organization;
&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp;}

&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp;public virtual IList&amp;lt;Role&amp;gt; Roles { get; set; }
&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp;public virtual string Login { get; set; }
&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp;public virtual string Password { get; set; }
&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp;public virtual string Title { get; set; }
&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp;public virtual string LastName { get; set; }
&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp;public virtual string FirstName { get; set; }
&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp;public virtual DateTime? LastLoginTime { get; set; }
&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp;public virtual Partner Organization { get; set; }
&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp;public string Currency { get; set; }
&amp;nbsp;&amp;nbsp; }
&lt;/pre&gt;&lt;br /&gt;
First, I write a view model for this. You can use the business model directly; I prefer to use view models.&lt;br /&gt;
It doesn't really matter for our topic, except that it makes differences between pure model&amp;nbsp;and jqGrid-enabled one clearer.&lt;br /&gt;
&lt;br /&gt;
Now, let's add attributes - the main reason this post is born is that a lot of samples in the wild&amp;nbsp;use to define jqGrid model in the JavaScript code, thus duplicating columns definitions and lots of other stuff.&lt;br /&gt;
I'm a big follwer of DRY, so I always strieve to eliminate duplication. Thus, defining attributes on the model&amp;nbsp;like below is the ONLY thing I need to do to have both grid with formatting and client and server side validation.&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="c-sharp" name="code"&gt;&amp;nbsp;&amp;nbsp; public class EmployeeViewModel: IJqBasedViewModel
&amp;nbsp;&amp;nbsp; {
&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp;public static void ConfigureAutoMapper()
&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp;{
&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; AutoMapper.Mapper.CreateMap&amp;lt;Employee, EmployeeViewModel&amp;gt;()
&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;.MapFrom(x =&amp;gt; x.LastLoginTime == null ? "" : MyDate.Format(x.LastLoginTime.Value), x =&amp;gt; x.LastLoginTime)
&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;.MapFrom(x =&amp;gt; x.Roles.Select(r =&amp;gt; r.Name).Join(", "), x =&amp;gt; x.RolesAll);
&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; AutoMapper.Mapper.CreateMap&amp;lt;EmployeeViewModel, Employee&amp;gt;()
&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;.Ignore(x =&amp;gt; x.LastLoginTime, x =&amp;gt; x.Id, x =&amp;gt; x.Roles);
&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp;}

&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp;[Visible(false)]
&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp;public string id { get; set; }

&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp;[UIHint("select", "HTML", "dataUrl", "~/Partners/SelectList")]
&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp;[Visible(false), Required, Display(Name = "Organization")]
&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp;public string OrganizationId { get; set; }
&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp;[Immutable, Display(Order = 1, Name = "Organization")]
&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp;[JqFormatter("partnerLink", "baseLinkUrl", "~/Partners/Show")]
&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp;public string OrganizationName { get; set; }

&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp;public string Title { get; set; }
&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp;[Required]
&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp;public string LastName { get; set; }
&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp;public string FirstName { get; set; }

&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp;[Email]
&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp;public string Email { get; set; }
&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp;[Required]
&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp;public string Login { get; set; }
&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp;[Required, UIHint("password"), Visible(false)]
&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp;public string Password { get; set; }

&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp;[Visible(false)]
&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp;[UIHint("select", "HTML", "dataUrl", "~/Roles/SelectList", "multiple", "true", "size", "5")]
&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp;public IList&amp;lt;string&amp;gt; Roles { get; set; }
&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp;[Immutable, Display(Name = "Roles")]
&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp;public string RolesAll { get; set; }

&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp;[Immutable]
&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp;public string Currency { get; set; }
&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp;[Immutable, Display(Name = "Last Login")]
&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp;public string LastLoginTime { get; set; }
&amp;nbsp;&amp;nbsp; }
&lt;/pre&gt;&lt;br /&gt;
Let's review that. First, a static method defines AutoMapper config. This is my own project's convention;&amp;nbsp;I use that to easily add AutoMapper pieces. Application startup code looks for all view models and calls&amp;nbsp;ConfigureAutoMapper if present. The view model implements IJqBasedViewModel interface; this is just to have&lt;br /&gt;
the "id" property which is always required for jqGrid.&lt;br /&gt;
&lt;br /&gt;
AutoMapper maps Organization.Id to OrganizationId, and Organization.Name to OrganizationName. Why we need two?&lt;br /&gt;
The first one appears when we edit the row, thus Visible(false). The second one is display in the grid,&amp;nbsp;thus Immutable. UIHint is used to define the control - in this case, dropdown with values populated from the&amp;nbsp;provided dataUrl. JqFormatter is used to format values in the grid; in this case "partnerLink" is our own&amp;nbsp;JavaScript function, but it could be "'showlink'" - a standard jqGrid formatter (notice '').&lt;br /&gt;
Both would use row's id to generate the link.&lt;br /&gt;
UIHint and JqFormatter support any jqGrid controls and formatters, as well as their parameters. They also apply&amp;nbsp;some processing logic - for example, use Url.Content() for paramters that contain "url".&lt;br /&gt;
&lt;br /&gt;
Other attributes should be self-explanatory. Note that not only they result in jqGrid options applied, but also&amp;nbsp;adds server-side validation (e.g. Required).&lt;br /&gt;
&lt;br /&gt;
Other available attributes and internal behaviour (rendered by JqGrid.cs):&lt;br /&gt;
- bool properties generate check images from jQuery CSS framework in the grid, and checkboxes in the edit form;&lt;br /&gt;
- enum properties generate drop down lists with values from the enum;&lt;br /&gt;
- UIHint where value is typeof(type) that implements IJqGridSelectSource allows to provide custom select values;&lt;br /&gt;
- [Range] generates min/max edit rules;&lt;br /&gt;
- int generates integer-only edits;&lt;br /&gt;
- ExDisplay controls label in edit form and width of column;&lt;br /&gt;
- CamelPropertyNames automatically generate "Camel Property Name" column names and edit labels;&lt;br /&gt;
- UIHint("date") setup datepicker (with customer initDatePicker function);&lt;br /&gt;
- and more.&lt;br /&gt;
&lt;br /&gt;
Now that we defined the view model and how it should look and be edited, left define the controller.&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="c-sharp" name="code"&gt;&amp;nbsp;&amp;nbsp; public class UsersController : JqGridControllerBase&amp;lt;Employee, EmployeeViewModel&amp;gt;
&amp;nbsp;&amp;nbsp; {
&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp;public UsersController(IUserRepository userRepository)
&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp;{
&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; this.userRepository = userRepository;
&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp;}

&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp;protected override PageResult&amp;lt;Employee&amp;gt; InternalGet(PagedRequest request)
&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp;{
&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; request.Override(OrganizationName =&amp;gt; "Organization.Name", Roles =&amp;gt; "Roles.Name");
&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; return userRepository.GetAll&amp;lt;Employee&amp;gt;(request);
&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp;}

&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp;protected override void InternalDelete(Employee entity)
&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp;{
&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; userRepository.Delete(entity);
&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp;}

&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp;protected override Employee InternalConstructEntity(EmployeeViewModel data)
&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp;{
&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; var organization = GetEntityFromRepository&amp;lt;Partner&amp;gt;(userRepository, data.OrganizationId);
&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; return organization == null ? null : new Employee(organization);
&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp;}

&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp;protected override void InternalSave(Employee user, EmployeeViewModel data)
&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp;{
&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; var organization = GetEntityFromRepository&amp;lt;Partner&amp;gt;(userRepository, data.OrganizationId);
&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; user.Organization = organization;
&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; userRepository.SaveOrUpdate(user);
&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp;}

&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp;private readonly IUserRepository userRepository;
&amp;nbsp;&amp;nbsp; }
&lt;/pre&gt;&lt;br /&gt;
Yes, that's it. Four methods to define CRUD operations low level. Few notes:&lt;br /&gt;
- request.Override replaces jqGrid column names with database (NHibernate) column names;&lt;br /&gt;
- GetEntityFromRepository just safely converts string id to Guid and calls repository;&lt;br /&gt;
- some error handling code is omitted for clarity.&lt;br /&gt;
&lt;br /&gt;
Behind the CRUD template methods, JqGridBaseController defines few action methods:&lt;br /&gt;
- Index to render page with the grid&lt;br /&gt;
- JsonIndex to retrieve and return data in json format;&lt;br /&gt;
- Delete to delete entity;&lt;br /&gt;
- Save to create or update entity;&lt;br /&gt;
- and SelectList as a bonus - to render select list options for jqGrid forms - just in case.&lt;br /&gt;
&lt;br /&gt;
Nothing really fancy. I'm sure many of you can do better. But it is simple and extensible enough.&lt;br /&gt;
You're not forced to use JqGridController base (or anything else from this post) but it fits nicely with other parts&amp;nbsp;to provide quick and easy way to build CRUD pages.&lt;br /&gt;
&lt;br /&gt;
There's also another (similar) controller which is used to edit collections inside entities - for example,&amp;nbsp;user's address list. It does so by taking both entity id and index in the collection as parameters. Once again&amp;nbsp;it's completely transparent to the developer who only needs to provide CRUD template methods.&lt;br /&gt;
&lt;br /&gt;
A lot of data driven stuff occurs in the userRepository.GetAll&amp;lt;Employee&amp;gt;(request) call. The request here comes&amp;nbsp;from the jqGrid which indicates page, rows per page, sorting, filtered fields, and item to highlight.&lt;br /&gt;
The GetAll method takes all of this into consideration, and return a page of data, sorted, filtered,&amp;nbsp;and containing the item that user wants to see. And it does this in a generic way independently of the entity type.&lt;br /&gt;
&lt;br /&gt;
Now, the final piece of the puzzle is to create the view with jqGrid inside. Let's do it:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="c-sharp" name="code"&gt;&amp;nbsp;&amp;nbsp; &amp;lt;viewdata model="string"/&amp;gt;
&amp;nbsp;&amp;nbsp; &amp;lt;set Title="'Users'" /&amp;gt;

&amp;nbsp;&amp;nbsp; &amp;lt;content name="bootstrap"&amp;gt;
&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;lt;script&amp;gt;
&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; function partnerLink(cell, options, row) {
&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;return "&amp;lt;a href=\"" + options.colModel.formatoptions.baseLinkUrl + "?id="
&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; + row.OrganizationId + "\"&amp;gt;" + cell + "&amp;lt;/a&amp;gt;";
&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; }
&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; $(function() {
&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;var model = [${Html.JqGridModel&amp;lt;EmployeeViewModel&amp;gt;(null)}];
&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;createJqGrid("#grid", model,
&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; "${Url.Href&amp;lt;UsersController&amp;gt;(c =&amp;gt; c.Delete(null))}",
&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; {
&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;sortname: "OrganizationName",
&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;url: "${Url.Href&amp;lt;UsersController&amp;gt;(c =&amp;gt; c.JsonIndex(null, null))}",
&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;editurl: "${Url.Href&amp;lt;UsersController&amp;gt;(c =&amp;gt; c.Save(null))}"
&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; }, {}, "${Model}");
&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;$("#grid").filterToolbar();
&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; });
&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;lt;/script&amp;gt;
&amp;nbsp;&amp;nbsp; &amp;lt;/content&amp;gt;

&amp;nbsp;&amp;nbsp; &amp;lt;table id="grid"&amp;gt;&amp;lt;/table&amp;gt;
&amp;nbsp;&amp;nbsp; &amp;lt;div id="pager"&amp;gt;&amp;lt;/div&amp;gt;
&lt;/pre&gt;&lt;br /&gt;
This is not ASP.NET WebForms but don't be scared; it's better! It's Spark View Engine and I would suggest you&amp;nbsp;to give it a chance. Not that it matters for our journey.&lt;br /&gt;
&lt;br /&gt;
So, here you can see our "partnerLink" function that creates a link to the partner organization. In the page&amp;nbsp;load function, we use a special html helper method that takes our view model and renders jqGrid colModel array&amp;nbsp;from it:&lt;br /&gt;
&lt;br /&gt;
var model = [${Html.JqGridModel&amp;lt;EmployeeViewModel&amp;gt;(null)}];&lt;br /&gt;
&lt;br /&gt;
Then we call a helper JavaScript function that makes most of the .jqGrid() values for us, so that we just&amp;nbsp;provide grid id, colModel array, and couple of urls (load, edit, delete). But we can still override anything&amp;nbsp;we need - change model before we pass it to createJqGrid, pass jqGrid options, and so on.&lt;br /&gt;
&lt;br /&gt;
Notice that this method can be made even smarter if we always use JqGridBasedController - since we'll be able&amp;nbsp;to pass just "Users" and it will generate CRUD urls for us. But I'm happy with the current level of DRY.&lt;br /&gt;
&lt;br /&gt;
Now, it was a long journey, but only because I did introduce a bunch of concepts. The real work can be done in&amp;nbsp;10 minutes or less - define the view model, put few attributes to tweak the appearence and the behaviour,&amp;nbsp;tell the controller how to link the entity and the repository, and put the grid into the view. Most of this&amp;nbsp;is very mechanical and can be even copy/pasted, the only decisions one has to make is what attributes&amp;nbsp;to put on the view model - which is, naturally, can't be automated since only developer (and user) can decide.&lt;br /&gt;
&lt;br /&gt;
In next post(s), I'll explain the "under the hood" stuff. Meanwhile I will attach &lt;a href="http://queen3.at.tut.by/jqgrid_mvc_src.zip"&gt;full source code&lt;/a&gt; - which you can't compile but can learn and use "as is".&lt;br /&gt;
&lt;br /&gt;
Hope this will be useful for somebody.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8281741202770949929-2368545033222926166?l=sprokhorenko.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sprokhorenko.blogspot.com/feeds/2368545033222926166/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://sprokhorenko.blogspot.com/2009/12/dedicated-to-my-wife.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8281741202770949929/posts/default/2368545033222926166'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8281741202770949929/posts/default/2368545033222926166'/><link rel='alternate' type='text/html' href='http://sprokhorenko.blogspot.com/2009/12/dedicated-to-my-wife.html' title='jqGrid + ASP.NET MVC: quick and powerful'/><author><name>Sergey Prokhorenko</name><uri>http://www.blogger.com/profile/06389461574659526392</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://4.bp.blogspot.com/_St_fXOeTKCk/Sp0sRG9IkRI/AAAAAAAAAAM/Fccwc6J00SE/S220/1344263.jpeg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8281741202770949929.post-7133053746343234121</id><published>2009-12-08T15:02:00.003+02:00</published><updated>2009-12-08T15:03:43.260+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ASP.NET MVC'/><category scheme='http://www.blogger.com/atom/ns#' term='Spark'/><title type='text'>Spark View Engine: hidden gems</title><content type='html'>I use Spark View Engine quite extensively and still haven't found all of its great features.&lt;br /&gt;
&lt;br /&gt;
Among those are conditional attributes. Here's a simple example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div &amp;lt;%= isactive ? "" : "style='display:none'"%&amp;gt; ....&amp;gt;...&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The same using conditional attributes:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style="display:none?{!isactive}"  ....&amp;gt;...&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
It's not just shorter and easier to read. It nicely illustrates the main Spark mantra: allow HTML to dominate the flow. In the second example we can see HTML, while in the first one we can't.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8281741202770949929-7133053746343234121?l=sprokhorenko.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sprokhorenko.blogspot.com/feeds/7133053746343234121/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://sprokhorenko.blogspot.com/2009/12/spark-view-engine-hidden-gems.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8281741202770949929/posts/default/7133053746343234121'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8281741202770949929/posts/default/7133053746343234121'/><link rel='alternate' type='text/html' href='http://sprokhorenko.blogspot.com/2009/12/spark-view-engine-hidden-gems.html' title='Spark View Engine: hidden gems'/><author><name>Sergey Prokhorenko</name><uri>http://www.blogger.com/profile/06389461574659526392</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://4.bp.blogspot.com/_St_fXOeTKCk/Sp0sRG9IkRI/AAAAAAAAAAM/Fccwc6J00SE/S220/1344263.jpeg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8281741202770949929.post-441399092446125819</id><published>2009-12-03T16:00:00.000+02:00</published><updated>2009-12-03T16:00:25.468+02:00</updated><title type='text'>Why PDF sucks</title><content type='html'>Searching for jquery specific answers I stumbled upon a question on StackOverflow:&lt;br /&gt;
&lt;br /&gt;
&lt;blockquote&gt;How do I prevent user from changing font size, and breaking my beautiful menu design?&lt;br /&gt;
&lt;/blockquote&gt;&lt;br /&gt;
That's terrible. One of the biggest reason for me to use FireFox is that there're so many extensions that allow to view the page the way that I like, and not page's crazy author. I can force my fonts, my colors, I can set minimal font size... I have BIG monitor and I always hated those "cool" designers doing fixed-width designs with small fonts that completely break when I zoom page 200%.&lt;br /&gt;
&lt;br /&gt;
Now, PDF has one similar limitation. I can't change fonts there. I just hate thin wide Courier text.&lt;br /&gt;
&lt;br /&gt;
Yes this may work for printed books. And this is another reason why I prefer reading on screen.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8281741202770949929-441399092446125819?l=sprokhorenko.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sprokhorenko.blogspot.com/feeds/441399092446125819/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://sprokhorenko.blogspot.com/2009/12/why-pdf-sucks.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8281741202770949929/posts/default/441399092446125819'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8281741202770949929/posts/default/441399092446125819'/><link rel='alternate' type='text/html' href='http://sprokhorenko.blogspot.com/2009/12/why-pdf-sucks.html' title='Why PDF sucks'/><author><name>Sergey Prokhorenko</name><uri>http://www.blogger.com/profile/06389461574659526392</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://4.bp.blogspot.com/_St_fXOeTKCk/Sp0sRG9IkRI/AAAAAAAAAAM/Fccwc6J00SE/S220/1344263.jpeg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8281741202770949929.post-1932257388729442863</id><published>2009-12-02T18:28:00.006+02:00</published><updated>2009-12-02T18:33:29.222+02:00</updated><title type='text'>Content sliding effect using jQuery</title><content type='html'>In my current project I needed to provide a visual feedback to the user - to indicate that the content was switched.&lt;br /&gt;
&lt;br /&gt;
The closest approximation to what I needed was the &lt;a href="http://jqueryfordesigners.com/coda-slider-effect/"&gt;Coda Slider Effect&lt;/a&gt;. However it seemed to operate on fixed layouts only. My content is tables with complex data inside, with different (fluid) heights, so I thought maybe I need to invent something else.&lt;br /&gt;
&lt;br /&gt;
So here it is. The idea is very simple and I really think - just like Paul McCartney did the morning he invented Yesterday - that this should have been already invented by somebody else. But maybe it's not. So...&lt;br /&gt;
&lt;br /&gt;
Suppose we have tabs-like content, with only one tab shown at a time. In attached example these are two tables, one is hidden. We need to switch them - .hide() old, .show() new - so that user sees a "slide" effect.&lt;br /&gt;
&lt;br /&gt;
The solution is to create absolute-positioned div that contains both of these tables - next to each other - also absolute positioned - and animate their "left" property so that the cloned tables slide. Since they're positioned over the real content, this looks like the real tables slide.&lt;br /&gt;
&lt;br /&gt;
Few notes on the implementation:&lt;br /&gt;
&lt;br /&gt;
- master parent div needs "overflow: hidden" so that children are "cut" - disappearing while sliding;&lt;br /&gt;
- to apply animation to a single element, we put sliding tables inside another div called "slider";&lt;br /&gt;
- the "easing" effect is applied to make animation better.&lt;br /&gt;
&lt;br /&gt;
That's it. Very simple, actually. Works very smooth in FireFox (3.6b4), Chrome (4), and IE6. &lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;&lt;a href="http://queen3.at.tut.by/slide.html"&gt;Watch the demo here&lt;/a&gt;&lt;/b&gt;.&lt;br /&gt;
Click on [1][2] "buttons".&lt;br /&gt;
&lt;br /&gt;
So where's the source code? It's in the demo. Open the demo page source code, it's very simple. It's adapted from the working project so it's not a "clean" example - but I don't care ;-)&lt;br /&gt;
&lt;br /&gt;
Well, actually the demo has few bugs: for example, back slide may not work as expected in IE6. Also, it will take few modifications to slide contents "in between" (as in Coda slider) - a simple modification to build several absolute-positioned content elements instead of two ones. But I leave fixing all these as an exercise for those who's interested. In my project it works fine.&lt;br /&gt;
&lt;br /&gt;
Hope this helps someone.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8281741202770949929-1932257388729442863?l=sprokhorenko.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sprokhorenko.blogspot.com/feeds/1932257388729442863/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://sprokhorenko.blogspot.com/2009/12/content-sliding-effect-using-jquery.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8281741202770949929/posts/default/1932257388729442863'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8281741202770949929/posts/default/1932257388729442863'/><link rel='alternate' type='text/html' href='http://sprokhorenko.blogspot.com/2009/12/content-sliding-effect-using-jquery.html' title='Content sliding effect using jQuery'/><author><name>Sergey Prokhorenko</name><uri>http://www.blogger.com/profile/06389461574659526392</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://4.bp.blogspot.com/_St_fXOeTKCk/Sp0sRG9IkRI/AAAAAAAAAAM/Fccwc6J00SE/S220/1344263.jpeg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8281741202770949929.post-3057442093226677856</id><published>2009-11-30T15:38:00.000+02:00</published><updated>2009-11-30T15:38:33.388+02:00</updated><title type='text'>Do fonts matter?</title><content type='html'>I'm very picky about the fonts I use in my text editor. I'm not going to name any - that's very personal. But I constantly struggle to find a better one - I'm never satisfied.&lt;br /&gt;
&lt;br /&gt;
In my old DOS days, I even used to create my own console font and load it via special driver (the excellent &lt;a href="en.wikipedia.org/wiki/KeyRus"&gt;keyrus&lt;/a&gt;).&lt;br /&gt;
&lt;br /&gt;
Today, I'm choosing between Windows and Linux way of doing subpixel rendering. I have always been a fan of Linux. But its font rendering back in beginning of millenium was very bad, even though I tried few tricks like recompiling freetype myself.&lt;br /&gt;
&lt;br /&gt;
Recently I installed Ubuntu... it seemed that fonts there were ugly, again. I discussed this with one of my co-workers who used Ubuntu at work; he explained that font rendering is not worse than in Windows; it's different, and is actually better.&lt;br /&gt;
&lt;br /&gt;
Well, right. OK.&lt;br /&gt;
&lt;br /&gt;
But after few days in Ubuntu, I do accept this myself. Ubuntu fonts are better. I always liked &lt;b&gt;thick&lt;/b&gt; fonts; that's why I use ClearType on Windows, not because it makes letters smooth. But ClearType is much thinner comparing to Ubuntu fonts. And if one doesn't use a magnifier glass to look at fonts, they're more readable.&lt;br /&gt;
&lt;br /&gt;
For 10 year I believed in ClearType and did not like anything else; now I'm trying to finally move to Ubuntu just because I like how fonts there look like.&lt;br /&gt;
&lt;br /&gt;
Unfortunately, Ubuntu is SO buggy at times; but that's the topic for another post.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8281741202770949929-3057442093226677856?l=sprokhorenko.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sprokhorenko.blogspot.com/feeds/3057442093226677856/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://sprokhorenko.blogspot.com/2009/11/do-fonts-matter.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8281741202770949929/posts/default/3057442093226677856'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8281741202770949929/posts/default/3057442093226677856'/><link rel='alternate' type='text/html' href='http://sprokhorenko.blogspot.com/2009/11/do-fonts-matter.html' title='Do fonts matter?'/><author><name>Sergey Prokhorenko</name><uri>http://www.blogger.com/profile/06389461574659526392</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://4.bp.blogspot.com/_St_fXOeTKCk/Sp0sRG9IkRI/AAAAAAAAAAM/Fccwc6J00SE/S220/1344263.jpeg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8281741202770949929.post-9010164591082806073</id><published>2009-11-25T11:42:00.000+02:00</published><updated>2009-11-25T11:42:06.609+02:00</updated><title type='text'>FireFox is once again the best</title><content type='html'>I've recently switched to Chrome at home. It's just faster. At work I need more power so I can't avoid FireFox. But it was slow... &lt;br /&gt;
&lt;br /&gt;
...only until I realized that 3.6b3 is out. I couldn't believe how &lt;b&gt;FAST&lt;/b&gt; it is. It's even faster than Chrome. And with &lt;a href="https://addons.mozilla.org/en-US/firefox/addon/10674"&gt;Chromifox Extreme&lt;/a&gt; plus &lt;a href="https://addons.mozilla.org/en-US/firefox/addon/13505"&gt;titlebar removal addon&lt;/a&gt; plus &lt;a href="https://addons.mozilla.org/en-US/firefox/addon/4762"&gt;hide menu bar&lt;/a&gt; (tweak version in .rdf) it looks &lt;b&gt;exactly&lt;/b&gt; like Chrome, so I have as much screen space as I need (plus the lovely Chrome theme of course). Wonderful. Browsing is fun again!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8281741202770949929-9010164591082806073?l=sprokhorenko.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sprokhorenko.blogspot.com/feeds/9010164591082806073/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://sprokhorenko.blogspot.com/2009/11/firefox-is-once-again-best.html#comment-form' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8281741202770949929/posts/default/9010164591082806073'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8281741202770949929/posts/default/9010164591082806073'/><link rel='alternate' type='text/html' href='http://sprokhorenko.blogspot.com/2009/11/firefox-is-once-again-best.html' title='FireFox is once again the best'/><author><name>Sergey Prokhorenko</name><uri>http://www.blogger.com/profile/06389461574659526392</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://4.bp.blogspot.com/_St_fXOeTKCk/Sp0sRG9IkRI/AAAAAAAAAAM/Fccwc6J00SE/S220/1344263.jpeg'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8281741202770949929.post-3712013755472073345</id><published>2009-11-19T15:07:00.000+02:00</published><updated>2009-11-19T15:07:23.379+02:00</updated><title type='text'>NAnt is so convenient</title><content type='html'>After several days of fighting with MSBuild I'm going back to NAnt. It's just &lt;b&gt;SO&lt;/b&gt; convoluted every time I need something new. ItemGroup is very slow parsing my fitnesse folder, MSBuild community tasks are not found and no error details are given about where it tries to look in... And overall syntax is too machine-alike.&lt;br /&gt;
&lt;br /&gt;
I did everything I tried in MSBuild with NAnt in 20 minutes, including looking for nant dist. So much better.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8281741202770949929-3712013755472073345?l=sprokhorenko.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sprokhorenko.blogspot.com/feeds/3712013755472073345/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://sprokhorenko.blogspot.com/2009/11/nant-is-so-convenient.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8281741202770949929/posts/default/3712013755472073345'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8281741202770949929/posts/default/3712013755472073345'/><link rel='alternate' type='text/html' href='http://sprokhorenko.blogspot.com/2009/11/nant-is-so-convenient.html' title='NAnt is so convenient'/><author><name>Sergey Prokhorenko</name><uri>http://www.blogger.com/profile/06389461574659526392</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://4.bp.blogspot.com/_St_fXOeTKCk/Sp0sRG9IkRI/AAAAAAAAAAM/Fccwc6J00SE/S220/1344263.jpeg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8281741202770949929.post-4384882199963268890</id><published>2009-11-13T13:25:00.000+02:00</published><updated>2009-11-13T13:25:21.208+02:00</updated><title type='text'>My eyes are pleased to see Windows 7</title><content type='html'>Recently I installed Windows 7 RTM and had an issue with it - basically I had to work in Windows XP until I resolved it.&lt;br /&gt;
&lt;br /&gt;
Getting back to Windows 7 after that, I couldn't believe how much better its font rendering feels to my eyes. I don't know why; I can't prove it; but I do not want to go back to XP, that's for sure.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8281741202770949929-4384882199963268890?l=sprokhorenko.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sprokhorenko.blogspot.com/feeds/4384882199963268890/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://sprokhorenko.blogspot.com/2009/11/my-eyes-are-pleased-to-see-windows-7.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8281741202770949929/posts/default/4384882199963268890'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8281741202770949929/posts/default/4384882199963268890'/><link rel='alternate' type='text/html' href='http://sprokhorenko.blogspot.com/2009/11/my-eyes-are-pleased-to-see-windows-7.html' title='My eyes are pleased to see Windows 7'/><author><name>Sergey Prokhorenko</name><uri>http://www.blogger.com/profile/06389461574659526392</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://4.bp.blogspot.com/_St_fXOeTKCk/Sp0sRG9IkRI/AAAAAAAAAAM/Fccwc6J00SE/S220/1344263.jpeg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8281741202770949929.post-184426301740750330</id><published>2009-11-03T16:38:00.000+02:00</published><updated>2009-11-03T16:38:20.005+02:00</updated><title type='text'>Convenient Distinct()</title><content type='html'>Linq, while very powerful and flexible, lacks many of the useful functions. Here I propose an extension to the default Distinct() method, so that it takes lambda expression instead of full-blown comparer.&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="c-sharp" name="code"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; public class FuncEqualityComparer&amp;lt;T&amp;gt; : IEqualityComparer&amp;lt;T&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Func&amp;lt;T, T, bool&amp;gt; func;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Func&amp;lt;T, int&amp;gt; hash;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; public FuncEqualityComparer(Func&amp;lt;T, T, bool&amp;gt; func, Func&amp;lt;T, int&amp;gt; hash)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; this.func = func;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; this.hash = hash;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; public bool Equals(T x, T y)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return func(x, y);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; public int GetHashCode(T obj)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return hash(obj);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; public static IEnumerable&amp;lt;T&amp;gt; Distinct&amp;lt;T, Y&amp;gt;(this IEnumerable&amp;lt;T&amp;gt; list, Func&amp;lt;T, Y&amp;gt; getfield)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return list.Distinct(new FuncEqualityComparer&amp;lt;T&amp;gt;(
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; (o1, o2) =&amp;gt; getfield(o1).Equals(getfield(o2)), o =&amp;gt; getfield(o).GetHashCode()));
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; public static IEnumerable&amp;lt;T&amp;gt; Distinct&amp;lt;T&amp;gt;(this IEnumerable&amp;lt;T&amp;gt; list, Func&amp;lt;T, T, bool&amp;gt; compare, Func&amp;lt;T, int&amp;gt; hash)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return list.Distinct(new FuncEqualityComparer&amp;lt;T&amp;gt;(compare, hash));
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }
&lt;/pre&gt;&lt;br /&gt;
Now, we can call &lt;b&gt;list.Distinct(x =&gt; x.InnerField)&lt;/b&gt; to shrink list by the InnerField.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8281741202770949929-184426301740750330?l=sprokhorenko.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sprokhorenko.blogspot.com/feeds/184426301740750330/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://sprokhorenko.blogspot.com/2009/11/convenient-distinct.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8281741202770949929/posts/default/184426301740750330'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8281741202770949929/posts/default/184426301740750330'/><link rel='alternate' type='text/html' href='http://sprokhorenko.blogspot.com/2009/11/convenient-distinct.html' title='Convenient Distinct()'/><author><name>Sergey Prokhorenko</name><uri>http://www.blogger.com/profile/06389461574659526392</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://4.bp.blogspot.com/_St_fXOeTKCk/Sp0sRG9IkRI/AAAAAAAAAAM/Fccwc6J00SE/S220/1344263.jpeg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8281741202770949929.post-6266293243494819776</id><published>2009-11-02T11:45:00.001+02:00</published><updated>2009-11-02T11:49:39.050+02:00</updated><title type='text'>Context matters</title><content type='html'>For ages, when I right-click on a table in the MS SQL Management Studio, I don't get "Open" as the first item - while this is the standard across all other MS products, including Visual Studio and Windows Explorer, and Query Analyzer - the best MSSQL tool ever - and it was abandoned since SQL2000. Can someone explain, why the first context menu item for any table in MSSQL 2008 Management Studio is&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;New&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
I don't get it. When I right click on the table, do I mean to create a new one? I don't think so. But someone at MS SQL team actually does.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8281741202770949929-6266293243494819776?l=sprokhorenko.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sprokhorenko.blogspot.com/feeds/6266293243494819776/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://sprokhorenko.blogspot.com/2009/11/context-matters.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8281741202770949929/posts/default/6266293243494819776'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8281741202770949929/posts/default/6266293243494819776'/><link rel='alternate' type='text/html' href='http://sprokhorenko.blogspot.com/2009/11/context-matters.html' title='Context matters'/><author><name>Sergey Prokhorenko</name><uri>http://www.blogger.com/profile/06389461574659526392</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://4.bp.blogspot.com/_St_fXOeTKCk/Sp0sRG9IkRI/AAAAAAAAAAM/Fccwc6J00SE/S220/1344263.jpeg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8281741202770949929.post-8961021874862312016</id><published>2009-10-29T15:14:00.001+02:00</published><updated>2009-10-29T15:15:05.611+02:00</updated><title type='text'>It is it</title><content type='html'>A real comment I've just written:&lt;br /&gt;
&lt;span style="color: #6aa84f;"&gt;// since it manages it itself&lt;/span&gt;&lt;br /&gt;
Now, English does have it's own funny corners...&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8281741202770949929-8961021874862312016?l=sprokhorenko.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sprokhorenko.blogspot.com/feeds/8961021874862312016/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://sprokhorenko.blogspot.com/2009/10/it-is-it.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8281741202770949929/posts/default/8961021874862312016'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8281741202770949929/posts/default/8961021874862312016'/><link rel='alternate' type='text/html' href='http://sprokhorenko.blogspot.com/2009/10/it-is-it.html' title='It is it'/><author><name>Sergey Prokhorenko</name><uri>http://www.blogger.com/profile/06389461574659526392</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://4.bp.blogspot.com/_St_fXOeTKCk/Sp0sRG9IkRI/AAAAAAAAAAM/Fccwc6J00SE/S220/1344263.jpeg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8281741202770949929.post-6810711844760350022</id><published>2009-10-22T18:26:00.000+03:00</published><updated>2009-10-22T18:26:11.962+03:00</updated><title type='text'>A real example of ViewModel</title><content type='html'>Why do we need ViewModel? Because domain entities don't always share the purpose with the view data.&lt;br /&gt;
&lt;br /&gt;
Take a real example of some orders (or products) that depend on each other. They may be contained in simple IList because the domain may happily call GetDependent() and that's all it needs.&lt;br /&gt;
&lt;br /&gt;
But in a view, it has to be displayed hierarchically and grouped by customer. Which means list of customers with order ViewModels nested inside ViewModels, etc. And we need to resolve cross-dependencies.&lt;br /&gt;
&lt;br /&gt;
Now, should domain entities know about all the issues required by the view? Nope. Should we bend entities to contain data in the format required by the view? NO, please - I don't want to do recursion just to apply prices! Should the view go this funky GroupBy/Where/if (GetDependent().Contains())...? I doubt so. The logic that cuts domain entities into the data usable for view is highly independent. That's why ViewModel is good - we extract complex code into separate, understandable and usable piece, with respect to SRP (single responsibility principle), leaving our view concentrating on how to present this information.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8281741202770949929-6810711844760350022?l=sprokhorenko.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sprokhorenko.blogspot.com/feeds/6810711844760350022/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://sprokhorenko.blogspot.com/2009/10/real-example-of-viewmodel.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8281741202770949929/posts/default/6810711844760350022'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8281741202770949929/posts/default/6810711844760350022'/><link rel='alternate' type='text/html' href='http://sprokhorenko.blogspot.com/2009/10/real-example-of-viewmodel.html' title='A real example of ViewModel'/><author><name>Sergey Prokhorenko</name><uri>http://www.blogger.com/profile/06389461574659526392</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://4.bp.blogspot.com/_St_fXOeTKCk/Sp0sRG9IkRI/AAAAAAAAAAM/Fccwc6J00SE/S220/1344263.jpeg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8281741202770949929.post-3925539353681671042</id><published>2009-10-22T11:18:00.000+03:00</published><updated>2009-10-22T11:18:57.799+03:00</updated><title type='text'>CSS is the future of the UI</title><content type='html'>Some people think that web UI is far behind the desktop apps. I disagree. Some browsers are (kind of, it's not JavaScript that is hard; the DOM is), but HTML+CSS is not.&lt;br /&gt;
&lt;br /&gt;
Do you remember MFC? .NET 1.1? They did not even have the concept of layout. Well, .NET 2.0 brought the Dock property. Hoorah! Now I can avoid manually positioning my controls! And then they invented WPF.&lt;br /&gt;
&lt;br /&gt;
Web does have this - already. It was a long way to separate content from style, semantics from look. And being a big followers of concerns separation and DRY, I prefer this over any fancy desktop UI widget with flashing lights. To me, the desktop apps only now start to follow the beauty of the markup+style paradigm. Do you often see a desktop app that resizes its tables and controls when I maximize it?&lt;br /&gt;
&lt;br /&gt;
I have a dream that one day this will merge into a single great technology where CSS will be unified across all execution engines... so XUL, HTML, CSS, WPF, and other things will become the next big thing... at least, I believe that's where it's going to.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8281741202770949929-3925539353681671042?l=sprokhorenko.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sprokhorenko.blogspot.com/feeds/3925539353681671042/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://sprokhorenko.blogspot.com/2009/10/css-is-future-of-ui.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8281741202770949929/posts/default/3925539353681671042'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8281741202770949929/posts/default/3925539353681671042'/><link rel='alternate' type='text/html' href='http://sprokhorenko.blogspot.com/2009/10/css-is-future-of-ui.html' title='CSS is the future of the UI'/><author><name>Sergey Prokhorenko</name><uri>http://www.blogger.com/profile/06389461574659526392</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://4.bp.blogspot.com/_St_fXOeTKCk/Sp0sRG9IkRI/AAAAAAAAAAM/Fccwc6J00SE/S220/1344263.jpeg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8281741202770949929.post-3327188550865403187</id><published>2009-10-20T10:48:00.001+03:00</published><updated>2009-10-20T11:21:39.119+03:00</updated><title type='text'>Ajax is not easy</title><content type='html'>There're lots of posts how one can add ajax form or link in couple of lines. These are lies. There's much more about it. Yes it's easy enough to learn how to hold an axe, but for first few months of working with wood there's a high chance of hurting yourself; not to say that the result won't be a masterpiece.&lt;br /&gt;
&lt;br /&gt;
Back to ajax, I now start to see glitches here and there.&lt;br /&gt;
&lt;br /&gt;
For example, you do $.get() and your server happily returns "login" page which is displayed in the comments section... what's worse, the code can actually accept it as valid result. This is because user went to cached page, where browser did not check the login, and from there $.get() went to the server, where user's login is checked this time - expired.&lt;br /&gt;
&lt;br /&gt;
Another example, I load some input form dynamically... but with Ajax, when user clicks submit and there're server-side validation errors, I need to redisplay the form. So I either return some error in predefined format, or the complete form HTML and check if there's validation-error element in the returned data - and then either redisplay it or treat as success response.&lt;br /&gt;
&lt;br /&gt;
Not to say that, for example, FireFox does not preserve custom headers during redicrect, so the app has no idea that this is the ajax request, and renders full page. &lt;br /&gt;
&lt;br /&gt;
All this happens because Ajax breaks the normal page flow. Redirects do not redirect. Page refresh destroys all the pretty ajax-loaded divs. And so on.&lt;br /&gt;
&lt;br /&gt;
Ajax is wonderful, but doing it the right way is not easy. There're issues that one need to learn. As always, I'd say.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8281741202770949929-3327188550865403187?l=sprokhorenko.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sprokhorenko.blogspot.com/feeds/3327188550865403187/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://sprokhorenko.blogspot.com/2009/10/ajax-is-not-easy.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8281741202770949929/posts/default/3327188550865403187'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8281741202770949929/posts/default/3327188550865403187'/><link rel='alternate' type='text/html' href='http://sprokhorenko.blogspot.com/2009/10/ajax-is-not-easy.html' title='Ajax is not easy'/><author><name>Sergey Prokhorenko</name><uri>http://www.blogger.com/profile/06389461574659526392</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://4.bp.blogspot.com/_St_fXOeTKCk/Sp0sRG9IkRI/AAAAAAAAAAM/Fccwc6J00SE/S220/1344263.jpeg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8281741202770949929.post-2008591834934903747</id><published>2009-10-17T20:45:00.000+03:00</published><updated>2009-10-17T20:45:43.915+03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='jQuery'/><title type='text'>jQuery</title><content type='html'>The more I work with jQuery - and I'm not expert at all but can do tweaks here and there - the more I think that whenever you need to do something fancy, it is easier, faster, and more fun to do it yourself than to look for a plugin. Sure, sometimes you need a plugin, but if I start to look for it first, I fail, because I don't know what I need. If I start by doing the thing myself, I will understand it in 5 minutes, and then I &lt;i&gt;may&lt;/i&gt;&amp;nbsp;go and look for some plugin - this time knowing exactly the kind of. Or I may have the feature done in those 5 minutes. Because, it's usually 80% CSS and only 20% jQuery. And I leave CSS to designers.&lt;br /&gt;
&lt;br /&gt;
jQuery is so damn good that I can almost &lt;b&gt;read&lt;/b&gt;&amp;nbsp;what I want to do in the JavaScript code - when clicked hide this, when hover show this - just a clear intent of what users asked me to do. And it's absolutely easy even for beginners like me to play with the page - it's 5x time longer to look for plugins in Google than to try it myself.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8281741202770949929-2008591834934903747?l=sprokhorenko.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sprokhorenko.blogspot.com/feeds/2008591834934903747/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://sprokhorenko.blogspot.com/2009/10/jquery.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8281741202770949929/posts/default/2008591834934903747'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8281741202770949929/posts/default/2008591834934903747'/><link rel='alternate' type='text/html' href='http://sprokhorenko.blogspot.com/2009/10/jquery.html' title='jQuery'/><author><name>Sergey Prokhorenko</name><uri>http://www.blogger.com/profile/06389461574659526392</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://4.bp.blogspot.com/_St_fXOeTKCk/Sp0sRG9IkRI/AAAAAAAAAAM/Fccwc6J00SE/S220/1344263.jpeg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8281741202770949929.post-6918793819726579664</id><published>2009-09-30T13:00:00.001+03:00</published><updated>2009-09-30T13:54:48.926+03:00</updated><title type='text'>Why yield and IEnumerable is good?</title><content type='html'>IEnumerable is kind of similar to lazy loading in NHibernate. Not only it will defer execution until entity (the colleciton in our case) is accessed. It can prevent execution at all!&lt;br /&gt;
&lt;br /&gt;
For example, we return IEnumerable&amp;lt;&amp;gt; from some method, where we do a lot of calculations, doing yield return for items that match our filters.&lt;br /&gt;
Suppose, the consumer of the returned IEnumerable&amp;lt;&amp;gt; just wants to know if there're any results. It can do enumerable.Any() or enumerable.FirstOrDefault(), and in fact we don't need to execute the whole filters loop because of this call, since once we get the first yield, we know the result!&lt;br /&gt;
&lt;br /&gt;
Another example, suppose we return { IEnumerable&amp;lt;Price&amp;gt; Prices; bool FreeOfCharge; } to our UI. If FreeOfCharge is false, we do not show the prices table, writing "Free Of Charge" instead, and the calculations do not occur at all. &lt;br /&gt;
&lt;br /&gt;
NHibernate used to do the same with collections. For example, it won't fetch data for .Count - it will just do SELECT COUNT(*).&lt;br /&gt;
&lt;br /&gt;
Another similarity is that if we are not careful enough, we can do bad things like N+1 in NHibernate or use .Count() == 0 instead of !Any().&lt;br /&gt;
&lt;br /&gt;
Anyway, all of this really allows us to concentrate on application logic, putting infrastructure and optimizations to the underlying engine.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8281741202770949929-6918793819726579664?l=sprokhorenko.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sprokhorenko.blogspot.com/feeds/6918793819726579664/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://sprokhorenko.blogspot.com/2009/09/why-yield-and-ienumerable-is-good.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8281741202770949929/posts/default/6918793819726579664'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8281741202770949929/posts/default/6918793819726579664'/><link rel='alternate' type='text/html' href='http://sprokhorenko.blogspot.com/2009/09/why-yield-and-ienumerable-is-good.html' title='Why yield and IEnumerable is good?'/><author><name>Sergey Prokhorenko</name><uri>http://www.blogger.com/profile/06389461574659526392</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://4.bp.blogspot.com/_St_fXOeTKCk/Sp0sRG9IkRI/AAAAAAAAAAM/Fccwc6J00SE/S220/1344263.jpeg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8281741202770949929.post-8724706329183095539</id><published>2009-09-29T15:32:00.000+03:00</published><updated>2009-09-29T15:32:49.452+03:00</updated><title type='text'>DRY with FluentHtml</title><content type='html'>I'm a big fan of DRY - Don't Repeat Yourself. I hate duplication. I suppose this is because I'm lazy, I want to do something once and only once (which is another mantra). ASP.NET MVC views are not exceptions.&lt;br /&gt;
&lt;br /&gt;
So, recently I've added &lt;a href="http://stephenwalther.com/blog/archive/2008/09/10/asp-net-mvc-tip-43-use-data-annotation-validators.aspx"&gt;DataAnnotations&lt;/a&gt; support to my project. And, because I use &lt;a href="http://lunaverse.wordpress.com/2008/11/24/mvcfluenthtml-fluent-html-interface-for-ms-mvc/"&gt;FluentHtml&lt;/a&gt; from MvcContrib, it was natural to want FluentHtml (and my views) to support the [Required] and [Display] attributes automatically. Is it easy to do without nodifying MvcContrib sources?&lt;br /&gt;
&lt;br /&gt;
Huh. It took me 5 minutes to implement. Here's a good start:&lt;br /&gt;
&lt;pre class="c-sharp" name="code"&gt;&amp;nbsp;&amp;nbsp; public static class Html
&amp;nbsp;&amp;nbsp; {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; public static Element&amp;lt;T&amp;gt; UseAnnotations&amp;lt;T&amp;gt;(this Element&amp;lt;T&amp;gt; element) where T: Element&amp;lt;T&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; var attributes = (element as IMemberElement).ForMember.Member.GetCustomAttributes(false);

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; var display = attributes.OfType&amp;lt;DisplayAttribute&amp;gt;().FirstOrDefault();
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (display != null)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; element.Label(display.Description);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; else if (element is ISupportsAutoLabeling)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ((ISupportsAutoLabeling)element).SetAutoLabel();

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; var required = attributes.OfType&amp;lt;RequiredAttribute&amp;gt;().FirstOrDefault();
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (required != null)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; element.LabelAfter("*");
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; element.Class("required");
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return element;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }
&amp;nbsp;&amp;nbsp; }
&lt;/pre&gt;and inside view&lt;br /&gt;
&lt;br /&gt;
&amp;lt;%= this.TextBox(x =&amp;gt; x.CompanyName).UseAnnotations() %&amp;gt;&lt;br /&gt;
&lt;br /&gt;
I suppose this is &lt;b&gt;very&lt;/b&gt; easy, isn't it?&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8281741202770949929-8724706329183095539?l=sprokhorenko.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sprokhorenko.blogspot.com/feeds/8724706329183095539/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://sprokhorenko.blogspot.com/2009/09/dry-with-fluenthtml.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8281741202770949929/posts/default/8724706329183095539'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8281741202770949929/posts/default/8724706329183095539'/><link rel='alternate' type='text/html' href='http://sprokhorenko.blogspot.com/2009/09/dry-with-fluenthtml.html' title='DRY with FluentHtml'/><author><name>Sergey Prokhorenko</name><uri>http://www.blogger.com/profile/06389461574659526392</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://4.bp.blogspot.com/_St_fXOeTKCk/Sp0sRG9IkRI/AAAAAAAAAAM/Fccwc6J00SE/S220/1344263.jpeg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8281741202770949929.post-7852267336945502182</id><published>2009-09-29T14:12:00.000+03:00</published><updated>2009-09-29T14:12:36.049+03:00</updated><title type='text'>Beware of global attributes</title><content type='html'>ModelStateToTempData attribute is used in ASP.NET MVC (MvcContrib) to preserve model state between redirects. It is usually useful to have it, with very rare exceptions, so I have this attribute on my base controller.&lt;br /&gt;
&lt;br /&gt;
Which is fine until someone adds the same attribute to a separate action. Bang! Duplicated model state errors.&lt;br /&gt;
&lt;br /&gt;
Global data and behavior &lt;b&gt;always&lt;/b&gt; leads to confusion. Even if it looks innocent at first.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8281741202770949929-7852267336945502182?l=sprokhorenko.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sprokhorenko.blogspot.com/feeds/7852267336945502182/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://sprokhorenko.blogspot.com/2009/09/beware-of-global-attributes.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8281741202770949929/posts/default/7852267336945502182'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8281741202770949929/posts/default/7852267336945502182'/><link rel='alternate' type='text/html' href='http://sprokhorenko.blogspot.com/2009/09/beware-of-global-attributes.html' title='Beware of global attributes'/><author><name>Sergey Prokhorenko</name><uri>http://www.blogger.com/profile/06389461574659526392</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://4.bp.blogspot.com/_St_fXOeTKCk/Sp0sRG9IkRI/AAAAAAAAAAM/Fccwc6J00SE/S220/1344263.jpeg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8281741202770949929.post-8001561053320528888</id><published>2009-09-29T09:51:00.000+03:00</published><updated>2009-09-29T09:51:03.303+03:00</updated><title type='text'>Google Chrome: a replacement for IE6</title><content type='html'>Google Chrome lacks so many tiny features that I can't live without (remembered-per-site zoom, for example), I couldn't use it for a single day. I can't believe someone consider it a replacement for FireFox... for IE6, maybe. This should be the same type of users - those who need surf only.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8281741202770949929-8001561053320528888?l=sprokhorenko.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sprokhorenko.blogspot.com/feeds/8001561053320528888/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://sprokhorenko.blogspot.com/2009/09/google-chrome-replacement-for-ie6.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8281741202770949929/posts/default/8001561053320528888'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8281741202770949929/posts/default/8001561053320528888'/><link rel='alternate' type='text/html' href='http://sprokhorenko.blogspot.com/2009/09/google-chrome-replacement-for-ie6.html' title='Google Chrome: a replacement for IE6'/><author><name>Sergey Prokhorenko</name><uri>http://www.blogger.com/profile/06389461574659526392</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://4.bp.blogspot.com/_St_fXOeTKCk/Sp0sRG9IkRI/AAAAAAAAAAM/Fccwc6J00SE/S220/1344263.jpeg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8281741202770949929.post-1581659581499101574</id><published>2009-09-28T14:28:00.000+03:00</published><updated>2009-09-28T14:28:39.003+03:00</updated><title type='text'>Regions are bad</title><content type='html'>#region's are bad. A lot of people have already blogged about it. I completely agree with it, but today I had another glance of this dirty feeling about them...&lt;br /&gt;
&lt;br /&gt;
I have a suite of orders, and changes to one order can affect others. So they notify each other about such changes. Now, I started putting "changed" event handlers into each different order class. I &lt;b&gt;knew&lt;/b&gt; from the beginning this was bad. I &lt;b&gt;knew&lt;/b&gt; I'd have to refactor it. This kind of breaks SoC and bloats order classes. But today I got a confirmation for this - that was a desire to put #region around my event handlers to hide this too big and not completely suitable for this class code block...&lt;br /&gt;
&lt;br /&gt;
What? Too big? Doesn't belong here? There's nothing worse than hiding problems behind pretty lies - and I mean #region here. All of the troubles in the world are because we don't call things what they really are (c) some smart ancient guy.&lt;br /&gt;
&lt;br /&gt;
#region usually tries to hide the &lt;a href="http://www.codinghorror.com/blog/archives/000326.html"&gt;broken window&lt;/a&gt; in your code. This is a disorder, a chaos that will eat you sooner or later if you allow it to grow in a safe place behind the #region.&lt;br /&gt;
&lt;br /&gt;
P.S. Yes, there're legal uses for #region, but those are rare cases.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8281741202770949929-1581659581499101574?l=sprokhorenko.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sprokhorenko.blogspot.com/feeds/1581659581499101574/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://sprokhorenko.blogspot.com/2009/09/regions-are-bad.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8281741202770949929/posts/default/1581659581499101574'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8281741202770949929/posts/default/1581659581499101574'/><link rel='alternate' type='text/html' href='http://sprokhorenko.blogspot.com/2009/09/regions-are-bad.html' title='Regions are bad'/><author><name>Sergey Prokhorenko</name><uri>http://www.blogger.com/profile/06389461574659526392</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://4.bp.blogspot.com/_St_fXOeTKCk/Sp0sRG9IkRI/AAAAAAAAAAM/Fccwc6J00SE/S220/1344263.jpeg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8281741202770949929.post-6336207577310040629</id><published>2009-09-27T23:46:00.001+03:00</published><updated>2009-09-27T23:46:40.177+03:00</updated><title type='text'>Too clean to be real</title><content type='html'>&lt;div style="color: blue;"&gt;&amp;lt;% Html.RenderAction&amp;lt;SomeWidgetController&amp;gt;(c =&amp;gt; MyWidget()) %&amp;gt;  &lt;br /&gt;
&lt;/div&gt;Some people consider this bad practice as it puts too much control in the view (&lt;a href="http://markmail.org/message/mmkugbjl2dqmqnqk#query:+page:1+mid:6yxdhc4tl5katwef+state:results"&gt;quote&lt;/a&gt;).&lt;br /&gt;
&lt;br /&gt;
I can't believe this is said about the architecture (ASP.NET MVC) where you have no choice but to do&lt;br /&gt;
&lt;div style="color: blue;"&gt;Html.BeginForm&amp;lt;SomeController&amp;gt;(c =&amp;gt; c.Process())&lt;br /&gt;
&lt;/div&gt;and that's even the better variation of the default&lt;br /&gt;
&lt;div style="color: blue;"&gt;Html.BeginForm("action", "controller")&lt;br /&gt;
&lt;/div&gt;&lt;br /&gt;
- isn't this the same thing? Isn't it the view who chooses what controller does process the form? Why can't it do the same for the widget (RenderAction) it cares about?&lt;br /&gt;
&lt;br /&gt;
Or shall we have our ViewModels specify PostUrl, EditFormAction? If so, we can just have .WidgetTarget and View will blindly RenderAction on it. KISS.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8281741202770949929-6336207577310040629?l=sprokhorenko.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sprokhorenko.blogspot.com/feeds/6336207577310040629/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://sprokhorenko.blogspot.com/2009/09/too-clean-to-be-real.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8281741202770949929/posts/default/6336207577310040629'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8281741202770949929/posts/default/6336207577310040629'/><link rel='alternate' type='text/html' href='http://sprokhorenko.blogspot.com/2009/09/too-clean-to-be-real.html' title='Too clean to be real'/><author><name>Sergey Prokhorenko</name><uri>http://www.blogger.com/profile/06389461574659526392</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://4.bp.blogspot.com/_St_fXOeTKCk/Sp0sRG9IkRI/AAAAAAAAAAM/Fccwc6J00SE/S220/1344263.jpeg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8281741202770949929.post-2973491069526904784</id><published>2009-09-27T20:32:00.000+03:00</published><updated>2009-09-27T20:32:54.681+03:00</updated><title type='text'>Code monkeys</title><content type='html'>The very moment when I read this text&lt;br /&gt;
&lt;blockquote&gt;Trying to get a good product out of an army of monkeys requires constant policing&lt;br /&gt;
&lt;/blockquote&gt;in Ayende's &lt;a href="http://ayende.com/Blog/archive/2007/06/02/Effective-Software-Development-or-Policing-Of-Monkeys.aspx"&gt;post&lt;/a&gt; I understood why there're so many standards for development processes (read CMM, waterflow, and so on). And why I never understood the need for such things.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8281741202770949929-2973491069526904784?l=sprokhorenko.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sprokhorenko.blogspot.com/feeds/2973491069526904784/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://sprokhorenko.blogspot.com/2009/09/code-monkeys.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8281741202770949929/posts/default/2973491069526904784'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8281741202770949929/posts/default/2973491069526904784'/><link rel='alternate' type='text/html' href='http://sprokhorenko.blogspot.com/2009/09/code-monkeys.html' title='Code monkeys'/><author><name>Sergey Prokhorenko</name><uri>http://www.blogger.com/profile/06389461574659526392</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://4.bp.blogspot.com/_St_fXOeTKCk/Sp0sRG9IkRI/AAAAAAAAAAM/Fccwc6J00SE/S220/1344263.jpeg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8281741202770949929.post-3729078975796693773</id><published>2009-09-25T22:24:00.000+03:00</published><updated>2009-09-25T22:24:20.301+03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ASP.NET MVC'/><title type='text'>Controllers: get off my business!</title><content type='html'>There're many debates about what controllers in (ASP.NET) MVC should do. I'm going to tell what they should &lt;b&gt;not&lt;/b&gt; do - they should not deal with any business logic. Now, why is that and what is business logic after all?&lt;br /&gt;
&lt;br /&gt;
There's very simple rule of thumb that always work for me when I try to separate eggs from chickens: imaging that you're going to have another "UI" for your domain layer, this time a console application. Will you have to copy/paste your code from the ASP.NET MVC controller action to your console command-line switch processing routine? If yes, then obviously you have business logic in the controller.&lt;br /&gt;
And it better be moved somewhere, into the domain layer. If this means introducing new service - let it be so (but try your  Occam's razor first). Don't let it hang around in your controller. Because, when it grows, you'll eventually need to strip it our there. &lt;b&gt;Anyway&lt;/b&gt;. And it will be much harder because there will be more chances to break existing functionality.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8281741202770949929-3729078975796693773?l=sprokhorenko.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sprokhorenko.blogspot.com/feeds/3729078975796693773/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://sprokhorenko.blogspot.com/2009/09/controllers-get-off-my-business.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8281741202770949929/posts/default/3729078975796693773'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8281741202770949929/posts/default/3729078975796693773'/><link rel='alternate' type='text/html' href='http://sprokhorenko.blogspot.com/2009/09/controllers-get-off-my-business.html' title='Controllers: get off my business!'/><author><name>Sergey Prokhorenko</name><uri>http://www.blogger.com/profile/06389461574659526392</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://4.bp.blogspot.com/_St_fXOeTKCk/Sp0sRG9IkRI/AAAAAAAAAAM/Fccwc6J00SE/S220/1344263.jpeg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8281741202770949929.post-5348187536657943642</id><published>2009-09-25T13:54:00.005+03:00</published><updated>2009-09-25T13:58:15.373+03:00</updated><title type='text'>Linq again. Again? Linq? Yes...</title><content type='html'>Suppose I've written (or borrowed from someone ;-) a little helper like this:&lt;br /&gt;
&lt;pre class="c-sharp" name="code"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; [DebuggerStepThrough]
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; public static void ForEach&amp;lt;T&amp;gt;(this IEnumerable&amp;lt;T&amp;gt; enumerable, Action&amp;lt;T&amp;gt; action)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&amp;nbsp;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; foreach (var x in enumerable) action(x);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }
&lt;/pre&gt;Now, is it really helpful? Why would one want to write&lt;br /&gt;
&lt;pre class="c-sharp" name="code"&gt;orders.ForEach(order =&amp;gt; order.Status = OrderStatus.New);
&lt;/pre&gt;Doesn't it take it a bit to extreme?&lt;br /&gt;
&lt;br /&gt;
OK. What about if I need a generic changes notification method:&lt;br /&gt;
&lt;pre class="c-sharp" name="code"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; public virtual void NotifyOrderChanges(IEnumerable&amp;lt;Product&amp;gt; products, Action&amp;lt;Order&amp;gt; invokeHandlers)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; var dependent = GetDependentOrders(products);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; foreach (var order in dependent)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; invokeHandlers(order);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }
&lt;/pre&gt;Looks pretty straightforward, right? But what about this one:&lt;br /&gt;
&lt;pre class="c-sharp" name="code"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; public virtual void NotifyOrderChanges(IEnumerable&amp;lt;Product&amp;gt; products, Action&amp;lt;Order&amp;gt; invokeHandlers)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; var dependent = GetDependentOrders(products);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; dependent.ForEach(invokeHandlers);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }
&lt;/pre&gt;Does it look better? I would definitely say so.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8281741202770949929-5348187536657943642?l=sprokhorenko.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sprokhorenko.blogspot.com/feeds/5348187536657943642/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://sprokhorenko.blogspot.com/2009/09/linq-again-again-linq-yes.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8281741202770949929/posts/default/5348187536657943642'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8281741202770949929/posts/default/5348187536657943642'/><link rel='alternate' type='text/html' href='http://sprokhorenko.blogspot.com/2009/09/linq-again-again-linq-yes.html' title='Linq again. Again? Linq? Yes...'/><author><name>Sergey Prokhorenko</name><uri>http://www.blogger.com/profile/06389461574659526392</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://4.bp.blogspot.com/_St_fXOeTKCk/Sp0sRG9IkRI/AAAAAAAAAAM/Fccwc6J00SE/S220/1344263.jpeg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8281741202770949929.post-3705699070965919573</id><published>2009-09-24T11:54:00.002+03:00</published><updated>2009-09-24T11:55:35.044+03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ASP.NET MVC'/><category scheme='http://www.blogger.com/atom/ns#' term='DRY'/><title type='text'>Html.ValidationMessage replacement</title><content type='html'>Having to repeat Html.ValidationMessage near every control isn't fun, especially given that it will NOT be displayed most of the time.&lt;br /&gt;
Here's a generic solution to setup validation message once and only once - in your master page:&lt;br /&gt;
&lt;pre class="c-sharp" name="code"&gt;&amp;nbsp;&amp;nbsp; &amp;lt;script type="text/javascript"&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; $(function() { 
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;% foreach (var error in ViewData.ModelState.Keys) { %&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;%= "$('*[name=\"" + error + "\"]').addClass('input-validation-error');" %&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;% } %&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; });
&amp;nbsp;&amp;nbsp; &amp;lt;/script&amp;gt;
&lt;/pre&gt;Now, the code above just adds a validation class... but this can be any fancy jQuery code - flash, add hints, and so on.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8281741202770949929-3705699070965919573?l=sprokhorenko.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sprokhorenko.blogspot.com/feeds/3705699070965919573/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://sprokhorenko.blogspot.com/2009/09/htmlvalidationmessage-replacement.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8281741202770949929/posts/default/3705699070965919573'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8281741202770949929/posts/default/3705699070965919573'/><link rel='alternate' type='text/html' href='http://sprokhorenko.blogspot.com/2009/09/htmlvalidationmessage-replacement.html' title='Html.ValidationMessage replacement'/><author><name>Sergey Prokhorenko</name><uri>http://www.blogger.com/profile/06389461574659526392</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://4.bp.blogspot.com/_St_fXOeTKCk/Sp0sRG9IkRI/AAAAAAAAAAM/Fccwc6J00SE/S220/1344263.jpeg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8281741202770949929.post-3685606013454947727</id><published>2009-09-24T10:14:00.000+03:00</published><updated>2009-09-24T10:14:17.492+03:00</updated><title type='text'>Windows 7 logon screen</title><content type='html'>There're always things that make life easier and you don't notice that... until they're gone.

In old days, after I press Ctrl-Alt-Del, I could type my password and click Enter before the logon screen appears. And it was accepted even though it wasn't on screen at the time of typing.

Now it's gone. In Windows 7, this little convenient trick doesn't work. I have to wait for the logon to appear.

Well, I don't like to wait.

Nevertheless, Windows 7 is good. It has its own, new little tricks.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8281741202770949929-3685606013454947727?l=sprokhorenko.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sprokhorenko.blogspot.com/feeds/3685606013454947727/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://sprokhorenko.blogspot.com/2009/09/windows-7-logon-screen.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8281741202770949929/posts/default/3685606013454947727'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8281741202770949929/posts/default/3685606013454947727'/><link rel='alternate' type='text/html' href='http://sprokhorenko.blogspot.com/2009/09/windows-7-logon-screen.html' title='Windows 7 logon screen'/><author><name>Sergey Prokhorenko</name><uri>http://www.blogger.com/profile/06389461574659526392</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://4.bp.blogspot.com/_St_fXOeTKCk/Sp0sRG9IkRI/AAAAAAAAAAM/Fccwc6J00SE/S220/1344263.jpeg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8281741202770949929.post-6955962357648759654</id><published>2009-09-23T15:09:00.002+03:00</published><updated>2009-09-23T15:09:52.357+03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ASP.NET MVC'/><title type='text'>ASP.NET MVC binding cheatsheet</title><content type='html'>A very useful list of possible combinations that the default MVC model binder gives us:
&lt;a href="http://marcomagdy.com/2009/09/03/asp-net-mvc-model-binding-form-inputs-to-action-parameters/"&gt;http://marcomagdy.com/2009/09/03/asp-net-mvc-model-binding-form-inputs-to-action-parameters/&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8281741202770949929-6955962357648759654?l=sprokhorenko.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sprokhorenko.blogspot.com/feeds/6955962357648759654/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://sprokhorenko.blogspot.com/2009/09/aspnet-mvc-binding-cheatsheet.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8281741202770949929/posts/default/6955962357648759654'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8281741202770949929/posts/default/6955962357648759654'/><link rel='alternate' type='text/html' href='http://sprokhorenko.blogspot.com/2009/09/aspnet-mvc-binding-cheatsheet.html' title='ASP.NET MVC binding cheatsheet'/><author><name>Sergey Prokhorenko</name><uri>http://www.blogger.com/profile/06389461574659526392</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://4.bp.blogspot.com/_St_fXOeTKCk/Sp0sRG9IkRI/AAAAAAAAAAM/Fccwc6J00SE/S220/1344263.jpeg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8281741202770949929.post-6242761077258060922</id><published>2009-09-22T15:02:00.000+03:00</published><updated>2009-09-22T15:02:37.758+03:00</updated><title type='text'>Who drives the Moore's law?</title><content type='html'>I've recently tried the &lt;strike&gt;new&lt;/strike&gt; VS 2010 Beta. It looks awesome and I like it. I'm a visual guy and like the pretty vista-style editor, etc. However the performance was so-o-o bad, I couldn't believe it. Sure it's Beta, but on the other side they use WPF for the editor (and probably other parts). It looks great, but it really begs Intel engineers to make a new 10GHz double-quad core processor. with embedded IL processor.

And my VS 2008 started to eat my memory sometimes. The new project is web app with MVC, custom view engine (Spark) with its own add-on, and so on... a pretty new environment for me. So I'm not sure if I can blame VS, but it used to eat 1GB of RAM if I leave it hibernated for several days (I do not like to close my working environment).&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8281741202770949929-6242761077258060922?l=sprokhorenko.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sprokhorenko.blogspot.com/feeds/6242761077258060922/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://sprokhorenko.blogspot.com/2009/09/who-drives-moores-law.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8281741202770949929/posts/default/6242761077258060922'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8281741202770949929/posts/default/6242761077258060922'/><link rel='alternate' type='text/html' href='http://sprokhorenko.blogspot.com/2009/09/who-drives-moores-law.html' title='Who drives the Moore&apos;s law?'/><author><name>Sergey Prokhorenko</name><uri>http://www.blogger.com/profile/06389461574659526392</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://4.bp.blogspot.com/_St_fXOeTKCk/Sp0sRG9IkRI/AAAAAAAAAAM/Fccwc6J00SE/S220/1344263.jpeg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8281741202770949929.post-8949192436706132173</id><published>2009-09-22T14:46:00.004+03:00</published><updated>2009-09-22T14:55:48.946+03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='C#'/><title type='text'>Another little Linq example</title><content type='html'>Is it clear what do this code does? &lt;br /&gt;
&lt;pre class="c-sharp" name="code"&gt;var itemsToDelete = GetPendingItems();
order.Items.RemoveIf(itemsToDelete.Contains);&lt;/pre&gt;
&lt;br /&gt;
&lt;br /&gt;
Now, what is the RemoveIf method? It's not in C#, right? Yes, but we can add it.
&lt;pre class="c-sharp" name="code"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; public static void RemoveIf&amp;lt;T&amp;gt;(this IList&amp;lt;T&amp;gt; list, Func&amp;lt;T, bool&amp;gt; predicate)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; for (int i = 0; i &amp;lt; list.Count; )
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (predicate(list[i]))
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; list.RemoveAt(i);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; else
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; i++;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }
&lt;/pre&gt;
Now, a little nice part is that RemoveIf accepts method name as argument, not only a lambda expression like "x =&amp;gt; itemsToDelete.Contains(x)". This is automatically recognized and suggested by ReSharper, so one doesn't even have to know about it - the clever guys have already done it for us.&lt;br /&gt;
&lt;br /&gt;
Now, the expressiveness of the line "order.Items.RemoveIf(itemsToDelete.Contains);" is unbelievable. And one doesn't have to write any more code at all (except for RemoveIf written once).&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8281741202770949929-8949192436706132173?l=sprokhorenko.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sprokhorenko.blogspot.com/feeds/8949192436706132173/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://sprokhorenko.blogspot.com/2009/09/another-little-linq-example.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8281741202770949929/posts/default/8949192436706132173'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8281741202770949929/posts/default/8949192436706132173'/><link rel='alternate' type='text/html' href='http://sprokhorenko.blogspot.com/2009/09/another-little-linq-example.html' title='Another little Linq example'/><author><name>Sergey Prokhorenko</name><uri>http://www.blogger.com/profile/06389461574659526392</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://4.bp.blogspot.com/_St_fXOeTKCk/Sp0sRG9IkRI/AAAAAAAAAAM/Fccwc6J00SE/S220/1344263.jpeg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8281741202770949929.post-6148106658731347424</id><published>2009-09-21T14:30:00.000+03:00</published><updated>2009-09-21T14:30:46.745+03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='humor'/><title type='text'>How do programmers talk</title><content type='html'>A real world example. One programmer (1) meet another one (2) to whom (1) owes money:&lt;br /&gt;
(1) Uhm! [takes him wallet and passes money to (2)&lt;br /&gt;
(2) Ah!&lt;br /&gt;
&lt;br /&gt;
That's it.&lt;br /&gt;
&lt;br /&gt;
Now imagine the same with two non-programmers, or maybe even women?&lt;br /&gt;
(1) Hi! You know what, I think I owe money to you.&lt;br /&gt;

(2) Right! It's not urgent, though.&lt;br /&gt;

(1) Anyway, I'm gonna... (takes the wallet) here it is (passes money to (2))&lt;br /&gt;

(2) That's nice because I'm actually going to lunch. Wanna join?&lt;br /&gt;
etc.

&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8281741202770949929-6148106658731347424?l=sprokhorenko.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sprokhorenko.blogspot.com/feeds/6148106658731347424/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://sprokhorenko.blogspot.com/2009/09/how-do-programmers-talk.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8281741202770949929/posts/default/6148106658731347424'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8281741202770949929/posts/default/6148106658731347424'/><link rel='alternate' type='text/html' href='http://sprokhorenko.blogspot.com/2009/09/how-do-programmers-talk.html' title='How do programmers talk'/><author><name>Sergey Prokhorenko</name><uri>http://www.blogger.com/profile/06389461574659526392</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://4.bp.blogspot.com/_St_fXOeTKCk/Sp0sRG9IkRI/AAAAAAAAAAM/Fccwc6J00SE/S220/1344263.jpeg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8281741202770949929.post-8493352130446321378</id><published>2009-09-21T13:43:00.001+03:00</published><updated>2009-09-21T13:43:57.703+03:00</updated><title type='text'>Syntax Highlighter</title><content type='html'>Wow, http://fazibear.blogspot.com/2007/09/blogger-syntax-higlighter.html does a great job! And it's so very easy to use.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8281741202770949929-8493352130446321378?l=sprokhorenko.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sprokhorenko.blogspot.com/feeds/8493352130446321378/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://sprokhorenko.blogspot.com/2009/09/syntax-highlighter.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8281741202770949929/posts/default/8493352130446321378'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8281741202770949929/posts/default/8493352130446321378'/><link rel='alternate' type='text/html' href='http://sprokhorenko.blogspot.com/2009/09/syntax-highlighter.html' title='Syntax Highlighter'/><author><name>Sergey Prokhorenko</name><uri>http://www.blogger.com/profile/06389461574659526392</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://4.bp.blogspot.com/_St_fXOeTKCk/Sp0sRG9IkRI/AAAAAAAAAAM/Fccwc6J00SE/S220/1344263.jpeg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8281741202770949929.post-3769414236318462358</id><published>2009-09-21T13:03:00.007+03:00</published><updated>2009-09-21T14:31:09.986+03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ASP.NET MVC'/><title type='text'>My custom ASP.NET MVC entity binding</title><content type='html'>I've read Jimmy Bogard's blog and ASP.NET MVC In Action (not finished yet), and I really bought into ViewModel concept. Really. I hate messing with strings, magic parameters coming from knowledge that Create(Product product) parameter is named "product", not "prd", and so on. (One thing I also like but will probably wait until MVC v2 is generic InputFor with templates). I also like the idea of model binders. Controller action doing just it's job is so much easier to read and test than controller action doing 5 repository accesses. Not to say that it is code duplication in its very ugliness, and code duplication is what I hate most (because I'm lazy).&lt;br /&gt;
&lt;br /&gt;
So I really try to keep my MVC controllers clean and move all binding and form id =&amp;gt; repository code to model binders. There're problems, though - as always.&lt;br /&gt;
&lt;br /&gt;
Suppose I want to allow to select our entity (from a dropdown, etc)
on a page, let's say Product. As a result I may receive this:&lt;br /&gt;
&lt;pre class="c-sharp" name="code"&gt;public ActionResult SelectedAction(Guid productId)
{
}
&lt;/pre&gt;
But, I want to use model binders power, so instead I write model binder to get my product from repository and instead use&lt;br /&gt;
&lt;pre class="prettyprint"&gt;&lt;code&gt;public ActionResult SelectedAction(Product product)
{
&amp;nbsp; &amp;nbsp;if (ModelState.IsValid) {} else {}
}
&lt;/code&gt;&lt;/pre&gt;
My model binder will set model state to false if product is invalid.
Now, there're problems with this approach:&lt;br /&gt;
&lt;ol&gt;
&lt;li&gt;It's not always easy to use strongly-typed methods like
Html.ActionLink(c =&amp;gt; c.SelectedAction(id)) since we need to pass
Product, not id.&lt;/li&gt;
&lt;li&gt;It's not good to use entities as controller parameters, anyway.&lt;/li&gt;
&lt;li&gt;If model state is invalid, and I want to redirect back and show
error, I can't preserve selected product! Because bound product is not
set and my id is not there. I'd like to do RedirectToAction(c =&amp;gt;
c.Redisplay(product)) but of course this is not possible.&lt;/li&gt;
&lt;/ol&gt;
Now, seems like I'm back to use "Guid productId" as parameter...
However, there's one solution that I'd like to present:&lt;br /&gt;
&lt;pre class="c-sharp" name="code"&gt;   public class EntityViewModel&amp;lt;T&amp;gt; where T : BaseEntity
   {
      public EntityViewModel(Guid id)
      {
         this.Id = id;
      }

      public static implicit operator EntityViewModel&amp;lt;T&amp;gt;(T entity)
      {
         return new EntityViewModel&amp;lt;T&amp;gt;(entity.Id);
      }

      public override string ToString()
      {
         return Id.ToString();
      }

      public Guid Id { get; set; }
      public T Instance { get; set; }
   }
&lt;/pre&gt;
all the problems are solved:&lt;br /&gt;
&lt;ol&gt;
&lt;li&gt;I can pass EntityViewModel with only Id set if I have only Id. &lt;/li&gt;
&lt;li&gt;I don't use entity as parameter. Moreover, I
can use EntityViewModel as property inside another ViewModel. &lt;/li&gt;
&lt;li&gt;I can pass EntityViewModel back to RedirectToController and it will
keep its Id value, which will be
redisplayed to user along with the validation messages (thanks to
MVCContrib and ModelStateToTempData / PassParametersDuringRedirect).&lt;/li&gt;
&lt;/ol&gt;
The model binder will get Instance from the repository and will set
model state errors like "Not found in database" and so on. And I can
use things like ActionLink(c =&amp;gt;
c.Action(Model.MyProductViewModelProperty)).&lt;br /&gt;
&lt;br /&gt;
I'm only starting to explore the possibilities with this approach, but it did already saved me a bunch of minutes and keystrokes.&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8281741202770949929-3769414236318462358?l=sprokhorenko.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sprokhorenko.blogspot.com/feeds/3769414236318462358/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://sprokhorenko.blogspot.com/2009/09/my-custom-aspnet-mvc-entity-binding.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8281741202770949929/posts/default/3769414236318462358'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8281741202770949929/posts/default/3769414236318462358'/><link rel='alternate' type='text/html' href='http://sprokhorenko.blogspot.com/2009/09/my-custom-aspnet-mvc-entity-binding.html' title='My custom ASP.NET MVC entity binding'/><author><name>Sergey Prokhorenko</name><uri>http://www.blogger.com/profile/06389461574659526392</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://4.bp.blogspot.com/_St_fXOeTKCk/Sp0sRG9IkRI/AAAAAAAAAAM/Fccwc6J00SE/S220/1344263.jpeg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8281741202770949929.post-5257978134892264626</id><published>2009-09-21T12:04:00.001+03:00</published><updated>2009-09-21T14:31:29.509+03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ASP.NET MVC'/><title type='text'></title><content type='html'>One problem with ASP.NET MVC, is that how many bad examples one can see on the net, and how hard it's to find a good one. All the articles there are bloated with Linq-to-SQL directly in controllers, entities used as controller parameters as well as directly in views, bloated with presentation concerns like validation attributes, and so on.&lt;br /&gt;
&lt;br /&gt;
I suppose this is because ASP.NET MVC does not force any particular style, unlike Ruby on Rails, for example. &lt;br /&gt;
&lt;br /&gt;
I've only found a couple sources of good MVC style to follow, basically these are Jimmy Bogard's &lt;a href="http://www.lostechies.com/blogs/jimmy_bogard/archive/2009/04/24/how-we-do-mvc.aspx"&gt;blog &lt;/a&gt;and &lt;a href="http://www.manning.com/palermo/"&gt;ASP.NET MVC in Action&lt;/a&gt; book. Not accidentally, Jimmy&lt;a href="http://www.manning.com/palermo/excerpt_abouttheauthors.html"&gt; co-authors&lt;/a&gt; this book.&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8281741202770949929-5257978134892264626?l=sprokhorenko.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sprokhorenko.blogspot.com/feeds/5257978134892264626/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://sprokhorenko.blogspot.com/2009/09/one-problem-with-asp.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8281741202770949929/posts/default/5257978134892264626'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8281741202770949929/posts/default/5257978134892264626'/><link rel='alternate' type='text/html' href='http://sprokhorenko.blogspot.com/2009/09/one-problem-with-asp.html' title=''/><author><name>Sergey Prokhorenko</name><uri>http://www.blogger.com/profile/06389461574659526392</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://4.bp.blogspot.com/_St_fXOeTKCk/Sp0sRG9IkRI/AAAAAAAAAAM/Fccwc6J00SE/S220/1344263.jpeg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8281741202770949929.post-3523741234457910449</id><published>2009-09-20T11:40:00.002+03:00</published><updated>2009-09-20T11:40:45.964+03:00</updated><title type='text'>ScribeFire</title><content type='html'>Hmm, looks like posts made with ScribeFire (for FireFox) have incorrect font and do not have Google Analytics scripts. Not sure if it's ScribeFire problem... but it looks so.&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8281741202770949929-3523741234457910449?l=sprokhorenko.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sprokhorenko.blogspot.com/feeds/3523741234457910449/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://sprokhorenko.blogspot.com/2009/09/scribefire.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8281741202770949929/posts/default/3523741234457910449'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8281741202770949929/posts/default/3523741234457910449'/><link rel='alternate' type='text/html' href='http://sprokhorenko.blogspot.com/2009/09/scribefire.html' title='ScribeFire'/><author><name>Sergey Prokhorenko</name><uri>http://www.blogger.com/profile/06389461574659526392</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://4.bp.blogspot.com/_St_fXOeTKCk/Sp0sRG9IkRI/AAAAAAAAAAM/Fccwc6J00SE/S220/1344263.jpeg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8281741202770949929.post-2839213448602651002</id><published>2009-09-20T11:38:00.000+03:00</published><updated>2009-09-20T11:38:47.208+03:00</updated><title type='text'>Count(Any)</title><content type='html'>&lt;i&gt;&lt;span ##00ffffff??="" background-color:=""&gt;&lt;span style="font-family: Verdana; font-size: 8pt;"&gt;The 
Microsoft Sync Framework SDK provides developers with everything that they need 
to build sync ecosystems that integrate any application with any data from any 
store, by using any protocol over any network.&lt;/span&gt;&lt;/span&gt;&lt;/i&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;span ##00ffffff??="" background-color:=""&gt;&lt;span style="font-family: Verdana; font-size: 8pt;"&gt;I think there're too few "any" words here. This should read:&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;span ##00ffffff??="" background-color:=""&gt;&lt;span style="font-family: Verdana; font-size: 8pt;"&gt;The 
Microsoft Sync Framework SDK provides any developers with anything that they need 
to build any sync ecosystems that integrate any application with any data from any 
store, by using any protocol over any network.&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;span ##00ffffff??="" background-color:=""&gt;&lt;span style="font-family: Verdana; font-size: 8pt;"&gt;Or, even better:&lt;/span&gt;&lt;/span&gt;&lt;span ##00ffffff??="" background-color:=""&gt;&lt;span style="font-family: Verdana; font-size: 8pt;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span ##00ffffff??="" background-color:=""&gt;&lt;span style="font-family: Verdana; font-size: 8pt;"&gt;The 
Microsoft &lt;/span&gt;&lt;/span&gt;&lt;span ##00ffffff??="" background-color:=""&gt;&lt;span style="font-family: Verdana; font-size: 8pt;"&gt;provides any developers with anything that they need.&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;span ##00ffffff??="" background-color:=""&gt;&lt;span style="font-family: Verdana; font-size: 8pt;"&gt;That's right.&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span ##00ffffff??="" background-color:=""&gt;&lt;span style="font-family: Verdana; font-size: 8pt;"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span ##00ffffff??="" background-color:=""&gt;&lt;span style="font-family: Verdana; font-size: 8pt;"&gt; &lt;/span&gt;&lt;/span&gt;&lt;span ##00ffffff??="" background-color:=""&gt;&lt;span style="font-family: Verdana; font-size: 8pt;"&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8281741202770949929-2839213448602651002?l=sprokhorenko.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sprokhorenko.blogspot.com/feeds/2839213448602651002/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://sprokhorenko.blogspot.com/2009/09/countany.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8281741202770949929/posts/default/2839213448602651002'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8281741202770949929/posts/default/2839213448602651002'/><link rel='alternate' type='text/html' href='http://sprokhorenko.blogspot.com/2009/09/countany.html' title='Count(Any)'/><author><name>Sergey Prokhorenko</name><uri>http://www.blogger.com/profile/06389461574659526392</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://4.bp.blogspot.com/_St_fXOeTKCk/Sp0sRG9IkRI/AAAAAAAAAAM/Fccwc6J00SE/S220/1344263.jpeg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8281741202770949929.post-3773414706801617212</id><published>2009-09-18T18:47:00.003+03:00</published><updated>2009-09-18T19:30:16.336+03:00</updated><title type='text'>Linq</title><content type='html'>&lt;div xmlns="http://www.w3.org/1999/xhtml"&gt;
I have to say, that even though it's soo easy to abuse this power, Linq capabilities are amazing. Look at this line:&lt;br /&gt;
Items.SelectMany(x =&amp;gt; x.Products).ToList();&lt;br /&gt;
Here the order returns all the products that its items hold. Now, what will it take with foreach or even for loops? And what expresses the intent better?&lt;br /&gt;
&lt;br /&gt;
This is what C++ miss, even though boost tries to provide it via lambda functors... but those are just a pale shade of the C# great feature.&lt;br /&gt;
&lt;br /&gt;
And we do not say Lisp yet ;-) If we talk about it and parenthesises specifically, does anybody like this:&lt;br /&gt;
items.Select(item =&amp;gt; item.Products.Where(p =&amp;gt; items.SelectedProducts.Any(sp =&amp;gt; sp.Group == p.Group)).SelectMany(p =&amp;gt; p.Subproducts).SingleOrDefault();&lt;br /&gt;
&lt;br /&gt;
Whoops. I don't know what that means but I want to run and hide. And did I miss a parenthesis there?&lt;br /&gt;
&lt;br /&gt;
And yes, I need the source code syntax highlighter... &lt;br /&gt;
&lt;br /&gt;
&lt;div class="zemanta-pixie"&gt;
&lt;img alt="" class="zemanta-pixie-img" ilo-full-src="http://img.zemanta.com/pixy.gif?x-id=250e9faa-ea15-8995-96a9-8b1047a15dfd" src="http://img.zemanta.com/pixy.gif?x-id=250e9faa-ea15-8995-96a9-8b1047a15dfd" /&gt;&lt;br /&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8281741202770949929-3773414706801617212?l=sprokhorenko.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sprokhorenko.blogspot.com/feeds/3773414706801617212/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://sprokhorenko.blogspot.com/2009/09/linq.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8281741202770949929/posts/default/3773414706801617212'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8281741202770949929/posts/default/3773414706801617212'/><link rel='alternate' type='text/html' href='http://sprokhorenko.blogspot.com/2009/09/linq.html' title='Linq'/><author><name>Sergey Prokhorenko</name><uri>http://www.blogger.com/profile/06389461574659526392</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://4.bp.blogspot.com/_St_fXOeTKCk/Sp0sRG9IkRI/AAAAAAAAAAM/Fccwc6J00SE/S220/1344263.jpeg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8281741202770949929.post-9057899362752410764</id><published>2009-09-10T18:01:00.001+03:00</published><updated>2009-09-10T18:01:47.534+03:00</updated><title type='text'>Fluent / NHibernate / AutoMapping: hiding complexity?</title><content type='html'>&lt;div xmlns='http://www.w3.org/1999/xhtml'&gt;I have Item with two collections: IList&amp;lt;Product&amp;gt; GoodProducts, IList&amp;lt;Product&amp;gt; BadProducts.&lt;br/&gt;Now, what is the default mapping for this, produced by Fluent NHibernate?&lt;br/&gt;Items ()&lt;br/&gt;Products (ItemId)&lt;br/&gt;And what is the result of new Item ( new List{product1}, new List{product2} )?&lt;br/&gt;Items1 ()&lt;br/&gt;Products1 (1)&lt;br/&gt;Products2 (1)&lt;br/&gt;That is, now we have two products, and both points to the item... now, when we load our item back, NHibernate happily populates both Good and Bad collections with both products. Why? Because they both refer to the same parent item.&lt;br/&gt;&lt;br/&gt;And this is because we don't actually have HasMany, it's HasManyToMany. But it's not always easy to guess when you save your item and get it back with kind of duplicated products...&lt;br/&gt;&lt;br/&gt;We &lt;b&gt;can&lt;/b&gt; use HasMany but with Products (IsGood) or Products (GoodItemId, BadItemId) but this is weird I guess.&lt;br/&gt;&lt;br/&gt;&lt;div class='zemanta-pixie'&gt;&lt;img src='http://img.zemanta.com/pixy.gif?x-id=12077a6d-bbf9-8b76-bbf4-2b7d1ef3477e' alt='' class='zemanta-pixie-img'/&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8281741202770949929-9057899362752410764?l=sprokhorenko.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sprokhorenko.blogspot.com/feeds/9057899362752410764/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://sprokhorenko.blogspot.com/2009/09/fluent-nhibernate-automapping-hiding.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8281741202770949929/posts/default/9057899362752410764'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8281741202770949929/posts/default/9057899362752410764'/><link rel='alternate' type='text/html' href='http://sprokhorenko.blogspot.com/2009/09/fluent-nhibernate-automapping-hiding.html' title='Fluent / NHibernate / AutoMapping: hiding complexity?'/><author><name>Sergey Prokhorenko</name><uri>http://www.blogger.com/profile/06389461574659526392</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://4.bp.blogspot.com/_St_fXOeTKCk/Sp0sRG9IkRI/AAAAAAAAAAM/Fccwc6J00SE/S220/1344263.jpeg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8281741202770949929.post-534031129308286093</id><published>2009-09-09T16:52:00.001+03:00</published><updated>2009-09-09T16:52:23.528+03:00</updated><title type='text'>Unit tests without design?</title><content type='html'>&lt;div xmlns='http://www.w3.org/1999/xhtml'&gt;I find it impossible to do unit testing without some semi-final classes design that is not going change much.&lt;br/&gt;During last week my classes changed from Order with Products to OrderSuite/Order/OrderItem/OrderAction/Products/LegacyItem and that's as a result of groking requirements.&lt;br/&gt;Not to mention controllers.&lt;br/&gt;&lt;br/&gt;Now, implementing this stuff is what helped me to grok the requirements.&lt;br/&gt;&lt;br/&gt;So unless I can design the whole thing on the whiteboard... I can't do too many tests for the thing that is going to change the very next day.&lt;br/&gt;&lt;br/&gt;Well, "plan to throw away" may work here... when I feel that I grok the whole thing and that design is stabilized, maybe it's time to pretend that I'm starting from scratch... so that I can write innocent unit tests. But meanwhile, I find it impossible.&lt;br/&gt;&lt;br/&gt;That's only in my case, a poor guy without any design at all. If you got the design, you're happier than I am.&lt;br/&gt;&lt;br/&gt;&lt;div class='zemanta-pixie'&gt;&lt;img src='http://img.zemanta.com/pixy.gif?x-id=4acd452e-1ddc-8cd3-82bf-d56ef449220b' alt='' class='zemanta-pixie-img'/&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8281741202770949929-534031129308286093?l=sprokhorenko.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sprokhorenko.blogspot.com/feeds/534031129308286093/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://sprokhorenko.blogspot.com/2009/09/unit-tests-without-design.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8281741202770949929/posts/default/534031129308286093'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8281741202770949929/posts/default/534031129308286093'/><link rel='alternate' type='text/html' href='http://sprokhorenko.blogspot.com/2009/09/unit-tests-without-design.html' title='Unit tests without design?'/><author><name>Sergey Prokhorenko</name><uri>http://www.blogger.com/profile/06389461574659526392</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://4.bp.blogspot.com/_St_fXOeTKCk/Sp0sRG9IkRI/AAAAAAAAAAM/Fccwc6J00SE/S220/1344263.jpeg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8281741202770949929.post-3963007215401656148</id><published>2009-09-09T16:09:00.001+03:00</published><updated>2009-09-09T16:09:32.555+03:00</updated><title type='text'>Why you should be translating exceptions between layers</title><content type='html'>&lt;div xmlns='http://www.w3.org/1999/xhtml'&gt;Today I tried to add SSL support to the local IIS7 web site. I only added a dummy certificate, nothing more, I tell you. Well, maybe restarted IIS just in case. And here's what I got: no access to the site, including plain HTTP (80). Trying to find out what happened, I realized that my site was stopped. I tried to start it and got this nice message:&lt;br/&gt;&lt;b&gt;The process cannot access the file because it is being used by another process&lt;/b&gt;&lt;br/&gt;Now, what do you think happened? Is it about certificate file? Or what?&lt;br/&gt;&lt;br/&gt;I could never guess... but Google is a big help as usual. That was my Skype interfering with ports 80/443.&lt;br/&gt;&lt;br/&gt;Now, I do understand that OS tends to see any shit as a file. That is what makes Unix so cool to OS geeks. And it is cool. However, if you as application opens a port, gets a native error code, and throws it into the face of the user, that misses one big thing.&lt;br/&gt;&lt;br/&gt;The &lt;b&gt;context.&lt;br/&gt;&lt;br/&gt;&lt;/b&gt;If you read file, error should be "cannot read file". Not "descriptor is missing" from some crazy inner file descriptor table-lookup procedure.&lt;br/&gt;If you open a port, the error should be "Cannot open port". Not "cannot access file". I do not insist on translating "ACCESS_DENIED" to "Port is used by another application". A simple "Trying to open port: ACCESS_DENIED" is good for me.&lt;br/&gt;&lt;br/&gt;So, when you catch IOException, don't just throw it into the outer world. Tell them what you were doing... throw ConfigFileReadError instead. Then, when you try to start some application, it will make much more sense to see that the problem is with the config file, not with  "some file" (is my .exe corrupted???).&lt;br/&gt;&lt;br/&gt;&lt;div class='zemanta-pixie'&gt;&lt;img src='http://img.zemanta.com/pixy.gif?x-id=9a84c1fa-7b33-86e7-8077-a517f9e24485' alt='' class='zemanta-pixie-img'/&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8281741202770949929-3963007215401656148?l=sprokhorenko.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sprokhorenko.blogspot.com/feeds/3963007215401656148/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://sprokhorenko.blogspot.com/2009/09/why-you-should-be-translating.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8281741202770949929/posts/default/3963007215401656148'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8281741202770949929/posts/default/3963007215401656148'/><link rel='alternate' type='text/html' href='http://sprokhorenko.blogspot.com/2009/09/why-you-should-be-translating.html' title='Why you should be translating exceptions between layers'/><author><name>Sergey Prokhorenko</name><uri>http://www.blogger.com/profile/06389461574659526392</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://4.bp.blogspot.com/_St_fXOeTKCk/Sp0sRG9IkRI/AAAAAAAAAAM/Fccwc6J00SE/S220/1344263.jpeg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8281741202770949929.post-1477356401087221007</id><published>2009-09-08T10:53:00.001+03:00</published><updated>2009-09-08T10:53:15.048+03:00</updated><title type='text'>Domain driven design - listen to your domain</title><content type='html'>&lt;div xmlns='http://www.w3.org/1999/xhtml'&gt;I'm working on a web application which is kind of port of a legacy application built around MS Commerce Server. Now, while I can see that MSCS is a powerful beast, it is truly a beast to a high degree. Basically, the generality that is put into it makes the business logic bend to comply with MSCS, not with the business logic.&lt;br/&gt;&lt;br/&gt;Anyway, the ported project is developed using DDD (to the extent that I grok it). And the important lesson that I learned along the way - listen to your domain. Or, maybe even obey to it.&lt;br/&gt;&lt;br/&gt;The mistake was to inherit the generality of the old system. For example, product can have prices in different currencies. In old system, all prices were separate products, linked to the priceless one. This made lots of trouble in old system, and it did same in the new one... because the domain language does not speak "products related to products with prices where relation is...". It speaks "products have prices in different currencies". &lt;br/&gt;&lt;br/&gt;Naturally, when you work with wrong domain, you still have to get the result that domain requires; so you &lt;b&gt;translate&lt;/b&gt; your wrong domain design into the right one to perform actions, and you do this everywhere, because now your code say "((PricedProduct)product.GetProductWithRelation(new Relation(currency))).Price", not just "product.GetPrice(currency)".&lt;br/&gt;Now, if instead of products of products you just add prices to products, there's nothing left to do. The domain speaks for itself. And what is more important, you do &lt;b&gt;understand&lt;/b&gt; the code. You don't need those weird relations just because it's more abstract, powerful, general, and... YAGNI. What you need is a simple, understandable, and maintainable system.&lt;br/&gt;&lt;br/&gt;And &lt;b&gt;this&lt;/b&gt; is one of the powerful sides of the DDD.&lt;br/&gt;&lt;br/&gt;&lt;div class='zemanta-pixie'&gt;&lt;img src='http://img.zemanta.com/pixy.gif?x-id=44faf76e-06e6-8f58-8970-a00df744c1f1' alt='' class='zemanta-pixie-img'/&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8281741202770949929-1477356401087221007?l=sprokhorenko.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sprokhorenko.blogspot.com/feeds/1477356401087221007/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://sprokhorenko.blogspot.com/2009/09/domain-driven-design-listen-to-your.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8281741202770949929/posts/default/1477356401087221007'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8281741202770949929/posts/default/1477356401087221007'/><link rel='alternate' type='text/html' href='http://sprokhorenko.blogspot.com/2009/09/domain-driven-design-listen-to-your.html' title='Domain driven design - listen to your domain'/><author><name>Sergey Prokhorenko</name><uri>http://www.blogger.com/profile/06389461574659526392</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://4.bp.blogspot.com/_St_fXOeTKCk/Sp0sRG9IkRI/AAAAAAAAAAM/Fccwc6J00SE/S220/1344263.jpeg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8281741202770949929.post-1523003639955541365</id><published>2009-09-01T14:30:00.002+03:00</published><updated>2009-09-01T15:54:52.614+03:00</updated><title type='text'>Anemic Domain Model</title><content type='html'>&lt;div xmlns="http://www.w3.org/1999/xhtml"&gt;
Foreword: after few thoughts I decided to start blog in English, not Russian. After all, I can't imagine a quite-enough-professional programmer not being able to read English.&lt;br /&gt;
Another foreword: why blogging? because sometimes we want to say something. And because Joel said that writing essays helps to be a programmer.&lt;br /&gt;
&lt;br /&gt;
So, in my current project I started with Sharp Architecture and domain-driven design (DDD). This is quite new to me so I'm still learning. And so I read blogs and discussions. Not all of them are useful. It's actually a pity that so many articles are too simple and often wrong, with people not understanding the matter (hey, this one is surely an exception).&lt;br /&gt;
&lt;br /&gt;
One of the topic that seems to cause most useful discussions is "Anemic Domain Model" &lt;a href="http://www.theserverside.com/news/thread.tss?thread_id=38047#193682"&gt;here&lt;/a&gt;. Quite outdated but has a lot of different real-world opinions. Still, a lot of people there just do not understand what "Anemic Domain Model" is, even though Martin Fowler himself &lt;a href="http://www.theserverside.com/news/thread.tss?thread_id=38047#193682"&gt;clarified&lt;/a&gt; the point in the thread. I suppose this is what they call &lt;a href="http://www.nlpu.com/whatnlp.htm"&gt;map of reality&lt;/a&gt; in psychology. The developers are just too concerned about the persistence; that's what the see in every issue out there. This means that they do not think in terms of domain, still.&lt;br /&gt;
&lt;br /&gt;
Now, how do I dare to criticize all the people as I'm a mighty God Programmer? No I don't. It's just a phenomena that I found. In lots of other talks and posts people criticize Fowler for telling them to put persistence logic into entities; that's how 90% blogs out there understand the anti-"Anemic Domain Model" issue. That was so damn strange that I decided to make a post about it.&lt;br /&gt;
&lt;br /&gt;
So, what means avoiding Anemic Domain Model? it is about having "domain behavior" in the entities. This can't be easily achieved. For example, I had couple of entities and a service to create and populate them - say, order, order items, and products inside them. Then, I read the requirements, and understood that I have several types of order items, and several types of products. I added subclasses, put construction logic into entities - BANG! I don't need the service anymore, my entities provide behavior depending on order item and product types, and they can use that information to calculate prices.&lt;br /&gt;
&lt;br /&gt;
Now, where's the persistence in the above case? None. That's about classes design only.&lt;br /&gt;
&lt;br /&gt;
And yes, this depends on the domain. The design evolves over the time; there can be lots of cases when we'll need services. There can be cases when our domain model remains anemic after all the development - so maybe it's how our domain looks like...&lt;br /&gt;
&lt;br /&gt;
The point is not whether Anemic Domain Model is good or evil (we do not live in a b&amp;amp;w world). The point here is that people tends to interpret ideas according to their experience. And it was almost impossible to find a good example or article on the subject which does not speak about persistence. Hey, we talk about &lt;b&gt;domain model&lt;/b&gt;! Where's the persistence word here?&lt;br /&gt;
&lt;br /&gt;
&lt;div class="zemanta-pixie"&gt;
&lt;img alt="" class="zemanta-pixie-img" src="http://img.zemanta.com/pixy.gif?x-id=c7b5ea5d-4b5a-84ff-ad3d-557ff7f3cb42" /&gt;&lt;/div&gt;
&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8281741202770949929-1523003639955541365?l=sprokhorenko.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sprokhorenko.blogspot.com/feeds/1523003639955541365/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://sprokhorenko.blogspot.com/2009/09/anemic-domain-model.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8281741202770949929/posts/default/1523003639955541365'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8281741202770949929/posts/default/1523003639955541365'/><link rel='alternate' type='text/html' href='http://sprokhorenko.blogspot.com/2009/09/anemic-domain-model.html' title='Anemic Domain Model'/><author><name>Sergey Prokhorenko</name><uri>http://www.blogger.com/profile/06389461574659526392</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://4.bp.blogspot.com/_St_fXOeTKCk/Sp0sRG9IkRI/AAAAAAAAAAM/Fccwc6J00SE/S220/1344263.jpeg'/></author><thr:total>0</thr:total></entry></feed>
