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>

Haskell n00b – value/type constructors confusion

Posted in functional programming by benjaminplee on 03.06.09

As I slowly attempt to teach myself Haskell and the basics of functional programming, I will try and post some of my thoughts and confusions as they come.  If anyone sees me doing something wrong, please speak up.  My ego is not tied to the code I post so much as the fact that someone read it and took the time to respond.

As I was reading chapter 3 of Real World Haskell yesterday, I got myself all turned around.  And, like any good man driving a car, I refused to ask for directions and kept driving around until things started to look familiar again.

The task at hand was to write a function which would convert the List data type the authors defined earlier in the chapter to a native array.

data List a = Cons a (List a)
| Nil
deriving (Show)

fromList (x:xs) = Cons x (fromList xs)
fromList []     = Nil

The authors also gave an example of a function which would convert arrays to Lists.  My job was to create the reverse.  My first attempt is below:

fromList2 List a b = a : (fromList2 b)
fromList2 Nil = []

This had some potential, but doesn’t compile complaining about a lack of a data constructor ‘List‘.  My confusion was around the difference between the type constructor and the value constructor.  List is the type constructor for the List type.  Cons is the value constructor for an object who type happens to be a List type.  Coming from a Java/C# background, when I first read about pattern matching, I immediately assumed it was matching against the type of objects.  Well, that’s true and false.  In Java the type and value of something are two different things.  In Haskell, they are linked and can not change.  Therefore, when writing a pattern matching function, we need to look at the value of the parameter (ie the value constructor and values) and NOT the “type”.  I should have realized this when I wrote the second line.  Nil is not the same kind of construct as List, which should have set of a red flag for me.

To make things even more confusing, when I wrote the above code to try and test my new function, I head already read the author’s comments about how since type constructors and value constructors are really two different things and can never be used where the other was intended, they are normally named the same (Cons was used for readability).  Normally, and how I typed it out at first without realizing it, it would be written with both constructors named the same – List.

The other confusing thing for me was the difference between type variables and “normal” variables.  When defining the new abstract type List, ‘a‘ represents a type variable, or a place holder for the type of the actually object passed in.  Since nothing within the definition of a List needs to know the type of the parameter, we can get away with it being unknown until creation time.  When defining a function, the variable no longer represents the objects type, but the object itself.  Haskell is strongly and statically typed, but doesn’t require you to specificy exactly what type a variable is.  It inferes it from how you use it.

Thus, the correct anser is:

fromList2 (Cons x xs) = x : (fromList2 xs)
fromList2 Nil = []

Trying to work with the type constructors, value constructors, type variables, etc all at once was a bit much.  The way I really figured this out was to build up to it with another example.  Here is the code I wrote which taught me what I was doing wrong above.  Maybe it will help someone else someday.

myListOrgChart = Cons "ben" (Cons "boss" (Cons "ceo" Nil))
listOrgChart = fromList2 myListOrgChart

data Person = Employee Int String Person
| Consultant String
| NoOne
deriving (Show)

name (Employee _ name _) = name
name (Consultant name) = name

managerName (Employee _ _ manager) = name manager
managerName (Consultant name) = name

orgChart (Employee _ name manager) = name : orgChart manager
orgChart (Consultant name) = name : name : []
orgChart NoOne = []

ceo = Employee 1 "ceo" NoOne
boss = Employee 2 "boss" ceo
ben = Employee 3 "ben" boss
joe = Consultant "joe"

benOrgChart = orgChart ben

Follow

Get every new post delivered to your Inbox.