相同的 DataAnnotation 属性在同一属性上重复

发布于 2024-12-13 18:44:10 字数 574 浏览 2 评论 0原文

我正在处理一些非常疯狂的自定义验证。基本上,根据下拉列表的选择,将确定针对目标属性验证哪些值。

例如,我有以下下拉列表:

1 = 汽车
2 = 卡车

在我的自定义验证中,如果选择是汽车,则该值不能超过 20。如果选择是卡车,则该值不能超过 40。

所以我的属性需要看起来像这样:

[ValueBelowIf("1", 20)]
[ValueBelowIf("2", 40)]
public int Value { get; set; }

当然,为了让它编译,我必须在我的自定义属性上设置它:

[AttributeUsage(AttributeTargets.Property, AllowMultiple = true)]
public class ValueBelowIfAttribute : ValidationAttribute, IClientValidatable

但是,似乎只有第一个属性被绑定 - 第二个属性被忽略。

我做错了什么?

I have some pretty crazy custom validation I'm working on. Basically, based on the selection of a dropdown, that will determine what values are validated against the target property.

For example, I have the following dropdown:

1 = Car
2 = Truck

On my custom validation, if the selection is car, then the value can't be more than 20. If the selection is truck, the value can't be more than 40.

So my attributes need to look something like this:

[ValueBelowIf("1", 20)]
[ValueBelowIf("2", 40)]
public int Value { get; set; }

Of course, to even get it to compile, I have to set this on my custom attribute:

[AttributeUsage(AttributeTargets.Property, AllowMultiple = true)]
public class ValueBelowIfAttribute : ValidationAttribute, IClientValidatable

However, it appears only the first attribute is being bound -- the second is ignored.

What am I doing wrong?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

等待圉鍢 2024-12-20 18:44:10

您需要覆盖 类型ID。 MVC 的验证器将仅根据其 TypeId 值评估每个唯一属性。

将您的属性实现更改为以下内容,它将起作用:

[AttributeUsage(AttributeTargets.Property, AllowMultiple = true)]
public class ValueBelowIfAttribute : ValidationAttribute, IClientValidatable
{
  private object _typeId = new object();
  public override object TypeId
  {
    get { return this._typeId; }
  }
  // OTHER CODE
}

根据我的收集,AllowMultiple(至少在 MVC 的情况下)只是告诉编译器该属性多次出现是有效的,但控制这些属性的方式是 TypeId属性在运行时评估。

这可能很有用,因为您可以静态地(在编译时)允许多次应用相同的属性类型,但在运行时忽略逻辑上重复的属性。例如,在我的示例中,我可以返回属性参数的哈希码,而不是返回保证唯一的 new object()。在这种情况下,如果您这样做:

[ValueBelowIf("1", 20)]
[ValueBelowIf("2", 40)]
[ValueBelowIf("2", 40)]
public int Value { get; set; }

将不会评估第二个 [ValueBelowIf("2", 40)]

阅读更多详细信息,我在这里找到了答案:
http://www.paraesthesia.com/archive/2010/03/02/the-importance-of-typeid-in-asp.net-mvc-dataannotations-validation-attributes.aspx

You need to override the default implementation of TypeId. MVC's validator will only evaluate each unique attribute based on it's TypeId value.

Change your attribute implementation to the following, and it'll work:

[AttributeUsage(AttributeTargets.Property, AllowMultiple = true)]
public class ValueBelowIfAttribute : ValidationAttribute, IClientValidatable
{
  private object _typeId = new object();
  public override object TypeId
  {
    get { return this._typeId; }
  }
  // OTHER CODE
}

From what I gather, AllowMultiple, at least in the case of MVC, just tells the compiler that the attribute is valid appearing multiple times, but it is TypeId that controls how those attributes are evaluated at runtime.

This can be useful because you can statically (at compile time) allow the same attribute type to be applied multiple times, but at runtime ignore logically duplicated attributes. For example, in my example instead of returning a guaranteed-unique new object(), I could return a hashcode of the attribute parameters. In that case, if you did:

[ValueBelowIf("1", 20)]
[ValueBelowIf("2", 40)]
[ValueBelowIf("2", 40)]
public int Value { get; set; }

the second [ValueBelowIf("2", 40)] would not be evaluated.

Read more details where I came across the answer here:
http://www.paraesthesia.com/archive/2010/03/02/the-importance-of-typeid-in-asp.net-mvc-dataannotations-validation-attributes.aspx

情释 2024-12-20 18:44:10

您正在尝试将类范围的验证逻辑实现到属性验证技术中。不要那样做!使用适当的类验证机制,例如实现 IValidatableObject,或使用 FluentValidation

You are trying to implement class-wide validation logic into property-validation technique. Dont do that! Use proper class-validation mechanism instead, for example implement IValidatableObject, or use FluentValidation

貪欢 2024-12-20 18:44:10

由于 C# 属性是有限的常量,因此我发现实现此目的的最佳方法是通过构造函数将所有值作为单独的值提供。这很丑陋,但却是唯一可以做到的方法。

例如:

[AttributeUsage(AttributeTargets.Property, AllowMultiple = true)]
public class ValueBelowIfAttribute : ValidationAttribute, IClientValidatable
{
    public string IfValue { get; set; }
    public int BelowValue { get; set; }
    public string IfValue2 { get; set; }
    public int BelowValue2 { get; set; }
    public string IfValue3 { get; set; }
    public int BelowValue3 { get; set; }

    public ValueBelowIfAttribute(string ifValue, int belowValue)
    {
        // do stuff
    }

    public ValueBelowIfAttribute(string ifValue, int belowValue, string ifValue2, int belowValue2)
    {
        // do stuff
    }

    public ValueBelowIfAttribute(string ifValue, int belowValue, string ifValue2, int belowValue2, string ifValue3, int belowValue3)
    {
        // do stuff
    }
}

Since C# Attrbiutes are limited constants, I found the best way to accomplish this is to provide all values through the constructor as separate values. This is ugly, but the only way it can be done.

For example:

[AttributeUsage(AttributeTargets.Property, AllowMultiple = true)]
public class ValueBelowIfAttribute : ValidationAttribute, IClientValidatable
{
    public string IfValue { get; set; }
    public int BelowValue { get; set; }
    public string IfValue2 { get; set; }
    public int BelowValue2 { get; set; }
    public string IfValue3 { get; set; }
    public int BelowValue3 { get; set; }

    public ValueBelowIfAttribute(string ifValue, int belowValue)
    {
        // do stuff
    }

    public ValueBelowIfAttribute(string ifValue, int belowValue, string ifValue2, int belowValue2)
    {
        // do stuff
    }

    public ValueBelowIfAttribute(string ifValue, int belowValue, string ifValue2, int belowValue2, string ifValue3, int belowValue3)
    {
        // do stuff
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文