繁体   English   中英

日期的MVC模型验证

[英]MVC model validation for date

MVC 5是否有任何默认验证,可以在其中设置日期的最小值和最大值?

在我的模型中,我想要日期验证

    public class MyClass
    {               
        [Required(ErrorMessage="Start date and time cannot be empty")]
        //validate:Must be greater than current date
        [DataType(DataType.DateTime)]
        public DateTime StartDateTime { get; set; }

        [Required(ErrorMessage="End date and time cannot be empty")]
        //validate:must be greater than StartDate
        [DataType(DataType.DateTime)]
        public DateTime EndDateTime { get; set; }            
    }

附:根据此Asp.Net网站 ,在DateTime中使用Range验证器存在问题,因此不建议这样做。

注意:jQuery验证不适用于Range属性和DateTime。 例如,即使日期在指定范围内,以下代码也将始终显示客户端验证错误:

[Range(typeof(DateTime), "1/1/1966", "1/1/2020")]

您将需要禁用jQuery日期验证才能将Range属性与DateTime一起使用。 在模型中编译硬日期通常不是一个好习惯,因此不建议使用Range属性和DateTime。

我也知道,有诸如Fluent ValidationFoolproof之类的Nuget软件包可以验证和检查一个日期是否大于另一个日期,但是我想知道默认情况下是否可以检查日期的最小值和最大值。

从我在MVC 5.1的新增功能中所看到的,它支持MaxLengthMinLength验证。

无需禁用jQuery日期验证(这可能会导致其他问题)。 您只需要重写$.validatorrange方法。

默认情况下,它适用于数值(然后回退到字符串比较),因此您可以添加以下脚本(在jquery.validate.jsjquery.validate.unobtrusive.js ,但不包装在$(document).ready

$.validator.methods.range = function(value, element, param) {
    if ($(element).attr('data-val-date')) {
        var min = $(element).attr('data-val-range-min');
        var max = $(element).attr('data-val-range-max');
        var date = new Date(value).getTime();
        var minDate = new Date(min).getTime();
        var maxDate = new Date(max).getTime();
        return this.optional(element) || (date >= minDate && date <= maxDate);
    }
    // use the default method
    return this.optional( element ) || ( value >= param[ 0 ] && value <= param[ 1 ] );
};

然后,您可以在属性上使用RangeAttribute

[Range(typeof(DateTime), "1/1/1966", "1/1/2020")]
public DateTime Date { get; set; }

我将使用System.ComponentModel.DataAnnotations中的IValidatableObject接口来执行此操作,该接口允许您添加额外的验证规则,在其中可以执行更多检查。 将接口添加到您的类中,然后实现Validate方法,您可以在其中将StartDateTime与当前日期/时间进行比较,还可以将EndDateTime与StartDateTime进行比较,例如

public class MyClass : IValidatableObject
{               
    [Required(ErrorMessage="Start date and time cannot be empty")]
    //validate:Must be greater than current date
    [DataType(DataType.DateTime)]
    public DateTime StartDateTime { get; set; }

    [Required(ErrorMessage="End date and time cannot be empty")]
    //validate:must be greater than StartDate
    [DataType(DataType.DateTime)]
    public DateTime EndDateTime { get; set; }       

    public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
    {
        List<ValidationResult> results = new List<ValidationResult>();

        if (StartDateTime < DateTime.Now)
        {
            results.Add(new ValidationResult("Start date and time must be greater than current time", new []{"StartDateTime"}));
        }

        if (EndDateTime <= StartDateTime)
        {
            results.Add(new ValidationResult("EndDateTime must be greater that StartDateTime", new [] {"EndDateTime"}));
        }

        return results;
    }     
}

唯一的潜在缺点是Validate在服务器端运行,而不是在jQuery验证中运行。

通常,当我要验证服务器中的某些内容时,会使用此解决方案。 我知道您可以依赖MVC使用的验证模型,但是在进行验证时,我试图使用一个单独的项目,以防需要对其进行单元测试。 假设您有两个应用程序,一个桌面程序和一个Web,然后两者都可以共享ValidationProject,而不必在两个应用程序中为相同的“视图” /“屏幕”重复代码。 这里的想法是将验证项目隔离为解决方案的独立项目。

因此,您可以从NuGet下载FluentValidation项目,FluentValidation使用构造函数中的Rules,您可以在此处查看文档https://github.com/JeremySkinner/FluentValidation/wiki

例如,您的“日期”规则可以以这种方式使用,您还可以在其中放置最小值和最大值的规则:

public class CustomerValidator: AbstractValidator<Customer> {
  public CustomerValidator() {
                    RuleFor(customer => customer.startDate)
                    .NotNull()
                    .WithMessage("You should select a start date")
                    .Must(d => d.HasValue && d.Value <= DateTime.Today)
                    .WithMessage("The start date should not be greather than current month/year");
  }

现在在您的控制器中

[HttpPost]
public ActionResult Index(Customer c)
{
  if(ModelState.IsValid)
  {
    var validator= new CustomerValidator();
    var valResult = validator.Validate(c);

    if (valResult.Errors.Count != 0)
    {
       valResult.Errors.ForEach(x => ModelState.AddModelError(x.PropertyName, x.ErrorMessage));
       return View(vm);
    }

    //Your code here
  }
}

我认为只需添加属性“ Range”即可

[Range(typeof(DateTime), "01/01/1900", "06/06/2079", ErrorMessageResourceType = typeof(Resources.Patient), ErrorMessageResourceName = "DateOfBirth_Range")] 

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM