【问题标题】:Regular Expression stop crashing正则表达式停止崩溃
【发布时间】:2012-02-18 05:48:01
【问题描述】:

考虑这段代码:

[Required]
[RegularExpression(@"\d{2,2}/\d{2,2}/\d{4,4} \d{2,2}:\d{2,2}:\d{2,2}", 
ErrorMessage = "Wrong Syntax Entered, Needed:day/Month/Year Hour:Minutes:Seconds")]
public DateTime Posted { get; set; }

当我输入这个值时,我的应用程序崩溃了:00/00/0000 00:00:00

有没有办法阻止这种情况并使其更加现实?我想允许日期,所以它只允许最多 31 天或更短的 1 天,并允许最多 12 个月和最少 1 天?

【问题讨论】:

  • 不一样这是崩溃
  • 当您说“崩溃”时,您的意思是抛出未捕获的异常?对吗?
  • 当我输入 00/00/0000 00:00:00 时是的

标签: c# regex


【解决方案1】:

正则表达式是验证日期和时间的错误方法。请改用DateTime.TryParse。

编辑:

这是一个例子:

using System;
using System.Globalization;

...

bool valid;
DateTime dt;
valid = DateTime.TryParseExact(inputString, "dd/MM/yyyy HH:mm:ss", CultureInfo.InvariantCulture, DateTimeStyles.None, out dt);

【讨论】:

  • 您能举个例子吗,或者我可以修改我当前的表达式,使其停止 00/00/00 00:00:00 并允许最多 31 和最少 1 天和几个月最少 1 和最多 12 个
  • @user1137472:我添加了一个示例。
  • 谢谢老实说我不知道​​这意味着我试图通过创建一个类来实现大卫给出的答案没有成功感谢您的努力
  • 我不知道把它放在哪里,它做了什么或者它去了哪里很抱歉浪费了你的时间,但我想要一个简单的答案,并想停止 00/00/0000 00:00: 00 并且通过明确的验证仅允许 1 到 31 天和 1 到 12 个月我以前见过,但我不记得在哪里感谢您的所有努力
【解决方案2】:

我同意 @MRAB 的观点,即 TryParse 可能更易于管理和维护。

这个SO question 也尝试做你正在做的事情,他们创建了一个自定义属性(源自RegularExpressionAttribute)似乎已经解决了他的问题。也许对你有帮助。

希望这会有所帮助。

【讨论】:

    【解决方案3】:

    另外,在 ModelBinder 中更改 FormatException 消息(但要走很远......)。

    DefaultModelBinder.GetValueInvalidResource 是静态方法。我无法覆盖此方法。因为我创建了 CustomModelBinder 类并重写了 SetProperty 方法。

    [Required]
    [AdditionalMetadata(
     "PropertyValueInvalid",
     "Wrong Syntax Entered, Needed:day/Month/Year Hour:Minutes:Seconds")]
    public DateTime? Posted { get; set; }
    

    并创建自定义 ModelBinder

    public class CustomModelBinder : DefaultModelBinder
    {
        protected override void SetProperty(ControllerContext controllerContext, ModelBindingContext bindingContext, System.ComponentModel.PropertyDescriptor propertyDescriptor, object value)
        {
            base.SetProperty(controllerContext, bindingContext, propertyDescriptor, value);
    
            var propertyMetadata = bindingContext.PropertyMetadata[propertyDescriptor.Name];
            var invalidMessage = propertyMetadata.AdditionalValues.ContainsKey("PropertyValueInvalid")
                                     ? (string)propertyMetadata.AdditionalValues["PropertyValueInvalid"]
                                     : string.Empty;
            if (string.IsNullOrEmpty(invalidMessage))
            {
                return;
            }
    
            // code from DefaultModelBinder
            string fullPropertyKey = CreateSubPropertyName(bindingContext.ModelName, propertyDescriptor.Name);
            if (!bindingContext.ValueProvider.ContainsPrefix(fullPropertyKey))
            {
                return;
            }
            ModelState modelState = bindingContext.ModelState[fullPropertyKey];
            foreach (ModelError error in modelState.Errors.Where(err => String.IsNullOrEmpty(err.ErrorMessage) && err.Exception != null).ToList())
            {
                for (Exception exception = error.Exception; exception != null; exception = exception.InnerException)
                {
                    if (exception is FormatException)
                    {
                        string displayName = propertyMetadata.GetDisplayName();
                        string errorMessageTemplate = invalidMessage;
                        string errorMessage = String.Format(CultureInfo.CurrentCulture, errorMessageTemplate,
                                                            modelState.Value.AttemptedValue, displayName);
                        modelState.Errors.Remove(error);
                        modelState.Errors.Add(errorMessage);
                        break;
                    }
                }
            }
        }
    }
    

    这个怎么样?

    【讨论】:

    • 我不知道你写了什么,人们说 regx 不好?看看那段代码,你永远无法理解它的作用。我想要的只是一个不使用服务器端验证的正则表达式,只想要一个日期和时间表达式我理解你的专业人士,但给我这段代码就像给婴儿一把枪
    【解决方案4】:

    使用正则表达式验证数据时间将导致复杂的正则表达式,如

    ^([0][1-9]||[1-2][0-9]||[3][0-1])/([0][1-9]||[1][1-2])/([1][0-9]{3}) ([0][1-9]||[1][0-2]):([0][1-9]||[1-5][0-9]):([0][1-9]||[1-5][0-9])$
    

    但我仍然怀疑它可能会错过一些边缘情况。

    如果您使用的是 MVC3,那么使用自我验证模型的最佳方法如下,

    public class TestModel:IValidatableObject
        {
            string MyDateTime{get;set;}
    
            public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
            {
                List<ValidationResult> v = new List<ValidationResult>();
                DateTime dt = default(DateTime);
                DateTime.TryParseExact(MyDateTime, "dd/MM/yyyy HH:mm:ss", CultureInfo.InvariantCulture,DateTimeStyles.None,out dt);
                if (dt.Equals(default(DateTime)))
                    v.Add(new ValidationResult("Invalid Date time"));
                return v;
            }
        }
    

    【讨论】:

    • 如果我要实现它会是一个部分类吗?
    猜你喜欢
    • 2012-08-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-10-29
    • 1970-01-01
    • 1970-01-01
    • 2014-11-28
    • 1970-01-01
    相关资源
    最近更新 更多