<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/rss2full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><rss xmlns:blogChannel="http://backend.userland.com/blogChannelModule" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:pingback="http://madskills.com/public/xml/rss/module/pingback/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:geo="http://www.w3.org/2003/01/geo/wgs84_pos#" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:creativeCommons="http://backend.userland.com/creativeCommonsRssModule" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" version="2.0">
  <channel>
    <title>Try-Catch-FAIL</title>
    <description>Failure is inevitable.</description>
    <link>http://trycatchfail.com/blog/</link>
    <docs>http://www.rssboard.org/rss-specification</docs>
    <generator>BlogEngine.NET 1.4.0.0</generator>
<language>en-GB</language><blogChannel:blogRoll>http://trycatchfail.com/blog/opml.axd</blogChannel:blogRoll><blogChannel:blink>http://www.dotnetblogengine.net/syndication.axd</blogChannel:blink><dc:creator>Matt Honeycutt</dc:creator><dc:title>Try-Catch-FAIL</dc:title><creativeCommons:license>http://creativecommons.org/licenses/by-nc-nd/2.0/</creativeCommons:license><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" href="http://feeds.feedburner.com/Try-catch-fail" type="application/rss+xml" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com" /><item><title>Stack Overflow Careers</title><description>&lt;p&gt;&lt;a href="http://www.joelonsoftware.com/items/2009/11/05.html" target="_blank"&gt;Joel just announced&lt;/a&gt; the launch of &lt;a href="http://careers.stackoverflow.com/" target="_blank"&gt;Stack Overflow Careers&lt;/a&gt;.&amp;#160; Like most things Joel, this seems to be built around his idea of how the world should be, which is actually pretty cool, since in his world we’d all be treated like super stars.&amp;#160; I do however take issue with one of his statements:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;&lt;em&gt;Instead of submitting a resume, you’ll fill out a CV, which links back to your Stack Overflow account, so that you can demonstrate your reputation in the community and show us all how smart you really are. To a hiring manager, the fact that you took the time to help a fellow programmer with a detailed answer in some obscure corner of programming knowledge, and demonstrated mastery, is a lot more relevant than the Latin Club you joined in school.&lt;/em&gt;&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;Maybe I’m wrong, but I actually disagree.&amp;#160; I don’t think having an uber Stack Overflow reputation means that you’re a great catch for a potential employer.&amp;#160; In fact, I think it may mean the &lt;strong&gt;opposite&lt;/strong&gt;.&amp;#160; Along the same lines, I don’t think &lt;strong&gt;not&lt;/strong&gt; having 50 bajillion points on Stack Overflow means you are not knowledgable and skilled.&amp;#160; &lt;/p&gt;  &lt;p&gt;Why do I say these things?&amp;#160; Well, the day consists of 24 hours.&amp;#160; Let’s assume you sleep for 8 of those (I know that’s probably on the high side for most of us).&amp;#160; Let’s assume preparing for and commuting to/from work eats up another 2 hours a day on average.&amp;#160; We’re down to 14 hours.&amp;#160; Let’s assume we don’t work for all of that, let’s say we spend 4 hours doing things outside of work.&amp;#160; That leaves 10 hours a day.&amp;#160; Let’s say I don’t work much overtime, so my employer gets 9 of those hours.&amp;#160; That leaves me with one hour a day.&amp;#160; Exactly when am I going to fit in time to read and answer 50,000 questions on Stack Overflow to rack up some serious reputation?&amp;#160; I don’t think people are doing it in the “free time” on Saturday and Sunday.&amp;#160; Are they doing so on the clock for their employers?&amp;#160; I bet most of them are.&amp;#160; While I agree that participating in Stack Overflow can be a good thing, I see people that spend entirely too much time on there.&amp;#160; If I was their employer, I’d be cutting their pay.&amp;#160; &lt;/p&gt;  &lt;p&gt;If I’m an employer, I’m paying people to add value &lt;em&gt;to the business&lt;/em&gt;, not to chit-chat with their peers. If I see a resume that lists a ridiculously high Stack Overflow reputation, I’m throwing that resume in the trash, because I’m pretty sure that person is going to spend more time on Stack Overflow than on doing real work.&lt;/p&gt;  &lt;p&gt;Let’s look at someone else (me).&amp;#160; I don’t spend much time on Stack Overflow at all.&amp;#160; I lurk on quite a few mailing lists and forums, I follow several good blogs, and I read any spare chance I get, but I don’t participate much.&amp;#160; If I can’t find an answer to a problem through other channels (such as newsgroups, forums, and mailing lists), I might post a question or discussion, but that’s about it.&amp;#160; I don’t spend a lot of time participating &lt;strong&gt;because I’m too busy doing real work&lt;/strong&gt;.&amp;#160; Simply put, while I’d love to participate, I don’t have time.&amp;#160; I’m too busy adding value to our products. &lt;/p&gt;  &lt;p&gt;The same goes for Twitter and blogs.&amp;#160; I actually know of several cases where someone was hired partly because they had a lot of followers either on their blog or on their Twitter account.&amp;#160; If I see someone that’s hyper-active on either Twitter or their blog, I’m going to have the exact opposite reaction.&amp;#160; &lt;/p&gt;  &lt;p&gt;Thoughts?&amp;#160; Am I being totally selfish to use Stack Overflow (and other sites) in a mostly read-only manner?&amp;#160; How exactly am I a worse dev because I don’t spend time on Stack Overflow grinding out reputation points?&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/Try-catch-fail/~4/VuMcUDPP22Q" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/Try-catch-fail/~3/VuMcUDPP22Q/post.aspx</link><author>matt.nospam@nospam.trycatchfail.com (Matt)</author><comments>http://trycatchfail.com/blog/post/2009/11/05/Stack-Overflow-Careers.aspx#comment</comments><guid isPermaLink="false">http://trycatchfail.com/blog/post.aspx?id=5b9c892f-2269-4cec-a737-acc9c63141b5</guid><pubDate>Thu, 05 Nov 2009 03:13:14 -1300</pubDate><category>Misc</category><dc:publisher>Matt</dc:publisher><pingback:server>http://trycatchfail.com/blog/pingback.axd</pingback:server><pingback:target>http://trycatchfail.com/blog/post.aspx?id=5b9c892f-2269-4cec-a737-acc9c63141b5</pingback:target><slash:comments>2</slash:comments><trackback:ping>http://trycatchfail.com/blog/trackback.axd?id=5b9c892f-2269-4cec-a737-acc9c63141b5</trackback:ping><wfw:comment>http://trycatchfail.com/blog/post/2009/11/05/Stack-Overflow-Careers.aspx#comment</wfw:comment><wfw:commentRss>http://trycatchfail.com/blog/syndication.axd?post=5b9c892f-2269-4cec-a737-acc9c63141b5</wfw:commentRss><feedburner:origLink>http://trycatchfail.com/blog/post.aspx?id=5b9c892f-2269-4cec-a737-acc9c63141b5</feedburner:origLink></item><item><title>Fun little ASP.NET MVC bug</title><description>&lt;p&gt;I have a master page that serves as a template for a few related pages.&amp;#160; Both the master page and the views that use it are strongly typed, and they all use the same view model data type.&amp;#160; The declarations look like this:&lt;/p&gt;  &lt;pre class="brush: xml; gutter: false; toolbar: false;"&gt;&amp;lt;%@ Master Language=&amp;quot;C#&amp;quot; Inherits=&amp;quot;System.Web.Mvc.ViewMasterPage&amp;lt;SearchDataModel&amp;gt;&amp;quot; MasterPageFile=&amp;quot;~/Views/Shared/InSpire.Master&amp;quot; %&amp;gt;
...

&amp;lt;%@ Page Language=&amp;quot;C#&amp;quot; MasterPageFile=&amp;quot;Search.Master&amp;quot; Inherits=&amp;quot;System.Web.Mvc.ViewPage&amp;lt;SearchDataModel&amp;gt;&amp;quot; %&amp;gt;
...&lt;/pre&gt;

&lt;p&gt;Access the model works just fine on the views, but trying to access properties of the model from the master page results in this error message:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;b&gt;&lt;/b&gt;&lt;em&gt;CS1061: &lt;strong&gt;'object&lt;/strong&gt;&lt;strong&gt;'&lt;/strong&gt; does not contain a definition for 'Query' and no extension method 'Query' accepting a first argument of type &lt;strong&gt;'object&lt;/strong&gt;&lt;strong&gt;'&lt;/strong&gt; could be found. &lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Note the part in bold: it thinks my model is of type object!&amp;#160; This is despite the fact that I told it the type when I declared the page.&amp;#160; If I first cast the Model property on the master page to the view model type, it works fine.&amp;#160; Anyone know what’s going on?&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/Try-catch-fail/~4/jZwP3prS7bI" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/Try-catch-fail/~3/jZwP3prS7bI/post.aspx</link><author>matt.nospam@nospam.trycatchfail.com (Matt)</author><comments>http://trycatchfail.com/blog/post/2009/10/29/Fun-little-ASPNET-MVC-bug.aspx#comment</comments><guid isPermaLink="false">http://trycatchfail.com/blog/post.aspx?id=4d2d0e3d-8e8e-4573-970d-db61207a8fea</guid><pubDate>Thu, 29 Oct 2009 05:34:52 -1300</pubDate><category>ASP.NET</category><dc:publisher>Matt</dc:publisher><pingback:server>http://trycatchfail.com/blog/pingback.axd</pingback:server><pingback:target>http://trycatchfail.com/blog/post.aspx?id=4d2d0e3d-8e8e-4573-970d-db61207a8fea</pingback:target><slash:comments>0</slash:comments><trackback:ping>http://trycatchfail.com/blog/trackback.axd?id=4d2d0e3d-8e8e-4573-970d-db61207a8fea</trackback:ping><wfw:comment>http://trycatchfail.com/blog/post/2009/10/29/Fun-little-ASPNET-MVC-bug.aspx#comment</wfw:comment><wfw:commentRss>http://trycatchfail.com/blog/syndication.axd?post=4d2d0e3d-8e8e-4573-970d-db61207a8fea</wfw:commentRss><feedburner:origLink>http://trycatchfail.com/blog/post.aspx?id=4d2d0e3d-8e8e-4573-970d-db61207a8fea</feedburner:origLink></item><item><title>An auto-hiding menu bar with jQuery</title><description>&lt;p&gt;What do you do with links/buttons/actions that are likely to be infrequently used, but should still be available to users anywhere in the system?&amp;#160; That’s the question I had to answer for the new InSpire search engine we’re working on at my day job.&amp;#160; The sort of links I am talking about are &lt;em&gt;logout&lt;/em&gt;, &lt;em&gt;preferences&lt;/em&gt;, &lt;em&gt;help&lt;/em&gt;, and various admin commands (for administrators only).&amp;#160; These actions are not really part of the application per se, they are more part of the basic application framework that needs to be available to the user.&amp;#160; We didn’t want to take up valuable space in our UI with these things (plus we wanted to keep the UI as basic as possible), so where do you put these things?&lt;/p&gt;  &lt;p&gt;I decided I would try an auto-hiding sliding menu.&amp;#160; The behavior I wanted was identical to the Windows task bar when the &lt;em&gt;Auto-hide the task bar&lt;/em&gt; option is selected.&amp;#160; After a little jQuery and CSS magic, and some help from &lt;a href="http://www.lullabot.com/articles/bitchin_search_box" target="_blank"&gt;Jeff Robbin’s great article&lt;/a&gt; on an auto-hiding search box, I had a solution that works in IE 8, Firefox, and Chrome.&lt;/p&gt;  &lt;p&gt;First, &lt;a href="http://www.trycatchfail.com/demos/AutoHideMenu.html" target="_blank"&gt;check out the demo&lt;/a&gt;.&amp;#160; The menu bar is themed using jQuery UI, so if your app uses jQuery UI, you will get a consistent look-and-feel.&amp;#160; Also note that my menu bar doesn’t suffer from the same bug that Jeff Robbin’s article does: when you mouse-over and mouse-out my menu bar very quickly a few times, it doesn’t get stuck in a show/hide loop.&amp;#160; Let’s look at the code to see why.&amp;#160; First, the markup and CSS:&lt;/p&gt;  &lt;pre class="brush: xml; gutter: false; toolbar: false;"&gt;&amp;lt;style type=&amp;quot;text/css&amp;quot;&amp;gt;
#siteMenuBar
{
    position: fixed;
    top: 0px;
    left: 0px;
    width: 100%;
    height: 30px;
    margin-top: -27px;
}

#siteMenuBar &amp;gt; #menuContainer
{
    margin-left: auto;
    margin-right: auto;
    width: 100%;
    height: 25px;
    padding-top: 5px;
}

#siteMenuBar ul
{
    float: right;
    list-style-type: none;
    margin: 0;
    padding: 0;
    font-size: 0.9em;
}

#siteMenuBar li
{
    display: inline-block;
    margin: 0;
    padding: 0 5px 0 5px;
    margin-right: 10px;
}

#siteMenuBar ul:first-child
{
    float: left;
    margin-left: 10px;
}
&amp;lt;/style&amp;gt;
...
&amp;lt;div id=&amp;quot;siteMenuBar&amp;quot; class=&amp;quot;ui-widget&amp;quot;&amp;gt;
    &amp;lt;div id=&amp;quot;menuContainer&amp;quot; class=&amp;quot;ui-widget-header&amp;quot;&amp;gt;
        &amp;lt;ul&amp;gt;
            &amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#&amp;quot;&amp;gt;Administration&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
            &amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#&amp;quot;&amp;gt;Design Guidelines&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
            &amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#&amp;quot;&amp;gt;Other Link&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
        &amp;lt;/ul&amp;gt;
        &amp;lt;ul&amp;gt;
            &amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#&amp;quot;&amp;gt;Preferences?&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
            &amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#&amp;quot;&amp;gt;Logout&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
        &amp;lt;/ul&amp;gt;
    &amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;&lt;/pre&gt;

&lt;p&gt;The markup is pretty clean.&amp;#160; There is an outer container for the menu, then an inner container for the actual menu.&amp;#160; The inner container is probably not necessary, but having it allows you the opportunity to do some neat style nesting.&amp;#160; The actual menu is implemented as two unordered lists.&amp;#160; The CSS floats one of the menus to the left, and the other to the right, giving you two groups to add menu items to.&amp;#160; &lt;/p&gt;

&lt;p&gt;The styles are a little more complex.&amp;#160; The outer container is giving a fixed position at the top of the window, then positioned &lt;strong&gt;mostly&lt;/strong&gt; off screen with negative margin.&amp;#160; This leaves a small handle visible that the user can mouse-over to show the menu.&amp;#160; The inner container applies a little padding to the menus and could be used to make the menu bar appear to be less than 100% of the window width (though in this case it is allowed to fully fill the menu bar area).&amp;#160; Next, the actual menus are styled and positioned.&amp;#160; Note that both are initially floated to the right, but using the pseudo-selector &lt;em&gt;first-child&lt;/em&gt;, we bump the first menu back to the left.&amp;#160; &lt;/p&gt;

&lt;p&gt;Now let’s look at the code:&lt;/p&gt;

&lt;pre class="brush: xml; gutter: false; toolbar: false;"&gt;var timeout = null;
var initialMargin = parseInt($(&amp;quot;#siteMenuBar&amp;quot;).css(&amp;quot;margin-top&amp;quot;));

$(&amp;quot;#siteMenuBar&amp;quot;).hover(
    function() {
        if (timeout) {
            clearTimeout(timeout);
            timeout = null;
        }
        $(this).animate({ marginTop: 0 }, 'fast');
    },
    function() {
        var menuBar = $(this);
        timeout = setTimeout(function() {
            timeout = null;
            menuBar.animate({ marginTop: initialMargin }, 'slow');
        }, 1000);
    }
);&lt;/pre&gt;

&lt;p&gt;Note the timeout variable.&amp;#160; This is &lt;strong&gt;key&lt;/strong&gt; in fixing the bug that exists on auto-hiding search box.&amp;#160; For flexibility, we also grab the top margin so that we can hide the menu back to its original state.&lt;/p&gt;

&lt;p&gt;The real core of the technique is the jQuery &lt;em&gt;hover&lt;/em&gt; handler.&amp;#160; We supply two functions: one to execute when the mouse hovers over the menu bar, the other to handle mouse out.&amp;#160; The first time the mouse over handler is executed, the timeout will be null, so it will immediately animate the menu bar, removing the negative margin and making it visible.&amp;#160; On mouse out, the &lt;em&gt;setTimeout&lt;/em&gt; function is used to schedule the menu to be hidden one second later.&amp;#160; Note that I’m assigning the return of &lt;em&gt;setTimeout&lt;/em&gt; to my timeout variable.&amp;#160; This is what prevents the menu bar from ending up in a bounce-loop like the search box.&amp;#160; It allows me to &lt;em&gt;cancel&lt;/em&gt; the hide action.&amp;#160; If the bar is scheduled to be hidden and the user moves the mouse back over the menu bar, the mouse over handler clears the timeout.&amp;#160; Without that bit of logic, even if you move mouse back over the menu bar, the setTimeout function will hide the menu out from under the user, which can lead to that funky show/hide cycle.&amp;#160; &lt;/p&gt;

&lt;p&gt;So, there you have it: a simple, clean auto-hide menu with jQuery.&amp;#160; This could easily be encapsulated in a jQuery plug-in for easy re-use (not really needed in my case though since the master page is responsible for rendering it).&amp;#160; Anyway, let me know if you have any suggestions!&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/Try-catch-fail/~4/51iDJwVJeXQ" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/Try-catch-fail/~3/51iDJwVJeXQ/post.aspx</link><author>matt.nospam@nospam.trycatchfail.com (Matt)</author><comments>http://trycatchfail.com/blog/post/2009/10/29/An-auto-hiding-menu-bar-with-jQuery.aspx#comment</comments><guid isPermaLink="false">http://trycatchfail.com/blog/post.aspx?id=98d9365c-dd49-44c4-a667-d62a4d889b99</guid><pubDate>Thu, 29 Oct 2009 04:52:16 -1300</pubDate><category>jQuery</category><category>UI</category><dc:publisher>Matt</dc:publisher><pingback:server>http://trycatchfail.com/blog/pingback.axd</pingback:server><pingback:target>http://trycatchfail.com/blog/post.aspx?id=98d9365c-dd49-44c4-a667-d62a4d889b99</pingback:target><slash:comments>0</slash:comments><trackback:ping>http://trycatchfail.com/blog/trackback.axd?id=98d9365c-dd49-44c4-a667-d62a4d889b99</trackback:ping><wfw:comment>http://trycatchfail.com/blog/post/2009/10/29/An-auto-hiding-menu-bar-with-jQuery.aspx#comment</wfw:comment><wfw:commentRss>http://trycatchfail.com/blog/syndication.axd?post=98d9365c-dd49-44c4-a667-d62a4d889b99</wfw:commentRss><feedburner:origLink>http://trycatchfail.com/blog/post.aspx?id=98d9365c-dd49-44c4-a667-d62a4d889b99</feedburner:origLink></item><item><title>A simple WCF host application</title><description>&lt;p&gt;I’ve been struggling with getting some of our backend components to play nice over WCF for the past couple of days.&amp;#160; Our situation is a little more complex than most I think; our systems have dependencies on a variety of COM libraries, uses some Java APIs via &lt;a href="http://www.ikvm.net/" target="_blank"&gt;IKVM.NET&lt;/a&gt;, and has differing capabilities as far as 64-bit goes.&amp;#160; &lt;/p&gt;  &lt;p&gt;&lt;strong&gt;What didn’t work&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;So I tried &lt;em&gt;many&lt;/em&gt; things over the course of the last week.&amp;#160; The following is basically a brain dump of every issue I ran in to as well as solutions if I ever found one:&lt;/p&gt;  &lt;p&gt;&lt;em&gt;IIS Hosting&lt;/em&gt;&lt;/p&gt;  &lt;p&gt;The services we were trying to host were to be exposed over the NetTcpBinding, which works fine with IIS7+.&amp;#160; I was able to get stripped-down “Hello, World!” prototype working quite quickly.&amp;#160; What &lt;strong&gt;didn’t&lt;/strong&gt; work was hosting &lt;strong&gt;our&lt;/strong&gt; service in IIS7.&amp;#160; As it turns out, there are apparently some major issues with using IKVM.NET in an ASP.NET environment, which is apparently how even NetTcpBinding services are hosted in IIS.&amp;#160; Bummer.&amp;#160; I never found a solution to this problem.&lt;/p&gt;  &lt;p&gt;&lt;em&gt;Sending large objects&lt;/em&gt;&lt;/p&gt;  &lt;p&gt;Some of the objects we were transmitting over the wire were up to 10MB in size.&amp;#160; Out of the box, WCF will explode with helpful messages about buffer sizes and such.&amp;#160; This was easy to fix through configuration, just be sure you put the config on the right end of the channel (the server-side):&lt;/p&gt;  &lt;pre class="brush: xml;"&gt;&amp;lt;system.serviceModel&amp;gt;
&amp;lt;services&amp;gt;
  &amp;lt;service ... &amp;gt;
    &amp;lt;endpoint binding=&amp;quot;netTcpBinding&amp;quot; bindingConfiguration=&amp;quot;MyCustomBinding&amp;quot; ...&amp;gt;
    &amp;lt;/endpoint&amp;gt;
    ...
  &amp;lt;/service&amp;gt;
&amp;lt;/services&amp;gt;
...
&amp;lt;bindings&amp;gt;
  &amp;lt;netTcpBinding&amp;gt;
    &amp;lt;binding name=&amp;quot;MyCustomBinding&amp;quot; ... maxBufferSize=&amp;quot;20971520&amp;quot; maxReceivedMessageSize=&amp;quot;20971520&amp;quot; &amp;gt;
      &amp;lt;readerQuotas maxArrayLength=&amp;quot;10485760&amp;quot; maxStringContentLength=&amp;quot;10485760&amp;quot; /&amp;gt;
    &amp;lt;/binding&amp;gt;
  &amp;lt;/netTcpBinding&amp;gt;
&amp;lt;/bindings&amp;gt;
&amp;lt;/system.serviceModel&amp;gt;&lt;/pre&gt;

&lt;p&gt;&lt;em&gt;Sending too many objects too quickly&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;We ran into some timeout issues when many threads tried to hammer the service with large amounts of data in parallel.&amp;#160; By default, WCF communications will time out after 1:00.&amp;#160; While that should be enough &lt;strong&gt;most&lt;/strong&gt; of the time, it isn’t always the case.&amp;#160; Fortunately again, it’s a pretty easy fix, just increase the timeout values.&amp;#160; The timeout can be configured on the proxy client-side and on the server-side.&amp;#160; You will probably need to change it on both sides (I did).&amp;#160; &lt;/p&gt;

&lt;p&gt;&lt;em&gt;IDisposawhat?&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;It’s well-known that WCF proxies are in fact &lt;a href="http://trycatchfail.com/blog/post/2009/09/27/A-fixed-ClientBase-class-for-WCF-proxies.aspx" target="_blank"&gt;broken&lt;/a&gt;.&amp;#160; See my &lt;a href="http://trycatchfail.com/blog/post/2009/09/27/A-fixed-ClientBase-class-for-WCF-proxies.aspx" target="_blank"&gt;previous article&lt;/a&gt; about how we created a better base class for our proxies.&amp;#160; &lt;/p&gt;

&lt;p&gt;&lt;em&gt;Port Sharing&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;If the service you are trying to expose over WCF implements multiple contracts, you will need to expose multiple endpoints.&amp;#160; You probably don’t want to have each contract on a separate port, but by default, that’s what you will have to do, because you can’t have two listeners on the same port.&amp;#160; &lt;em&gt;Net.Tcp Port Sharing Service&lt;/em&gt; to the rescue!&amp;#160; This Windows Service, installed along with the .NET Framework, enables your WCF NetTcpBinding endpoints share ports.&amp;#160; After making sure the service is enabled (it is disabled by default), you can take advantage of it by setting the &lt;em&gt;portSharingEnabled&lt;/em&gt; attribute to &lt;em&gt;true&lt;/em&gt; on the binding configuration, like so:&lt;/p&gt;

&lt;pre class="brush: xml;"&gt;&amp;lt;system.serviceModel&amp;gt;
    &amp;lt;services&amp;gt;
        &amp;lt;service ...&amp;gt;
            &amp;lt;endpoint binding=&amp;quot;netTcpBinding&amp;quot; bindingConfiguration=&amp;quot;MyCustomBinding&amp;quot; ...&amp;gt;
            &amp;lt;/endpoint&amp;gt;
            ...
        &amp;lt;/service&amp;gt;
    &amp;lt;/services&amp;gt;
    ...
    &amp;lt;bindings&amp;gt;
        &amp;lt;netTcpBinding&amp;gt;
            &amp;lt;binding name=&amp;quot;MyCustomBinding&amp;quot; portSharingEnabled=&amp;quot;true&amp;quot; ...&amp;gt;
                ...
            &amp;lt;/binding&amp;gt;
        &amp;lt;/netTcpBinding&amp;gt;
    &amp;lt;/bindings&amp;gt;
&amp;lt;/system.serviceModel&amp;gt;&lt;/pre&gt;

&lt;p&gt;&lt;strong&gt;The Final Host&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;As I said, our services were not compatible with IIS hosting due to various COM issues as well as IKVM.NET dependencies.&amp;#160; That left us with two options: self-host the services in a custom application, or create Windows Services to serve as hosts.&amp;#160; We decided to go the self-host route so that deploying our services would remain dirt-simple (it doesn’t get much simpler than XCOPY).&amp;#160; Below is a skeleton class that you can use to host a WCF service in a console application.&amp;#160; Pressing Ctrl+C will shut the service down gracefully and exit:&lt;/p&gt;

&lt;pre class="brush: csharp;"&gt;class Program
{
    //Log4net logger
    private static readonly ILog mLogger = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);

    private static readonly AutoResetEvent mStopFlag = new AutoResetEvent(false);

    static void Main(string[] args)
    {
        //When the user hits Ctrl+C, the server will be shut down. 
        Console.CancelKeyPress += delegate
                                    {
                                        mLogger.Info(&amp;quot;Shutting down server thread.&amp;quot;);
                                        mStopFlag.Set();
                                    };

        var serverThread = new Thread(ServerThread) {IsBackground = true};
        serverThread.Start();

        serverThread.Join();
    }

    private static void ServerThread()
    {
        //This will grab the WCF configuration from the app.config file.
        using (ServiceHost host = new ServiceHost(new MyService()))
        {
            host.Open();

            mLogger.Debug(&amp;quot;Service is online and awaiting requests...&amp;quot;);

            Console.WriteLine(&amp;quot;running&amp;quot;);
            mStopFlag.WaitOne();
        }

        Console.WriteLine(&amp;quot;stopped&amp;quot;);
    }
}&lt;/pre&gt;

&lt;p&gt;&lt;strong&gt;Suggestions&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I confess to being a total WCF newb, so it’s quite likely that I’ve done something wrong.&amp;#160; If you see any incorrect information or have suggestions for things we could do better, &lt;strong&gt;please&lt;/strong&gt; let me know. :)&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;**UPDATE – 10/29/09**&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;There is actually a bug in the host application I presented.&amp;#160; While it will allow the background thread to shut down gracefully, it will still cause the application to abort abnormally, which means any pending finalizers and things won’t be executed.&amp;#160; To resolve the issue, use the following CancelKeyPress handler instead:&lt;/p&gt;

&lt;pre class="brush: xml; gutter: false; toolbar: false;"&gt;Console.CancelKeyPress += delegate(object sender, ConsoleCancelEventArgs cancelEventArgs)
                            {
                                mLogger.Info(&amp;quot;Shutting down server thread.&amp;quot;);
                                mStopFlag.Set();
                                //This is IMPORTANT.
                                cancelEventArgs.Cancel = true;
                            };&lt;/pre&gt;

&lt;p&gt;Thanks go to James for pointing this out.&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/Try-catch-fail/~4/Q_MCGB1-exE" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/Try-catch-fail/~3/Q_MCGB1-exE/post.aspx</link><author>matt.nospam@nospam.trycatchfail.com (Matt)</author><comments>http://trycatchfail.com/blog/post/2009/10/27/A-simple-WCF-host-application.aspx#comment</comments><guid isPermaLink="false">http://trycatchfail.com/blog/post.aspx?id=011e5788-424b-41ae-a81b-4b4d640e4c49</guid><pubDate>Tue, 27 Oct 2009 06:59:58 -1300</pubDate><category>WCF</category><dc:publisher>Matt</dc:publisher><pingback:server>http://trycatchfail.com/blog/pingback.axd</pingback:server><pingback:target>http://trycatchfail.com/blog/post.aspx?id=011e5788-424b-41ae-a81b-4b4d640e4c49</pingback:target><slash:comments>1</slash:comments><trackback:ping>http://trycatchfail.com/blog/trackback.axd?id=011e5788-424b-41ae-a81b-4b4d640e4c49</trackback:ping><wfw:comment>http://trycatchfail.com/blog/post/2009/10/27/A-simple-WCF-host-application.aspx#comment</wfw:comment><wfw:commentRss>http://trycatchfail.com/blog/syndication.axd?post=011e5788-424b-41ae-a81b-4b4d640e4c49</wfw:commentRss><feedburner:origLink>http://trycatchfail.com/blog/post.aspx?id=011e5788-424b-41ae-a81b-4b4d640e4c49</feedburner:origLink></item><item><title>Please stop over-using the var keyword</title><description>&lt;p&gt;I just watched an excellent presentation by &lt;a href="http://www.lostechies.com/blogs/jimmy_bogard/default.aspx"&gt;Jimmy Bogard&lt;/a&gt; on &lt;a href="http://www.c4mvc.net/"&gt;UI testing with ASP.NET MVC&lt;/a&gt;.&amp;#160; While I really enjoyed the presentation and got a lot of really good ideas for how to improve how I work with MVC, I saw something that I really did &lt;strong&gt;not&lt;/strong&gt; like: lots of &lt;em&gt;var&lt;/em&gt; keywords.&amp;#160; Here’s an example (recreated from memory so it might not be exactly right) of one of the methods he showed during his presentation:&lt;/p&gt;  &lt;pre class="brush: csharp;"&gt;...

var id = UINameHelper.GetName(expression);

var func = expression.Compile();

var value = func(model);

...&lt;/pre&gt;

&lt;p&gt;What’s wrong with that code?&amp;#160; Well, unless I know the API, which I don’t, I don’t know the types of the variables.&amp;#160; I can make certain assumptions about their types (the first is probably a string, the next is presumably a Func&amp;lt;T1,T2&amp;gt;, the third I’m not sure about), but I don’t know for sure unless I inspect the code further.&amp;#160; Sure, intellisense is going to help, but I don’t have intellisense when I’m watching a presentation or looking at a code sample over someone’s shoulder. I have the code, and that’s it.&amp;#160; The code should be readable without an IDE.&amp;#160; It should be just as clear when I’m using Notepad++ or looking at it on your blog as when I’m digging through it with VS.NET. &lt;/p&gt;

&lt;p&gt;There are times when the &lt;em&gt;var&lt;/em&gt; keyword can make code more readable.&amp;#160; A great example is when working with complex generics:&lt;/p&gt;

&lt;pre class="brush: csharp;"&gt;//Less readable
Dictionary&amp;lt;int,Pair&amp;lt;Foo,Bar&amp;gt;&amp;gt; lookup = new Dictionary&amp;lt;int,Pair&amp;lt;Foo,Bar&amp;gt;&amp;gt;();

//More readable
var lookup = new Dictionary&amp;lt;int,Pair&amp;lt;Foo,Bar&amp;gt;&amp;gt;();&lt;/pre&gt;

&lt;p&gt;So, a request to all my fellow developers out there: please use the &lt;em&gt;var&lt;/em&gt; keyword carefully.&amp;#160; I don’t think it should ever be used when assigning a variable to a method’s return value.&amp;#160; I think it should only be used when it actually *improves* readability of the code, and never when it takes away from it.&amp;#160; &lt;/p&gt;

&lt;p&gt;Thoughts?&amp;#160; Is &lt;em&gt;var&lt;/em&gt; the best thing since sliced bread or the worst thing since IE6?&amp;#160; When do you think it’s ok to use &lt;em&gt;var&lt;/em&gt;?&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/Try-catch-fail/~4/gJoHEbnR-Ew" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/Try-catch-fail/~3/gJoHEbnR-Ew/post.aspx</link><author>matt.nospam@nospam.trycatchfail.com (Matt)</author><comments>http://trycatchfail.com/blog/post/2009/10/21/Please-stop-over-using-the-var-keyword.aspx#comment</comments><guid isPermaLink="false">http://trycatchfail.com/blog/post.aspx?id=9a54c6c9-94e1-47f3-a25e-9cd4a3ded66d</guid><pubDate>Wed, 21 Oct 2009 05:21:05 -1300</pubDate><category>What NOT To Do</category><dc:publisher>Matt</dc:publisher><pingback:server>http://trycatchfail.com/blog/pingback.axd</pingback:server><pingback:target>http://trycatchfail.com/blog/post.aspx?id=9a54c6c9-94e1-47f3-a25e-9cd4a3ded66d</pingback:target><slash:comments>9</slash:comments><trackback:ping>http://trycatchfail.com/blog/trackback.axd?id=9a54c6c9-94e1-47f3-a25e-9cd4a3ded66d</trackback:ping><wfw:comment>http://trycatchfail.com/blog/post/2009/10/21/Please-stop-over-using-the-var-keyword.aspx#comment</wfw:comment><wfw:commentRss>http://trycatchfail.com/blog/syndication.axd?post=9a54c6c9-94e1-47f3-a25e-9cd4a3ded66d</wfw:commentRss><feedburner:origLink>http://trycatchfail.com/blog/post.aspx?id=9a54c6c9-94e1-47f3-a25e-9cd4a3ded66d</feedburner:origLink></item><item><title>The long road to fixing delete behavior in liteGrid</title><description>&lt;p&gt;A lot has been going on with &lt;a href="http://code.google.com/p/litegrid/" target="_blank"&gt;liteGrid&lt;/a&gt; recently.&amp;#160; The application at my day job that necessitated its creation is nearing production, and numerous additional features are being implemented in support of finishing that app.&amp;#160; One of the big things that recently came up was making sure delete operations worked when the grid was in “tree grid” mode (meaning the TreeGridModule was loaded).&amp;#160; While liteGrid has supported deletes for some time, it didn’t work correctly with tree grids.&amp;#160; When I was tasked with fixing this deficiency, I initially thought “&lt;em&gt;this will be easy, I just need to remove the children when the parent is deleted!”&lt;/em&gt;&amp;#160; As is often the case in software, this was a gross oversimplification of the issue.&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;Why so complex?&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;If the grid was static, yeah, it would be a&amp;#160; simple matter of deleting children once a parent has been deleted.&amp;#160; Unfortunately, the grid is no longer static.&amp;#160; Users can add new rows (via RowAdditionModule) and now they can re-arrange rows and change the parent/child relationships (via DraggableRowsModule).&amp;#160; Deletes in liteGrid have always been a synchronous operation, while everything else is asynchronous.&amp;#160; Why is this bad?&amp;#160; Well, think about it for a second.&amp;#160; Let’s assume I have the following structure initially:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://trycatchfail.com/blog/image.axd?picture=WindowsLiveWriter/ThelongroadtofixingdeletebehaviorinliteG_A215/flat.jpg"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="flat" border="0" alt="flat" src="http://trycatchfail.com/blog/image.axd?picture=WindowsLiveWriter/ThelongroadtofixingdeletebehaviorinliteG_A215/flat_thumb.jpg" width="244" height="41" /&gt;&lt;/a&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;This is the structure the server knows about: I have 4 widgets that are not related.&amp;#160; Now let’s say that I re-arrange things like so: &lt;/p&gt;  &lt;p&gt;&lt;a href="http://trycatchfail.com/blog/image.axd?picture=WindowsLiveWriter/ThelongroadtofixingdeletebehaviorinliteG_A215/nested.jpg"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="nested" border="0" alt="nested" src="http://trycatchfail.com/blog/image.axd?picture=WindowsLiveWriter/ThelongroadtofixingdeletebehaviorinliteG_A215/nested_thumb.jpg" width="244" height="40" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;Let’s assume I haven’t saved yet.&amp;#160; At this point, the client has a very different view of the relationships than the server does.&amp;#160; The client knows that everything is now nested under &lt;em&gt;Test 1&lt;/em&gt; while the server still thinks everything is a singleton leaf.&amp;#160; Under the old model, what happens when I click the delete button for Test 1?&amp;#160; The server will remove Test 1, and that’s it. As far as it knows, Test 1 had no children.&amp;#160; But the client knows that Test 1 had children and will assume that they’ve been deleted, too.&amp;#160; See the problem?&lt;/p&gt;  &lt;p&gt;Let’s consider another case.&amp;#160; Say we start out with the parts nested as in the second figure, but flatten them out so that they are all singleton leaves as in the first diagram.&amp;#160; Again, until we save, the server and client have very different views.&amp;#160; If we delete Test 1 on the client, the server will also delete Test 2, 3, and 4, since it thinks those items are nested under Test 1.&amp;#160; &lt;/p&gt;  &lt;p&gt;The root of the problem is that deletes are synchronous while all other operations are batched.&amp;#160; &lt;/p&gt;  &lt;p&gt;&lt;strong&gt;The solution&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;Once the root problem is well-understood, fixing it was seemingly straight-forward: make deletes a batch operation just like adds, moves, and edits.&amp;#160; Batching everything allows the server to update its state so that its view of the world matches the client before it starts nuking things.&amp;#160; While this &lt;strong&gt;sounds&lt;/strong&gt; easy, it was, in fact, not.&amp;#160; &lt;/p&gt;  &lt;p&gt;First, there were the expected problems with Internet Explorer.&amp;#160; I won’t dive into too many details, suffice to say that Internet Explorer 8’s table rendering is absolute junk.&amp;#160; I don’t know how, but they actually made it worse than it was in IE 7.&amp;#160; &lt;/p&gt;  &lt;p&gt;Ignoring the IE8 problems, I still had to do a fair amount of work to get the user experience that I wanted.&amp;#160; Since deletes would be batched until the user clicked the Save button, I wanted deleted rows to be clearly visible, effectively disabled (meaning they couldn’t be edited or moved), and I wanted the delete operation to be undoable.&amp;#160; This would have been fairly simple if not for the tree grid module, which makes everything more complex.&amp;#160; HTML tables really aren’t well-suited for rendering nested sets like this.&amp;#160; &lt;/p&gt;  &lt;p&gt;&lt;a href="http://trycatchfail.com/blog/image.axd?picture=WindowsLiveWriter/ThelongroadtofixingdeletebehaviorinliteG_A215/deleteInAction.jpg"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="You have no idea how hard this was..." border="0" alt="You have no idea how hard this was..." src="http://trycatchfail.com/blog/image.axd?picture=WindowsLiveWriter/ThelongroadtofixingdeletebehaviorinliteG_A215/deleteInAction_thumb.jpg" width="244" height="54" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;Disabling the rows was a problem.&amp;#160; I didn’t want the delete module to have to know about all the current and future modules that might have added behavior to the grid, so removing the behavior manually was not an option.&amp;#160; Instead, I used jQuery’s clone method to create a copy of the deleted row and its children.&amp;#160; The clones maintained the classes and data of the originals but none of the event handlers, effectively disabling them.&amp;#160; I replaced the original rows with the clones and provided a button to undo the delete operation.&amp;#160; When clicked, the rows are re-bound to their data items, which (thankfully) restores all the functionality added by other liteGrid modules.&amp;#160; At the end of the day, I had a nice batch solution that was not much more complex than my original solution for handling deletes.&amp;#160; &lt;/p&gt;  &lt;p&gt;You can check out the &lt;a href="http://www.trycatchfail.com/liteGridDemo/demo.htm" target="_blank"&gt;latest demo online&lt;/a&gt;.&amp;#160; Code as always is available on the SVN repository. &lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/Try-catch-fail/~4/NyP_TSRUntE" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/Try-catch-fail/~3/NyP_TSRUntE/post.aspx</link><author>matt.nospam@nospam.trycatchfail.com (Matt)</author><comments>http://trycatchfail.com/blog/post/2009/10/19/The-long-road-to-fixing-delete-behavior-in-liteGrid.aspx#comment</comments><guid isPermaLink="false">http://trycatchfail.com/blog/post.aspx?id=c0cd3848-3134-4e1b-8f7f-126c6dd6854e</guid><pubDate>Mon, 19 Oct 2009 03:46:12 -1300</pubDate><category>liteGrid</category><dc:publisher>Matt</dc:publisher><pingback:server>http://trycatchfail.com/blog/pingback.axd</pingback:server><pingback:target>http://trycatchfail.com/blog/post.aspx?id=c0cd3848-3134-4e1b-8f7f-126c6dd6854e</pingback:target><slash:comments>2</slash:comments><trackback:ping>http://trycatchfail.com/blog/trackback.axd?id=c0cd3848-3134-4e1b-8f7f-126c6dd6854e</trackback:ping><wfw:comment>http://trycatchfail.com/blog/post/2009/10/19/The-long-road-to-fixing-delete-behavior-in-liteGrid.aspx#comment</wfw:comment><wfw:commentRss>http://trycatchfail.com/blog/syndication.axd?post=c0cd3848-3134-4e1b-8f7f-126c6dd6854e</wfw:commentRss><feedburner:origLink>http://trycatchfail.com/blog/post.aspx?id=c0cd3848-3134-4e1b-8f7f-126c6dd6854e</feedburner:origLink></item><item><title>Improving jQuery&amp;rsquo;s Validation Plug-in</title><description>&lt;p&gt;One of the 50 or so tasks I’m juggling at my day job deals with coming up with UI standards for one of our applications.&amp;#160; I’m trying to think through every common scenario we have, design how it should work from a UI stand point (both the perceived UI as well as the HTML markup and CSS), and create examples to illustrate the standards.&amp;#160; One of the scenarios I thought of was forms and validation.&amp;#160; Ugh.&amp;#160; I have spent the better part of a day now fighting with the &lt;a href="http://bassistance.de/jquery-plugins/jquery-plugin-validation/" target="_blank"&gt;jQuery Validation plug-in&lt;/a&gt;.&amp;#160; It is the &lt;em&gt;defacto&lt;/em&gt; standard for validation in jQuery.&amp;#160; While it is powerful, and I really like being able to specify validation rules by simply applying CSS classes, it leaves a lot to be desired in the area of flexibility.&amp;#160; &lt;/p&gt;  &lt;p&gt;&lt;strong&gt;What I wanted&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;Here’s what I wanted for our forms and validation: fluid width, labels for each element, and (hidden) labels for element validation messages when needed.&amp;#160; If I didn’t want to display a validation message, I just wanted to be able to omit the label.&amp;#160; I didn’t want to have to do a bunch of JavaScript config.&amp;#160; I also wanted exact control over how the error labels were rendered.&amp;#160; Sometimes I wanted error labels to have a special class or other styles.&amp;#160; Basically, I wanted to be able to write &lt;strong&gt;zero&lt;/strong&gt; JavaScript code to get a nicely-formatted, validated form that I had complete control over.&amp;#160; &lt;/p&gt;  &lt;p&gt;Out of the box, while it does allow you to use your own error labels, the Validation plug-in is very dumb in how it uses them.&amp;#160; First, it strips &lt;strong&gt;all&lt;/strong&gt; CSS classes from the labels when it unhides them.&amp;#160; Very, very annoying.&amp;#160; There does not seem to be a good way to override this behavior without resorting to major hacking (like I did below).&amp;#160; Second, if you do specify a custom label, it will only use it for the first validator applied to an element.&amp;#160; If you have multiple validators applied to a single element, it will still add a new label element for the second validator.&amp;#160; I ran into this as soon as I tried to have a required E-mail field.&amp;#160; &lt;strong&gt;Ugh&lt;/strong&gt;. &lt;/p&gt;  &lt;p&gt;The good news is that it &lt;strong&gt;is&lt;/strong&gt; possible to get the simple layout I wanted with minimal JavaScript config.&amp;#160; The bad news is that it was an incredible pain in the rear to get there and involved a lot of browsing through the Validation plug-in’s source code.&amp;#160; &lt;/p&gt;  &lt;p&gt;&lt;strong&gt;How I did it&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;One of the nice things about jQuery Validation is that you can specify defaults that will apply to all instances.&amp;#160; So once I figured out how to get the behavior I wanted, it was easy to encapsulate it where the entire application would be able to leverage it easily.&amp;#160; So what’s the solution?&amp;#160; Fugliness. &lt;/p&gt;  &lt;p&gt;First, you need to specify a &lt;em&gt;showErrors&lt;/em&gt; callback.&amp;#160; When specified, this is invoked and allows you to fully control the display of error messages.&amp;#160; It receives two parameters, an &lt;em&gt;errorMap&lt;/em&gt; which is useless, and an &lt;em&gt;errorList &lt;/em&gt;that contains validation errors.&amp;#160; My approach was to loop through the errorList, get the name of each element, look for a corresponding label element with class &lt;em&gt;error&lt;/em&gt;, and unhide it.&amp;#160; This allowed me to fully control validation messages via markup, and it made it easy to choose not to display a validation message at all.&amp;#160; Yes, this does mean that I lost the ability to display a different error message for different validators (such as one when an E-mail field is blank versus when it has an invalid address), but I prefer to have a single validation message for each element anyway.&amp;#160; &lt;/p&gt;  &lt;p&gt;Unhiding the error label is only part of the solution.&amp;#160; You also need to highlight the element that the error corresponds to.&amp;#160; This can be achieved by using the optional highlight callback.&amp;#160; In this callback, you can add the error class.&amp;#160; Be warned, you must manually call your own callback from your showErrors callback, otherwise highlight and the corresponding unhighlight callbacks will never be invoked.&amp;#160; This is the part that is fugly. &lt;/p&gt;  &lt;p&gt;Here’s the full source code, which I wrapped in a .js file and included alongside the main jQuery Validation .js file.&amp;#160; This insures consistent behavior everywhere we use the jQuery Validation plug-in in our project.&lt;/p&gt;  &lt;pre class="brush: js; gutter: false; toolbar: false;"&gt;$.validator.setDefaults({
    showErrors: function(errorMap, errorList) {
        var validation = this;
        $(errorList).each(function() {
            var error = this;
            var errorLabel = $(&amp;quot;label[for='&amp;quot; + error.element.name + &amp;quot;'].error&amp;quot;);
            errorLabel.css(&amp;quot;display&amp;quot;, &amp;quot;inline-block&amp;quot;);
            validation.settings.highlight(error.element);
        })

        for (var i = 0, elements = this.validElements(); elements[i]; i++) {
            validation.settings.unhighlight(elements[i], validation.settings.errorClass, validation.settings.validClass);
        }
    },
    highlight: function(element) {
        $(element).addClass(&amp;quot;error&amp;quot;);
    },
    unhighlight: function(element) {
        $(element).removeClass(&amp;quot;error&amp;quot;);
        $(&amp;quot;label[for='&amp;quot; + element.name + &amp;quot;'].error&amp;quot;).hide();
    }
});&lt;/pre&gt;

&lt;p&gt;This is the final product: &lt;/p&gt;

&lt;p&gt;&lt;a href="http://trycatchfail.com/blog/image.axd?picture=WindowsLiveWriter/ImprovingjQuerysValidationPlugin_E6B3/validation.jpg"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="validation" border="0" alt="validation" src="http://trycatchfail.com/blog/image.axd?picture=WindowsLiveWriter/ImprovingjQuerysValidationPlugin_E6B3/validation_thumb.jpg" width="244" height="126" /&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;And the corresponding markup:&lt;/p&gt;

&lt;pre class="brush: xml; gutter: false; toolbar: false;"&gt;&amp;lt;fieldset&amp;gt;
    &amp;lt;legend&amp;gt;A simple comment form with submit validation and default messages&amp;lt;/legend&amp;gt;
    &amp;lt;div class=&amp;quot;wrapper&amp;quot;&amp;gt;
        &amp;lt;p&amp;gt;
            &amp;lt;label for=&amp;quot;name&amp;quot;&amp;gt;
                Name:&amp;lt;/label&amp;gt;
            &amp;lt;input type=&amp;quot;text&amp;quot; id=&amp;quot;name&amp;quot; name=&amp;quot;name&amp;quot; size=&amp;quot;25&amp;quot; class=&amp;quot;required&amp;quot; minlength=&amp;quot;2&amp;quot; /&amp;gt;
            &amp;lt;label for=&amp;quot;name&amp;quot; class=&amp;quot;error&amp;quot;&amp;gt;
                Please enter a valid name.&amp;lt;/label&amp;gt;
        &amp;lt;/p&amp;gt;
        &amp;lt;p&amp;gt;
            &amp;lt;label for=&amp;quot;email&amp;quot;&amp;gt;
                E-Mail:&amp;lt;/label&amp;gt;
            &amp;lt;input type=&amp;quot;text&amp;quot; id=&amp;quot;email&amp;quot; name=&amp;quot;email&amp;quot; size=&amp;quot;25&amp;quot; class=&amp;quot;required email&amp;quot; /&amp;gt;
            &amp;lt;label for=&amp;quot;email&amp;quot; class=&amp;quot;error&amp;quot;&amp;gt;
                Please enter a valid E-mail address.&amp;lt;/label&amp;gt;
        &amp;lt;/p&amp;gt;
        &amp;lt;p&amp;gt;
            &amp;lt;label for=&amp;quot;url&amp;quot;&amp;gt;
                URL:&amp;lt;/label&amp;gt;
            &amp;lt;input type=&amp;quot;text&amp;quot; id=&amp;quot;url&amp;quot; name=&amp;quot;url&amp;quot; size=&amp;quot;25&amp;quot; class=&amp;quot;url&amp;quot; value=&amp;quot;&amp;quot; /&amp;gt;
            &amp;lt;label for=&amp;quot;url&amp;quot; class=&amp;quot;error&amp;quot;&amp;gt;
                Please enter a valid URL.&amp;lt;/label&amp;gt;
        &amp;lt;/p&amp;gt;
        &amp;lt;p&amp;gt;
            &amp;lt;label for=&amp;quot;state&amp;quot;&amp;gt;
                State:&amp;lt;/label&amp;gt;
            &amp;lt;select name=&amp;quot;state&amp;quot; id=&amp;quot;state&amp;quot; class=&amp;quot;required&amp;quot;&amp;gt;
                &amp;lt;option&amp;gt;&amp;lt;/option&amp;gt;
                &amp;lt;option&amp;gt;Tennessee&amp;lt;/option&amp;gt;
                &amp;lt;option&amp;gt;Georgia&amp;lt;/option&amp;gt;
                &amp;lt;option&amp;gt;South Carolina&amp;lt;/option&amp;gt;
            &amp;lt;/select&amp;gt;
            &amp;lt;label for=&amp;quot;state&amp;quot; class=&amp;quot;error&amp;quot;&amp;gt;
                Please select a state.&amp;lt;/label&amp;gt;
        &amp;lt;/p&amp;gt;
        &amp;lt;p&amp;gt;
            &amp;lt;label for=&amp;quot;terms&amp;quot;&amp;gt;&amp;amp;nbsp;&amp;lt;/label&amp;gt;
            &amp;lt;input type=&amp;quot;checkbox&amp;quot; name=&amp;quot;terms&amp;quot; value=&amp;quot;terms&amp;quot; class=&amp;quot;required&amp;quot; /&amp;gt;
            &amp;lt;label for=&amp;quot;terms&amp;quot; class=&amp;quot;checkbox&amp;quot;&amp;gt;I have read and accept the terms.&amp;lt;/label&amp;gt;
            &amp;lt;label for=&amp;quot;terms&amp;quot; class=&amp;quot;error&amp;quot;&amp;gt;You must accept the terms.&amp;lt;/label&amp;gt;
        &amp;lt;/p&amp;gt;
        &amp;lt;p&amp;gt;
            &amp;lt;label for=&amp;quot;comment&amp;quot; class=&amp;quot;textarea&amp;quot;&amp;gt;
                Your comment:&amp;lt;/label&amp;gt;&amp;lt;br /&amp;gt;
            &amp;lt;textarea id=&amp;quot;comment&amp;quot; name=&amp;quot;comment&amp;quot; cols=&amp;quot;22&amp;quot; class=&amp;quot;required&amp;quot;&amp;gt;&amp;lt;/textarea&amp;gt;
        &amp;lt;/p&amp;gt;
        &amp;lt;p&amp;gt;
            &amp;lt;input class=&amp;quot;submit&amp;quot; type=&amp;quot;submit&amp;quot; value=&amp;quot;Submit&amp;quot; /&amp;gt;
        &amp;lt;/p&amp;gt;
    &amp;lt;/div&amp;gt;
&amp;lt;/fieldset&amp;gt;&lt;/pre&gt;

&lt;p&gt;It’s not perfect, but I’m happy with the markup, and I’m happy with the UI.&amp;#160; Hopefully I didn’t miss something obvious with the Validation plug-in that would have saved me half a days work.&amp;#160; If I did, feel free to tell me how stupid I am. :)&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/Try-catch-fail/~4/BIhZ8jlAdVw" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/Try-catch-fail/~3/BIhZ8jlAdVw/post.aspx</link><author>matt.nospam@nospam.trycatchfail.com (Matt)</author><comments>http://trycatchfail.com/blog/post/2009/10/14/Improving-jQueryrsquo3bs-Validation-Plug-in.aspx#comment</comments><guid isPermaLink="false">http://trycatchfail.com/blog/post.aspx?id=c3808189-7001-4115-8b8c-82136f02206e</guid><pubDate>Wed, 14 Oct 2009 08:24:12 -1300</pubDate><category>jQuery</category><dc:publisher>Matt</dc:publisher><pingback:server>http://trycatchfail.com/blog/pingback.axd</pingback:server><pingback:target>http://trycatchfail.com/blog/post.aspx?id=c3808189-7001-4115-8b8c-82136f02206e</pingback:target><slash:comments>0</slash:comments><trackback:ping>http://trycatchfail.com/blog/trackback.axd?id=c3808189-7001-4115-8b8c-82136f02206e</trackback:ping><wfw:comment>http://trycatchfail.com/blog/post/2009/10/14/Improving-jQueryrsquo3bs-Validation-Plug-in.aspx#comment</wfw:comment><wfw:commentRss>http://trycatchfail.com/blog/syndication.axd?post=c3808189-7001-4115-8b8c-82136f02206e</wfw:commentRss><feedburner:origLink>http://trycatchfail.com/blog/post.aspx?id=c3808189-7001-4115-8b8c-82136f02206e</feedburner:origLink></item><item><title>The additive nature of bad code</title><description>&lt;p&gt;It really shouldn’t be a surprise, but I have recently witnessed firsthand how a little bad code sprinkled here-and-there quickly adds up to a lot of BAD code that’s painful to work with.&amp;#160; That’s the scenario we’re facing now with our &lt;a href="http://www.asp.net/mvc" target="_blank"&gt;ASP.NET MVC&lt;/a&gt; application.&amp;#160; Our team conducts peer reviews for every bug/feature, but we’ve still built up a small mountain of technical debt that we’re going to have to pay sooner or later.&amp;#160; Our once-clean code base has become complex and difficult to work with.&amp;#160; Even simple changes are starting to take progressively longer to implement.&amp;#160; &lt;/p&gt;  &lt;p&gt;How did this happen?&amp;#160; There are probably several reasons, but I think one cause is that we’re still too lax in our peer reviews.&amp;#160; If we don’t see something that’s &lt;strong&gt;HOLY CRAP THAT’S BAD&lt;/strong&gt;, we let it slide, even if we don’t really like the solution.&amp;#160;&amp;#160; At least, I think that’s how I’m contributing to the problem.&amp;#160; Starting today though, I’m going to resolve to be a lot more strict on my reviews.&amp;#160; If something doesn’t &lt;em&gt;feel &lt;/em&gt;right, even if I can’t put my finger on it immediately, I’m going to spend the time to find a better solution.&amp;#160; The alternative is what we’ve done: start with good code, then progressively keep adding a &lt;em&gt;little&lt;/em&gt; bad code here and there until we’ve ended up with a big heaping mess of poorly-structured code. &lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/Try-catch-fail/~4/om-_0e_prjo" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/Try-catch-fail/~3/om-_0e_prjo/post.aspx</link><author>matt.nospam@nospam.trycatchfail.com (Matt)</author><comments>http://trycatchfail.com/blog/post/2009/10/12/The-additive-nature-of-bad-code.aspx#comment</comments><guid isPermaLink="false">http://trycatchfail.com/blog/post.aspx?id=63bd0e3a-93cb-402d-ae29-da60dc71f436</guid><pubDate>Mon, 12 Oct 2009 03:06:09 -1300</pubDate><category>What NOT To Do</category><dc:publisher>Matt</dc:publisher><pingback:server>http://trycatchfail.com/blog/pingback.axd</pingback:server><pingback:target>http://trycatchfail.com/blog/post.aspx?id=63bd0e3a-93cb-402d-ae29-da60dc71f436</pingback:target><slash:comments>0</slash:comments><trackback:ping>http://trycatchfail.com/blog/trackback.axd?id=63bd0e3a-93cb-402d-ae29-da60dc71f436</trackback:ping><wfw:comment>http://trycatchfail.com/blog/post/2009/10/12/The-additive-nature-of-bad-code.aspx#comment</wfw:comment><wfw:commentRss>http://trycatchfail.com/blog/syndication.axd?post=63bd0e3a-93cb-402d-ae29-da60dc71f436</wfw:commentRss><feedburner:origLink>http://trycatchfail.com/blog/post.aspx?id=63bd0e3a-93cb-402d-ae29-da60dc71f436</feedburner:origLink></item><item><title>liteGrid &amp;ndash; now with draggable rows!</title><description>&lt;p&gt;I’ve just finished up the draggable rows module for &lt;a href="http://code.google.com/p/litegrid/" target="_blank"&gt;liteGrid&lt;/a&gt;.&amp;#160; You can check out the demo page &lt;a href="http://www.trycatchfail.com/liteGridDemo/demo.htm" target="_blank"&gt;here&lt;/a&gt;.&amp;#160; The module supports the tree-grid module (but does not require it).&amp;#160; It’s built using jQuery UI’s draggable and droppable behaviors.&amp;#160; I’ve tested it on IE 8, Firefox 3.5, and Chrome, and it seems to work fine everywhere.&amp;#160; If you find a bug, please report it.&lt;/p&gt;  &lt;p&gt;As part of this change, I’ve altered the behavior of the tree-grid module.&amp;#160; Prior to this release, it added it’s own column for the tree expander.&amp;#160; As of this release, it (and the draggable rows module) requires that you define a “utils” column.&amp;#160; Both the drag handle and the row expander will be added to this column.&amp;#160; If the column isn’t defined, an error will be logged to the console, and both modules will abort initialization.&amp;#160; &lt;/p&gt;  &lt;p&gt;In other liteGrid news, I noticed that the resizable columns are no longer working Chrome.&amp;#160; I will try to fix this ASAP.&amp;#160; If anyone would like to tackle that bug, please &lt;a href="http://code.google.com/p/litegrid/issues/detail?id=8" target="_blank"&gt;feel free&lt;/a&gt;.&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/Try-catch-fail/~4/sc3PRxEiVMc" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/Try-catch-fail/~3/sc3PRxEiVMc/post.aspx</link><author>matt.nospam@nospam.trycatchfail.com (Matt)</author><comments>http://trycatchfail.com/blog/post/2009/10/09/liteGrid-ndash3b-now-with-draggable-rows!.aspx#comment</comments><guid isPermaLink="false">http://trycatchfail.com/blog/post.aspx?id=f0299390-8757-4118-badc-438312bba6dc</guid><pubDate>Fri, 09 Oct 2009 05:14:59 -1300</pubDate><category>liteGrid</category><dc:publisher>Matt</dc:publisher><pingback:server>http://trycatchfail.com/blog/pingback.axd</pingback:server><pingback:target>http://trycatchfail.com/blog/post.aspx?id=f0299390-8757-4118-badc-438312bba6dc</pingback:target><slash:comments>0</slash:comments><trackback:ping>http://trycatchfail.com/blog/trackback.axd?id=f0299390-8757-4118-badc-438312bba6dc</trackback:ping><wfw:comment>http://trycatchfail.com/blog/post/2009/10/09/liteGrid-ndash3b-now-with-draggable-rows!.aspx#comment</wfw:comment><wfw:commentRss>http://trycatchfail.com/blog/syndication.axd?post=f0299390-8757-4118-badc-438312bba6dc</wfw:commentRss><feedburner:origLink>http://trycatchfail.com/blog/post.aspx?id=f0299390-8757-4118-badc-438312bba6dc</feedburner:origLink></item><item><title>Product Review: Balsamiq Mockups for Desktop</title><description>&lt;p&gt;It seems like I’ve been doing a lot of user-experience (UX) design at my day job lately.&amp;#160; It’s not an area I consider one of my core strengths.&amp;#160; Up until recently, I would actually say it was a major weakness, but I was fortunate enough to take a HCI (human-computer interface) class while working on my masters degree. That class got me pointed in the right direction (I think).&amp;#160; I still suck at matching colors and coming up with pretty graphics, but I like to think that I can usually come up with good ideas for &lt;strong&gt;how&lt;/strong&gt; things should be laid out and what the user experience should be like.&amp;#160; &lt;/p&gt;  &lt;p&gt;One of the valuable practices that I picked up was using rough mockups to prototype the UX.&amp;#160; When I say &lt;em&gt;rough&lt;/em&gt;, I mean it.&amp;#160; I’m talking about prototypes drawn with simple lines and boxes in MS Paint.&amp;#160; Many people don’t even go that far and will instead stick to paper-and-pen.&amp;#160; I’ve even read about design sessions where they literally use paper, glue, and odds-and-ends lying around the office to come up with new UIs.&amp;#160; The benefit to taking such a low-quality approach to the prototypes is that it helps people focus on the &lt;em&gt;interaction and experience&lt;/em&gt; instead of tripping over issues like button color and fonts.&amp;#160; &lt;/p&gt;  &lt;p&gt;While MS Paint works, and I’ve done quite a few mockups using it, making a mockup in Paint&amp;#160; is not a fast process.&amp;#160; It involves a lot of copy-and-paste, and a lot of try-this-didn’t-work-undo-it.&amp;#160; Fortunately there are tools to help you build rough mockups.&amp;#160; Today, I’ll be doing a review of one: &lt;a href="http://www.balsamiq.com/products/mockups" target="_blank"&gt;Balsamiq Mockups&lt;/a&gt;. &lt;/p&gt;  &lt;p&gt;&lt;strong&gt;About Balsamiq Mockups&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;Mockups is a tool for creating mockups with a pen-and-paper feel, but using a more productive drag-and-drop approach.&amp;#160; There are a variety of versions available.&amp;#160; There is a free (but limited) &lt;a href="http://www.balsamiq.com/demos/mockups/Mockups.html" target="_blank"&gt;web version&lt;/a&gt;, a &lt;a href="http://www.balsamiq.com/products/mockups/desktop" target="_blank"&gt;desktop edition&lt;/a&gt;, and &lt;a href="http://www.balsamiq.com/products/mockups/plugin" target="_blank"&gt;plug-in versions&lt;/a&gt; for a variety of wiki and bug trackers.&amp;#160; According to their site, the current version features over 75 controls, 150+ icons, and a slew of keyboard shortcuts, which I’m still trying to learn. &lt;/p&gt;  &lt;p&gt;&lt;strong&gt;Impressions&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;I have been using the online version of Balsamiq Mockups for a few odd things over the last couple of months, but I only recently took the plunge and got the desktop version (thanks to Balsamiq giving me a license so that I could fully evaluate it!).&amp;#160; Mockups is an Adobe AIR application, so not surprisingly, the web version and the desktop version feel almost identical.&amp;#160; The bulk of the UI is across the top while the canvas occupies most of the remaining space below.&amp;#160; In the desktop version, there are tabs across the bottom for each open mockup.&amp;#160;&amp;#160; Getting started is easy: simply drag a control onto the canvas, and you’re off!&amp;#160; Controls like labels and text boxes that can hold values will immediately go into edit mode.&amp;#160; Clicking on an existing control brings up a floating panel with fairly standard options: move to front, move to back, group/ungroup, etc.&amp;#160; &lt;/p&gt;  &lt;p&gt;For advanced users, there is also a quick-add box that allows you to type the name of a control and add it to the canvas.&amp;#160; Once you have a good feel for what controls are available to you, you will probably find that this is faster than hunting for controls with your mouse. &lt;/p&gt;  &lt;p&gt;&lt;strong&gt;Things I liked…&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;Overall, I was very pleased with Mockups.&amp;#160; Building a prototype UI with it was significantly more efficient than my old method of sketching things out in MS Paint.&amp;#160; I found that most of the controls that I wanted to use where built-in and flexible enough (for the most part) to support what I wanted to prototype.&amp;#160; Unlike the web version, the desktop version supports multiple open documents via a tabbed interface, which is really helpful when you’re fleshing out multiple screens for an application and want to quickly switch between them.&amp;#160; &lt;/p&gt;  &lt;p&gt;One of the cool things about Mockups is how open and flexible Balsamiq is with its development.&amp;#160; They issue new releases almost weekly (as can be seen &lt;a href="http://www.balsamiq.com/blog/category/release-announcements/" target="_blank"&gt;here&lt;/a&gt;), and bugs, suggestions, and questions can be submitted easily through their &lt;a href="http://www.getsatisfaction.com/balsamiq" target="_blank"&gt;Get Satisfaction portal&lt;/a&gt;.&amp;#160; They also have a community-driven site for sharing mockups and new controls called &lt;a href="http://mockupstogo.net/" target="_blank"&gt;Mockups To Go&lt;/a&gt;.&amp;#160; &lt;/p&gt;  &lt;p&gt;Another area where the openness of Mockups shines is the native file format.&amp;#160; Your mockups are stored as XML and can easily be consumed by other applications.&amp;#160; In fact, there are numerous 3rd party tools that you can use to help take your mockups to the next step, such as &lt;a href="http://www.napkee.com/" target="_blank"&gt;Napkee&lt;/a&gt; and a tool to convert from &lt;a href="http://vi.to/bmml/" target="_blank"&gt;Mockups to Image Maps&lt;/a&gt;.&lt;/p&gt;  &lt;p&gt;One other nice thing I noticed is that I can actually drag-and-drop files on Mockups to open them.&amp;#160; Drag-and-drop works for both the native BMML files as well as XML exports from the web version of the tool.&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;Things I didn’t like…&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;First, and this is &lt;strong&gt;very&lt;/strong&gt; nitpicky, I only counted &lt;strong&gt;74 &lt;/strong&gt;controls, not the &lt;em&gt;75 &lt;/em&gt;that are claimed (and yeah, I double-checked my tally twice).&amp;#160; Maybe the 75th icon doesn’t show up under “All”?&amp;#160; Fortunately the controls available via Mockups to Go more than makes up for the missing 75th control.&lt;/p&gt;  &lt;p&gt;Probably the biggest annoyance I encountered while using Mockups was controls randomly shifting slightly when selected. Sometimes things &lt;strong&gt;appear &lt;/strong&gt;to move by a few pixels even though they’re really still in the same place.&amp;#160; When selected, sometimes controls would appear to jump down and to the right by one or two pixels.&amp;#160; Tapping “left” to nudge it would cause it to bounce back up where it was before.&amp;#160; I know it isn’t actually moving since it doesn’t register with Undo/Redo.&amp;#160; &lt;em&gt;NOTE: I didn’t notice it until just now, but this is actually a well-known bug, described &lt;/em&gt;&lt;a href="http://www.getsatisfaction.com/balsamiq/topics/objects_sometimes_move_jump_when_selected"&gt;&lt;em&gt;by this issue&lt;/em&gt;&lt;/a&gt;&lt;em&gt;.&amp;#160; I hope it gets fixed soon, because it is &lt;strong&gt;very annoying&lt;/strong&gt;.&amp;#160; &lt;/em&gt;&lt;/p&gt;  &lt;p&gt;Another random annoyance was the options panel.&amp;#160; While it manages to stay out of the way most of the time, I did frequently find that its default placement was very much in the way.&amp;#160; Especially when working in or near a corner of the canvas, the panel would seem to inevitable be right where I didn’t want it to be.&amp;#160; While you can drag it out of the way, it seems like it could position itself a little more intelligently.&amp;#160; I also question why the panel is needed at all.&amp;#160; Why not make it a context-sensitive toolbar or “ribbon” instead?&amp;#160; There seems to be plenty of free space available in the existing toolbar at the top of the application. &lt;/p&gt;  &lt;p&gt;Another thing I noticed was that I sometimes received “file exists” warnings when saving a mockup even when the file actually &lt;strong&gt;didn’t&lt;/strong&gt; exist yet.&amp;#160; Apparently mockups does not pay attention to the file extension, so trying to save “Mockup.bmml” into a folder that contains “Mockup.xml” will cause these incorrect warnings to occur.&amp;#160; &lt;/p&gt;  &lt;p&gt;&lt;strong&gt;Suggestions&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;After making over a dozen different mockups, I have come up with a few things I’d like to see.&amp;#160;&amp;#160; First, I’d really like to see some sort of toolbar or ribbon-like interface instead of the floating control properties panel.&amp;#160; Second, creating a tab for a new mockup can currently be accomplished by right-clicking on an existing tab and selecting the appropriate option, but I’d love to see a Firefox-like “+” button for adding a new tab with a single click.&amp;#160; Also related to the tabs, they currently order themselves alphabetically, but this isn’t always the way I want to order my open documents.&amp;#160; Being able to reorder them would be a nice, simple addition. &lt;/p&gt;  &lt;p&gt;A final suggestion: consider lowering the price.&amp;#160; At $79, it’s too high for my impulse-buy reflex.&amp;#160; If it was priced at $30, for example, I probably would have bought it without spending more than a few minutes playing with the web version.&amp;#160; As it is though, $79 isn’t expensive, but it means that I have to think a little harder before buying it.&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;Final Thoughts&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;I still haven’t decided if Mockups is for me.&amp;#160; There are alternatives, such as &lt;a href="http://www.microsoft.com/video/en/us/details/1eea789b-c69c-4b09-a13b-b7422c0ff104"&gt;Microsoft Sketchflow&lt;/a&gt;, and I need to spend time playing with those to decide which tool is really the best fit for me.&amp;#160; I do strongly recommend that anyone needing to do UI development consider some sort of tool for doing quick mockups, and Balsamiq Mockups is definitely an option to consider. &lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/Try-catch-fail/~4/d302OnlHrz0" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/Try-catch-fail/~3/d302OnlHrz0/post.aspx</link><author>matt.nospam@nospam.trycatchfail.com (Matt)</author><comments>http://trycatchfail.com/blog/post/2009/10/04/Product-Review-Balsamiq-Mockups-for-Desktop.aspx#comment</comments><guid isPermaLink="false">http://trycatchfail.com/blog/post.aspx?id=f0c1feb7-b47c-4c43-a281-3ca52b3f8cf1</guid><pubDate>Sun, 04 Oct 2009 05:57:06 -1300</pubDate><category>UI</category><dc:publisher>Matt</dc:publisher><pingback:server>http://trycatchfail.com/blog/pingback.axd</pingback:server><pingback:target>http://trycatchfail.com/blog/post.aspx?id=f0c1feb7-b47c-4c43-a281-3ca52b3f8cf1</pingback:target><slash:comments>2</slash:comments><trackback:ping>http://trycatchfail.com/blog/trackback.axd?id=f0c1feb7-b47c-4c43-a281-3ca52b3f8cf1</trackback:ping><wfw:comment>http://trycatchfail.com/blog/post/2009/10/04/Product-Review-Balsamiq-Mockups-for-Desktop.aspx#comment</wfw:comment><wfw:commentRss>http://trycatchfail.com/blog/syndication.axd?post=f0c1feb7-b47c-4c43-a281-3ca52b3f8cf1</wfw:commentRss><feedburner:origLink>http://trycatchfail.com/blog/post.aspx?id=f0c1feb7-b47c-4c43-a281-3ca52b3f8cf1</feedburner:origLink></item></channel>
</rss>
