【问题标题】:How to validate model in .Net Core 3.1 in console app when the model contains another class's object as a property using DataAnnotations?当模型包含另一个类的对象作为使用 DataAnnotations 的属性时,如何在控制台应用程序中验证 .Net Core 3.1 中的模型?
【发布时间】:2021-01-08 13:18:19
【问题描述】:

我有以下请求模型:

public class VisitRequest
    {
        public ProviderInfo Provider { get; set; }

        [Required]
        [MaxLength(64)]
        public string PayerId { get; set; }
    }

我有如下自定义类:

 public class ProviderInfo
    {
        [Required]
        [MaxLength(15)]
        public string TaxId { get; set; }

        [Required(ErrorMessage = " Qualifier is required.")]
        [MaxLength(15)]
        public string NPI { get; set; }
    }

我目前正在使用 ValidationContext 进行模型验证:

var visitData = JsonConvert.DeserializeObject<VisitRequest>(jsonString);
var vc = new ValidationContext(visitData);
var errorResults = new List<ValidationResult>();
var isValid = Validator.TryValidateObject(visitData, vc, errorResults, true);

我的演示 json 请求如下:

{
'Member': {
  'Qualifier': 'MedicaidID',
  'Identifier': '100'
  },                
  'ExternalVisitID': '123456789',
}

现在我在 ErrorResult 中收到 ErrorMessage 为:

PayerId is required.

但我没有得到自定义类的验证。如何在 .Net Core Console 应用程序 中实现这一点? 我对 .Net Core 还很陌生,因此我们将不胜感激。谢谢!


更新:

我遵循了@John H 给出的答案,但仍然存在一个问题。

如果我的要求是:

'Provider' : {
      'TaxId' : null
}

它会正常工作,因为它能够识别这是类型 ProviderInfo 对象。

但如果我的请求不包含有关提供者的任何信息:

{
'ExternalVisitID': '123456789',
'EVVMSID': '100', 
}

那么它无法验证对象。

【问题讨论】:

    标签: c# .net validation .net-core data-annotations


    【解决方案1】:

    简而言之,这不起作用,因为TryValidateObject 不支持复杂嵌套类型的验证。这也是这种类型的 .NET Framework 版本的问题,@reustmd 创建了一个NuGet Package 来解决这个问题。不幸的是,它不支持 .NET Core,但我发现有一个 package forked from this 支持。来自自述文件:

    安装

    可作为 NuGet-Package dataannotationsvalidator:

    安装包数据注解验证器

    用法

    查看文件DataAnnotationsValidator/DataAnnotationsValidator.Tests/DataAnnotationsValidatorTests.cs

    简短示例:

    var 验证器 = new DataAnnotationsValidator.DataAnnotationsValidator();

    var validationResults = new List();

    validator.TryValidateObjectRecursive(modelToValidate, validationResults);

    这应该可以解决您的问题。

    顺便说一句,我还发现 this proposal 正在讨论将此功能添加到 .NET。如果您对该提案的技术设计讨论感兴趣,请参阅 .NET 基金会discussingit 发布的视频。

    更新

    对于上面的场景,我已经安装了上面的包,更改了 VisitRequest 类以使提供程序成为必需

    public class VisitRequest
    {
        [Required]
        public ProviderInfo Provider { get; set; }
    
        [Required]
        [MaxLength(64)]
        public string PayerId { get; set; }
    }
    

    然后运行以下内容:

    var jsonString = @"{
        ""ExternalVisitID"": ""123456789"",
        ""EVVMSID"": ""100""
    }";
    
    var modelToValidate = JsonConvert.DeserializeObject<VisitRequest>(jsonString);
    
    var validator = new DataAnnotationsValidator.DataAnnotationsValidator();
    
    var validationResults = new List<ValidationResult>();
    
    validator.TryValidateObjectRecursive(modelToValidate, validationResults);
    
    foreach (var item in validationResults)
    {
        Console.WriteLine(item.ErrorMessage);
    
        foreach (var memberName in item.MemberNames)
        {
            Console.WriteLine($"\t{memberName}");
        }
    }
    

    产生以下输出:

    The Provider field is required.
        Provider
    The PayerId field is required.
        PayerId
    

    如果您想单独列出缺少的提供程序的每个字段,即使 JSON 的那部分是空的,我认为您必须派生 NuGet 包并进行这些更改。但这可能是 .NET 没有开箱即用地支持此功能的原因,因为人们对其行为方式有不同的期望。

    【讨论】:

    • 非常感谢您的帮助!自2天以来,我一直在尝试解决此问题。 ?
    • @VivekSheth 没问题。 :)
    • 我正在使用这个包,但我遇到了一个问题,你可以看看我在问题中添加的更新。
    • @VivekSheth 如果您希望Provider 属性是必需的,那么您应该用[Required] public ProviderInfo Provider { get; set; } 标记它。这会告诉你它完全丢失了。正如您现在所拥有的,ProviderInfo 属性仅是必需的 如果您在 JSON 中包含 provider
    • 我已经将它标记为[必需],但如果 JSON 请求不包含该属性,它仍然不会验证它。
    猜你喜欢
    • 2020-05-02
    • 1970-01-01
    • 1970-01-01
    • 2014-04-09
    • 1970-01-01
    • 2020-11-07
    • 1970-01-01
    • 1970-01-01
    • 2014-10-15
    相关资源
    最近更新 更多