Asp.net-Mvc
無法從 MVC2 中的自定義驗證屬性設置成員名
我通過繼承 ValidationAttribute 創建了一個自定義驗證屬性。該屬性在類級別應用於我的視圖模型,因為它需要驗證多個屬性。
我壓倒一切
protected override ValidationResult IsValid(object value, ValidationContext validationContext)並返回:
new ValidationResult("Always Fail", new List<string> { "DateOfBirth" });在 DateOfBirth 是我的視圖模型上的屬性之一的所有情況下。
當我執行我的應用程序時,我可以看到它受到了影響。ModelState.IsValid 正確設置為 false,但是當我檢查 ModelState 內容時,我看到 Property DateOfBirth 不包含任何錯誤。相反,我有一個值為 null 的空字元串 Key 和一個包含我在驗證屬性中指定的字元串的異常。
這導致在使用 ValidationMessageFor 時不會在我的 UI 中顯示錯誤消息。如果我使用 ValidationSummary,那麼我可以看到錯誤。這是因為它與屬性無關。
看起來好像它忽略了我在驗證結果中指定了成員名的事實。
為什麼會這樣,我該如何解決?
所要求的範常式式碼:
[AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = true)] public class ExampleValidationAttribute : ValidationAttribute { protected override ValidationResult IsValid(object value, ValidationContext validationContext) { // note that I will be doing complex validation of multiple properties when complete so this is why it is a class level attribute return new ValidationResult("Always Fail", new List<string> { "DateOfBirth" }); } } [ExampleValidation] public class ExampleViewModel { public string DateOfBirth { get; set; } }
我不知道解決此行為的簡單方法。這就是我討厭數據註釋的原因之一。對FluentValidation做同樣的事情會很輕鬆:
public class ExampleViewModelValidator: AbstractValidator<ExampleViewModel> { public ExampleViewModelValidator() { RuleFor(x => x.EndDate) .GreaterThan(x => x.StartDate) .WithMessage("end date must be after start date"); } }FluentValidation 對ASP.NET MVC 有很好的支持和集成。
大家好。
還在尋找解決方案?
我今天解決了同樣的問題。您必須創建將驗證 2 個日期的自定義驗證屬性(範例如下)。然後您需要適配器(驗證器),它將使用您的自定義屬性驗證模型。最後一件事是將適配器與屬性綁定。也許一些例子會比我解釋得更好:)
開始了:
日期比較屬性.cs:
[AttributeUsage(AttributeTargets.Class, AllowMultiple = true, Inherited = true)] public class DateCompareAttribute : ValidationAttribute { public enum Operations { Equals, LesserThan, GreaterThan, LesserOrEquals, GreaterOrEquals, NotEquals }; private string _From; private string _To; private PropertyInfo _FromPropertyInfo; private PropertyInfo _ToPropertyInfo; private Operations _Operation; public string MemberName { get { return _From; } } public DateCompareAttribute(string from, string to, Operations operation) { _From = from; _To = to; _Operation = operation; //gets the error message for the operation from resource file ErrorMessageResourceName = "DateCompare" + operation.ToString(); ErrorMessageResourceType = typeof(ValidationStrings); } public override bool IsValid(object value) { Type type = value.GetType(); _FromPropertyInfo = type.GetProperty(_From); _ToPropertyInfo = type.GetProperty(_To); //gets the values of 2 dates from model (using reflection) DateTime? from = (DateTime?)_FromPropertyInfo.GetValue(value, null); DateTime? to = (DateTime?)_ToPropertyInfo.GetValue(value, null); //compare dates if ((from != null) && (to != null)) { int result = from.Value.CompareTo(to.Value); switch (_Operation) { case Operations.LesserThan: return result == -1; case Operations.LesserOrEquals: return result <= 0; case Operations.Equals: return result == 0; case Operations.NotEquals: return result != 0; case Operations.GreaterOrEquals: return result >= 0; case Operations.GreaterThan: return result == 1; } } return true; } public override string FormatErrorMessage(string name) { DisplayNameAttribute aFrom = (DisplayNameAttribute)_FromPropertyInfo.GetCustomAttributes(typeof(DisplayNameAttribute), true).SingleOrDefault(); DisplayNameAttribute aTo = (DisplayNameAttribute)_ToPropertyInfo.GetCustomAttributes(typeof(DisplayNameAttribute), true).SingleOrDefault(); return string.Format(ErrorMessageString, !string.IsNullOrWhiteSpace(aFrom.DisplayName) ? aFrom.DisplayName : _From, !string.IsNullOrWhiteSpace(aTo.DisplayName) ? aTo.DisplayName : _To); } }DateCompareAttributeAdapter.cs:
public class DateCompareAttributeAdapter : DataAnnotationsModelValidator<DateCompareAttribute> { public DateCompareAttributeAdapter(ModelMetadata metadata, ControllerContext context, DateCompareAttribute attribute) : base(metadata, context, attribute) { } public override IEnumerable<ModelValidationResult> Validate(object container) { if (!Attribute.IsValid(Metadata.Model)) { yield return new ModelValidationResult { Message = ErrorMessage, MemberName = Attribute.MemberName }; } } }全球突擊:
protected void Application_Start() { // ... DataAnnotationsModelValidatorProvider.RegisterAdapter(typeof(DateCompareAttribute), typeof(DateCompareAttributeAdapter)); }CustomViewModel.cs:
[DateCompare("StartDateTime", "EndDateTime", DateCompareAttribute.Operations.LesserOrEquals)] public class CustomViewModel { // Properties... public DateTime? StartDateTime { get; set; } public DateTime? EndDateTime { get; set; } }