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は、この要素を「StartDate」ではなく「Task.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 に答える