假设我有一个StartDate和一个EndDate,我想检查EndDate是否距离开始日期不超过3个月
public class DateCompare : ValidationAttribute
{
public String StartDate { get; set; }
public String EndDate { get; set; }
//Constructor to take in the property names that are supposed to be checked
public DateCompare(String startDate, String endDate)
{
StartDate = startDate;
EndDate = endDate;
}
public override bool IsValid(object value)
{
var str = value.ToString();
if (string.IsNullOrEmpty(str))
return true;
DateTime theEndDate = DateTime.ParseExact(EndDate, "yyyy-MM-dd HH:mm:ss", CultureInfo.InvariantCulture);
DateTime theStartDate = DateTime.ParseExact(StartDate, "yyyy-MM-dd HH:mm:ss", CultureInfo.InvariantCulture).AddMonths(3);
return (DateTime.Compare(theStartDate, theEndDate) > 0);
}
}
我想将此实现到我的验证中
[DateCompare(“StartDate”,“EndDate”,ErrorMessage =“交易只能是3个月!”)
我知道我在这里收到错误...但是如何在asp.net mvc中进行这种业务规则验证
答案 0 :(得分:8)
这是一个迟到的答案,但我想分享给其他人。以下是我如何使用不显眼的客户端验证来验证所有内容:
创建属性类:
public class DateCompareValidationAttribute : ValidationAttribute, IClientValidatable
{
public enum CompareType
{
GreatherThen,
GreatherThenOrEqualTo,
EqualTo,
LessThenOrEqualTo,
LessThen
}
private CompareType _compareType;
private DateTime _fromDate;
private DateTime _toDate;
private string _propertyNameToCompare;
public DateCompareValidationAttribute(CompareType compareType, string message, string compareWith = "")
{
_compareType = compareType;
_propertyNameToCompare = compareWith;
ErrorMessage = message;
}
#region IClientValidatable Members
/// <summary>
/// Generates client validation rules
/// </summary>
public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context)
{
ValidateAndGetCompareToProperty(metadata.ContainerType);
var rule = new ModelClientValidationRule();
rule.ErrorMessage = ErrorMessage;
rule.ValidationParameters.Add("comparetodate", _propertyNameToCompare);
rule.ValidationParameters.Add("comparetype", _compareType);
rule.ValidationType = "compare";
yield return rule;
}
#endregion
protected override ValidationResult IsValid(object value, ValidationContext validationContext)
{
// Have to override IsValid method. If you have any logic for server site validation, put it here.
return ValidationResult.Success;
}
/// <summary>
/// verifies that the compare-to property exists and of the right types and returnes this property
/// </summary>
/// <param name="containerType">Type of the container object</param>
/// <returns></returns>
private PropertyInfo ValidateAndGetCompareToProperty(Type containerType)
{
var compareToProperty = containerType.GetProperty(_propertyNameToCompare);
if (compareToProperty == null)
{
string msg = string.Format("Invalid design time usage of {0}. Property {1} is not found in the {2}", this.GetType().FullName, _propertyNameToCompare, containerType.FullName);
throw new ArgumentException(msg);
}
if (compareToProperty.PropertyType != typeof(DateTime) && compareToProperty.PropertyType != typeof(DateTime?))
{
string msg = string.Format("Invalid design time usage of {0}. The type of property {1} of the {2} is not DateType", this.GetType().FullName, _propertyNameToCompare, containerType.FullName);
throw new ArgumentException(msg);
}
return compareToProperty;
}
}
注意:如果要验证时间长度,请向约束器添加另一个参数,并更改此特定类型的比较的枚举器
将属性添加到字段中,如下所示:
[DateCompareValidation(DateCompareValidationAttribute.CompareType.GreatherThenOrEqualTo, "This Date must be on or after another date", compareWith: "AnotherDate")]
记下您生成的html是如何更改的。它应包括验证消息,比较日期的字段名称等。生成的parms将以“data-val-compare”开头。在GetClientValidationRules方法中设置ValidationType =“compare”时,您定义了此“比较”。
现在您需要匹配javascript代码:添加验证适配器和验证方法。我在这里使用了无数方法,但你不必这样做。我建议将此代码放在一个单独的javascript文件中,以便此文件与您的属性类一起变得像一个控件,可以在任何地方使用。
$。validator.unobtrusive.adapters.add( '相比', ['comparetodate','comparetype'], function(options){ options.rules ['compare'] = options.params; options.messages ['compare'] = options.message; } );
$.validator.addMethod("compare", function (value, element, parameters) {
// value is the actuall value entered
// element is the field itself, that contain the the value (in case the value is not enough)
var errMsg = "";
// validate parameters to make sure everyting the usage is right
if (parameters.comparetodate == undefined) {
errMsg = "Compare validation cannot be executed: comparetodate parameter not found";
alert(errMsg);
return false;
}
if (parameters.comparetype == undefined) {
errMsg = "Compare validation cannot be executed: comparetype parameter not found";
alert(errMsg);
return false;
}
var compareToDateElement = $('#' + parameters.comparetodate).get();
if (compareToDateElement.length == 0) {
errMsg = "Compare validation cannot be executed: Element to compare " + parameters.comparetodate + " not found";
alert(errMsg);
return false;
}
if (compareToDateElement.length > 1) {
errMsg = "Compare validation cannot be executed: more then one Element to compare with id " + parameters.comparetodate + " found";
alert(errMsg);
return false;
}
//debugger;
if (value && !isNaN(Date.parse(value))) {
//validate only the value contains a valid date. For invalid dates and blanks non-custom validation should be used
//get date to compare
var compareToDateValue = $('#' + parameters.comparetodate).val();
if (compareToDateValue && !isNaN(Date.parse(compareToDateValue))) {
//if date to compare is not a valid date, don't validate this
switch (parameters.comparetype) {
case 'GreatherThen':
return new Date(value) > new Date(compareToDateValue);
case 'GreatherThenOrEqualTo':
return new Date(value) >= new Date(compareToDateValue);
case 'EqualTo':
return new Date(value) == new Date(compareToDateValue);
case 'LessThenOrEqualTo':
return new Date(value) <= new Date(compareToDateValue);
case 'LessThen':
return new Date(value) < new Date(compareToDateValue);
default:
{
errMsg = "Compare validation cannot be executed: '" + parameters.comparetype + "' is invalid for comparetype parameter";
alert(errMsg);
return false;
}
}
return true;
}
else
return true;
}
else
return true;
});
这只关注客户端不显眼的验证。如果你需要服务器端,你必须在isValid方法的覆盖中有一些逻辑。此外,您可以使用Reflection使用显示属性等生成错误消息,并使消息参数可选。
答案 1 :(得分:4)
我只想知道如何在班级而不是在属性级别这样做。如果您创建MVC应用程序,则帐户模型将显示下面所示的方法。
<强>类别:强>
[PropertiesMustMatch("Password",
"ConfirmPassword", ErrorMessage =
"Password and confirmation password
do not match.")]
public class RegisterModel
{
[Required(ErrorMessage = "Required")]
[DataType(DataType.EmailAddress)]
[DisplayName("Your Email")]
public string Email { get; set; }
[Required(ErrorMessage = "Required")]
[ValidatePasswordLength]
[DataType(DataType.Password)]
[DisplayName("Password")]
public string Password { get; set; }
[Required(ErrorMessage = "Required")]
[DataType(DataType.Password)]
[DisplayName("Re-enter password")]
public string ConfirmPassword { get; set; }
}
验证方法:
[AttributeUsage(AttributeTargets.Class, AllowMultiple = true, Inherited = true)]
public sealed class PropertiesMustMatchAttribute : ValidationAttribute
{
private const string _defaultErrorMessage = "'{0}' and '{1}' do not match.";
private readonly object _typeId = new object();
public PropertiesMustMatchAttribute(string originalProperty, string confirmProperty)
: base(_defaultErrorMessage)
{
OriginalProperty = originalProperty;
ConfirmProperty = confirmProperty;
}
public string ConfirmProperty
{
get;
private set;
}
public string OriginalProperty
{
get;
private set;
}
public override object TypeId
{
get
{
return _typeId;
}
}
public override string FormatErrorMessage(string name)
{
return String.Format(CultureInfo.CurrentUICulture, ErrorMessageString,
OriginalProperty, ConfirmProperty);
}
public override bool IsValid(object value)
{
PropertyDescriptorCollection properties = TypeDescriptor.GetProperties(value);
object originalValue = properties.Find(OriginalProperty, true /* ignoreCase */).GetValue(value);
object confirmValue = properties.Find(ConfirmProperty, true /* ignoreCase */).GetValue(value);
return Object.Equals(originalValue, confirmValue);
}
}
答案 2 :(得分:4)
实体:
[MetadataType(typeof(MyEntity_Validation))]
public partial class MyEntity
{
}
public class MyEntity_Validation
{
[Required(ErrorMessage="'Date from' is required")]
public DateTime DateFrom { get; set; }
[CompareDatesValidatorAttribute("DateFrom")]
public DateTime DateTo { get; set; }
}
属性:
public sealed class CompareDatesValidatorAttribute : ValidationAttribute
{
private string _dateToCompare;
private const string _errorMessage = "'{0}' must be greater or equal'{1}'";
public CompareDatesValidatorAttribute(string dateToCompare)
: base(_errorMessage)
{
_dateToCompare = dateToCompare;
}
public override string FormatErrorMessage(string name)
{
return string.Format(_errorMessage, name, _dateToCompare);
}
protected override ValidationResult IsValid(object value, ValidationContext validationContext)
{
var dateToCompare = validationContext.ObjectType.GetProperty(_dateToCompare);
var dateToCompareValue = dateToCompare.GetValue(validationContext.ObjectInstance, null);
if (dateToCompareValue != null && value != null && (DateTime)value < (DateTime)dateToCompareValue)
{
return new ValidationResult(FormatErrorMessage(validationContext.DisplayName));
}
return null;
}
}
2。密码
实体:
public string Password { get; set; }
[Compare("Password", ErrorMessage = "ConfirmPassword must match Password")]
public string ConfirmPassword { get; set; }
我希望它有所帮助
答案 3 :(得分:2)
属性
public class CompareValidatorAttribute : ValidationAttribute, IInstanceValidationAttribute
{
public CompareValidatorAttribute(string prefix, string propertyName) {
Check.CheckNullArgument("propertyName", propertyName);
this.propertyName = propertyName;
this.prefix = prefix;
}
string propertyName, prefix;
public string PropertyName
{
get { return propertyName; }
}
public string Prefix
{
get { return prefix; }
}
#region IInstanceValidationAttribute Members
public bool IsValid(object instance, object value)
{
var property = instance.GetType().GetProperty(propertyName);
var targetValue = property.GetValue(instance, null);
if ((targetValue == null && value == null) || (targetValue != null && targetValue.Equals(value)))
return true;
return false;
}
#endregion
public override bool IsValid(object value)
{
throw new NotImplementedException();
}
}
界面
public interface IInstanceValidationAttribute
{
bool IsValid(object instance, object value);
}
验证器
public class CompareValidator : DataAnnotationsModelValidator<CompareValidatorAttribute>
{
public CompareValidator(ModelMetadata metadata, ControllerContext context, CompareValidatorAttribute attribute)
: base(metadata, context, attribute)
{
}
public override IEnumerable<ModelValidationResult> Validate(object container)
{
if (!(Attribute as IInstanceValidationAttribute).IsValid(container, Metadata.Model))
yield return (new ModelValidationResult
{
MemberName = Metadata.PropertyName,
Message = Attribute.ErrorMessage
});
}
public override IEnumerable<ModelClientValidationRule> GetClientValidationRules()
{
var rule = new ModelClientValidationRule() { ErrorMessage = Attribute.ErrorMessage, ValidationType = "equalTo" };
rule.ValidationParameters.Add("equalTo", "#" + (!string.IsNullOrEmpty(Attribute.Prefix) ? Attribute.Prefix + "_" : string.Empty)+ Attribute.PropertyName);
return new[] { rule };
}
}
注册:
DataAnnotationsModelValidatorProvider.RegisterAdapter(typeof(CompareValidatorAttribute), typeof(CompareValidator));
答案 4 :(得分:2)
感谢您的信息。当我想将验证消息绑定到属性时,我不知所措。如果你换行
[AttributeUsage(AttributeTargets.Class)]
为...
[AttributeUsage(AttributeTargets.Property)]
您可以将比较移到特定属性之上。谢谢(你的)信息!由于我的客户端仍在3.5 sp1上运行,因此提供了很多帮助。 悲伤的脸