【问题标题】:Asp.Net Core Model Validation *Multiple* AttributesAsp.Net Core 模型验证 *多个* 属性
【发布时间】:2017-03-09 12:02:46
【问题描述】:

我有一个 Asp.Net Core 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 基础结构不允许单个属性返回多个错误字符串。

我确实向 Microsoft 报告了它,但想知道除了 2 版本之外是否还有其他人可以想到解决方法?

【问题讨论】:

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


    【解决方案1】:

    .Net Core + .Net 框架

    您可以覆盖属性中的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 框架

    如果您只针对 .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 接口来实现这一点。

    【讨论】:

    • 我的属性基于 MVC Foolproof 开源项目,我快速查看了该代码,它们并没有覆盖 TypeId,所以我猜你发现了问题:)。希望。我明天去测试。谢谢!
    • @SledgeHammer 很高兴为您提供帮助。您可能需要仔细检查 TypeId 属性的设置方式。我使用的是新的object,但 MSDN 使用的是 GUID。 (不确定是否重要。)
    • 等等...我很困惑。 ValidationAttribute 没有 TypeId 属性?这似乎是 .Net 4.x 而不是 Core 的一部分?
    • 是的......核心没有那个属性。然后我尝试用 base.GetHashCode() ^ DependentProperty.GetHashCode() 覆盖 GetHashCode(),但这似乎不起作用。但我通过覆盖 Equals 并检查 DependentProperties 是否相等来让它工作。
    • @SledgeHammer 圣斗士,你是对的!我今天学到了一些新东西。我继续并更新了我的答案以反映这一点。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-02-17
    • 1970-01-01
    • 1970-01-01
    • 2017-12-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多