C#MVC 3:在属性属性中防止魔术字符串

Bri*_*get 1 c# data-annotations asp.net-mvc-3

我在互联网上找到了一个RequiredIfAttribute,我将其修改为RequiredNotIf.该属性可以像这样使用.

[RequiredNotIf("LastName", null, ErrorMessage = "You must fill this.")]
public string FirstName { get; set; }

[RequiredNotIf("FirstName", null, ErrorMessage = "You must fill this")]
public string LastName { get; set; }
Run Code Online (Sandbox Code Playgroud)

和属性的源代码 ......

[AttributeUsageAttribute(AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Parameter, AllowMultiple = true)]
public class RequiredNotIfAttribute : RequiredAttribute, IClientValidatable
{
    private string OtherProperty { get; set; }
    private object Condition { get; set; }

    public RequiredNotIfAttribute(string otherProperty, object condition)
    {
        OtherProperty = otherProperty;
        Condition = condition;
    }

    protected override ValidationResult IsValid(object value, ValidationContext validationContext)
    {
        var property = validationContext.ObjectType.GetProperty(OtherProperty);
        if (property == null)
        {
            return new ValidationResult(String.Format("Property {0} not found.", OtherProperty));
        }

        var propertyValue = property.GetValue(validationContext.ObjectInstance, null);
        var conditionIsMet = !Equals(propertyValue, Condition);
        return conditionIsMet ? base.IsValid(value, validationContext) : null;
    }

    public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context)
    {
        var rule = new ModelClientValidationRule
        {
            ErrorMessage = FormatErrorMessage(metadata.GetDisplayName()),
            ValidationType = "requiredif",
        };

        var depProp = BuildDependentPropertyId(metadata, context as ViewContext);

        var targetValue = (Condition ?? "").ToString();
        if (Condition != null && Condition is bool)
        {
            targetValue = targetValue.ToLower();
        }

        rule.ValidationParameters.Add("otherproperty", depProp);
        rule.ValidationParameters.Add("condition", targetValue);

        yield return rule;
    }

    private string BuildDependentPropertyId(ModelMetadata metadata, ViewContext viewContext)
    {
        var depProp = viewContext.ViewData.TemplateInfo.GetFullHtmlFieldId(OtherProperty);
        var thisField = metadata.PropertyName + "_";
        if (depProp.StartsWith(thisField))
        {
            depProp = depProp.Substring(thisField.Length);
        }
        return depProp;
    }
}
Run Code Online (Sandbox Code Playgroud)

这个的缺点 - 正如我所看到的 - 是属性"header"中的魔术字符串.我怎么能摆脱它?

Dar*_*rov 5

你无法摆脱它,因为属性是元数据,值必须在编译时知道.如果你想在没有魔术字符串的情况下进行更高级的验证,我强烈建议你使用FluentValidation.NET.以声明方式使用属性执行验证是非常有限的恕我直言.只需看看你必须为标准创建的源代码的数量,以及RequiredIf或RequiredNotIf.当他们选择Data Annotations进行验证时,我不知道框架的设计者在想什么.这太荒谬了.也许在未来他们会丰富它并允许更复杂的场景,但在那之前我坚持使用FV.