当模型包含另一个 class 的对象作为 属性 使用 DataAnnotations 时,如何在控制台应用程序中验证 .Net Core 3.1 中的模型?

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?

我有以下请求模型:

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

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

我的自定义 class 如下:

 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.

但我没有得到自定义 class 的验证。如何在 .Net Core Console 应用程序 中实现? 我是 .Net Core 的新手,所以任何帮助都是 appreciated.Thanks!


更新:

我按照@John H 给出的答案进行了操作,但仍然存在一个问题。

如果我的要求是:

'Provider' : {
      'TaxId' : null
}

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

但是如果我的请求不包含任何关于提供商的信息:

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

那么它就无法验证对象。

简而言之,这不起作用,因为 TryValidateObject 不支持复杂嵌套类型的验证。对于这种类型的 .NET Framework 版本,这也是一个问题,@reustmd 创建了一个 NuGet Package to solve the problem. Unfortunately, it doesn't support .NET Core, but I found there is a package forked from this 来解决这个问题。来自自述文件:

Installation

Available as NuGet-Package dataannotationsvalidator:

Install-Package dataannotationsvalidator

Usage

See file DataAnnotationsValidator/DataAnnotationsValidator.Tests/DataAnnotationsValidatorTests.cs

Short example:

var validator = new DataAnnotationsValidator.DataAnnotationsValidator();

var validationResults = new List<ValidationResult>();

validator.TryValidateObjectRecursive(modelToValidate, validationResults);

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

顺便说一句,我也找到了this proposal discussing adding this functionality to .NET. If you're interested in a technical design discussion of that proposal, there is a video posted by the .NET Foundation discussing

更新

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

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 不立即支持此功能的原因,因为人们对它的行为方式有不同的期望。