10

I have a regular expression that i'm trying to figure out for a .NET Data Annotation Validation model that i'm using. Currently it looks like this

[RegularExpression("^((?!City)[a-zA-Z '])+$", ErrorMessage = "City is required and must be properly formatted.")]

The first half of this regex is to account for City, the second half is to make sure its only letters and spaces.

The default value for the input text box is City, so just "City" cant pass validation. I can't seem to get the first section of that regex to have these cases pass.

Cityville  
City City
Jersey City
Arizona City

But this case not pass:

City

Any help would be greatly appreciated.

*EDIT* This one did the trick:

^((?!^City$)[a-zA-Z '])+$

I updated all of my validation to include this. Just in case you want to see what i'm doing. Here if the code for the whole validation data model that i'm using. (updated with the correct regex)

public class FormModel {
    [Required(ErrorMessage = "First Name is a Required field.")]
    [DataType(DataType.Text)]
    [Display(Order = 1, Name = "FirstName")]
    [RegularExpression("^((?!^First Name$)[a-zA-Z '])+$", ErrorMessage = "First name is required and must be properly formatted.")]
    public string FirstName { get; set; }

    [Required(ErrorMessage = "Last Name is a Required field.")]
    [DataType(DataType.Text)]
    [Display(Order = 2, Name = "LastName")]
    [RegularExpression("^((?!^Last Name$)[a-zA-Z '])+$", ErrorMessage = "Last name is required and must be properly formatted.")]
    public string LastName { get; set; }

    [Required(ErrorMessage = "Address is a Required field.")]
    [DataType(DataType.Text)]
    [Display(Order = 3, Name = "Address")]
    [RegularExpression("^((?!^Address$)[0-9A-Za-z #.,])+$", ErrorMessage = "Address is required and must be properly formatted.")]
    public string Address { get; set; }

    [DataType(DataType.Text)]
    [Display(Order = 4, Name = "Address2")]
    public string Address2 { get; set; }

    [Required(ErrorMessage = "City is a Required field.")]
    [DataType(DataType.Text)]
    [RegularExpression("^((?!^City$)[a-zA-Z '])+$", ErrorMessage = "City is required and must be properly formatted.")]
    [Display(Order = 6, Name = "City")]
    public string City { get; set; }

    [Required( ErrorMessage = "State is a Required field." )]
[DataType( DataType.Text )]
[Display( Order = 7, Name = "State" )]
public IEnumerable<String> State { get; set; }

[Required( ErrorMessage = "Zip is a Required field." )]
[DataType( DataType.Text )]
[RegularExpression( "\\d{5}",
        ErrorMessage = "Zip Code is required and must be properly formatted.")]
[Display( Order = 8, Name = "Zip" )]
public String Zip { get; set; }

[Required( ErrorMessage = "Phone is a Required field." )]
[DataType( DataType.PhoneNumber )]
[RegularExpression( "^[01]?[- .]?\\(?[2-9]\\d{2}\\)?[- .]?\\d{3}[- .]?\\d{4}$",
        ErrorMessage = "Phone is required and must be properly formatted.")]
[Display( Order = 9, Name = "Phone" )]
public string Phone { get; set; }

[Required( ErrorMessage = "Email is a Required field." )]
[DataType( DataType.EmailAddress )]

[RegularExpression( "^[A-Za-z0-9._%+-]*@[A-Za-z0-9.-]*\\.[A-Za-z0-9-]{2,}$",
        ErrorMessage = "Email is required and must be properly formatted.")]
[Display( Order = 10, Name = "Email" )]
public string Email { get; set; }
Chris Limina
  • 113
  • 1
  • 1
  • 7

5 Answers5

4

Try this out for the regular expression - ^((?!^City$)[a-zA-Z '])+$
To do a negative check for "City", I have added a start (^) & end ($) characters to City. I have tested it at http://regex101.com/r/bF4bZ3 and it seems to work if I am understanding the requirement correctly.

2

Other answers have given you the help with the regular expression that you requested. I'm going to comment on a slightly different aspect - the default value should be something meaningful, or nothing at all ("City" is a bad default value).

What you probably wanted to do was put placeholder text, which disappears as soon as you enter the textbox. You can do this with the Prompt property of Display attribute if you're using NET 4.5 - see this answer for details.

Not using a fake default value means you can just use [Required] and the users will need to enter something, and stops you needing to keep track of what your fake default values are.

Just to throw another spanner in the works, "City" is a valid place name - there are two villages called City in Wales and an area in Zurich!

Community
  • 1
  • 1
Richard
  • 29,854
  • 11
  • 77
  • 120
  • If i had it my way i would just use labels for everything. unfortunately creative likes to come up with forms that mess up my form validation. What i will do eventually is try using this as an alternative to .NET data annotations. http://fluentvalidation.codeplex.com/ – Chris Limina May 28 '13 at 18:52
1

(?!City) means City Zero Width Negative Lookahead, so, ^((?!City)[a-zA-Z '])+$ means:

  • Contains only letters spaces and '
  • Does not contain City

Here is how to disallow City:

//Regular Expression    
//^(?!^\s*City\s*$)[a-zA-Z ']+$
//as a .Net string  
string str = "^(?!^\\s*City\\s*$)[a-zA-Z ']+$"

Demo

Ahmed KRAIEM
  • 10,267
  • 4
  • 30
  • 33
1

Negative matching in regular expressions is generally a bad idea, it's just not designed that way. The best method would be to check against:

"^City$"

And negate the test. In this case you don't really have an option to do that.

You are really close, you just need to move your anchors into the negative lookahead, and give the string a min length.

(?!^City$)[-a-zA-Z ]{4,}

This will match anything that is 4 characters or more that is not "City".

Without the min length the "ity" in "City" will be a match which won't help you.

You can reduce the min length to 3 by adding a look behind if you like.

(?!^City$)[-a-zA-Z ]{3,}(?<!^City$)
0

This is actually a really small mistake on your part. Change your Regex to:

^(?!^City$)[a-zA-Z ']+$

And you'll have the desired effect. Basically the + means one or more times, and since you had the WHOLE expression enclosed in brackets which were to occur one or more times, it would find the "City" match at any point in the string... This instead says, in English: Not "City", and letters and spaces or single quotes one or more times.

A good tool to test Regex is Regex Hero: http://regexhero.net/tester

Haney
  • 32,775
  • 8
  • 59
  • 68
  • 1
    This doesn't match `City City`. You need a `$` in the look ahead to make sure there isn't anything after City. – juharr May 28 '13 at 16:19