ASP.NET MVC - Choose which validation annotations to use

99封情书 提交于 2019-12-24 15:29:40

问题


I have a model with properties that look like this:

public class YourDetails {

  [Required(ErrorMessage = "Code is required")]
  [StringLength(10, ErrorMessage = "Code length is wrong", MinimumLength = 2)]
  [Range(0, int.MaxValue, ErrorMessage = "Please enter a value bigger than {1}")]
  public int Code { get; set; }

}

The UI validation is setup the usual out of the box way with unobtrusive JS validation plugin.

The issue: I have 2 navigation actions, back and next. Next is fine, validation fires when things are wrong, and when things are right i.e. .isValid() returns true, the data is passed to the DB service etc etc.

However when I press 'back' I have a requirement to validate the form/ViewModel differently prior to saving. I.e. make sure Code is a positive integer, but don't bother with the Required or StringLength validation.

So basically I want to validate fully on Next but partially on Back. Is that possible?


回答1:


When I've done something similar in the past the easiest way i found was to use fluent validation http://fluentvalidation.codeplex.com/wikipage?title=mvc. You can pass parameters to the validator and switch to different rule sets.




回答2:


I've used the following conditional "Required" & "StringLength" attributes in the past and they work well.

Required If Attribute:

using System;
using System.ComponentModel.DataAnnotations;
using System.Reflection;

namespace Website.Core.Mvc.DataAnnotations
{
    [AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Field | AttributeTargets.Property, AllowMultiple = true)]
    public class RequiredIfAttribute : RequiredAttribute
    {
        public string OtherProperty { get; set; }

        public object OtherPropertyValue { get; set; }

        public RequiredIfAttribute(string otherProperty, object value)
            : base()
        {
            OtherProperty = otherProperty;
            OtherPropertyValue = value;
        }

        private object _TypeId = new object();

        public override object TypeId
        {
            get
            {
                return _TypeId;
            }
        }

        protected override ValidationResult IsValid(object value, ValidationContext validationContext)
        {
            PropertyInfo property = validationContext.ObjectType.GetProperty(this.OtherProperty);
            if (property == null)
            {
                return new ValidationResult(this.OtherProperty + " not found");
            }

            // Get 
            object actualOtherPropertyValue = property.GetValue(validationContext.ObjectInstance, null);

            // If the other property matches the expected value then validate as normal
            if (IsRequired(OtherPropertyValue, actualOtherPropertyValue))
            {
                // Call base and validate required as normal
                ValidationResult isValid = base.IsValid(value, validationContext);
                return isValid;
            }
            return ValidationResult.Success;
        }

        protected virtual bool IsRequired(object otherPropertyValue, object actualOtherPropertyValue)
        {
            return object.Equals(OtherPropertyValue, actualOtherPropertyValue);
        }
    }
}

String Length If Attribute:

using System.ComponentModel.DataAnnotations;
using System.Reflection;

namespace Website.Core.Mvc.DataAnnotations
{
    public class StringLengthIfAttribute : StringLengthAttribute
    {
        public string OtherProperty { get; set; }

        public object OtherPropertyValue { get; set; }

        public StringLengthIfAttribute(int maximumLength, string otherProperty, object value)
            : base(maximumLength)
        {
            OtherProperty = otherProperty;
            OtherPropertyValue = value;
        }

        protected override ValidationResult IsValid(object value, ValidationContext validationContext)
        {
            PropertyInfo property = validationContext.ObjectType.GetProperty(this.OtherProperty);
            if (property == null)
            {
                return new ValidationResult(this.OtherProperty + " not found");
            }

            // Get 
            object actualOtherPropertyValue = property.GetValue(validationContext.ObjectInstance, null);

            // If the other property matches the expected value then validate as normal
            if (object.Equals(OtherPropertyValue, actualOtherPropertyValue))
            {
                // Call base and validate required as normal
                return base.IsValid(value, validationContext);
            }
            return null;
        }
    }
}

Example Usage:

public class MyModel
{
    [RequiredIf("IsBack", false)]
    public string Name { get; set; }

    public bool IsBack { get; set; } 
}


来源:https://stackoverflow.com/questions/15811559/asp-net-mvc-choose-which-validation-annotations-to-use

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!