web-dev-qa-db-ja.com

日付のMVCモデル検証

日付の最小値と最大値を設定できる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 Website によると、DateTimeのRangeバリデーターの使用に問題があり、推奨されていません。

注:jQuery検証は、Range属性とDateTimeでは機能しません。たとえば、次のコードは、日付が指定された範囲内であっても、常にクライアント側の検証エラーを表示します。

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

DateTimeでRange属性を使用するには、jQueryの日付検証を無効にする必要があります。一般に、モデルで厳密な日付をコンパイルすることはお勧めできません。そのため、Range属性とDateTimeの使用は推奨されません。

また、 Fluent ValidationFoolproof のようなNugetパッケージがあることを知っていますデフォルトでは、日付の最小値と最大値を確認するものがあります。

MVC 5.1の新機能 で見たものから、 MaxLength および MinLength 検証のサポートがあります。

17
Cybercop

JQueryの日付検証を無効にする必要はありません(他の問題を引き起こす可能性があります)。 $.validatorrangeメソッドをオーバーライドするだけです。

デフォルトでは、数値で動作し(その後、文字列比較にフォールバックします)、次のスクリプトを追加できます(jquery.validate.jsおよびjquery.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; }
7
user3559349

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検証ではなくサーバー側で実行されることです。

6
PhilPursglove

通常、サーバー内の何かを検証する場合にこのソリューションを使用します。 MVCが使用する検証モデルに依存できることはわかっていますが、検証を行うときは、ユニットテストを行う必要がある場合に備えて別のプロジェクトを使用しようとしています。デスクトップとWebの2つのアプリケーションがあり、両方が同じ「表示」/「画面」に対して両方のアプリケーションでコードを繰り返す代わりに、ValidationProjectを共有できるとしましょう。ここでのアイデアは、検証プロジェクトをソリューションの独立したプロジェクトとして分離することです。

NuGetからFluentValidationプロジェクトをダウンロードできます。FluentValidationはコンストラクター内でルールを使用します。ここでドキュメントを参照できます 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
  }
}
0
Zinov