How can I set a RegularExpression data annotation's regular expression argument at runtime? - regex

We manage several ASP.NET MVC client web sites, which all use a data annotation like the following to validate customer email addresses (I haven't included the regex here, for readability):
[Required(ErrorMessage="Email is required")]
[RegularExpression(#"MYREGEX", ErrorMessage = "Email address is not valid")]
public string Email { get; set; }
What I would like to do is to centralise this regular expression, so that if we make a change to it, all of the sites immediately pick it up and we don't have to manually change it in each one.
The problem is that the regex argument of the data annotation must be a constant, so I cannot assign a value I've retrieved from a config file or database at runtime (which was my first thought).
Can anyone help me with a clever solution to this—or failing that, an alternative approach which will work to achieve the same goal? Or does this just require us to write a specialist custom validation attribute which will accept non-constant values?

The easiest way is to write a custom ValidationAttribute that inherits from RegularExpressionAttribute, so something like:
public class EmailAttribute : RegularExpressionAttribute
{
public EmailAttribute()
: base(GetRegex())
{ }
private static string GetRegex()
{
// TODO: Go off and get your RegEx here
return #"^[\w-]+(\.[\w-]+)*#([a-z0-9-]+(\.[a-z0-9-]+)*?\.[a-z]{2,6}|(\d{1,3}\.){3}\d{1,3})(:\d{4})?$";
}
}
That way, you still maintain use of the built in Regex validation but you can customise it. You'd just simply use it like:
[Email(ErrorMessage = "Please use a valid email address")]
Lastly, to get to client side validation to work, you would simply add the following in your Application_Start method within Global.asax, to tell MVC to use the normal regular expression validation for this validator:
DataAnnotationsModelValidatorProvider.RegisterAdapter(typeof(EmailAttribute), typeof(RegularExpressionAttributeAdapter));

Checkout ScotGu's [Email] attribute (Step 4: Creating a Custom [Email] Validation Attribute).

Do you really want to put the regex in database/config file, or do you just want to centralise them? If you just want to put the regex together, you can just define and use constants like
public class ValidationRegularExpressions {
public const string Regex1 = "...";
public const string Regex2 = "...";
}
Maybe you want to manage the regexes in external files, you can write a MSBuild task to do the replacement when you build for production.
If you REALLY want to change the validation regex at runtime, define your own ValidationAttribute, like
[RegexByKey("MyKey", ErrorMessage = "Email address is not valid")]
public string Email { get; set; }
It's just a piece of code to write:
public class RegexByKeyAttribute : ValidationAttribute {
public RegexByKey(string key) {
...
}
// override some methods
public override bool IsValid(object value) {
...
}
}
Or even just:
public class RegexByKeyAttribute : RegularExpressionAttribute {
public RegexByKey(string key) : base(LoadRegex(key)) { }
// Be careful to cache the regex is this operation is expensive.
private static string LoadRegex(string key) { ... }
}
Hope it's helpful: http://msdn.microsoft.com/en-us/library/cc668224.aspx

Why not just write you own ValidationAttribute?
http://msdn.microsoft.com/en-us/library/system.componentmodel.dataannotations.validationattribute.aspx
Then you can configure that thing to pull the regex from a registry setting... config file... database... etc... etc..
How to: Customize Data Field Validation in the Data Model Using Custom

Related

how to validate email in javafx TextField?

GOAL:
I'm trying to validate the user's email address as he/she types.
I'm just using simple regex because I don't want to use any external library. Also if use the regex like in here regex email for java I'm encountering error PatternSyntaxException that's why I prefer simple regex for now.
So I put the TextFormatter and UnaryOperator inside the initialize method.
#FXML
public void initialize()
{
//1. USE UNARY FIRST TO MAKE FILTER BEFORE USING TEXTFORMATTER
UnaryOperator <TextFormatter.Change> filterEmail = (change ->{
if(change.getControlNewText().matches("^(.+)#(.+)$*"))
{
lblEmailError.setVisible(false);
txtEmailAdd.setBorder(null);
return change;
}
else
{
lblEmailError.setText("Invalid Email");
lblEmailError.setVisible(true);
txtEmailAdd.setBorder(new Border(new BorderStroke(Color.RED, BorderStrokeStyle.SOLID, new CornerRadii(3), new BorderWidths(2), new Insets(-2))));
return null;
}
});
TextFormatter <String> tf = new TextFormatter<String>(filterEmail);
txtEmailAdd.setTextFormatter(tf);
}
But as long as the FXML loads I can't type anymore in the TextField and can't be edited anymore. I can't type anything. Maybe there is something wrong with my condition or I'm wrong putting it inside the initialize method.
I'm lost. I have already dug the web on how to validate email in java using regex.
like this Java regex email
I'm also using SceneBuilder to build the fxml. Any help will do thanks in advance.

Can we edit Spring validation annotation without changing the source code?

public class Foo {
#NotNull
#Pattern(regexp = "[0-9]+"
private String number;
}
Have requirement to support negative number at production site. Is there a way we can change regex value or disabling validation without changing the source class? any configuration to add in xml?
I know we can edit regex but looking for option without editing source file.
Spring uses regex validation, so you can simply tweak the regex pattern like this:
public class Foo {
#NotNull
#Pattern(regexp = "-?[0-9]+")
private String number;
}
However, if you mean about parameterizing the pattern, then you can use a property like this:
public class Foo {
#NotNull
#Pattern(regexp = "${regex.pattern}")
private String number;
}
And add in application.properties the property
regex.pattern=-?[0-9]+

DataAnnotation TextArea Multiple Emails

I am using MVC 3.
I have a text area in which user can enter multiple emails addresses. Emails can be separated by a comma and a space. User may hit enter in the box as well.
Is there an attribute that can handle this scenario?
I am using regular expression to check for the characters and it is failing for "abc#abc.com, tyz#tyz.com"
Here is my regular expression:
[RegularExpression(#"([a-zA-Z0-9 .#-_\n\t\r]+)", ErrorMessage = ValidationMessageConstants.EmailAdressInvalid)]
What am i missing here? This regular expression is off the following post:
DataAnnotations validation (Regular Expression) in asp.net mvc 4 - razor view
Out of the box, .NET 4.5 has the System.ComponentModel.DataAnnotations.EmailAddressAttribute found in the System.ComponentModel.DataAnnotations assembly, but this is limited to validating just one email address. Hence, if you have a model that accepts delimitted email address and you decorate the property with this attribute, it will fail since it will treat the entire string as one email.
What I've done is create an extended emailaddress attribute that validates the delimited email addresses:
[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Parameter, AllowMultiple = false)]
public class EmailAddressExAttribute : DataTypeAttribute
{
#region privates
private readonly EmailAddressAttribute _emailAddressAttribute = new EmailAddressAttribute();
#endregion
#region ctor
public EmailAddressExAttribute() : base(DataType.EmailAddress){ }
#endregion
#region Overrides
/// <summary>
/// Checks if the value is valid
/// </summary>
/// <param name="value"></param>
/// <returns></returns>
public override bool IsValid(object value)
{
var emailAddr = Convert.ToString(value);
if (string.IsNullOrWhiteSpace(emailAddr)) return false;
//lets test for mulitple email addresses
var emails = emailAddr.Split(new[] {';', ' ', ','}, StringSplitOptions.RemoveEmptyEntries);
return emails.All(t => _emailAddressAttribute.IsValid(t));
}
#endregion
}
You can now decorate any string property with this new extended attribute to validate delimited email addresses. You can update the delimiters to include any special characters you want to use as well.
Hope this helps!
You not stating what the question is, so I will have to assume from your answer that data annotations aren't working as you would expect.
Having that assumption in mind, its very easy why is it not working: data annotation operates on the entire field, text area in your case. It will work as expected if you have only one email. Since you have multiple emails in that field, separated by comma or space, the field in its entirety doesn't reflect what data annotation for email prescribes and fails.
To answer your numbered questions:
No, there is no out of the box
The regular expression you using doesn't account for multiple emails, but one. The solution in your case will be either to
Data annotation using RegEx for multiple emails separated as you'd like or
Have custom validation attribute doing it for you
Following the links above you will see very good examples of "how to" and hopefully get you going in the right direction.
Hope this helps, please let me know if not.

What is ScaffoldColumn and RegularExpression attributes

I am trying to learn MVC4 and i've come to this chapter called validation.
I came to know about DataAnnotations and they have pretty neat attributes to do some server side validation. In book they have only explained about [Required] and [Datatype] attribute. However in asp.net website i saw something called ScaffoldColumn and RegularExpression.
Can someone explain what they are, even though I know little what RegularExpression does.
Also are there any other important validation attributes I should know?
Scaffold Column dictates if when adding a view based on that datamodel it should/not scaffold the column. So forexample your model's id field is a good candidate for you to specify ScaffoldColumn(false), and other foreign key fields etc.
I you specify a regular expression, then if you scaffold a new view for that model,edit customer for example, a regex or regular expression on field will enforce that entered data must match that format.
You can read about ScaffoldColumnAttribute Class here
[MetadataType(typeof(ProductMetadata))]
public partial class Product
{
}
public class ProductMetadata
{
[ScaffoldColumn(true)]
public object ProductID;
[ScaffoldColumn(false)]
public object ThumbnailPhotoFileName;
}
And about RegularExpressionAttribute Class you can read here.
using System;
using System.Web.DynamicData;
using System.ComponentModel.DataAnnotations;
[MetadataType(typeof(CustomerMetaData))]
public partial class Customer
{
}
public class CustomerMetaData
{
// Allow up to 40 uppercase and lowercase
// characters. Use custom error.
[RegularExpression(#"^[a-zA-Z''-'\s]{1,40}$",
ErrorMessage = "Characters are not allowed.")]
public object FirstName;
// Allow up to 40 uppercase and lowercase
// characters. Use standard error.
[RegularExpression(#"^[a-zA-Z''-'\s]{1,40}$")]
public object LastName;
}

RegularExpressionAttribute Not Working and I Don't Know Why

I have a simple view model class for MVC2 that has a MagicItem property:
public class VoodooViewModel {
[Required(AllowEmptyStrings = false,
ErrorMessage = "The Magic Item is required")]
[RegularExpression(#"^[^-]*$",
ErrorMessage = "Hyphens are not allowed in Magic Items.")]
public string MajorModel { get; set; }
}
I am simply trying to disallow hyphens in this property, but for the life of me I can't get it to work. Can anyone see what I'm doing wrong (the RequiredAttribute is working fine)?
To my eyes, the regex I have says "from the beginning of the string to the end, match anything that isn't a hyphen". I have tested this in the Regex tester here, and it works - but not in my code. I can't get the error to show no matter how many hyphens I put in it.
Like a tool, I forgot to check in the controller's action method to see if the ModelState was valid or not:
public ActionResult UberController(VoodooViewModel vvm)
{
if (!ModelState.IsValid) return View(vvm); //turns out this line is important
(...yaddayaddayadda...)
}
Thanks to Darin for pointing me in the right direction.