1

私はこの質問に基づいて、asp.netmvc3とjqueryvalidateを使用してカスタム検証属性を作成しました:

boolの代わりに文字列プロパティのグループで動作するように更新しました。これは問題なく動作します。しかし、カスタムErrorMessageで使用すると、カスタムメッセージが表示されないという問題が発生します。そして、その理由がわかりません。

[RequiredOneFromGroup("PhoneGroup", 
    ErrorMessageResourceName = "PhoneGroup", 
    ErrorMessageResourceType = typeof(WizardStrings))]
public String Mobile { get; set; } 
[RequiredOneFromGroup("PhoneGroup", 
    ErrorMessageResourceName = "PhoneGroup", 
    ErrorMessageResourceType = typeof(WizardStrings))]
public String Phone { get; set; }

カスタム検証属性は次のとおりです。

[AttributeUsage(AttributeTargets.Property)]
public class RequiredOneFromGroup : ValidationAttribute, IClientValidatable
{
    public RequiredOneFromGroup(string groupName)
    {
        ErrorMessage = string.Format("You must select at least one value from group \"{0}\"", groupName);
        GroupName = groupName;
    }

    public string GroupName { get; private set; }

    protected override ValidationResult IsValid(object value, ValidationContext validationContext)
    {
        foreach (var property in GetGroupProperties(validationContext.ObjectType))
        {
            var propertyValue = (string)property.GetValue(validationContext.ObjectInstance, null);
            if ( ! string.IsNullOrWhiteSpace(propertyValue))
            {
                // at least one property is true in this group => the model is valid
                return null;
            }
        }
        return new ValidationResult(FormatErrorMessage(validationContext.DisplayName));
    }

    private IEnumerable<PropertyInfo> GetGroupProperties(Type type)
    {
        return
            from property in type.GetProperties()
            where property.PropertyType == typeof(string)
            let attributes = property.GetCustomAttributes(typeof(RequiredOneFromGroup), false).OfType<RequiredOneFromGroup>()
            where attributes.Count() > 0
            from attribute in attributes
            where attribute.GroupName == GroupName
            select property;
    }

    public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context)
    {
        var groupProperties = GetGroupProperties(metadata.ContainerType).Select(p => p.Name);
        var rule = new ModelClientValidationRule
        {
            ErrorMessage = this.ErrorMessage
        };
        rule.ValidationType = string.Format("group", GroupName.ToLower());
        rule.ValidationParameters["propertynames"] = string.Join(",", groupProperties);
        yield return rule;
    }
}

ErrorMessageの手動設定を削除しようとしましたが、空のエラーメッセージが表示されます。モデルの名前付きパラメーターで指定したErrorMessageResourceNameの値を取得するにはどうすればよいですか?そして、カスタム検証属性がそれを表示するように設定するにはどうすればよいですか?

4

2 に答える 2

6

あなたのGetClientValidationRules方法で置き換えます:

var rule = new ModelClientValidationRule
{
    ErrorMessage = this.ErrorMessage
};

と:

var rule = new ModelClientValidationRule
{
    ErrorMessage = FormatErrorMessage(metadata.DisplayName)
};

またthis.ErrorMessage = ...、コンストラクターの行を削除します。ErrorMessageResourceNameErrorMessageとErrorMessageResourceType、検証属性のプロパティの両方を設定することはできません。それらは相互に排他的です。

于 2013-01-04T13:32:09.797 に答える
1

カスタム検証属性がValidationAttributeを継承しているため、ErrorMessageの処理は自然に行われると思いました。しかし、そうではないようです。

私は次のようにこの問題を回避しました:

    public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context)
    {
        var groupProperties = GetGroupProperties(metadata.ContainerType).Select(p => p.Name);
        var rule = new ModelClientValidationRule
        {
            // Replaced ErrorMessage with ErrorMessageString which 
            // will hold string value of ErrorMessageResourceName if there is
            ErrorMessage = this.ErrorMessageString
        };
        rule.ValidationType = string.Format("group", GroupName.ToLower());
        rule.ValidationParameters["propertynames"] = string.Join(",", groupProperties);
        yield return rule;
    }
于 2013-01-04T13:35:20.797 に答える