2

这是简化模型:

public class Person {
   public int Id;
   public string Name;
}

public class Task {
  public int Id;
  public int PersonId;
  public DateTime StartDate;
  [GreaterThan("StartDate")]
  public DateTime EndDate;
}

为了验证 EndDate >= StartDate,我编写了一般的GreaterThanAttribute。服务器端是微不足道的,但我在客户端验证上有问题。

我的 GreaterThanAttribute 从构造函数中获取了另一个属性(例如:“StartDate”),然后我将这个其他属性名称作为验证规则传递给 javascript。但它不起作用,因为 JS 不会找到这个元素,因为 MVC 将渲染并将其命名为“Task.StartDate”,而不是“StartDate”。

我的问题是,如何获取控制器将用于在 IClientValidatable.GetClientValidationRules() 中呈现我的模型的前缀?

谢谢

4

2 回答 2

2

以下是你如何实现它:

public class GreaterThanAttribute : ValidationAttribute, IClientValidatable
{
    private readonly string _otherProperty;
    public GreaterThanAttribute(string otherProperty)
    {
        _otherProperty = otherProperty;
    }

    public override string FormatErrorMessage(string name)
    {
        return string.Format(CultureInfo.CurrentCulture, ErrorMessageString, name, _otherProperty);
    }

    protected override ValidationResult IsValid(object value, ValidationContext validationContext)
    {
        var property = validationContext.ObjectType.GetProperty(_otherProperty);
        if (property == null)
        {
            return new ValidationResult(
                string.Format(
                    CultureInfo.CurrentCulture, 
                    "unknown property {0}", 
                    _otherProperty
                )
            );
        }
        var otherValue = (DateTime)property.GetValue(validationContext.ObjectInstance, null);
        var thisValue = (DateTime)value;
        if (thisValue <= otherValue)
        {
            return new ValidationResult(FormatErrorMessage(validationContext.DisplayName));
        }

        return null;
    }

    public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context)
    {
        var rule = new ModelClientValidationRule();
        rule.ErrorMessage = FormatErrorMessage(metadata.GetDisplayName());
        rule.ValidationType = "greaterthandate";
        rule.ValidationParameters["other"] = "*." + _otherProperty;
        yield return rule;
    }
}

在客户端:

(function ($) {
    var getModelPrefix = function (fieldName) {
        return fieldName.substr(0, fieldName.lastIndexOf('.') + 1);
    };

    var appendModelPrefix = function (value, prefix) {
        if (value.indexOf('*.') === 0) {
            value = value.replace('*.', prefix);
        }
        return value;
    };

    $.validator.unobtrusive.adapters.add('greaterthandate', ['other'], function (options) {
        var prefix = getModelPrefix(options.element.name),
            other = options.params.other,
            fullOtherName = appendModelPrefix(other, prefix),
            element = $(options.form).find(':input[name=' + fullOtherName + ']')[0];

        options.rules['greaterThanDate'] = element;
        if (options.message) {
            options.messages['greaterThanDate'] = options.message;
        }
    });

    $.validator.addMethod('greaterThanDate', function (value, element, params) {
        var otherDate = $(params).val();
        var thisDate = value;

        // TODO: put your custom date comparison implementation here between
        // the 2 values. Be careful here. Javascript date handling is culture dependent
        // so you might need to account for that when building your js Date instances

        return false;
    }, '');
})(jQuery);
于 2012-07-22T07:14:53.530 回答
0

这已经完成了。我建议您使用 FoolProof 验证。如果您不想这样做,您至少可以查看他们的源代码。这是一个链接

于 2012-07-22T06:52:58.830 回答