3

I have a number of form fields, such as phone numbers and postal codes, which can be left empty. However, when they are filled out, I want them to conform to strict formatting rules.

I am looking to employ Fluent Validation for this task, but I have yet to find anything which can do the following:

RuleFor(x => x.PhoneNumber)
  .Matches(@"^\d{3}-\d{3}-\d{4}$")
  .When(x => x.PhoneNumber.Length != 0)
  .WithMessage("Phone number must be a valid 10-digit phone number with dashes, in the form of “123-456-7890”")
  .Length(12, 12).When(x => x.PhoneNumber.Length >= 1).WithMessage("Phone number must be in the form of “123-456-7890”");

Right now both of these throw a “Object reference not set to an instance of an object.” error.

Am I making any sense, or is this not even possible with FluentValidation?

Peter O.
  • 32,158
  • 14
  • 82
  • 96
René Kåbis
  • 842
  • 2
  • 9
  • 28
  • Your `.Length()` and associated `.When()` are not even necessary - its already covered by the regex which required 12 characters. And I think the `.When()` associated with the `.Matches()` is also unnecessary since the regex is not evaluated if the value is empty. –  Mar 05 '16 at 06:56

1 Answers1

5

I think that you are getting “Object reference not set to an instance of an object.” when trying evaluate the length PhoneNumber property when it's null. First you need to check that it's not null and only then apply all the other rules. In addition to that regular expression that you used in Matches(@"^\d{3}-\d{3}-\d{4}$") already includes the length validation so you can safely remove

.Length(12, 12).When(x => x.PhoneNumber.Length >= 1).WithMessage("Phone number must be in the form of “123-456-7890”");

If you remove the length rule, something like that should work:

When(x =>  x.PhoneNumber != null, 
   () => {
      RuleFor(x => x.PhoneNumber).Matches(@"^\d{3}-\d{3}-\d{4}$")
      .WithMessage("Phone number must be a valid 10-digit phone number with dashes, in the form of “123-456-7890”");           
 });
Alex Art.
  • 8,711
  • 3
  • 29
  • 47
  • How do the two rules conflict? They both deal with 12 characters. The regex checks for the ###-###-#### pattern while the length just checks for an exact length of 12 characters. – René Kåbis Mar 05 '16 at 05:43
  • You are right i missed the dashes in the regular expression. updated an answer – Alex Art. Mar 05 '16 at 06:35
  • Not at work anymore. Even crazily dedicated programmers need sleep some time! ;-) – René Kåbis Mar 05 '16 at 07:47
  • Rock on, dude. This works! Accepted and upvoted! I don’t think I would have been able to figure out this one on my own, as I didn’t know I could put a plain `When` and encapsulate the `RuleFor`. Looked at hundreds of examples of Fluid Validation, and never came across something like this. – René Kåbis Mar 05 '16 at 21:53
  • Although I *did* make use of `!string.IsNullOrEmpty(x.CompanyCity)` instead of your null comparator, since the field may have been typed in, but then erased. AFAIK this then returns an empty field instead of a null field, which does make a difference. Quick question: are the field contents normally trimmed, or would I have to add a `.trim()` to my check to ensure that trailing blank spaces are trimmed out? – René Kåbis Mar 05 '16 at 21:57
  • The values are not trimmed by default so either trim explicitly or you can use `string.IsNullOrWhiteSpace` instead of `string.IsNullOrEmpty` – Alex Art. Mar 06 '16 at 08:18