Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/asp.net-mvc-3/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# C MVC 3:防止属性中出现魔术字符串_C#_Asp.net Mvc 3_Data Annotations - Fatal编程技术网

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

C# C MVC 3:防止属性中出现魔术字符串,c#,asp.net-mvc-3,data-annotations,C#,Asp.net Mvc 3,Data Annotations,我在互联网上找到了一个RequiredFattribute,我将其修改为RequiredNotIf。属性可以这样使用 [RequiredNotIf("LastName", null, ErrorMessage = "You must fill this.")] public string FirstName { get; set; } [RequiredNotIf("FirstName", null, ErrorMessage = "You must fill this")] public s

我在互联网上找到了一个RequiredFattribute,我将其修改为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; }
以及属性的源代码

[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;
    }
}

在我看来,这种方法的缺点是属性头中的魔术字符串。我怎样才能摆脱它?

假设你指的是另一个财产名称;你不能。属性只能使用有限数量的参数类型-表达式不是其中之一,因此不能使用lambda技巧,因为这无论如何都是一个好主意。C没有infoof/memberof操作符。所以你所拥有的只是像弦这样的东西

好吧,我想你可以添加一个非魔术键,即一个不直接绑定到成员名称的键,但这似乎有点过分了,例如:

// NOT a recommendation
[RequiredNotIf(1, ...)]
public string Foo {get;set;}

[SomeKey(1)]
public string Bar {get;set;}

这已删除了成员名称,但仍依赖于键1解析为另一个属性化成员,而且更为复杂。这一点也不太清楚,即在一个非平凡的类上,您可能需要上下扫描以查看哪个其他成员具有匹配的标记。我不是球迷;p

假设您指的是其他财产名称;你不能。属性只能使用有限数量的参数类型-表达式不是其中之一,因此不能使用lambda技巧,因为这无论如何都是一个好主意。C没有infoof/memberof操作符。所以你所拥有的只是像弦这样的东西

好吧,我想你可以添加一个非魔术键,即一个不直接绑定到成员名称的键,但这似乎有点过分了,例如:

// NOT a recommendation
[RequiredNotIf(1, ...)]
public string Foo {get;set;}

[SomeKey(1)]
public string Bar {get;set;}

这已删除了成员名称,但仍依赖于键1解析为另一个属性化成员,而且更为复杂。这一点也不太清楚,即在一个非平凡的类上,您可能需要上下扫描以查看哪个其他成员具有匹配的标记。我不是球迷;p

您无法摆脱它,因为属性是元数据,值必须在编译时已知。如果你想在没有魔法字符串的情况下进行更高级的验证,我强烈推荐你。以声明方式使用属性执行验证对IMHO来说是非常有限的。只要看看你必须为一些标准和简单的东西(如RequiredIf或RequiredNotIf)编写的源代码的数量就可以了。我不知道框架的设计者在选择数据注释进行验证时是怎么想的。这太可笑了。也许将来它们会丰富它并允许更复杂的场景,但在此之前,我坚持使用FV。

您无法摆脱它,因为属性是元数据,必须在编译时知道值。如果你想在没有魔法字符串的情况下进行更高级的验证,我强烈推荐你。以声明方式使用属性执行验证对IMHO来说是非常有限的。只要看看你必须为一些标准和简单的东西(如RequiredIf或RequiredNotIf)编写的源代码的数量就可以了。我不知道框架的设计者在选择数据注释进行验证时是怎么想的。这太可笑了。也许将来他们会丰富它,允许更复杂的场景,但在此之前,我坚持使用FV。

你确定需要吗?在您的用例中,必需的属性应该起作用。是的,我需要它。我使用for循环多次查看表单。因此,可能有一对FirstName和LastName都包含值,也可能有一对不包含值。如果一对只包含一个值,那么RequiredNotiF属性就变得很方便。您确定需要吗?在您的用例中,必需的属性应该起作用。是的,我需要它。我使用for循环多次查看表单。因此,可能有一对FirstName和LastName都包含值,也可能有一对不包含值。如果一对只包含一个值,那么RequiredNotiF属性就变得很方便。完全同意。我也在businesslayer上使用FluentValidation进行POCO验证。我使用dataannotations的唯一罕见的情况是,当我有一个视图处理未发送到DB的数据时,即联系人表单,这样我就可以在UI级别保留整个循环。对于其他一切,FluentValidation.FluentValidation似乎是一条出路!非常感谢。完全同意。我也在businesslayer上使用FluentValidation进行POCO验证。我使用dataannotations的唯一罕见的情况是,当我有一个视图处理未发送到DB的数据时,即联系人表单,这样我就可以在UI级别保留整个循环。对于其他一切,FluentValidation.FluentValidation似乎是一条出路!非常感谢。