Thursday, 15 December 2011

Rules are made to be broken

Through my years as a software developer I have built (or seen other developers built) systems that are very tightly coupled around rules. Very often the rules are explicit and are not my own, but from the business aka “business rules”.

Since it is a rule I start to design the system around the fact that the rule is always 100% true.

But what I do is locking my self in. Why?

Because. A couple of years (or months or weeks) later the rule is no longer 100% true. Very often the same person who told me this rule could never ever be broken is the one telling me to brake it. Since the system is designed around the fact that it can’t be broken, it’s usually pretty (or very) cumbersome to change it.

It can sound something like this.

– Why can’t I do “that” on “this page”?
- Well, because it’s built that way. It is not permitted to do that.
- But I must be able to do that!
- But, you told me at (some date) that it was a rule?
- Yes! But not when I want to do “that”!
- . . .

But it is understandable. We want to be certain about some things when we initially work out the demands for the system. But the users every-day work life is all made up by exceptions! It’s all made up by ways to brake the rules. And if you think of it, it would be a pretty boring job if it wasn’t so. You could easily be replaced by a machine.

And when you think about the rules (laws, morals and ethics etc.) that our society is made up out of. There is always an exception for them. If I where to build a system around some society I would definitely build a strong rule around not allowing anybody to kill anyone else. Most countries have a law for that! But. Depending on which country you live in, it is – sometimes – ok to kill someone. If you find an intruder with a knife in his hand when you come home and he attacks you with the knife, you are (by Swedish laws at least) allowed to kill the bastard (to defend you own life). In some countries *cough* or *cough* states *cough* (not mentioning any) the government holds the right to execute civilians. My system wouldn’t be built around that exception.

What am I trying to say?

Something like; always prepare your system to be able to brake rules. It will happen eventually. It’s hard. I know. It’s much easier to write “if (true)” than “if (true well… but…)”.

Or at least always prepare yourself for it, if you don’t want to prepare the code. And allow it to happen. It’s called being agile :-)

Friday, 11 November 2011

Øredev 2011, Day 3 - it's all over, but something new begins...

I'm so happy I got the opportunity to go to Øredev. It's such a huge inspiration and gives a lot of new ideas and new ways of thinking and coding.
It's been three wonderful days. Great speakers, great subjects, great ideas, great people, great food and great organisation from the Øredev crew! Perhaps to many geeks in one place though (and to few women)..? :-)

If you just gonna read one thing of all the session reviews below, skip to the Dan North review.
Otherwise, keep reading :-)

Keynote - Stack Overflow: Social Software for the Anti-Social Part II: Electric Boogaloo - Jeff Atwood
Pretty good speak. Nothing new. He gave his thoughts on how Stackoverflow works and how it became popular. End of story.

Building HTML5 Applications with Visual Studio 11 for Windows 8 - Tim Huckaby
The title doesn't corrolate to what he actually talked about. He actually didn't have time to show any building of any application at all. He didn't even show Visual Studio 11(!) Tim is a really good speaker though, so it was a very giving talk anyway.

He talked about HTML5 and that it's more of a "concept" than a standard. As we already knew.
Then he started to talk about what Steve Jobs did when he introduced the iPad. He actually helped Microsoft! Instantly, Steve "killed" flash instantly. And if Flash is dying, so will Silverlight. In the end. Tim didn't really say that, because he was recorded. But he someway did. And he felt sorry, because he had been a devoted WPF/Silverlight developer for many years.

Steve wrote this (saying that Flash will never be an option on iPhone or iPad), and apple responds with this:
Then Apple responds with this:
They actually didn't. But it's kind of what they did by not supporting it (if you don't have an iPad; the "Lego" brick is what is shown instead of the flash plugin when you browse a site with flash on it). Really funny!

Anyway. Apple loves HTML5! Google loves HTML5 (and is the most driving force in the HTML5 area)! And, Microsoft loves HTML5!

But. There's always a but. We, developers, are not representative for the vast majority of users out there in the world. There are very few browsers out there with HTML5 support. Because there are a lot of old browsers (and computers) out there. And, on the other hand, Silverlight is installed on more than 70% of all computers ou there. It's a bit of a dilemma! So, probably, we wont be doing full-scale HTML5 applications in the near future. And Silverlight will be a tempting option for a few years to come. But we eventually will be doing HTML5! Either we want it or not. Steve actually never wanted a specific language for the iPhone, he wanted all apps to be HTML5. But he also realized that it wasn't an option, the market wasn't ready for it.

So. Is it a step back to the old browser-support hell we had back in the late 90's? Yes! Does Flash and Silverlight offer better graphics, interaction and effects? Yes! But! HTML5 is a standard! And it will be available everywhere! The browser will no longer be filled with plugins, it will be the plugin. And don't worry about the other things. HTML6 is already on the drawing board. And this time it wont take 10 years to finish it!

Delivering Improved User Experience with Metro Style Win 8 Applications - Tim Huckaby
Part II by Tim. He didn't have many slides in this presentation. Well, he did. But he was mostly showing a lot of cool examples and demonstrations of Windows 8 (he hade a to- notch developer tablet with the latest build of Windows 8 on it - it was shaky :-). He also talked, and showed, a lot about NUI (Natural User Interface), YES! So it was kind of more a demo of Windows 8 and it's capabilities than anything else. So it's hard to summarize the talk.

But the coolest thing! He had a touch screen from a swedish company (from Lund) running Windows 8! He said it was the best touch screen he had ever seen or used! Nice! He also demonstrated the Kinect API for Windows (on Windows 8). He also braught up another guy to the stage (whom he had met in the bar the night before) that had created an eye recognition app. All with .NET and two simple web cameras! Impressive!

One thing that caught my mind was this slide:
  • NUI is mostly for consuming content, not creating.
    • Meaning, not for CRUD-apps, which I mostly create :-( He's right too.
  • Do not conform to the Windows GUI Spec! Yay!

Functional Javascript - Anders Janmyr
He started the presentation by mentioning Dan North talk by saying that Javascript is an uncertain langauge :-)
Otherwise this talk was not what I thought it would be. I thought I was going to learn some cool javascript stuff or architecture or something. But I learned nothing. He just burped up a lot of javascript functions. A lot! And that's it! What functions do you ask? Well: mixin, map, curry, fibonacci (of course) etc etc and finally the famous Y combinator. Totally waste of time! I could as well have read this by my self - if I had wanted to.
Do I have to say I left a red vote in the basket for this presentation?

Data Visualization with Canvas and CoffeeScript - Trevor Burnham
Another red vote in the basket :-( This was mainly a live coding session.
One great thing I learned though! Never use CoffeScript! For the second time in a row I see a CoffeScript presentation and the presenter gets lost. He had to give up! He sat a long time trying to figure stuff out but after a, way to long, time he went back to copying a prepared code. And this guy is an expert! It felt that he didn't have any tools to help him find the problem. Here is why I think CoffeScript is not something for my company (Active Solution):
  1. Adds unnecessary extra skill requirements.
    1. You have to find people (competence) that know CoffeScript. It's not something you learn in 15 minutes.
  2. You lose your Javascript skill. Because you learn CoffeScript instead.
  3. Adds another layer of abstraction that's not needed. And when something fails..? I don't want to think about it.
What about the Data Visualization part? He didn't really got there... He showed some bubbles that floated around on a HTML5 canvas.
He also had a slide that was a bit depressive.
  • The canvas in HTML5 has quite bad performance if you want to do more advanced stuff. But it gets better all the time when browsers starts using the GPU more and more.
  • Handling mouse/touch events on a canvas is hard. If you want user interaction, your'e on your own...
  • No "jQuery of Canvas" exists. But it probably is coming soon.

Patterns of Effective Delivery - Dan North
Dan North had some expecations to live up to from yesterdays talk. And he delivered. You like this guy so much that you get blind for what he says. You accept it all. But he actually has some really mind blowing thoughts.

First of all he was trying to encourage us. His experience as an agile mentor was that he was trying to get developers from stuck to anything. From zero to anything. Because that's an infinite improvement! :-)

Then he talked about optimisation. You need to optimise for something, and you always are.
Agile, as we know it and practice it, was optimised to be easy to learn. Optimised to be teached! Not optimised for effective delivery! It's true. Poker planning, backlogs, sprints, daily meetings etc. It's all about giving certainty - and we want to embrace uncertainty (if you remember my review on yesterdays keynote).
Then he started to talk about some patterns he thought could help to start thinking in new ways.

I'm not going in to details of those patterns because I'd be up all night. But basically:
  • Don't be afraid to not do TDD when you are really good at TDD. Because you know what TDD code looks like. This was on the pattern of "spike and stabilise".
  • A pattern he called "ginger cake": Don't be afraid to copy and paste code (!!!) Because you will eventually clean and adjust that code anyway. And sure, you may copy a bug, but more important - you copy a lot of good code! He compared it with a recipe he had for chocolate cake. On another recipe it said "Like chocolate cake but with ginger" :-) As an expert (or baker) you know when to break rules (or adjust a recipe to produce ginger cake instead of chocolate cake).
  • Be prepared to delete/remove your own code. Don't be emotionally attached to it. Instead, prepare to throw things away. Embrace uncertainty! How? Make small pieces of code that are specialized at one thing. Then thay are easy to throw away and replace. When you create a dragon of code, things get scary. Things that can be done better or adjusted for outer changes must be thrown away and replaced. Make it easy to do it. A pattern he called "short software half-life".
  • "Create urgency". You will never learn how to swim if you never remove your armbands. You will never learn how to ride a bicycle if you don't remove the support wheels!
  • A lot of other patterns he just briefly mentioned. 
He emphasized that you don't have to agree with any of these patterns (it's his). And, they are very contextual. In one context they suite very well, in another they may not.

But! The most important thing of all: what are you optimising for?

See this talk when it comes out! Well worth it!

From Solid to Liquid to Air, Cyborg Anthropology and the Future of the Interface - Amber Case
This talk really felt like you were listening to a TED talk. And she actually had talked at TED. She was very good! She talked about how we really already are cyborgs and how we have changed our tools from being an extension of physical selves (like a hammer) to extend our minds instead. She also hoped that mobile usage will stop drawing attention from other things to just being an extension of our selves. In some way...

Thank you for three wonderful days at Øredev! Hopefully I will have the opportunity to come back (maybe next year?)

This time I actually reviewed (briefly!) my post before publishing it. As Dan North said: from zero to anything is an infinite improvement :-)

Thursday, 10 November 2011

Øredev 2011, Day 2

Day two was very non-techie day for me. I tried to follow the UX track today. And when things get more abstract they are also harder to summarize. But I'll give it a try! :-)

Keynote - Embracing uncertainty - Dan North
The best talk of the day! And what a talk! I think I just fell in love with Dan North... Such a revelation!

For me the presentation was about that we only think that we are agile, but we're really not. Here is my interpretation of what Dan said (most things he actually said :-). He also said a lot more.

The agile manifesto back in 2001 was:

  • Individuals and interactions over processes and tools
  • Working software over comprehensive documentation
  • Customer collaboration over contract negotiation
  • Responding to change over following a plan

But now, in 2011, where are we? Well, it's become:
  • Processes and tools over individuals and interactions
    • What? It's true! How many agile tools and processes aren't we using? ...And build tools and deployment tools and processes and...
  • Comprehensive documentation over working software
    • No!? Yes! How many automated tests do you have? Do you use Selenium? Code coverage? Are you doing TDD? It's all documentation, in another form.
  • Contract negotiation over customer collaboration
    • This can't be true!? Sorry, it is! Do you do product backlog planning? Sprint planning? It's all contract negotiations! And often very little customer collaboration.
  • Following a plan over responding to change
    • Just because you have a product backlog and doing things in sprints doesn't mean you're responding to change! What is a backlog? It's just another word for a plan! And face it, how often does the product backlog corrolate at the end of the project? Research of this has been done and 50% of the product backlog isn't correct by the end.
The important thing - the whole thing - about the agile manifesto was to start collaborating! Business people and developers. Have we? No! Why?
Because we are rather wrong than uncertain! We actually crave for certainty. It's built in, we are not born to handle uncertainty. But we need to try to umbrace it.

Then he started talking about what to do about it. Not going in to details about that myself.
You can read more here
And also read Daniel Lee's thoughts on it here:

On little thing he said that got stuck. "What is the sound of one hand clapping?". Stupid question, there is no sound! But think about it... it's a great metaphor for what team work is all about! It's not about doing things three times faster than two persons doing separate things. It's about doing things one person could not have done - at all! Pause a moment and think about the greatness of this metaphor.

Welcome back! :-)

The next of the day was in the UX track :-)

UX: How hard could it be? What it is and isn't - Jeff Patton
I wont summarize, just pick out some goodies.
- Saying that a desing is bad is saying that I think it's bad.
- Developers should be more like doctors than waiters. Not to earn more money :-) But to be more of an investigator of what symptoms someone is suffering of than anything else.
- Our job isn't to build software - we change the world!
- UX has three layers:

Example of just the bottom layer:
Example of just the top two layers: Segway! No utility there...
Example of just the top layer: No good example, think "lipstick on a pig"!
UX needs all three!

Programming and minimalism - Jon Dahl
The only non-UX I went to. A lot of music in this talk. From classic music to rock and punk. And I liked that! :-)
The topic was on "what is good programming?". And then he compared music composing to programming.
Bach did a lot of complex music. Then someone thought, well I want something more simplistic. Mozart! After that someone thought, I want to do something more complex. Beethoven! And so this continues. To the days of Beatles (simple) to Led Zeppelin (complex) to punk and so on...
That's how programming works! Sometimes someone comes up with something complex, then someone else seeks simplicity, then... Nothing is better than the other.

Then he stated some good rules:
  1. Simple may be longer!
  2. Clever code is bad code
  3. Any code that isn't doing something is harming your project
  4. Accept constraints
  5. If it isn't business logic, move it to a library
  6. Don't over abstract
  7. Always actively clean up. Constantly
  8. Apply these rules wisely
  9. Simple code is beautiful
  10. Break hard problems down
A greate quote that got stuck: "Sorry for the long mail, I didn't have time to write shorter". Now compare that to programming, it's true isn't it?

Digital typography - Robby Ingebretsen
Meny things I already knew from this talk. But he basically talked about typography as:
Shape, Layout and Technology.
Then he gave a lot of tips for choosing fonts and how to pair them. Think of fonts as a cast for a play. They all may look good for them selves. But it is the total casting that makes it great.
  1. The easy way: one font family - many weights. Never wrong!
  2. Pair a serif with a sans - header in serif, body in sans.
  3. Strong with neutral
And look for contrasts!

Typography is 90% about spacing! On that topic he showed the grid (that he also talked a lot about in his next talk). Draw a grid over a typography layout. If the layout lines up nicely in a grid - you have something beautiful!

Also think about the golden ratio (1:1.618). Size your fonts relative to each other with this ratio. It looks good!

Design composition (part II) - Robby Ingebretsen
When you see something that feels good and looks good and has great user experience. You probably feel  unity! Unity is about: Order, Harmony amd Balance.
When you see something simple it's probably ordered. Design is all about that: Complex feels simple (perception of simplicity). And ordered is the key!
He then showed a lot of examples of great designs that all aligns with a grid, they all fit into a grid!
He also talked about whitespace or maybe empty space or something like that. It's good! Space can be wasted! But empty space is not necessarily wasted space. It's all about creating balance. He then talked about ways to create good balance and showed examples.

Winning the long term users - Donald Farmer
He talked about how to motivate and challange the users that are going to (or you want them to) use your application every day. He talked about always making the application "challange" your users. And preventing boredom.
He stated twitter as an example. He had 6915 followers. That's a challange for him, he wants 7000! Also he mentioned the LinkedIn profile and the challange to get the 100% profile. It keeps the users motivated by challanging them.
You could also create an app which compares your stats with others - like runkeeper.
Visualizing the stats is the key! Of course Donald is some product manager for QlikView, so he showed some examples of how great it is for data (and statistic) visualization.

Your users are like birds on a tree. When the berries are eaten they will fly to the next tree!

Finally he didn't like the word "end users". The end of what!? They are the beginning of something!

But wait! He also showed the hidden notepad feature! Create a txt file and put .LOG at the top. Now everytime you open the file with notepad it will insert a timestamp! Cool!

Cross-plattform UX Design - William Van Hecke
He started talking about his experience from adapting his product for different display sizes: iPhone, iPad and Mac. He stated 12 rules:
  1. New ways of thinking.
    You always have a "core" problem you want to solve. "The soul". And your app is just a window into that "problem". And when you are forced to create new windows you open up new ways of looking at the "problem". And it's good!
  2. Understand guidelines
    But leave them when you wish :-)
    What he means is that Apple has some guidelines on how the apps your'e creating should "look like". Think Microsoft Metro design. But you can also leave them if they don't apply. E.g. Apple says that a certain font should be used. But Apple them selves doesn't use it in the text editor - because it doesn't support italic!
  3. Dead ends (to avoid)
    1. Blow up your app
      I.e. just make your app bigger on a larger display. DON'T!
    2. Squish your app
      Opposite of 1 above - DON'T
    3. Add debris (to the extra space)
      All you will create is a pilot "cockpit", i.e. useless for anyone else than a pilot.
    4. Design is also saying "no!"
  4. Consistency is overrated; start from scratch
    Don't try to adapt your current app to fit into a smaller display. Instead you should start from scratch. See first rule!
  5. The right amount of easy
    Some things are really easy to do on an iPad but a lot harder than on iOS. But other things are impossible to do on iPad, but possible on iOS.
  6. Sharing
    Enable sharing between the different plattforms for the same app.
  7. Information Density
    Give content the space it deserves
  8. Focus
    Minimize distraction
  9. Behaviour
    This means the behaviour your app is encouraging! E.g. avoid the "Manual Autosave" :-)
  10. Consolidate functionality
    Minimize "UI furniture"
  11. Taps are cheap!
    - Super sommon stuff: 1 tap
    - Common stuff: "desktop clicks" x 2 is acceptable. It's actually true!
    - Everything else: go nuts!
  12. Sensible defaults
Point 0: Always serve the soul! (What the app is really for).

He also talked about the great 5 "Why?". Ask someone "Why?" questions to a response five times. It will get you the answer to the real problem.

That's it. Have to close! Must drink some pale ale now ;-) Once again I favor ale over typos.

Finally, I'm sorry for the long blog post, I didn't have time to make it shorter...

Wednesday, 9 November 2011

Øredev 2011, Day 1

I have never been to Øredev before. I must say I’m impressed so far. I like that it’s not so commercialized. Google and Microsoft together as friends as Phil Haacked twittered!

Keynote - Alexis Ohanian - Only your mom wants to use your website

Very good talk by Alexis! He mostly talked about the importance of really caring about your users. You should give a damn! As he put it. Only your mom cares about your lovely website, so to really stand out, you have to do something extra. Care about your users! Make something innovative to make them stay on your site. Bring your idea to life. The "old" sites that throws up hundreds of popups - the don't care about their users. He put his own created reddit as a good example, of course!

The talk was not so applicable to my current job situation as I mostly develop internal applications. But really good anyway!

Some small points I will bring with me:
  • Example of a great idea: make a lyrics site without obtrusive ads and popups (of course it's already on its way...).
  • Paging is bad! So glad someone says it. If you have like 20 pages of something - your not caring about your users. There not interested in 20 pages of something. Rethink!
  • Hipmunk: a flight booking site with a genius sorting: "Agony"! That's caring about your users! You don't want the cheapest flight if it's giving you agony!

Javascript effects - Seb Lee-Delisle
Also very good speaker and presenter! Maybe he felt that we scandinavians were a bit shy when we didn't respond to his "energy"? :-) He was hysterically funny too! Like it!

He skipped his slides and starting coding instead. Yay! In less than 30 minutes he had created an animated growing and swaying tree with HTML5 canvas and Javascript! Very impressive! Watch it here (its only html and js so source code is there automatically): You need a good browser like Firefox (even Chrome seems to dislike it)

He also had a server to which all spectators (with an iPhone or Android) connected to - with a browser (i.e. an url)!. Then he started "playing" with all our phones :-) Started flashing with them in a cool wave and all kinds of stuff. Very cool! We also played a little game with all our phones - together! All with Javascript in the mobile browser. The things you can do nowadays...

More cool stuff can be found here

.NET Collections Deep Dive - Gary Short

Love the scottish accent! :-)

He went through all the performance impacts of various collections and what is good for what. One type is great at insert, remove etc (like LinkedList) and some are great at lookups (like Dictionary)
One very interesting thing he mentioned was to always create a List with a initial size! If you don't the list grows with the double size for every add! 2, 4, 8, 16, 32, 64... And under the hood an Array.Copy() is done. Not so efficient! But if you initialize it with a given size - it also grows with that size. E.g. List(10) will grow with 10 for every add (10, 20, 30...).

Even if you create a list with initial values (List {1,2,3,4,5,6,7,8,9}) you should give it a default size (List(10) {1,2,3,4,5,6,7,8,9}). Because behind the scene it's doing Array.Copy() (and growing with the double size) for every value.

Also, never use List.Add() in a loop. Use AddRange() instead. Performance costs!

Still. All these perfomance costs are only noticable for > 10 000 items. So I don't know..?

HybridDictionary. Google it! :-)

Websockets: Hype or What? - Peter Moskovits

He used Prezi in his presentation - very powerful and different and interactive! I must start using it too!

HTTP is only half-duplex with quite a bit of overhead for every call (because that's how it is designed to work, and fits the needs great). Websockets is full-duplex with 2 bytes of overhead. That's right, 2 bytes! This means tremendous throughput! He had tested with 50K clients sending 50K mesages with < 3 ms latency! Impressive!

WebSockets are an W3C standard but also an IETF protocol. That means finally we have a standard that can be used in almost any browser on any plattform. There are also emulators for older browsers.
You can check if your browser support for websockets on or more details on (and look for websockets).
Think of all the applications you can build when latency is almost 0. If you update something on a site with your mobile, the change can be instantly shown on your desktop browser. I mean instantly!
Some cool demos:

Mobile Web using MVC 4, HTML 5 and jQuery Mobile - Phil Haack

I don't believe that mobile apps are the future (neither did Steve Jobs). If our company is ever going to build a mobile app it will be a web app for phones. We can't simply ignore all Android and iPhone users and just create an WP7 app! And we don't have customers with a budget to build and maintain all three platforms.

The solution is mobile web apps!

Phil's talk was more a demo of the beauty of jQuery Mobile than anything else. Intentionally or not, I don't know...
Some cool tips to make your current web app a mobile web app:

Architecture Without an End State - Michael Nygard

Don't know what to say. Goog presentation, hard to describe here. I don't think I was the right target for this speak. It didn't give me that much. I'll leave it.

Kinect for Windows - Tess Ferrandez

Very cool stuff you can do with the Kinect SDK för Windows (still in beta though).

She live-coded some tracking for skeleton detection and more. Very fun to interact physically and vocally with your app :-). Another guy (can't remember his name) had made a gesture learning app with kinect. He demonstrated it on stage. He fired up the app and told it "Record me!" (the app started "recording"). He made a posture and said "record!" and the posture was recorded. He repeated that three times and know the app had learned a new gesture! Then he said "Watch me!" and the app started watching. Then he made the gesture and the app detected that he made the gesture.

Another guy had made his home a bit interactive by turning on and off lights in the room depending on where i were in the room.

Keynote - Abstraction Distraction - Neal Ford

I my opinion, the best talk of the day! Best speaker!

The reason for that is that many of the things he said was things that I said on an internal company talk I held about NUI (Natural User Interface). The folder and file system abstraction is bad, the save-button abstraction is bad etc...

Or, other things like why the gmail "labels" are way better than putting mail in folders a la Outlook. Because a mail can be about many things, not just one thing (which suits in a folder)! And with the label abstraction we can now specify the only egg-laying mammal platipus :-). Which we can't with the standard hierarchical abstraction.

Very hard to summarize all the things he said...

But in a nutshell what he said was that any abstraction is inperfect. You just have to know it and adapt to the that fact.

Sorry for all the typos and bad english, it's late and my head is kind of full...

Wednesday, 2 November 2011

Running deployment package with 'IIS Web Application Name' as parameter

It doesn’t work in VS2010 sp1…

But there’s a hotfix: (I went for solution 3)

Now I can run the deployment package manually as:

Or you can skip the -setParam:name='IIS Web Application Name' part by editing project settings for the current configuration:


Monday, 24 October 2011

NLog and config transform

To make config transforms work with NLog you need to modify the config transform file slightly.
Edit the configuration in the transform file:

Now you can transform the nlog section in your config file like this:

Sunday, 9 October 2011

MVC 3: Custom Validation

Every time you need validation in an application you end up with something that needs a specific validation rule.

There’s lots of blog post on how to implement custom validation using MVC 3 and jQuery validation (+unobtrusive). So why write another one? I’m going to share my thoughts on how it’s working and the steps for implementing it. Thus, this may be more of a note to my self…

Lets say we want to validate a Swedish personal identity number (it has a specific format and a control number suffix, it’s unimportant for this example, just mentioning something that's not built-in :-)). I like to start with the JavaScript part. Since user interaction response should be as quickly and close to the interaction as possible.

First register the JavaScript function (that will perform the actual validation) to the jquery validator plugin:
   1: $.validator.addMethod('personalid', function (value, element, params) {
   2:     // Check if the field is optional
   3:     if (this.optional(element))
   4:         return true;
   6:     // Do some validation here (return true or false).    
   8:     return true;
   9: });
Now we have a function called “personalid” that will be called on validation. The name "personalid" is important, it will be used later. Keep it in mind!
  • value: the value to validate.
  • element: the element being validated
  • params: we’ll get to this later.
Next we also register to the unobtrusive validation adapter. It will convert the HTML5 data-val-personalid to a format that jQuery validator can handle. We’ll get to that later.
1: $.validator.unobtrusive.adapters.addBool('personalid');
Here we have some different functions to choose from. Depending on which we use, it will affect the params parameter in the previous function registration, like this:
  • addBool(‘personalid’): (the one we use) – params will be true.
  • addSingleVal(‘personalid’, ‘someparam’): params will contain a provided value (I'll show a little about that later…).
  • addMinMax(‘personalid’, ‘minparam’, ‘maxparam’): params will have params.min and params.max attributes containing values by HTML5 data attributes.
  • add: full “control”. requires a more detailed example:
1: $.validator.unobtrusive.adapters.add("personalid", ["param1", "param2", "param3"],
   2:     function (options) {
   3:         options.rules['personalid'] = {
   4:             param1: options.params.param1,
   5:             param2: options.params.param2,
   6:             param3: options.params.param3
   7:         };
   8:         options.messages['personalid'] = options.message;
   9:     }
  10: );
Here params will contain params.param1, params.param2 and params.param3.

Back to our validation. We only use addBool so let's write some C# for server validation and also to generate the HTML5 data-attributes to the MVC view.
1: public sealed class PersonalIdentityNumberAttribute : ValidationAttribute, IClientValidatable
   2: {
   3:     private const string DefaultErrorMessage = "Invalid {0}";
   5:     public string SomeParam { get; set; }
   7:     public PersonalIdentityNumberAttribute()
   8:         : base(DefaultErrorMessage)
   9:     { }
  11:     public override string FormatErrorMessage(string name)
  12:     {
  13:         // "name" is DisplayName of the property being validated.
  14:         // ErrorMessageString is set in constructor.
  15:         return string.Format(ErrorMessageString, name);
  16:     }
  18:     protected override ValidationResult IsValid(object value, ValidationContext validationContext)
  19:     {
  20:         if (value == null)
  21:             return ValidationResult.Success;
  23:         // Do some validation here, return ValidationResult.Success or new ValidationResult() for error.
  25:         return new ValidationResult(FormatErrorMessage(validationContext.DisplayName));
  26:     }
  29:     public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context)
  30:     {
  31:         ModelClientValidationRule clientValidationRule = new ModelClientValidationRule
  32:                                                              {
  33:                                                                  ErrorMessage = FormatErrorMessage(metadata.DisplayName),
  34:                                                                  ValidationType = "personalid"
  35:                                                              };
  36:         clientValidationRule.ValidationParameters.Add("someparam", SomeProperty);
  38:         return new[] {clientValidationRule};
  40:     }
  41: }

I think you can read the code yourself. Just some notes; SomeParam is totally unnecessary, I just want to show the principle. It will not even be parsed since we uses addBool, hence extra params will be ignored. But most important see lines 31-36, ValidationType is important. It corrolates to the name we registered in the jQuery validation above (addBool). I told you to remember this name ("personalid")! Also ValidationParameters.Add is important since it belongs to the name of addSingleVal above (but we don't use that one in this example). Or we can add more properties and use the add jQuery validation function.

Now we can use this attribute in our model:
   1: [Required(ErrorMessage = "Required")]
   2: [PersonalIdentityNumber(SomeParam = "foo")]
   3: [Display(Name = "Personal Identity Number")]
   4: public string PersonalIdentityNumber { get; set; }
Since we’ve implemented GetClientValidationRules this will be rendered as:
data-val-personalid="Invalid Personal Identity Number" 
id="PersonalIdentityNumber" name="PersonalIdentityNumber" type="text" value="" />

data-val-personalid comes from ValidationType (data-val-xxx) and has the value of the DisplayName. data-val-personalid-someparam comes from ValidationParameters.Add and has the value of SomeParam.

Now this can be used by the unobtrusive JavaScript we registered. And we have also created the server side validation.

If we had used the addSingleVal('personalid', 'someparam') instead, the params parameter would have been 'foo':
$.validator.addMethod('personalid', function (value, element, params) {
alert(params); // will alert: 'foo'

Or, if we had used add('personalid', ['param1', 'param2', 'param3']) instead (and had properties in the C# code, above, for them) the params parameter would have attributes like this:

$.validator.addMethod('personalid', function (value, element, params) {
alert(params.param1); // will alert: 'one'
alert(params.param2); // will alert: 'two'
alert(params.param3); // will alert: 'three'

Want to know how to really validate a swedish personal identity number? Read more here

Friday, 7 October 2011

MVC 3: Disable submit button on invalid input

…or enable it on valid input :-)
In a previous post I talked about having the submit (save) button disabled until valid input.
But how do you do that? I’m going to show you a way to do it using MVC 3 and its support for unobtrusive javascript/ajax. Remember this is *a* way, not *the* way to do it. Feel free to criticize it any way you want :-)
First my View (with just a single field):
   1: <div id="RegistrationPanel">
   2:     @using (Html.BeginForm("Save", "Registration"))
   3:     {
   4:         <div class="editor-label">
   5:             @Html.LabelFor(m => m.Name)
   6:         </div>
   8:         <div class="editor-field">
   9:             @Html.TextBoxFor(m => m.Name)
  10:             @Html.ValidationMessageFor(m => m.Name)
  11:         </div>
  13:         <input type="submit" value="Register" />
  14:     }
  15: </div>

Then my Model:
   1: public class RegistrationModel
   2: {
   3:     [Required(ErrorMessage = "Required field")]
   4:     [DisplayName("Name")]
   5:     public string Name { get; set; }
   6: }
Nothing special, very straight forward, very simplified. Using the built in support in MVC 3 for unobtrusive validation. As a note you can see I’m not using the Ajax.BeginForm, because I don’t like it. To much “magic” a la WebForms. I want to know (and control) what’s going on.

But now, let’s get on with the button disabling stuff.

First make sure you include all the javascript files you need:
   1: <script src="@Url.Content("~/Scripts/jquery-1.6.2.min.js")" type="text/javascript"></script>
   2: <script src="@Url.Content("~/Scripts/jquery-ui-1.8.16.min.js")" type="text/javascript"></script>
   3: <script src="@Url.Content("~/Scripts/modernizr-1.7.min.js")" type="text/javascript"></script>
   4: <script src="@Url.Content("~/Scripts/jquery.validate.min.js")" type="text/javascript"></script>
   5: <script src="@Url.Content("~/Scripts/jquery.validate.unobtrusive.min.js")" type="text/javascript"></script>
   6: <script src="@Url.Content("~/Scripts/jquery.unobtrusive-ajax.min.js")" type="text/javascript"></script>

The modernizr isn’t really needed here, but I include it anyway.

Then I also include a javascript file for my View. It contains all the “good” stuff:
   1: var Registration = (function () {
   2:     var form;
   3:     var submitButton;
   5:     return {
   6:         Init: function () {
   7:             form = $('#RegistrationPanel form');
   8:             submitButton = form.find('input[type=submit]');
   9:             submitButton.button();
  11:             // Get jquery validator object
  12:             var validator ='validator');
  13:             // Hook into the jquery validator showErrors event
  14:             validator.settings.showErrors = function () {
  15:                 var nrOfInvalids = this.numberOfInvalids();
  16:                 var buttonVerb = (nrOfInvalids > 0) ? 'disable' : 'enable';
  17:                 submitButton.button(buttonVerb);
  18:                 this.defaultShowErrors(); // also execute default action
  19:             };
  21:             form.submit(function () {
  22:                 if (form.valid()) {
  23:                     $.post(form.attr('action'), form.serialize(), function (jsonData) {
  24:                         // Notify user about success
  25:                     },
  26:                     'json');
  27:                 }
  28:                 return false;
  29:             });
  30:         }
  31:     };
  32: })();
  34: $(function() {
  35:     Registration.Init();
  36: });
That does it! I hook up to an event in the jquery validator showErrrors event (for disabling/enabling submit button).

This also keeps the server validation (TryUpdateModel).