C# 数据批注RegularExpressionAttribute为空/空

C# 数据批注RegularExpressionAttribute为空/空,c#,regex,asp.net-mvc,model-view-controller,data-annotations,C#,Regex,Asp.net Mvc,Model View Controller,Data Annotations,我正在使用RegularExpressionAttribute验证属性。属性需要允许长度为零的字符串、null或(仅)空格以外的任何内容。我使用的正则表达式是“^(?!^*$)^.+$” 如果值为null或空字符串,RegularExpressionAttribute.IsValid总是返回true,但我认为它应该是false(仅空格可以) 我不是正则表达式专家,但我相信表达式是可以的(如果我使用regex.IsMatch直接从我的代码验证正则表达式,空字符串将返回false-如预期的那样)。这

我正在使用
RegularExpressionAttribute
验证属性。属性需要允许长度为零的字符串、null或(仅)空格以外的任何内容。我使用的正则表达式是
“^(?!^*$)^.+$”

如果值为
null
空字符串
RegularExpressionAttribute.IsValid
总是返回true,但我认为它应该是false(仅空格可以)

我不是正则表达式专家,但我相信表达式是可以的(如果我使用
regex.IsMatch
直接从我的代码验证正则表达式,空字符串将返回false-如预期的那样)。这是RegularExpressionAttribute的问题吗

(我知道RequiredAttribute通常是一个快速的选项,但在这种情况下不是一个选项)

更新:

为了消除任何歧义,下面是一段简单的测试代码来演示:

    public class MyValueTester
    {
//      internal const string _REGEX_PATTERN = "^(?!\\s*$).+$";
//      internal const string _REGEX_PATTERN = @"^(?!\s*$)";
        internal const string _REGEX_PATTERN = @"[^ ]";



        public MyValueTester()
        {
            ProperValue = "hello";
            NullValue = null;
            SpaceValue = " ";
            LeadingSpaceValue = " hi";
            EmptyValue = "";
        }

        [RegularExpression(_REGEX_PATTERN, ErrorMessage = "To err is human")]
        public string ProperValue { get; set; }

        [RegularExpression(_REGEX_PATTERN, ErrorMessage = "To null is human")]
        public string NullValue { get; set; }

        [RegularExpression(_REGEX_PATTERN, ErrorMessage = "To space is human")]
        public string SpaceValue { get; set; }

        [RegularExpression(_REGEX_PATTERN, ErrorMessage = "To empty is human")]
        public string EmptyValue { get; set; }

        [RegularExpression(_REGEX_PATTERN, ErrorMessage = "To lead is human")]
        public string LeadingSpaceValue { get; set; }
    }
测试代码:

        MyValueTester myValueTester = new MyValueTester();

        ValidationContext validationContext = new ValidationContext(myValueTester);
        List<ValidationResult> validationResults = new List<ValidationResult>();

        Debug.WriteLine("=== Testing pattern '" + MyValueTester._REGEX_PATTERN + "' ===");

        var expectedResults = new[]
                            {
                                new {propertyName = "ProperValue", expectedPass = true},
                                new {propertyName = "LeadingSpaceValue", expectedPass = true},
                                new {propertyName = "NullValue", expectedPass = false},
                                new {propertyName = "SpaceValue", expectedPass = false},
                                new {propertyName = "EmptyValue", expectedPass = false},
                            };

        bool isMatch = Validator.TryValidateObject(myValueTester, validationContext, validationResults, true);

        foreach (var expectedResult in expectedResults)
        {
            ValidationResult validationResult = validationResults.FirstOrDefault(r => r.MemberNames.Contains(expectedResult.propertyName));
            string result = expectedResult.expectedPass ? (validationResult == null ? "Ok" : "** Expected Pass **") : (validationResult != null ? "Ok" : "** Expected Failure **");

            Debug.WriteLine("{0}: {1}", expectedResult.propertyName, result);
        }

事情不应该那么复杂。我不确定我是否理解完整的需求,但不仅仅是
“[^]”
有效吗?

令人沮丧的回答: 我确信RegularExpressionAttribute中有一个bug,尽管它在正则表达式中工作得很好,但在无法使用最简单的模式之后。结果证明,数据注释验证器使正则表达式的实现变得简单,以阻止新手错误。MSDN有这样的评论:

如果属性的值为null或空字符串(“”),则 值会自动通过对 RegularExpressionAttribute属性。验证该值是否为 如果不是null或空字符串,请使用RequiredAttribute属性


因此,从技术上讲,这不是一个错误——只是一个糟糕的想法。在我的例子中,修复方法是编写一个RegularExpressionAttribute扩展来处理null/empty(我可以通过在RegularExpressionAttribute::IsValid中使用适当的正则表达式来进行验证。

试试这个^(?!\s*$)。+您必须只匹配字符串的开头一次,试试
“^(?!\\s*$)+$”
。只使用
[必需]有什么问题吗
属性?为什么
[必需]
属性不是一个选项?对于未来的读者:使用
Required
属性的问题是,要让用户友好的文本显示为模型验证错误消息,现在需要将整个字符串复制/粘贴到两个属性中。这很混乱。正确,它应该一点也不复杂!唉,不,该模式不起作用.
=== Testing pattern '^(?!\s*$).+$' ===
ProperValue: Ok
LeadingSpaceValue: Ok
NullValue: ** Expected Failure **
SpaceValue: Ok
EmptyValue: ** Expected Failure **

=== Testing pattern '^(?!\S*$)' ===
ProperValue: ** Expected Pass **
LeadingSpaceValue: ** Expected Pass **
NullValue: ** Expected Failure **
SpaceValue: Ok
EmptyValue: ** Expected Failure **

=== Testing pattern '^(?!\s*$)' ===
ProperValue: ** Expected Pass **
LeadingSpaceValue: ** Expected Pass **
NullValue: ** Expected Failure **
SpaceValue: Ok
EmptyValue: ** Expected Failure **

=== Testing pattern '[^ ]' ===
ProperValue: ** Expected Pass **
LeadingSpaceValue: ** Expected Pass **
NullValue: ** Expected Failure **
SpaceValue: Ok
EmptyValue: ** Expected Failure **