Windows Phone 7 Deve Launch
# Wednesday, May 01, 2013

All of the applications I put into production use ELMAH to track unhandled exceptions.  In one our new releases of an application I noticed a semi-rare bug occurring through these logs.

Validation Failed

Validation Failed

System.Data.Entity.Validation.DbEntityValidationException: Validation failed for one or more entities.

I initially figured something extraordinary occurred for this to happen. Then it happened again and then another time. Now I felt it was time to give this error a more thorough review.  Something less then extraordinary was likely happening.

I use data annotations on my database model since I’m using Entity Framework Code First (EF CF) and in my view models.  I was a little concerned that some nefarious input was being entered that the client side unobtrusive JavaScript was missing as well as in my server side checks.

As it has almost always turned out when I suspect something like this, the true answer is something much simpler and sometimes even a bit embarrassing.

Here’s the offending view model / with the EF CF model.  Can you catch the issue?

//View Model
public class MyCourseViewModel
{
    [Display(Prompt = "Yada Yada Yada College")]
    [Required]
    public string College{ get; set; }
    [Display(Name = "Course Title", Prompt = "Intro to Psychology")]
    [Required]
    public string Name { get; set; }
    [Display(Name = "Course Prefix & Number", Prompt = "PSY 101")]
    [Required]
    public string CourseNumber{ get; set; }
//…more view model fields…. } //Database Model... public class MyDatabaseModel{ [StringLength(150)] public string College{ get; set; } [Required] [StringLength(150)] public string Name{ get; set; } [Required] [StringLength(25)] public string CourseNumber { get; set; } }

Mismatched Annotations

In my database model I set maximum lengths for my strings but I didn’t for my view model.  Enter the case where a user enters a value longer than the allowable amount and you have the client side & server side checks all pass on the view model but then an error occurs at the database model level since you’ve exceeded your length.

Takeaway

Make sure you at least have matched or created a more stringent rule in your view models as you do in your database models.  A simple oversight on my part and definitely not intentional.

Logging

Takeaway number two: Log, log, and log.  Then be sure to review those logs not just ignore them.  Take action when you begin to see a pattern.

Dealing with exceptions

Adding ELMAH to my MVC projects has been a breeze and has offered a great amount of insight into unforeseen bugs.  I often don’t react to the first new bug that ELMAH reports.  I instead look to see if it’s a pattern and when one emerges I then put it on my list to deal with.

Happy Coding! Smile

PS – I realize a better test setup would have been able to prevent this bug from ever making it into the wild. A unit test would have even missed this but not an integration test. Some extra food for thought on how testing can save your bacon…. Mmm… bacon.

Posted 05.01.2013  #    Comments [0]  | 
# Thursday, March 24, 2011

One of the awesome features in MVC is Unobtrusive JavaScript.  In MVC 3 apps you can set this in the web.config.  It’s on by default.

I have a legacy database that has a field that is required and doesn’t allow nulls but the application allows for empty strings to be entered into the field.  I know, what’s the point of requiring a field and allowing empty strings (if empty string actually means something, OK). 

When I set the Required Data Annotation with the AllowEmptyString=true on the field the validator was still returning an error.  On a hunch I set UnobtrusiveJavaScriptEnabled=false and then field began working as expected.

What gives?

MVC 3 uses jQuery validators when UnobtrusiveJavaScriptEnabled is true.  For the Required annotation it uses the jQuery required validator which doesn’t have the AllowEmptyString parameter or one like it.  Essentially, the validator ignores this parameter. Thanks to @srkirkland for pointing this out. And he would know, he runs the OSS Data Annotations Extensions project.

Happy Coding!

Posted 03.24.2011  #    Comments [2]  | 
# Wednesday, March 23, 2011

I’m working on the latest Entity Framework RC 4.1 that comes with Code First. In my quest I learned how the Data Annotations work on empty fields. Something I thought I knew but after being schooled by my simple MVC3 project I had a little help on twitter to set me straight.

I asked on twitter – Do Data Annotation validators run when the field is empty? Required does but my experiment on others don't seem to?

I mean, of course, duh, required would but it didn’t seem like the other validators were.  I was two validators.  The first was the String Length and I had set the Minumim and Maximum Length.  The other was the regular expression validator that wanted 4 digits.  When I emptied the fields, the validator appeared to not run because I didn’t get an error displayed.  If I entered a character then the validation appeared. 

What’s going on? It would make sense that for the String Length validator with a Minimum Length set that when nothing is entered it should fire right?  Clearly, we are below the minimum length.  I began to assume that the validators other than the Required didn’t run if the field is empty.  I always thought they did run. 

Well, @srkirkland to the rescue.  He set me straight.

@klabranche When a field is empty other vals will still run, just return valid always. Convention is non-required vals return true w/ null

…and @srkirkland would know, he runs the OSS Data Annotations Extensions project.

Convention is non-required validators will return true with nulls

I feel as though I should have known this but clearly I didn’t. Maybe, just maybe I had it way deep in the recesses of my mind. A lot of good that did me. :-) How about you?

For the purpose of this post let’s fire up reflector and see for ourselves!

regular expression annotation reflector code

All Data Annotations wield their magic in the IsValid method.  As you can see below the Regular Expression Annotation checks to see if the string coming in is null or empty and if it is return true.

public override bool IsValid(object value)
{
    this.SetupRegex();
    string str = Convert.ToString(value, CultureInfo.CurrentCulture);
    if (string.IsNullOrEmpty(str))
    {
        return true;
    }
    Match match = this.Regex.Match(str);
    return ((match.Success && (match.Index == 0)) && (match.Length == str.Length));
}

How about one more? String Length

string length annotation reflector code 

public override bool IsValid(object value)
{
    this.EnsureLegalLengths();
    int num = (value == null) ? 0 : ((string) value).Length;
    return ((value == null) || ((num >= this.MinimumLength) && (num <= this.MaximumLength)));
}

Again, you can see if the initial object coming in is null then return true.

Why this convention

I found a reference on Phil Haack’s blogs:

http://haacked.com/archive/2009/11/19/aspnetmvc2-custom-validation.aspx

Notice that if the value is null, we return true. This attribute is not intended to validate required fields. I’ll defer to the RequiredAttribute to validate whether the value is required or not. This allows me to place this attribute on an optional value and not have it show an error when the user leaves the field blank.


Where I went wrong

Back to the String Length validator. If it would fire for an empty string then we are essentially making the String Length validator a required field validator also.  This may seem logical and was my assumption. In reality, if this was true we would be making the String validator also a required validator. Having the convention on all non-required validators return true when their field is empty ensures those validators are not forcing an implicit required.  How fun would that be for a field we wanted to ensure was a certain format but could also be empty?

So there you have it.  I was ready to blame Code First or the Entity Framework, surely not my own assumptions. :-)

Happy Coding!

Posted 03.23.2011  #    Comments [0]  |