Thursday, January 21, 2010

ASP.NET MVC with Castle Validators, fluentHtml, and jQuery

Okay, so you remember this post about changing the default textbox value with jQuery? Well, I ran into a SNAFU because my required validation wasn’t working on the controller side of the house. If people submitted the form with “street address”, “city”, or “postal code”, it would post. Not a good thing! Granted I could add some jQuery validation to check the fields etc, but I like validating my input knowing that JavaScript is easily disabled…you should too :)

Just so you don’t have to flip to the other post, here’s the end-result I was looking for in the previous post:

So I thought okay well I’ll put the ValidateNotSameValue() attribute on my view model and it will be good. Well then I thought, what if I wanted to put “ZIP code” instead of “postal code”? I’d have to change the view and the view model and I don’t like them being that good of friends, so I came up with a solution and here it is…

Let’s take the Street Address textbox from the first post and create a ValidateNotSameValue() attribute on it. Now it looks like this:

private string _streetAddress;

ValidateNotSameValue(typeof(string), ViewDefaults.StreetAddress, ViewErrorMessages.InvalidStreetAddress)]
public string StreetAddress
get { return _streetAddress ?? ViewDefaults.StreetAddress; }
set { _streetAddress = value; }

So this says, ValidateNonEmpty and return the InvalidStreetAddress message. On a side note, I started putting my error messages in a separate class or sometimes an XML file a while back when I sat in on a Paul Sherrif talk at a VS Live event. It saves a lot of time and it’s strongly-typed, which I always like. Let’s keep on truckin…Next attribute says ValidateNotSameValue as ViewDefaults.StreetAddress and if they do equal, show the InvalidStreetAddress message. Basically that’s all there is to my trick…not that cool, but kind of I thought :)

At this point, the ViewDefaults class looks like this:

    public class ViewDefaults
public const string StreetAddress = "street address";

The main reason I wanted to go this route is because I show that same text in the view like this:

<%=this.TextBox(f => f.StreetAddress)
"Street Address: ")

So in order to get my jQuery to switch out the default value and put it back if nothing has been done, then I need to define the title. The reason I don’t set the Value to ViewDefaults.StreetAddress on the view and not in the view model is because when I return the view, the default would override the actual entry that failed validation. So the value HAS to match the actual view model values being passed around. (That doesn’t sound confusing at all??? Sorry bout that)

The other cool thing about having a ViewDefaults class is that you can set the default value for starter values or in dropdownlists, etc. Here’s an example of it being used in the DateOfBirth property on my view model.

        public DateTime DateOfBirth
get { return (_dateOfBirth == DateTime.MinValue) ? ViewDefaults.DateOfBirth : _dateOfBirth; }
set { _dateOfBirth = value; }

We know the default value of DateTime = DateTime.MinValue so obviously we wouldn’t want to display “1/1/0001” as a default value for a birth date. So the cool thing about the ViewDefaults is that we can set a default value for DateOfBirth and it looks like this:

        public static readonly DateTime DateOfBirth = DateTime.Now.AddYears(-10);

I wanted my default DateOfBirth to be right now minus 10 years. Now in my view, I can trust that my end-user will never see “1/1/0001”.

Anyhow, thought I’d share…there may be a better way, but I didn’t find one on my Google search. If you do find one, please share!

Thanks for reading!

Shout it

kick it on

blog comments powered by Disqus
Related Posts Plugin for WordPress, Blogger...