views:

57

answers:

2

I originally built my site in MVC 1.0 using the NerdDinner tutorial as a basic outline. Many of the early design decisions were made simply b/c "that's how NerdDinner did it" Since then, it has really grown and was converted to 2.0.

My validation still works the way NerdDinner did it and is very minimal, so although I've read about other ways, there was never any reason to change it.

I recently added some new fields of type decimal. Upon release, the user tried to enter values "$3000" and "3,000" and got a basic "not valid" error. I explained to him that he could only enter numbers in the field. I went into my validation, and added better validation for that field so that in the future they could get a more descriptive message. However, the field's value is being passed to my validation routine as null. If a valid decimal is entered, then it is passed to the validation routine. I had a validation for my date fields already there as well, and realized that the same thing is happening for them. All of my other validations are strings, and the validation is checking for things like characters which I don't allow, and that works great. But, in those cases it's not actually checking for something that the db would find to be invalid.

This is a sample of my validation:

  public IEnumerable<RuleViolation> GetRuleViolations()
    {

        if (String.IsNullOrEmpty(subcontract_no.Trim()))
            yield return new RuleViolation("Subcontract Number is required", "subcontract_no");

        if (db.subcontracts.Count(s => (s.subcontract_no == subcontract_no) && (s.subcontract_id != subcontract_id)) > 0)
            yield return new RuleViolation("Subcontract Number already exists", "subcontract_no");

        if (subcontract_no.Contains("/")) // quick fix, needs better validation
            yield return new RuleViolation("Subcontract Number cannot contain /", "subcontract_no");

       if (!isValidDate(expiration_date.ToString()))
            yield return new RuleViolation("Expiration Date is not valid", "expiration_date");

        if (!isValidDecimal(insurance_GLminreq.ToString()))
            yield return new RuleViolation("Insurance GL Level must be a number", "insurance_GLminreq");

The "isValidDate" and "isValidDecimal" routines work as I would expect, the problem is that if the value for insurance_GLminreq isn't a decimal, it gets passed as null rather than "$3,000" or whatever. Instead of the user seeing the "Insurance GL Level must be a number" message, they see "The value '$3,000' is not valid for insurance_GLminreq". I'd like the message to be more descriptive so they know why it isn't valid, also I'd rather if they didn't see the actual field name but something that matched the label for the field.

Is there a relatively quick way to fix this that doesn't involve rewriting how validations are done? This section of the site only has 3 users, and I've already explained to them to only input the number. I want this to work properly, but at this point and for this minor issue, I cannot spend a lot of time redoing it to use another validation method.

A: 

One way to fix this is to change your MVC model: make expiration_date and insurance_GLminreq strings.

If you haven't already done so, you'll need to introduce a view model that is convertible to and from your domain model, since you do want these values to be a DateTime and a decimal farther down the line. (See Steve Michelotti's ASP.NET MVC View Model Patterns for an excellent discussion of your options.)

Jeff Sternal
A: 

Wound up quickly getting around this by using the jquery validation plugin. http://bassistance.de/jquery-plugins/jquery-plugin-validation/

RememberME