Two Guys Arguing

C# Meta-Programming And Extension Methods Question

Posted in .net, functional programming, questions by benjaminplee on 12.30.10

First, it should be noted that my ASP.Net MVC-foo is yet great and I know this.  If you know a better way to do this, please take the time to explain how you are superior.  If you don’t, how will we ever know?

Working with ASP.Net MVC 2 client-side form validation this past week, I ran into two unfortunate (IMHO) facts which kept tripping me up:

  1. Html.ClientValidationEnabled() must be called as a scriptlet BEFORE the form is created
  2. Html.ValidateFor or Html.ValidationMessageFor must be called for EACH property of the model you want validated.

*** This StackOverflow answer includes a couple other important & useful things to note

These two issues (and many more) bother me about ASP.Net MVC 2 client-side validation but #2 in particular was really ticking me off.  I like that I can conditionally turn validation on/off on a field by field basis … but why make me enumerate all validation-needed model fields twice in my view!?  Especially in my case where I want validation turned on for ALL model object fields that have DataAnnotation Validations defined for.  Obviously the fields are going to be enumerated in the view once; how else are the text boxes and drop downs going to be created, but why make me list out each field AGAIN just to turn on validation?

All of this amounts to one WET solution. Am I missing something?

The best solution I have seen, and the one I am about to start implementing, is this one by Rick Anderson over at MSDN found via this related forum post.  The idea is to create additional Html helper extension methods which will combine the creation of the HTML form element with turning on and configuring validation.  This solution has the benefit of making me enumerate the model fields being used only ONCE in my view code and reads cleaner.

The only problem is that I have to walk through our application, find anywhere that is using a built in HtmlHelper extension method to build an HTML form element (e.g. input tag), build a new validating wrapper extension method that matches the signature of the original, and then replace the original code with the new extension method.  This can be done, but is time consuming and error prone.  And I am lazy.

The real issue …

I want to … create additional HtmlHelper extension methods based on all existing ones that produce form elements and take in a Linq expression to find the model property that first pass that expression to helper.ValidateFor() and then return the original extension method’s valued.

Is there any meta-programming feature or technique in C# that will allow me to concisely do that?

e.g.

Since Html.TextBoxFor(user => user.FirstName) is used in our app, as it stands I will am going to create a custom extension method similar to:

public static class ValidatingFormElementsExtension
{
  public static MvcHtmlString ValidatedTextBoxFor<TModel, TProperty>(this HtmlHelper<TModel> helper, Expression<Func<TModel, TProperty>> expression)
  {
    helper.ValidateFor(expression);
    return helper.TextBoxFor(expression);
  }

  // and so on for EACH one we use

}

Anyone have any ideas?  Am I completely off base with this? Is there a better way?

~~~~~~~~~~

<mini-related-rant>

A few more quick cracks at ASP.Net MVC  that I need to get off my chest

  • Why are so many things done in scriptlets!?  I feel like I am back in the vanilla JSP days of yesteryear.
  • They are Annotations in Java and Attributes in C# …. so why are the data validation attributes defined in System.ComponentModel.DataAnnotations?
  • I get that HTML checkbox form input fields have TRUE/FALSE values passed back when the form is submitted, and that doesn’t map perfectly to how other fields are handled by the Required attribute …. but why was NOTHING included to do this?  Having to use a RegularExpression validator for [Tt]rue is clumsy no?

</mini-related-rant>

One Response

Subscribe to comments with RSS.

  1. Craig said, on 04.09.11 at 9:21 am

    Just to hit on your final point, you can use Boolean.Parse to convert True/False to a bool value.


Leave a comment