Asp.Net核心模型验证*多个*属性

时间:2016-10-26 23:39:29

标签: c# asp.net-mvc validation asp.net-core

我有一个Asp.Net核心REST服务,我正在使用内置验证。我需要一些额外的功能,所以我找到了一些我需要的验证属性的例子,所以这里只是我模型的一小部分:

    [RequiredIfEmpty("B")]
    [RequiredIfEmpty("C")]
    public string A { get; set; }
    public string B { get; set; }
    public string C { get; set; }

所以,很明显我想要的是什么。如果B或C为空,我想验证是否指定了A.

当我发送一个验证失败的JSON请求时,我只得到:

"A is required when B is empty."

我期待得到:

"A is required when B is empty."
"A is required when C is empty."

因此,似乎验证代码在基于类型的属性上做了不同的,因为它忽略了第二个。如果我这样做,这进一步证明了:

    [RequiredIfEmpty("B")]
    [RequiredIfEmpty2("C")]
    public string A { get; set; }
    public string B { get; set; }
    public string C { get; set; }

RequiredIfEmpty2只是从RequiredIfEmpty派生而来,没有额外的代码。现在我得到了预期的结果:

"A is required when B is empty."
"A is required when C is empty."

在这个例子中,我只有2个依赖属性,所以创建一个2版本没什么大不了的,但它非常hacky而且我不喜欢它。

我考虑过更改RequiredIfEmpty属性以获取属性的字符串[],但似乎MVC基础结构不允许单个属性返回多个错误字符串。

我确实向微软报告了这个问题,但是想知道除了拥有2个版本之外是否有其他人可以考虑解决方案?

1 个答案:

答案 0 :(得分:2)

.Net Core + .Net Framework

您可以覆盖属性中的EqualsGetHashCode方法,以创建AllowMultiple属性之间的区别。

[AttributeUsage(AttributeTargets.Property, AllowMultiple = true, Inherited = false)]
public sealed class RequiredIfEmptyAttribute : RequiredAttribute
{
    private object _instance = new object();

    public override bool Equals(object obj) => _instance.Equals(obj);

    public override int GetHashCode() => _instance.GetHashCode();

    // all the rest of the code
}

。仅限.Net Framework

如果您仅定位.Net Framework,则可以使用TypeId属性作为同一类型的两个属性之间的唯一标识符。 (MSDN documentation

[AttributeUsage(AttributeTargets.Property, AllowMultiple = true, Inherited = false)]
public sealed class RequiredIfEmptyAttribute : RequiredAttribute
{
    public override object TypeId { get; } = new object();

    // all the rest of the code
}
  

我考虑过更改RequiredIfEmpty属性以获取属性的字符串[],但它并不像MVC基础结构允许单个属性返回的多个错误字符串一样。

正确。每个属性不能返回多个消息。但是,您可以实现IValidatableObject接口来实现此目的。